[rhq] Branch 'raw-config' - 241 commits - .classpath etc/custom-serverplugin etc/eclipse-tools etc/intellij-tools etc/m2 etc/samples .gitignore modules/core modules/enterprise modules/helpers modules/plugins
by John Sanda
.classpath | 12
.gitignore | 1
dev/null |binary
etc/custom-serverplugin/pom.xml | 165 --
etc/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin-content.xml | 20
etc/eclipse-tools/RHQ | 43
etc/eclipse-tools/RHQ_Ignore_Target.js | 21
etc/eclipse-tools/templates/schema.xmlcatalog | 8
etc/intellij-tools/rhq-style.xml | 56
etc/m2/settings-content.xml | 4
etc/samples/custom-serverplugin/pom.xml | 158 ++
etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java | 86 +
etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java | 41
etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml | 79 +
etc/samples/skeleton-plugin/pom.xml | 4
modules/core/client-api/src/main/resources/rhq-configuration.xsd | 2
modules/core/dbutils/pom.xml | 2
modules/core/dbutils/pom.xml.orig | 279 +++
modules/core/dbutils/src/main/scripts/dbsetup/amps-schema.xml | 5
modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml | 4
modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml | 35
modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml | 786 +++++-----
modules/core/domain/src/main/java/org/rhq/core/domain/cloud/Server.java | 6
modules/core/domain/src/main/java/org/rhq/core/domain/common/Tag.java | 121 +
modules/core/domain/src/main/java/org/rhq/core/domain/common/Taggable.java | 38
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java | 12
modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java | 35
modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSourceSyncStatus.java | 46
modules/core/domain/src/main/java/org/rhq/core/domain/content/Distribution.java | 76
modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFile.java | 184 ++
modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFilePK.java | 90 +
modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java | 3
modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersion.java | 2
modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersionContentSource.java | 21
modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java | 155 +
modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java | 21
modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistributionPK.java | 8
modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoTag.java | 129 +
modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoTagPK.java | 122 +
modules/core/domain/src/main/java/org/rhq/core/domain/criteria/RepoCriteria.java | 14
modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java | 233 ++
modules/core/domain/src/main/java/org/rhq/core/domain/plugin/PluginDeploymentType.java | 31
modules/core/domain/src/main/java/org/rhq/core/domain/plugin/PluginStatusType.java | 29
modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java | 2
modules/core/domain/src/test/java/org/rhq/core/domain/content/test/ContentSourceSyncResultsTest.java | 54
modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java | 199 ++
modules/core/domain/src/test/java/org/rhq/core/domain/test/QueryAllTest.java | 9
modules/core/plugin-container/src/main/java/org/rhq/core/pc/StandaloneContainer.java | 38
modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginManager.java | 2
modules/core/util/src/main/java/org/rhq/core/util/file/FileUtil.java | 64
modules/core/util/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java | 9
modules/enterprise/gui/perspectives/pom.xml | 33
modules/enterprise/gui/perspectives/sample-perspective-war/pom.xml | 143 +
modules/enterprise/gui/perspectives/sample-perspective-war/src/main/webapp/WEB-INF/web.xml | 12
modules/enterprise/gui/perspectives/sample-perspective-war/src/main/webapp/index.html | 14
modules/enterprise/gui/pom.xml | 1
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/DownloadsUIBean.java | 22
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java | 73
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java | 91 -
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java | 132 +
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/client/RemoteClientServlet.java | 16
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PageControlView.java | 28
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ContentSourceCandidateReposUIBean.java | 69
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ContentSourcePackageVersionsUIBean.java | 67
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java | 37
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoContentSourcesUIBean.java | 13
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDetailsUIBean.java | 21
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDistributionUIBean.java | 68
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java | 162 ++
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/download/DownloadServlet.java | 16
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java | 23
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml | 1
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml | 7
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/content-beans.xml | 16
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml | 11
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/content-navigation.xml | 28
modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp | 775 +++++----
modules/enterprise/gui/portal-war/src/main/webapp/css/win.css | 4
modules/enterprise/gui/portal-war/src/main/webapp/js/iframeSSI.js | 77
modules/enterprise/gui/portal-war/src/main/webapp/js/rhq.js | 2
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml | 24
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml | 27
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml | 36
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml | 125 +
modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/contentProvider.xhtml | 88 -
modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml | 126 +
modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/listRepos.xhtml | 25
modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml | 105 +
modules/enterprise/gui/portal-war/src/main/webapp/rhq/entity/layout/main.xhtml | 4
modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml | 313 ++-
modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/layout/main.xhtml | 4
modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/perspective/index.xhtml | 37
modules/enterprise/remoting/cli/pom.xml | 2
modules/enterprise/server/container/pom.xml | 9
modules/enterprise/server/container/src/main/license/license.xml | 26
modules/enterprise/server/container/src/main/resources/plugins/README.txt | 7
modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml | 26
modules/enterprise/server/ear/pom.xml | 21
modules/enterprise/server/ear/src/main/license/license.xml | 26
modules/enterprise/server/ear/src/main/resources/product-plugin-service.xml | 10
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/CloudManagerBean.java | 12
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/CloudManagerLocal.java | 19
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java | 276 +++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java | 66
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java | 132 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerLocal.java | 28
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerRemote.java | 71
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoException.java | 25
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerBean.java | 326 ++++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerLocal.java | 78
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoManagerRemote.java | 27
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/AgentManagerBean.java | 11
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java | 46
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerMBean.java | 28
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerServiceImpl.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerCommunicationsService.java | 9
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginDeploymentScanner.java | 694 --------
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginDeploymentScannerMBean.java | 91 -
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginScanner.java | 596 +++++++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScanner.java | 247 +++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScannerMBean.java | 122 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ProductPluginDeployer.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java | 584 +++++++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java | 494 ++++++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java | 187 ++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java | 272 +++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java | 275 +++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ClassLoaderManager.java | 222 ++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java | 33
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java | 411 ++++-
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainerConfiguration.java | 47
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/RootServerPluginClassLoader.java | 4
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java | 71
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginComponent.java | 73
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java | 124 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java | 126 -
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java | 386 ++++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java | 39
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java | 28
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java | 77
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java | 35
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertServerPluginContainer.java | 10
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java | 514 +++---
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderPluginManager.java | 203 --
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java | 72
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginManager.java | 118 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionDetails.java | 147 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionFileDetails.java | 83 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java | 67
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSyncReport.java | 77
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/PackageSource.java | 5
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginContainer.java | 10
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/perspective/PerspectiveServerPluginContainer.java | 10
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java | 51
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerService.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/ContentSourceSyncJob.java | 15
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/support/SupportManagerBean.java | 13
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java | 21
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java | 57
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/webservices/WebservicesManagerBean.java | 27
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java | 7
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java | 91 +
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java | 302 +++
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/core/plugin/DatabaseAndFilePluginDeploymentTest.java | 14
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java | 359 ++++
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java | 146 +
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginService.java | 187 ++
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginServiceMBean.java | 24
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java | 147 +
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java | 217 ++
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginServiceMBean.java | 24
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestLifecycleListener.java | 91 +
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java | 27
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java | 178 --
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginServiceMBean.java | 24
modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml | 17
modules/enterprise/server/plugins/disk/src/main/java/org/rhq/enterprise/server/plugins/disk/DiskSource.java | 3
modules/enterprise/server/plugins/rhnhosted/pom.xml | 507 +++---
modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/PrimaryXML.java | 297 +++
modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java | 178 +-
modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java | 142 +
modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnComm.java | 12
modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnDownloader.java | 9
modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnJaxbTransport.java | 208 ++
modules/enterprise/server/plugins/rhnhosted/src/main/resources/META-INF/rhq-serverplugin.xml | 14
modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/BaseRHNTest.java | 8
modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/PrimaryXMLTest.java | 161 ++
modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelperTest.java | 20
modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java | 212 ++
modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/MockRhnXmlRpcExecutor.java | 1
modules/enterprise/server/plugins/rhnhosted/src/test/resources/test-log4j.xml | 464 +++++
modules/enterprise/server/plugins/url/src/main/java/org/rhq/enterprise/server/plugins/url/UrlProvider.java | 3
modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/RepoProvider.java | 9
modules/enterprise/server/xml-schemas/pom.xml | 2
modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/AbstractScheduleType.java | 93 +
modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/CronScheduleType.java | 45
modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/PeriodicScheduleType.java | 45
modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ScheduledJobDefinition.java | 87 +
modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorMetadataParser.java | 263 +++
modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtil.java | 50
modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-perspective.xsd | 144 -
modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd | 124 +
modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java | 140 +
modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-alert.xml | 4
modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml | 66
modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java | 9
modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl | 5
modules/plugins/aliases/pom.xml | 229 ++
modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesComponent.java | 90 +
modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesDiscoveryComponent.java | 58
modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml | 48
modules/plugins/aliases/src/test/java/org/rhq/plugins/aliases/AliasesComponentTest.java | 97 +
modules/plugins/aliases/src/test/resources/etc/aliases | 7
modules/plugins/aliases/src/test/resources/log4j.xml | 33
modules/plugins/augeas/pom.xml | 18
modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java | 438 ++++-
modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java | 165 +-
modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/AugeasNode.java | 83 -
modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/AugeasVariable.java | 41
modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java | 150 +
modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/GlobFilter.java | 112 +
modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java | 287 +++
modules/plugins/cron/pom.xml | 217 ++
modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronComponent.java | 207 ++
modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronDiscoveryComponent.java | 29
modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronTabComponent.java | 149 +
modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronTabDiscoveryComponent.java | 78
modules/plugins/cron/src/main/resources/META-INF/rhq-plugin.xml | 188 ++
modules/plugins/cron/src/test/resources/log4j.xml | 32
modules/plugins/hosts-augeas/pom.xml | 218 --
modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/HostsAugeasComponent.java | 260 ---
modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/HostsAugeasDiscoveryComponent.java | 50
modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/util/AugeasUtility.java | 75
modules/plugins/hosts-augeas/src/main/resources/META-INF/rhq-plugin.xml | 60
modules/plugins/hosts-augeas/src/test/java/org/rhq/plugins/hosts/HostsAugeasComponentTest.java | 86 -
modules/plugins/hosts-augeas/src/test/resources/log4j.xml | 32
modules/plugins/hosts/pom.xml | 43
modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java | 97 -
modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java | 34
modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/Hosts.java | 74
modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/HostsComponentHelper.java | 7
modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/HostsEntry.java | 13
modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java | 57
modules/plugins/hosts/src/main/resources/META-INF/rhq-plugin.xml | 14
modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java | 164 +-
modules/plugins/hosts/src/test/resources/etc/hosts | 11
modules/plugins/hosts/src/test/resources/log4j.xml | 12
modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/MBeanResourceComponent.java | 3
modules/plugins/pom.xml | 3
modules/plugins/postfix/pom.xml | 226 ++
modules/plugins/postfix/src/main/java/org/rhq/plugins/postfix/PostfixServerComponent.java | 83 +
modules/plugins/postfix/src/main/java/org/rhq/plugins/postfix/PostfixServerDiscoveryComponent.java | 32
modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml | 51
modules/plugins/postfix/src/test/resources/log4j.xml | 40
modules/plugins/rhq-server/src/main/resources/META-INF/rhq-plugin.xml | 6
modules/plugins/samba/pom.xml | 44
modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaServerComponent.java | 192 --
modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaServerDiscoveryComponent.java | 38
modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaShareComponent.java | 124 -
modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaShareDiscoveryComponent.java | 37
modules/plugins/samba/src/main/resources/META-INF/rhq-plugin.xml | 109 -
modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java | 89 -
modules/plugins/samba/src/test/resources/etc/samba/smb.conf | 8
modules/plugins/samba/src/test/resources/log4j.xml | 12
modules/plugins/sudoers/pom.xml | 28
modules/plugins/sudoers/src/main/java/org/rhq/plugins/sudoers/SudoersComponent.java | 44
modules/plugins/sudoers/src/main/resources/META-INF/rhq-plugin.xml | 12
modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java | 141 +
modules/plugins/sudoers/src/test/resources/etc/sudoers | 11
modules/plugins/sudoers/src/test/resources/log4j.xml | 12
modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java | 9
modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/helper/TomcatApplicationDeployer.java | 8
274 files changed, 19311 insertions(+), 5765 deletions(-)
New commits:
commit 8bdcdafb19b0963ff7756f3de2b1e15c1114f81c
Merge: 1453e14... a6ef401...
Author: John Sanda <jsanda(a)redhat.com>
Date: Fri Nov 27 16:49:35 2009 -0500
Merge branch 'raw-config' of ssh://jsanda@git.fedorahosted.org/git/rhq/rhq into raw-config
commit 1453e1407ce8fb6a75281d9425b5558d7eae94f1
Author: John Sanda <jsanda(a)redhat.com>
Date: Fri Nov 27 16:46:00 2009 -0500
Fixing ordering of updates
diff --git a/modules/core/dbutils/pom.xml.orig b/modules/core/dbutils/pom.xml.orig
new file mode 100644
index 0000000..df61dc2
--- /dev/null
+++ b/modules/core/dbutils/pom.xml.orig
@@ -0,0 +1,279 @@
+<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-core-parent</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-dbutils</artifactId>
+ <packaging>jar</packaging>
+
+ <name>RHQ Database Utilities</name>
+ <description>Database schema setup, upgrade and other utilities</description>
+
+ <scm>
+ <connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/core/dbutils</connection>
+ <developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/core/dbutils</developerConnection>
+ </scm>
+
+ <properties>
+ <scm.module.path>modules/core/dbutils/</scm.module.path>
+<<<<<<< HEAD:modules/core/dbutils/pom.xml
+ <db.schema.version>2.62.2</db.schema.version>
+=======
+ <db.schema.version>2.69.1</db.schema.version>
+>>>>>>> master:modules/core/dbutils/pom.xml
+ </properties>
+
+ <dependencies>
+
+ <!-- 3rd Party Deps -->
+
+ <dependency>
+ <groupId>ant</groupId>
+ <artifactId>ant</artifactId>
+ <version>1.6.5</version>
+ </dependency>
+
+ <dependency>
+ <groupId>ant</groupId>
+ <artifactId>ant-launcher</artifactId>
+ <version>1.6.5</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>net.sourceforge.jtds</groupId>
+ <artifactId>jtds</artifactId>
+ <!-- NOTE: The version is defined in the root POM's dependencyManagement section. -->
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>process-classes</phase>
+ <configuration>
+ <tasks>
+ <!-- generate the I18N resource bundles -->
+ <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="**/*I18NResourceKeys.class" />
+ </classfileset>
+ </i18n>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>dbsetup-worker</id>
+ <phase>test</phase>
+ <configuration>
+ <tasks>
+ <property name="settings.localRepository" location="${user.home}/.m2/repository" />
+ <ant antfile="${basedir}/src/main/scripts/dbsetup-build.xml">
+ <property name="settings.localRepository" value="${settings.localRepository}" />
+ <!--<property name="ojdbc14.version" value="${ojdbc14.version}" />-->
+ <property name="ojdbc5.version" value="${ojdbc5.version}" />
+ <property name="postgresql.version" value="${postgresql.version}" />
+ <property name="h2.version" value="${h2.version}" />
+ <property name="jtds.version" value="${jtds.version}" />
+ <property name="task.classpath.property" refid="maven.test.classpath" />
+ <property name="rhq.ds.type-mapping" value="${rhq.test.ds.type-mapping}" />
+ <property name="rhq.ds.connection-url" value="${rhq.test.ds.connection-url}" />
+ <property name="rhq.ds.user-name" value="${rhq.test.ds.user-name}" />
+ <property name="rhq.ds.password" value="${rhq.test.ds.password}" />
+ <property name="project.version" value="${project.version}" />
+ <property name="db.schema.version" value="${db.schema.version}" />
+ <property name="dbsetup" value="${dbsetup}" />
+ <property name="dbsetup-uninstall" value="${dbsetup-uninstall}" />
+ <property name="dbsetup-upgrade" value="${dbsetup-upgrade}" />
+ <property name="dbsetup-export" value="${dbsetup-export}" />
+ </ant>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>generate-dbsetup-dbupgrade-xml-files</id>
+ <phase>process-classes</phase>
+ <configuration>
+ <tasks>
+ <property name="settings.localRepository" location="${user.home}/.m2/repository" />
+ <ant antfile="${basedir}/src/main/scripts/dbsetup-build.xml" target="dbsetup-combine">
+ <property name="settings.localRepository" value="${settings.localRepository}" />
+ <!--<property name="ojdbc14.version" value="${ojdbc14.version}" />-->
+ <property name="ojdbc5.version" value="${ojdbc5.version}" />
+ <property name="postgresql.version" value="${postgresql.version}" />
+ <property name="h2.version" value="${h2.version}" />
+ <property name="jtds.version" value="${jtds.version}" />
+ <property name="task.classpath.property" refid="maven.test.classpath" />
+ <property name="rhq.ds.type-mapping" value="${rhq.test.ds.type-mapping}" />
+ <property name="rhq.ds.connection-url" value="${rhq.test.ds.connection-url}" />
+ <property name="rhq.ds.user-name" value="${rhq.test.ds.user-name}" />
+ <property name="rhq.ds.password" value="${rhq.test.ds.password}" />
+ <property name="project.version" value="${project.version}" />
+ <property name="db.schema.version" value="${db.schema.version}" />
+ </ant>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <!--
+ This execution will abort the build if the database schema is not up to date.
+ If you want the build to continue, regardless of your currently installed schema,
+ then pass -Ddbsetup-do-not-check-schema to the mvn command line.
+ -->
+ <id>test-db-schema-version</id>
+ <phase>test</phase>
+ <configuration>
+ <tasks>
+ <property name="settings.localRepository" location="${user.home}/.m2/repository" />
+ <ant antfile="${basedir}/src/main/scripts/dbsetup-build.xml" target="dbsetup-check-schema">
+ <property name="settings.localRepository" value="${settings.localRepository}" />
+ <!--<property name="ojdbc14.version" value="${ojdbc14.version}" />-->
+ <property name="ojdbc5.version" value="${ojdbc5.version}" />
+ <property name="postgresql.version" value="${postgresql.version}" />
+ <property name="h2.version" value="${h2.version}" />
+ <property name="jtds.version" value="${jtds.version}" />
+ <property name="task.classpath.property" refid="maven.test.classpath" />
+ <property name="rhq.ds.type-mapping" value="${rhq.test.ds.type-mapping}" />
+ <property name="rhq.ds.connection-url" value="${rhq.test.ds.connection-url}" />
+ <property name="rhq.ds.user-name" value="${rhq.test.ds.user-name}" />
+ <property name="rhq.ds.password" value="${rhq.test.ds.password}" />
+ <property name="project.version" value="${project.version}" />
+ <property name="db.schema.version" value="${db.schema.version}" />
+ <property name="rhq.ds.driver-class" value="${rhq.test.ds.driver-class}" />
+ <property name="dbsetup-do-not-check-schema" value="${dbsetup-do-not-check-schema}" />
+ </ant>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemProperties>
+ <property>
+ <name>DatabaseTest.nofail</name>
+ <value>${DatabaseTest.nofail}</value>
+ </property>
+ <property>
+ <name>AntDatabaseTest.test-resources</name>
+ <value>${basedir}/src/test/resources</value>
+ </property>
+ </systemProperties>
+ <!-- The below is required for tests to run against Oracle. -->
+ <additionalClasspathElements>
+ <!--<additionalClasspathElement>${settings.localRepository}/ojdbc14/ojdbc14/${ojdbc14.version}/ojdbc14-${ojdbc14.version}.jar</additionalClasspathElement>-->
+ <additionalClasspathElement>${settings.localRepository}/com/oracle/ojdbc5/${ojdbc5.version}/ojdbc5-${ojdbc5.version}.jar</additionalClasspathElement>
+ </additionalClasspathElements>
+ </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>
+
+ </profiles>
+
+</project>
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 744794e..8eee404 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -2019,12 +2019,6 @@
precision="255" />
</schemaSpec>
-
- <schemaSpec version="2.63">
- <schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
- <schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
- </schemaSpec>
-
<schemaSpec version="2.62.2">
<schema-addColumn table="RHQ_CONFIG_DEF" column="CONFIG_FORMAT" columnType="VARCHAR2" />
<schema-alterColumn table="RHQ_CONFIG_DEF"
@@ -2033,6 +2027,11 @@
nullable="true" />
</schemaSpec>
+ <schemaSpec version="2.63">
+ <schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
+ <schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
+ </schemaSpec>
+
<!-- Generic tagging support -->
<schemaSpec version="2.64">
<schema-createSequence name="RHQ_TAG_ID_SEQ" initial="10001" />
commit e6b1d75091f0c36afe77bfe9d51dea6af498b865
Merge: c2f668e... db605e7...
Author: John Sanda <jsanda(a)redhat.com>
Date: Fri Nov 27 16:07:25 2009 -0500
Merge branch 'master' into raw-config
Conflicts:
.classpath
modules/core/dbutils/pom.xml
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java
diff --cc .gitignore
index 8def9cb,55de495..1d53abe
--- a/.gitignore
+++ b/.gitignore
@@@ -12,10 -12,7 +12,9 @@@ log
*.iml
*.ipr
*.iws
+.idea
+.idea/*
dev-container
- modules/dev-container
dev-agent
antlr-generated/
*.tokens
diff --cc modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index 2a078b8,07831eb..744794e
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@@ -1923,9 -1900,9 +1900,9 @@@
<schema-addColumn table="RHQ_REPO_KS_TREE" column="KICKSTART_TREE_ID" columnType="INTEGER" />
<schema-alterColumn table="RHQ_REPO_KS_TREE" column="KICKSTART_TREE_ID" nullable="false" />
<schema-addColumn table="RHQ_REPO_KS_TREE" column="LAST_MODIFIED" columnType="LONG" />
- <schema-alterColumn table="RHQ_REPO_KS_TREE" column="LAST_MODIFIED" nullable="false" />
+ <schema-alterColumn table="RHQ_REPO_KS_TREE" column="LAST_MODIFIED" nullable="false" precision="16" />
<schema-directSQL>
- <statement>
+ <statement>
ALTER TABLE RHQ_REPO_KS_TREE
ADD CONSTRAINT RHQ_REPO_KS_MAP_KEY
PRIMARY KEY ( REPO_ID, KICKSTART_TREE_ID )
@@@ -2028,20 -2005,184 +2005,192 @@@
-
</schema-directSQL>
</schemaSpec>
- <schemaSpec version="2.62.1">
+ <schemaSpec version="2.62">
+ <schema-alterColumn
+ table="RHQ_CONFIG_PROP_DEF"
+ column="NAME"
+ columnType="VARCHAR2"
+ precision="255" />
+
+ <schema-alterColumn
+ table="RHQ_CONFIG_PROPERTY"
+ column="NAME"
+ columnType="VARCHAR2"
+ precision="255" />
+ </schemaSpec>
+
+
+ <schemaSpec version="2.63">
<schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
<schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
+ </schemaSpec>
+
+ <schemaSpec version="2.62.2">
+ <schema-addColumn table="RHQ_CONFIG_DEF" column="CONFIG_FORMAT" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_CONFIG_DEF"
+ column="CONFIG_FORMAT"
+ precision="32"
+ nullable="true" />
</schemaSpec>
+ <!-- Generic tagging support -->
+ <schemaSpec version="2.64">
+ <schema-createSequence name="RHQ_TAG_ID_SEQ" initial="10001" />
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_TAG ( ID INTEGER PRIMARY KEY )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_TAG" column="ID" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="NAME" precision="200" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_TAG" column="NAME" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="DESCRIPTION" precision="500" columnType="VARCHAR2" />
+ </schemaSpec>
+
+ <!-- Distribution Files -->
+ <schemaSpec version="2.65">
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID INTEGER )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="DISTRIBUTION_ID" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" precision="256" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" precision="64" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" columnType="LONG" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" nullable="false" />
+ <schema-directSQL>
+ <statement targetDBVendor="postgresql">
+ CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
+ ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
+ </statement>
+ <statement targetDBVendor="oracle">
+ CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
+ ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
+ </statement>
+ </schema-directSQL>
+ <schema-directSQL>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_DISTRIBUTION_FILE
+ ADD CONSTRAINT RHQ_DIST_FILE_FKEY
+ FOREIGN KEY ( DISTRIBUTION_ID)
+ REFERENCES RHQ_DISTRIBUTION ( ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_DISTRIBUTION_FILE
+ ADD CONSTRAINT RHQ_DIST_FILE_FKEY
+ FOREIGN KEY ( DISTRIBUTION_ID)
+ REFERENCES RHQ_DISTRIBUTION ( ID )
+ </statement>
+ </schema-directSQL>
+ </schemaSpec>
+
+ <!-- RHQ_REPO_TAG_MAP -->
+ <schemaSpec version="2.66">
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_REPO_TAG_MAP ( REPO_ID INTEGER )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_REPO_TAG_MAP" column="REPO_ID" nullable="false" />
+ <schema-addColumn table="RHQ_REPO_TAG_MAP" column="TAG_ID" columnType="INTEGER" />
+ <schema-alterColumn table="RHQ_REPO_TAG_MAP" column="TAG_ID" nullable="false" />
+ <schema-directSQL>
+ <statement>
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD CONSTRAINT RHQ_REPO_TAG_MAP_KEY
+ PRIMARY KEY ( REPO_ID, TAG_ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD CONSTRAINT RHQ_REPO_TAG_MAP_REPO_ID_FKEY
+ FOREIGN KEY ( REPO_ID )
+ REFERENCES RHQ_REPO ( ID )
+ </statement>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD FOREIGN KEY ( REPO_ID )
+ REFERENCES RHQ_REPO ( ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD CONSTRAINT RHQ_REPO_TAG_MAP_TAG_ID_FKEY
+ FOREIGN KEY ( TAG_ID )
+ REFERENCES RHQ_TAG ( ID )
+ </statement>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD FOREIGN KEY ( TAG_ID )
+ REFERENCES RHQ_TAG ( ID )
+ </statement>
+ </schema-directSQL>
+ </schemaSpec>
+
+ <schemaSpec version="2.68">
+ <schema-createSequence name="RHQ_DISTRIBUTION_FILE_SEQ" initial="10001" />
+ <schema-directSQL>
+ <statement>
+ ALTER TABLE RHQ_DISTRIBUTION_FILE DROP CONSTRAINT RHQ_DISTRIBUTION_FILE_PKEY
+ </statement>
+ </schema-directSQL>
+
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="ID" columnType="INTEGER" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="ID" nullable="false" />
+
+ <schema-directSQL>
+ <statement>
+ ALTER TABLE RHQ_DISTRIBUTION_FILE ALTER COLUMN ID SET DEFAULT NEXTVAL('RHQ_DISTRIBUTION_FILE_ID_SEQ')
+ </statement>
+ </schema-directSQL>
+ </schemaSpec>
+
+ <!-- Add support for server-side plugins -->
+ <schemaSpec version="2.69">
+ <!-- add the new column that indicates if this is deployed on the SERVER or AGENT -->
+ <schema-addColumn table="RHQ_PLUGIN" column="DEPLOYMENT" columnType="VARCHAR2" precision="8"/>
+ <schema-directSQL>
+ <statement desc="Updating existing plugins with default deployment of AGENT">
+ UPDATE RHQ_PLUGIN SET DEPLOYMENT = 'AGENT'
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_PLUGIN" column="DEPLOYMENT" nullable="FALSE"/>
+
+ <!-- add the new column that provides configuration to a plugin -->
+ <schema-addColumn table="RHQ_PLUGIN" column="PLUGIN_CONFIG_ID" columnType="INTEGER" />
+ <schema-directSQL>
+ <statement desc="Creating RHQ_PLUGIN foreign key relation to RHQ_CONFIG for plugin config">
+ ALTER TABLE RHQ_PLUGIN
+ ADD CONSTRAINT RHQ_PLUGIN_P_CFG_ID_FKEY
+ FOREIGN KEY (PLUGIN_CONFIG_ID)
+ REFERENCES RHQ_CONFIG (ID)
+ </statement>
+ </schema-directSQL>
+
+ <!-- add the new column that provides configuration to a plugin -->
+ <schema-addColumn table="RHQ_PLUGIN" column="JOBS_CONFIG_ID" columnType="INTEGER" />
+ <schema-directSQL>
+ <statement desc="Creating RHQ_PLUGIN foreign key relation to RHQ_CONFIG for scheduled jobs">
+ ALTER TABLE RHQ_PLUGIN
+ ADD CONSTRAINT RHQ_PLUGIN_JOBS_CFG_ID_FKEY
+ FOREIGN KEY (JOBS_CONFIG_ID)
+ REFERENCES RHQ_CONFIG (ID)
+ </statement>
+ </schema-directSQL>
+ </schemaSpec>
+
+ <schemaSpec version="2.69.1">
+ <!-- add the new column that indicates if this is plugin has been deleted -->
+ <schema-addColumn table="RHQ_PLUGIN" column="STATUS" columnType="VARCHAR2" precision="16"/>
+ <schema-directSQL>
+ <statement desc="Updating existing plugins with status of INSTALLED">
+ UPDATE RHQ_PLUGIN SET STATUS = 'INSTALLED'
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_PLUGIN" column="STATUS" nullable="FALSE"/>
+ </schemaSpec>
+
</dbupgrade>
</target>
</project>
commit db605e78ebfb82d01f0ce4130f327c45170540c7
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 17:18:29 2009 -0500
get rid of the update query we don't need anymore
fix tests so they don't rely on that old update query
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index eda26d8..4047d10 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -187,25 +187,6 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " LEFT JOIN p.scheduledJobsConfiguration " //
+ " WHERE p.deployment = 'SERVER' AND p.status = 'INSTALLED' "), //
- // this query does not update the content blob or ctime
- @NamedQuery(name = Plugin.UPDATE_ALL_BUT_CONTENT, query = "" //
- + "UPDATE Plugin p " //
- + " SET p.name = :name, " //
- + " p.displayName = :displayName, " //
- + " p.description = :description, " //
- + " p.enabled = :enabled, " //
- + " p.status = :status, " //
- + " p.help = :help, " //
- + " p.version = :version, " //
- + " p.ampsVersion = :ampsVersion," //
- + " p.deployment = :deployment, " //
- + " p.pluginConfiguration = :pluginConfiguration, " //
- + " p.scheduledJobsConfiguration = :scheduledJobsConfiguration, " //
- + " p.path = :path, " //
- + " p.md5 = :md5, " //
- + " p.mtime = :mtime " //
- + " WHERE p.id = :id"),
-
// this query is how you enable and disable plugins
@NamedQuery(name = Plugin.UPDATE_PLUGINS_ENABLED_BY_IDS, query = "" //
+ "UPDATE Plugin p " //
@@ -256,7 +237,6 @@ public class Plugin implements Serializable {
public static final String QUERY_FIND_BY_IDS_AND_TYPE = "Plugin.findByIdsAndType";
public static final String QUERY_GET_NAMES_BY_ENABLED_AND_TYPE = "Plugin.findByEnabledAndType";
public static final String QUERY_GET_STATUS_BY_NAME_AND_TYPE = "Plugin.getStatusByNameAndType";
- public static final String UPDATE_ALL_BUT_CONTENT = "Plugin.updateAllButContent";
public static final String UPDATE_PLUGINS_ENABLED_BY_IDS = "Plugin.updatePluginsEnabledByIds";
@Column(name = "ID", nullable = false)
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index 07f8f97..729f7c2 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -131,23 +131,39 @@ public class PluginTest extends AbstractEJB3Test {
em.persist(jobsConfig);
em.flush(); // gotta get those two persists to flush to the DB
- q = em.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
- q.setParameter("id", id); // same as the one we just persisted
- q.setParameter("name", name);
- q.setParameter("path", path);
- q.setParameter("displayName", displayName);
- q.setParameter("enabled", enabled);
- q.setParameter("status", status);
- q.setParameter("md5", md5);
- q.setParameter("version", version);
- q.setParameter("ampsVersion", ampsVersion);
- q.setParameter("deployment", deployment);
- q.setParameter("pluginConfiguration", pluginConfig);
- q.setParameter("scheduledJobsConfiguration", jobsConfig);
- q.setParameter("description", description);
- q.setParameter("help", help);
- q.setParameter("mtime", System.currentTimeMillis());
- assert q.executeUpdate() == 1 : "Failed to update the plugin";
+ // do what ServerPluginsBean/ResourceMetadataManagerBean.updateServerPluginExceptContent does
+ Configuration config = plugin.getPluginConfiguration();
+ if (config != null) {
+ config = em.merge(config);
+ plugin.setPluginConfiguration(config);
+ }
+ config = plugin.getScheduledJobsConfiguration();
+ if (config != null) {
+ config = em.merge(config);
+ plugin.setScheduledJobsConfiguration(config);
+ }
+
+ Plugin pluginEntity = em.getReference(Plugin.class, plugin.getId());
+ pluginEntity.setName(name);
+ pluginEntity.setPath(path);
+ pluginEntity.setDisplayName(displayName);
+ pluginEntity.setEnabled(enabled);
+ pluginEntity.setStatus(status);
+ pluginEntity.setMd5(md5);
+ pluginEntity.setVersion(version);
+ pluginEntity.setAmpsVersion(ampsVersion);
+ pluginEntity.setDeployment(deployment);
+ pluginEntity.setPluginConfiguration(pluginConfig);
+ pluginEntity.setScheduledJobsConfiguration(jobsConfig);
+ pluginEntity.setDescription(description);
+ pluginEntity.setHelp(help);
+ pluginEntity.setMtime(System.currentTimeMillis());
+
+ try {
+ em.flush(); // make sure we push this out to the DB now
+ } catch (Exception e) {
+ throw new Exception("Failed to update a plugin that matches [" + plugin + "]", e);
+ }
em.close();
getTransactionManager().commit(); // must commit now
@@ -163,7 +179,7 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.isEnabled() == enabled;
assert plugin.getMD5().equals(md5);
assert plugin.getVersion().equals(version);
- q.setParameter("ampsVersion", ampsVersion);
+ assert plugin.getAmpsVersion().equals(ampsVersion);
assert plugin.getDescription().equals(description);
assert plugin.getDeployment() == PluginDeploymentType.SERVER;
assert plugin.getPluginConfiguration().equals(pluginConfig);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
index 9c971e0..d502f4e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
@@ -198,49 +198,38 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
entityManager.persist(plugin);
} else {
// agent plugins don't support these configs, but if/when they do in the future, this will support it
- boolean needFlush = false;
+ // make sure we create (if necessary) and attach the configs
Configuration config = plugin.getPluginConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setPluginConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
+ config = entityManager.merge(config);
+ plugin.setPluginConfiguration(config);
}
config = plugin.getScheduledJobsConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setScheduledJobsConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
- }
- if (needFlush) {
- entityManager.flush(); // must be flushed to the DB so the JPQL update below works
+ config = entityManager.merge(config);
+ plugin.setScheduledJobsConfiguration(config);
}
// update all the fields except content
- Query q = entityManager.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
- q.setParameter("id", plugin.getId());
- q.setParameter("name", plugin.getName());
- q.setParameter("path", plugin.getPath());
- q.setParameter("displayName", plugin.getDisplayName());
- q.setParameter("enabled", plugin.isEnabled());
- q.setParameter("status", plugin.getStatus());
- q.setParameter("md5", plugin.getMD5());
- q.setParameter("version", plugin.getVersion());
- q.setParameter("ampsVersion", plugin.getAmpsVersion());
- q.setParameter("deployment", plugin.getDeployment());
- q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
- q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
- q.setParameter("description", plugin.getDescription());
- q.setParameter("help", plugin.getHelp());
- q.setParameter("mtime", plugin.getMtime());
- if (q.executeUpdate() != 1) {
+ Plugin pluginEntity = entityManager.getReference(Plugin.class, plugin.getId());
+ pluginEntity.setName(plugin.getName());
+ pluginEntity.setPath(plugin.getPath());
+ pluginEntity.setDisplayName(plugin.getDisplayName());
+ pluginEntity.setEnabled(plugin.isEnabled());
+ pluginEntity.setStatus(plugin.getStatus());
+ pluginEntity.setMd5(plugin.getMD5());
+ pluginEntity.setVersion(plugin.getVersion());
+ pluginEntity.setAmpsVersion(plugin.getAmpsVersion());
+ pluginEntity.setDeployment(plugin.getDeployment());
+ pluginEntity.setPluginConfiguration(plugin.getPluginConfiguration());
+ pluginEntity.setScheduledJobsConfiguration(plugin.getScheduledJobsConfiguration());
+ pluginEntity.setDescription(plugin.getDescription());
+ pluginEntity.setHelp(plugin.getHelp());
+ pluginEntity.setMtime(plugin.getMtime());
+
+ try {
+ entityManager.flush(); // make sure we push this out to the DB now
+ } catch (Exception e) {
throw new Exception("Failed to update a plugin that matches [" + plugin + "]");
}
}
commit dfd17347dd6d8c2707bfab6ced27bd44b66f9120
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 16:42:23 2009 -0500
fix the update method so it can handle the config updates
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index ff7d6ca..49d6e53 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -383,56 +383,39 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (plugin.getId() == 0) {
throw new IllegalArgumentException("Plugin must already exist to update it");
} else {
- // make sure the configs are in the DB properly and we have their refs
- // this is because we are using JPQL update, so we need to do some of this "manually"
- boolean needFlush = false;
+ // make sure we create (if necessary) and attach the configs
Configuration config = plugin.getPluginConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setPluginConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
+ config = entityManager.merge(config);
+ plugin.setPluginConfiguration(config);
}
config = plugin.getScheduledJobsConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setScheduledJobsConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
- }
- if (needFlush) {
- entityManager.flush(); // must be flushed to the DB so the JPQL update below works
+ config = entityManager.merge(config);
+ plugin.setScheduledJobsConfiguration(config);
}
- // now we can JPQL update the row - all but content is updated here.
- // we assured our configs are persisted/attached above
- Query q = entityManager.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
- q.setParameter("id", plugin.getId());
- q.setParameter("name", plugin.getName());
- q.setParameter("path", plugin.getPath());
- q.setParameter("displayName", plugin.getDisplayName());
- q.setParameter("enabled", plugin.isEnabled());
- q.setParameter("status", plugin.getStatus());
- q.setParameter("md5", plugin.getMD5());
- q.setParameter("version", plugin.getVersion());
- q.setParameter("ampsVersion", plugin.getAmpsVersion());
- q.setParameter("deployment", plugin.getDeployment());
- q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
- q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
- q.setParameter("description", plugin.getDescription());
- q.setParameter("help", plugin.getHelp());
- q.setParameter("mtime", plugin.getMtime());
- if (q.executeUpdate() != 1) {
- throw new Exception("Failed to update a plugin that matches [" + plugin + "]");
- }
+ Plugin pluginEntity = entityManager.getReference(Plugin.class, plugin.getId());
+ pluginEntity.setName(plugin.getName());
+ pluginEntity.setPath(plugin.getPath());
+ pluginEntity.setDisplayName(plugin.getDisplayName());
+ pluginEntity.setEnabled(plugin.isEnabled());
+ pluginEntity.setStatus(plugin.getStatus());
+ pluginEntity.setMd5(plugin.getMD5());
+ pluginEntity.setVersion(plugin.getVersion());
+ pluginEntity.setAmpsVersion(plugin.getAmpsVersion());
+ pluginEntity.setDeployment(plugin.getDeployment());
+ pluginEntity.setPluginConfiguration(plugin.getPluginConfiguration());
+ pluginEntity.setScheduledJobsConfiguration(plugin.getScheduledJobsConfiguration());
+ pluginEntity.setDescription(plugin.getDescription());
+ pluginEntity.setHelp(plugin.getHelp());
+ pluginEntity.setMtime(plugin.getMtime());
- entityManager.flush(); // make sure we push this out to the DB now
+ try {
+ entityManager.flush(); // make sure we push this out to the DB now
+ } catch (Exception e) {
+ throw new Exception("Failed to update a plugin that matches [" + plugin + "]", e);
+ }
}
return plugin;
}
commit aadfbe12066b4cab890bc04fbd9a55c76df87fb4
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 13:19:15 2009 -0500
provide an API to get a list of all enabled and disabled plugins grouped by their type
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java
index a79dff5..bbeb84c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java
@@ -42,7 +42,7 @@ public class ContentManagerHelper {
}
MasterServerPluginContainer master = mbean.getMasterPluginContainer();
- pc = master.getPluginContainer(ContentServerPluginContainer.class);
+ pc = master.getPluginContainerByClass(ContentServerPluginContainer.class);
} catch (IllegalStateException ise) {
throw ise;
} catch (Exception e) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 2d67f3f..ff7d6ca 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -26,7 +26,9 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import javax.ejb.EJB;
import javax.ejb.Stateless;
@@ -54,6 +56,7 @@ import org.rhq.enterprise.server.authz.RequiredPermission;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
@@ -173,7 +176,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
String pluginName = doomedPlugin.getName();
doomedPlugins.add(pluginName);
if (master != null) {
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(pluginName);
+ AbstractTypeServerPluginContainer pc = master.getPluginContainerByPlugin(pluginName);
if (pc != null) {
try {
pc.unschedulePluginJobs(pluginName);
@@ -216,7 +219,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
String pluginName = doomedPlugin.getName();
doomedPlugins.add(pluginName);
if (master != null) {
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(pluginName);
+ AbstractTypeServerPluginContainer pc = master.getPluginContainerByPlugin(pluginName);
if (pc != null) {
try {
pc.unschedulePluginJobs(pluginName);
@@ -447,6 +450,27 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return status;
}
+ // we need this method to talk to the master plugin container because the plugin data model
+ // does not contain information as to what type a plugin is. It only has information about
+ // where the plugin is deployed (agent or server) but it doesn't indicate if a plugin
+ // if of type "alert plugin" or "generic plugin". That is only known when the plugin descriptor
+ // is parsed, which happens when the master plugin container is initialized. Therefore, this
+ // needs to get plugin info from the master plugin container while the master is running.
+ public Map<ServerPluginType, List<String>> getAllPluginsGroupedByType() {
+ Map<ServerPluginType, List<String>> allPlugins = new HashMap<ServerPluginType, List<String>>();
+
+ MasterServerPluginContainer master = LookupUtil.getServerPluginService().getMasterPluginContainer();
+ if (master != null) {
+ List<ServerPluginType> types = master.getServerPluginTypes();
+ for (ServerPluginType type : types) {
+ List<String> plugins = master.getAllPluginsByPluginType(type);
+ allPlugins.put(type, plugins);
+ }
+ }
+
+ return allPlugins;
+ }
+
/**
* This will write the contents of the given plugin file to the database.
* This will assume the MD5 in the database is already correct, so this
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index df685d4..a6a09bf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -2,6 +2,7 @@ package org.rhq.enterprise.server.plugin;
import java.io.File;
import java.util.List;
+import java.util.Map;
import javax.ejb.Local;
import javax.persistence.NoResultException;
@@ -9,6 +10,7 @@ import javax.persistence.NoResultException;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginStatusType;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
@@ -173,4 +175,13 @@ public interface ServerPluginsLocal {
* <code>null</code> indicates an unknown plugin.
*/
PluginStatusType getServerPluginStatus(String pluginName);
+
+ /**
+ * This will return a map containing all plugins currently known to the master plugin container.
+ * This will return installed plugins that are both enabled and disabled.
+ * Note that if the master plugin container is not running, an empty map is returned.
+ *
+ * @return names of all enabled and disabled plugins, keyed on their types
+ */
+ Map<ServerPluginType, List<String>> getAllPluginsGroupedByType();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index 8ebabd4..4ab3fb2 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -21,6 +21,7 @@ package org.rhq.enterprise.server.plugin.pc;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -46,11 +47,22 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
public class MasterServerPluginContainer {
private static final Log log = LogFactory.getLog(MasterServerPluginContainer.class);
+ /** The configuration for the master plugin container itself. */
private MasterServerPluginContainerConfiguration configuration;
+
+ /** the plugin containers for all the different types of plugins that are supported */
private Map<ServerPluginType, AbstractTypeServerPluginContainer> pluginContainers = new HashMap<ServerPluginType, AbstractTypeServerPluginContainer>();
+
+ /** the object that provides all the classloaders for all plugins */
private ClassLoaderManager classLoaderManager;
/**
+ * Because the individual plugin containers are only managing enabled plugins (they are never told about plugins that disabled).
+ * this map contains the lists of plugins that are disabled so others can find out what plugins are registered but not running.
+ */
+ private Map<ServerPluginType, List<String>> disabledPlugins = new HashMap<ServerPluginType, List<String>>();
+
+ /**
* Starts the master plugin container, which will load all plugins and begin managing them.
*
* @param config the master configuration
@@ -188,6 +200,7 @@ public class MasterServerPluginContainer {
}
this.pluginContainers.clear();
+ this.disabledPlugins.clear();
this.classLoaderManager = null;
this.configuration = null;
@@ -238,6 +251,55 @@ public class MasterServerPluginContainer {
}
/**
+ * Given a plugin type, this will return the names of all known plugins of that type.
+ * This includes all types that are currently started as well as plugins
+ * that have been disabled.
+ *
+ * If the master plugin container has not been started, this returns an empty list.
+ *
+ * @param pluginType
+ *
+ * @return list of both enabled and disabled plugins of the given type
+ */
+ public List<String> getAllPluginsByPluginType(ServerPluginType pluginType) {
+ List<String> allPlugins = new ArrayList<String>();
+
+ AbstractTypeServerPluginContainer pc = getPluginContainerByPluginType(pluginType);
+ if (pc != null) {
+ // add the enabled plugins
+ ServerPluginManager pluginManager = pc.getPluginManager();
+ if (pluginManager != null) {
+ Collection<ServerPluginEnvironment> envs = pluginManager.getPluginEnvironments();
+ if (envs != null) {
+ for (ServerPluginEnvironment env : envs) {
+ allPlugins.add(env.getPluginName());
+ }
+ }
+ }
+
+ // add the disabled plugins
+ List<String> disabled = this.disabledPlugins.get(pluginType);
+ if (disabled != null) {
+ allPlugins.addAll(disabled);
+ }
+ }
+
+ return allPlugins;
+ }
+
+ /**
+ * This will return all known server plugins types. These are the types of plugins
+ * that are supported by a server plugin container. You can obtain the server
+ * plugin container that manages a particular server plugin type via
+ * {@link #getPluginContainerByPluginType(ServerPluginType)}.
+ *
+ * @return all known server plugin types
+ */
+ public synchronized List<ServerPluginType> getServerPluginTypes() {
+ return new ArrayList<ServerPluginType>(this.pluginContainers.keySet());
+ }
+
+ /**
* Get the plugin container of the given class. This method provides a strongly typed return value,
* based on the type of plugin container the caller wants returned.
*
@@ -245,7 +307,7 @@ public class MasterServerPluginContainer {
* @return the plugin container of the given class (<code>null</code> if none found)
*/
@SuppressWarnings("unchecked")
- public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainer(Class<T> clazz) {
+ public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainerByClass(Class<T> clazz) {
for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
if (clazz.isInstance(pc)) {
return (T) pc;
@@ -262,7 +324,7 @@ public class MasterServerPluginContainer {
* @param pluginName
* @return the plugin container that is managing the named plugin of <code>null</code>
*/
- public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainer(String pluginName) {
+ public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainerByPlugin(String pluginName) {
for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
if (null != pc.getPluginManager().getPluginEnvironment(pluginName)) {
return (T) pc;
@@ -319,7 +381,7 @@ public class MasterServerPluginContainer {
if (pluginFiles != null) {
- List<String> disabledPlugins = getDisabledPluginNames();
+ List<String> allDisabledPlugins = getDisabledPluginNames();
for (File pluginFile : pluginFiles) {
if (pluginFile.getName().endsWith(".jar")) {
@@ -329,12 +391,19 @@ public class MasterServerPluginContainer {
ServerPluginDescriptorType descriptor;
descriptor = ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginUrl);
if (descriptor != null) {
- if (!disabledPlugins.contains(descriptor.getName())) {
+ if (!allDisabledPlugins.contains(descriptor.getName())) {
log.debug("pre-loaded server plugin from URL: " + pluginUrl);
plugins.put(pluginUrl, descriptor);
} else {
log.info("Server plugin [" + descriptor.getName()
+ "] is disabled and will not be initialized");
+ ServerPluginType pluginType = new ServerPluginType(descriptor);
+ List<String> disabledByType = this.disabledPlugins.get(pluginType);
+ if (disabledByType == null) {
+ disabledByType = new ArrayList<String>(1);
+ this.disabledPlugins.put(pluginType, disabledByType);
+ }
+ disabledByType.add(descriptor.getName());
}
}
} catch (Throwable t) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
index feba2fc..3e6bb34 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
@@ -29,6 +29,22 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
public class ServerPluginType {
private final Class<? extends ServerPluginDescriptorType> descriptorType;
+ /**
+ * Given an actual plugin descriptor object, this will create a plugin type
+ * that represents that kind of plugin.
+ *
+ * @param descriptor an actual descriptor parsed from a plugin
+ */
+ public ServerPluginType(ServerPluginDescriptorType descriptor) {
+ this((descriptor != null) ? descriptor.getClass() : null);
+ }
+
+ /**
+ * Given a type of plugin descriptor, this will create a plugin type
+ * that represents that kind of plugin.
+ *
+ * @param descriptorType
+ */
public ServerPluginType(Class<? extends ServerPluginDescriptorType> descriptorType) {
if (descriptorType == null) {
throw new NullPointerException("descriptorType must not be null");
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
index 1dace0b..9f0026b 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
@@ -23,6 +23,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.List;
+import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
@@ -32,12 +33,16 @@ import org.testng.annotations.Test;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.State;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericPluginManager;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener.LifecycleState;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.generic.GenericPluginDescriptorType;
@Test
public class GenericServerPluginTest extends AbstractEJB3Test {
@@ -76,10 +81,21 @@ public class GenericServerPluginTest extends AbstractEJB3Test {
List<ScheduledJobDefinition> schedules = component.context.getSchedules();
assert schedules == null;
+ ServerPluginsLocal serverPluginsLocal = LookupUtil.getServerPlugins();
+ Map<ServerPluginType, List<String>> map = serverPluginsLocal.getAllPluginsGroupedByType();
+ assert map.size() == 1;
+ List<String> pluginNames = map.get(new ServerPluginType(GenericPluginDescriptorType.class));
+ assert pluginNames.size() == 1;
+ assert pluginNames.get(0).equals("TestSimpleGenericPlugin");
+
// make sure everything is shutdown
this.pluginService.stopMasterPluginContainer();
assert pc.state == State.UNINITIALIZED;
assert component.state == LifecycleState.UNINITIALIZED;
+
+ // with the master down, this method should return an empty map
+ map = serverPluginsLocal.getAllPluginsGroupedByType();
+ assert map.size() == 0;
}
private File createPluginJar(String jarName, String descriptorXmlFilename) throws Exception {
commit 07ae93f34338458daa75082ef519b4b1851ddc0c
Merge: 5e17b2f... 2d97557...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 11:08:38 2009 -0500
Merge branch 'master' into pc
commit 2d97557a1e09ab13248f5da0e81a8d530731ed78
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 11:03:16 2009 -0500
Eagerly initializing underlying list and map in PropertyList and PropertyMap to avoid NPEs
This change was already made in the raw-config branch a while back, and needed to be
ported over.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
index 2bc77f9..c3e26a0 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
@@ -68,7 +68,7 @@ public class PropertyList extends Property {
@Cascade( { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.DELETE_ORPHAN })
@OneToMany(mappedBy = "parentList", targetEntity = Property.class, fetch = FetchType.EAGER)
//@IndexColumn(name = "list_index") TODO GH: This seems broken
- private List<Property> list;
+ private List<Property> list = new ArrayList<Property>();
@Transient
String memberPropertyName;
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
index 114720f..e8e15b7 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
@@ -68,7 +68,7 @@ public class PropertyMap extends Property implements AbstractPropertyMap {
@Cascade( { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.DELETE_ORPHAN })
@MapKey(name = "name")
@OneToMany(mappedBy = "parentMap", fetch = FetchType.EAGER)
- private Map<String, Property> map;
+ private Map<String, Property> map = new LinkedHashMap<String, Property>();
/**
* Creates a new unnamed and empty {@link PropertyMap} object.
commit 5e17b2f3837504924ab1ec1b7ba48d017f258ef2
Merge: 45e0f2f... ee2e8e8...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 10:17:56 2009 -0500
Merge branch 'master' into pc
commit 45e0f2f25b7230d65bc561bc63bd1e1cdd7c65f8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 10:15:39 2009 -0500
use the new deepCopy()
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 8cbffc9..2d67f3f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -96,13 +96,13 @@ public class ServerPluginsBean implements ServerPluginsLocal {
Configuration config = plugin.getPluginConfiguration();
if (config != null) {
config = entityManager.find(Configuration.class, config.getId());
- plugin.setPluginConfiguration(config.deepCopyWithoutProxies());
+ plugin.setPluginConfiguration(config.deepCopy());
}
config = plugin.getScheduledJobsConfiguration();
if (config != null) {
config = entityManager.find(Configuration.class, config.getId());
- plugin.setScheduledJobsConfiguration(config.deepCopyWithoutProxies());
+ plugin.setScheduledJobsConfiguration(config.deepCopy());
}
return plugin;
commit b3a962cfa61b2f05b4258b9a25e6e72819473191
Merge: c995032... 37bb080...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 09:57:31 2009 -0500
Merge branch 'master' into pc
commit ee2e8e847b18491a6093135b6ca906d6063679de
Merge: 1bca0f7... 37bb080...
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 09:54:22 2009 -0500
Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq
commit 1bca0f7c0327498c0dcb7ccb5953d3158c83a563
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 09:53:41 2009 -0500
Fixing compilation error that happened as a result of my refactoring RawConfiguration.deepCopy()
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java
index a4ce93b..491612a 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java
@@ -165,7 +165,7 @@ public class RawConfigCollection implements Serializable {
String u2 = updated.substring(2);
String original = new String(getCurrent().getContents());
if (!u2.equals(original)) {
- current = current.deepCopy();
+ current = current.deepCopy(false);
current.setContents(updated.getBytes());
//TODO update other values like MD5
modified.put(current.getPath(), current);
commit c995032cbc61261e353c523259810d076d586519
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 09:51:34 2009 -0500
fix NPE when plugin config or scheduled jobs config is null
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 1415bb5..8cbffc9 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -93,12 +93,17 @@ public class ServerPluginsBean implements ServerPluginsLocal {
public Plugin getServerPluginRelationships(Plugin plugin) {
plugin = getServerPlugin(plugin.getName()); // refresh all but the content field
- int pluginConfigId = plugin.getPluginConfiguration().getId();
- int scheduledJobsId = plugin.getScheduledJobsConfiguration().getId();
- Configuration pluginConfig = entityManager.find(Configuration.class, pluginConfigId);
- Configuration scheduledJobs = entityManager.find(Configuration.class, scheduledJobsId);
- plugin.setPluginConfiguration(pluginConfig.deepCopyWithoutProxies());
- plugin.setScheduledJobsConfiguration(scheduledJobs.deepCopyWithoutProxies());
+ Configuration config = plugin.getPluginConfiguration();
+ if (config != null) {
+ config = entityManager.find(Configuration.class, config.getId());
+ plugin.setPluginConfiguration(config.deepCopyWithoutProxies());
+ }
+
+ config = plugin.getScheduledJobsConfiguration();
+ if (config != null) {
+ config = entityManager.find(Configuration.class, config.getId());
+ plugin.setScheduledJobsConfiguration(config.deepCopyWithoutProxies());
+ }
return plugin;
}
@@ -239,7 +244,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
File currentFile = new File(pluginDir, doomedPlugin.getPath());
currentFile.delete();
} catch (Exception e) {
- log.error("Failed to delete the undeployed plugin [" + doomedPlugin.getPath() + "]. Cause: " + ThrowableUtil.getAllMessages(e));
+ log.error("Failed to delete the undeployed plugin [" + doomedPlugin.getPath() + "]. Cause: "
+ + ThrowableUtil.getAllMessages(e));
}
}
}
@@ -275,7 +281,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
@RequiredPermission(Permission.MANAGE_SETTINGS)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void setServerPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status)
- throws Exception {
+ throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
return; // nothing to do
}
@@ -291,7 +297,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
public Plugin registerServerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception {
if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
- throw new IllegalArgumentException("Plugin [" + plugin.getName() + "] must be a server plugin to be registered");
+ throw new IllegalArgumentException("Plugin [" + plugin.getName()
+ + "] must be a server plugin to be registered");
}
Plugin existingPlugin = null;
@@ -304,7 +311,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (existingPlugin != null) {
if (existingPlugin.getStatus() == PluginStatusType.DELETED) {
- throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName() + "], it has been marked as deleted");
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
+ + "], it has been marked as deleted");
}
Plugin obsolete = ServerPluginDescriptorUtil.determineObsoletePlugin(plugin, existingPlugin);
if (obsolete == existingPlugin) { // yes use == for reference equality
@@ -322,7 +330,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (plugin.getId() == 0) {
PluginStatusType status = getServerPluginStatus(plugin.getName());
if (PluginStatusType.DELETED == status) {
- throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName() + "], it has been previously marked as deleted.");
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
+ + "], it has been previously marked as deleted.");
}
entityManager.persist(plugin);
} else {
@@ -364,7 +373,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
// to entityManager.merge that plugin POJO, it would null out that blob column.
if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
- throw new IllegalArgumentException("Plugin [" + plugin.getName() + "] must be a server plugin to be updated");
+ throw new IllegalArgumentException("Plugin [" + plugin.getName()
+ + "] must be a server plugin to be updated");
}
if (plugin.getId() == 0) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index 803f7cf..df685d4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -42,6 +42,7 @@ public interface ServerPluginsLocal {
*
* @param plugin
* @return the same plugin, with the relationship data loaded
+ * @throws NoResultException when no plugin with that name exists
*/
Plugin getServerPluginRelationships(Plugin plugin);
commit 37bb080675c956c976ffc3110361c11e19ae87a0
Author: Galder Zamarreno <rnd(a)zamarreno.com>
Date: Wed Nov 25 15:20:34 2009 +0100
Operation returns only one result now.
diff --git a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
index 0388d8a..a657f42 100644
--- a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
+++ b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
@@ -527,7 +527,7 @@ public class Props {
private String displayName;
private String description;
private Set<SimpleProperty> params = new LinkedHashSet<SimpleProperty>();
- private Set<SimpleProperty> results = new LinkedHashSet<SimpleProperty>();
+ private SimpleProperty result;
public OperationProps(String name) {
this.name = name;
@@ -557,8 +557,12 @@ public class Props {
return params;
}
- public Set<SimpleProperty> getResults() {
- return results;
+ public SimpleProperty getResult() {
+ return result;
+ }
+
+ public void setResult(SimpleProperty result) {
+ this.result = result;
}
}
}
diff --git a/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl b/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
index ca498b5..0343787 100644
--- a/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
+++ b/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
@@ -60,11 +60,9 @@ name="${props.name}" <#-- TODO separate out plugin name and service name -->
</#list>
</parameters>
</#if>
- <#if operation.results?has_content>
+ <#if operation.result??>
<results>
- <#list operation.results as results>
- <c:simple-property name="${results.name}" />
- </#list>
+ <c:simple-property name="${operation.result.name}" />
</results>
</#if>
</operation>
commit cc1b2af501010b1734b42d4a70e30a43db65d3ee
Author: Galder Zamarreno <rnd(a)zamarreno.com>
Date: Wed Nov 25 14:37:33 2009 +0100
Returns for operations can now be generated.
diff --git a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
index 76b374b..0388d8a 100644
--- a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
+++ b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
@@ -527,6 +527,7 @@ public class Props {
private String displayName;
private String description;
private Set<SimpleProperty> params = new LinkedHashSet<SimpleProperty>();
+ private Set<SimpleProperty> results = new LinkedHashSet<SimpleProperty>();
public OperationProps(String name) {
this.name = name;
@@ -555,5 +556,9 @@ public class Props {
public Set<SimpleProperty> getParams() {
return params;
}
+
+ public Set<SimpleProperty> getResults() {
+ return results;
+ }
}
}
diff --git a/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl b/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
index a148a61..ca498b5 100644
--- a/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
+++ b/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
@@ -60,6 +60,13 @@ name="${props.name}" <#-- TODO separate out plugin name and service name -->
</#list>
</parameters>
</#if>
+ <#if operation.results?has_content>
+ <results>
+ <#list operation.results as results>
+ <c:simple-property name="${results.name}" />
+ </#list>
+ </results>
+ </#if>
</operation>
</#list>
<#else>
commit a0ab1b28c3ef8ab152c4decf9e8dbaebbede80dd
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 00:08:22 2009 -0500
Deleting directory that accidentally included in a previous commit
diff --git a/modules/core/domain/src/main/java/META-INF/MANIFEST.MF b/modules/core/domain/src/main/java/META-INF/MANIFEST.MF
deleted file mode 100644
index 3090f97..0000000
--- a/modules/core/domain/src/main/java/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,4 +0,0 @@
-Manifest-Version: 1.0
-Class-Path: i18nlog-1.0.9.jar jaxb-api-2.1.jar stax-api-1.0-2.jar acti
- vation-1.1.jar rhq-core-util-1.4.0-SNAPSHOT.jar jdom-1.0.jar
-
commit 1643800fb94b472d11bedc1d5d4d756b4ad54ee0
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 00:07:18 2009 -0500
[US 6] Refactoring Configuration.deepCopy() to properly handle hibernate proxies.
Refactoring implementors of DeepCopyable to take a boolean flag that indicates
whether or not to copy the id field. Unit tests have been updated to reflect the change.
Conflicts:
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java
diff --git a/modules/core/domain/src/main/java/META-INF/MANIFEST.MF b/modules/core/domain/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..3090f97
--- /dev/null
+++ b/modules/core/domain/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Class-Path: i18nlog-1.0.9.jar jaxb-api-2.1.jar stax-api-1.0-2.jar acti
+ vation-1.1.jar rhq-core-util-1.4.0-SNAPSHOT.jar jdom-1.0.jar
+
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
index 3ce2965..62bd8ce 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
@@ -454,55 +454,40 @@ public class Configuration implements Externalizable, Cloneable, AbstractPropert
* @return the new copy
*/
public Configuration deepCopy(boolean keepIds) {
- Configuration copy;
+ Configuration copy = new Configuration();
- try {
- copy = clone();
- } catch (CloneNotSupportedException e) {
- throw new RuntimeException("CloneNotSupported can't happen");
+ if (keepIds) {
+ copy.id = this.id;
}
- if (!keepIds) {
- copy.id = 0;
-
- for (Property property : copy.properties.values()) {
- clearIds(property);
- }
- }
+ copy.notes = this.notes;
+ copy.version = this.version;
+ createDeepCopyOfProperties(copy, keepIds);
+ createDeepCopyOfRawConfigs(copy, keepIds);
return copy;
}
- private void clearIds(Property property) {
- property.setId(0);
-
- if (property instanceof PropertyList) {
- for (Property childProperty : ((PropertyList) property).getList()) {
- clearIds(childProperty);
- }
- } else if (property instanceof PropertyMap) {
- for (Property childProperty : ((PropertyMap) property).getMap().values()) {
- clearIds(childProperty);
- }
- }
-
- return;
- }
-
public Configuration deepCopyWithoutProxies() {
Configuration copy = new Configuration();
copy.notes = this.notes;
copy.version = this.version;
+ createDeepCopyOfProperties(copy, false);
+ createDeepCopyOfRawConfigs(copy, false);
- for (Property property : this.properties.values()) {
- copy.put(property.deepCopy());
- }
+ return copy;
+ }
+ private void createDeepCopyOfRawConfigs(Configuration copy, boolean keepId) {
for (RawConfiguration rawConfig : rawConfigurations) {
- copy.addRawConfiguration(rawConfig.deepCopy());
+ copy.addRawConfiguration(rawConfig.deepCopy(keepId));
}
+ }
- return copy;
+ private void createDeepCopyOfProperties(Configuration copy, boolean keepId) {
+ for (Property property : this.properties.values()) {
+ copy.put(property.deepCopy(keepId));
+ }
}
/**
@@ -664,7 +649,22 @@ public class Configuration implements Externalizable, Cloneable, AbstractPropert
out.writeLong(version);
out.writeLong(ctime);
out.writeLong(mtime);
+ }
// Explicitly do not send the history relationship
+ private Map<String, Property> createDeepCopyOfMap() {
+ Map<String, Property> copy = new HashMap<String, Property>();
+ for (Map.Entry<String, Property> entry : this.properties.entrySet()) {
+ copy.put(entry.getKey(), entry.getValue().deepCopy(true));
+ }
+ return copy;
+ }
+
+ private Set<RawConfiguration> createDeepCopyOfRawConfigs() {
+ Set<RawConfiguration> copy = new HashSet<RawConfiguration>();
+ for (RawConfiguration rawConfig : this.rawConfigurations) {
+ copy.add(rawConfig.deepCopy(true));
+ }
+ return copy;
}
@SuppressWarnings("unchecked")
@@ -694,4 +694,4 @@ public class Configuration implements Externalizable, Cloneable, AbstractPropert
public Map<String, Property> getAllProperties() {
return this.properties;
}
-}
\ No newline at end of file
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/DeepCopyable.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/DeepCopyable.java
index e3e56d5..c680b04 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/DeepCopyable.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/DeepCopyable.java
@@ -25,6 +25,6 @@ package org.rhq.core.domain.configuration;
public interface DeepCopyable<T> {
- T deepCopy();
+ T deepCopy(boolean keepId);
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Property.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Property.java
index f4494c8..5c1ba79 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Property.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Property.java
@@ -127,7 +127,10 @@ public class Property implements Externalizable, DeepCopyable<Property> {
public Property() {
}
- protected Property(Property original) {
+ protected Property(Property original, boolean keepId) {
+ if (keepId) {
+ this.id = original.id;
+ }
this.errorMessage = original.errorMessage;
this.name = original.name;
}
@@ -284,7 +287,7 @@ public class Property implements Externalizable, DeepCopyable<Property> {
return ((this.name != null) ? this.name.hashCode() : 0);
}
- public Property deepCopy() {
+ public Property deepCopy(boolean keepId) {
return null;
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
index a2223d9..2bc77f9 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
@@ -86,8 +86,8 @@ public class PropertyList extends Property {
setName(name);
}
- protected PropertyList(PropertyList original) {
- super(original);
+ protected PropertyList(PropertyList original, boolean keepId) {
+ super(original, keepId);
}
/**
@@ -212,11 +212,11 @@ public class PropertyList extends Property {
return result;
}
- public PropertyList deepCopy() {
- PropertyList copy = new PropertyList(this);
+ public PropertyList deepCopy(boolean keepId) {
+ PropertyList copy = new PropertyList(this, keepId);
for (Property property : list) {
- copy.add(property.deepCopy());
+ copy.add(property.deepCopy(false));
}
return copy;
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
index 137c6fe..114720f 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
@@ -76,8 +76,8 @@ public class PropertyMap extends Property implements AbstractPropertyMap {
public PropertyMap() {
}
- protected PropertyMap(PropertyMap original) {
- super(original);
+ protected PropertyMap(PropertyMap original, boolean keepId) {
+ super(original, keepId);
}
/**
@@ -263,11 +263,11 @@ public class PropertyMap extends Property implements AbstractPropertyMap {
return result;
}
- public PropertyMap deepCopy() {
- PropertyMap copy = new PropertyMap(this);
+ public PropertyMap deepCopy(boolean keepId) {
+ PropertyMap copy = new PropertyMap(this, keepId);
for (Property property : map.values()) {
- copy.put(property.deepCopy());
+ copy.put(property.deepCopy(keepId));
}
return copy;
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 0824553..04aeb7e 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
@@ -70,8 +70,8 @@ public class PropertySimple extends Property implements Externalizable {
override = Boolean.FALSE;
}
- protected PropertySimple(PropertySimple original) {
- super(original);
+ protected PropertySimple(PropertySimple original, boolean keepId) {
+ super(original, keepId);
this.override = original.override;
this.unmaskedStringValue = original.unmaskedStringValue;
this.stringValue = original.stringValue;
@@ -85,9 +85,7 @@ public class PropertySimple extends Property implements Externalizable {
* @param name
* @param value
*/
- public PropertySimple(@NotNull
- String name, @Nullable
- Object value) {
+ public PropertySimple(@NotNull String name, @Nullable Object value) {
setName(name);
setValue(value);
}
@@ -98,8 +96,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setValue(@Nullable
- Object value) {
+ public void setValue(@Nullable Object value) {
if (value == null) {
stringValue = null;
return;
@@ -131,8 +128,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setStringValue(@Nullable
- String value) {
+ public void setStringValue(@Nullable String value) {
this.setValue(value);
}
@@ -157,8 +153,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setBooleanValue(@Nullable
- Boolean value) {
+ public void setBooleanValue(@Nullable Boolean value) {
this.setValue(value);
}
@@ -207,8 +202,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setIntegerValue(@Nullable
- Integer value) {
+ public void setIntegerValue(@Nullable Integer value) {
this.setValue(value);
}
@@ -232,8 +226,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setFloatValue(@Nullable
- Float value) {
+ public void setFloatValue(@Nullable Float value) {
this.setValue(value);
}
@@ -257,8 +250,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setDoubleValue(@Nullable
- Double value) {
+ public void setDoubleValue(@Nullable Double value) {
this.setValue(value);
}
@@ -336,8 +328,8 @@ public class PropertySimple extends Property implements Externalizable {
return result;
}
- public PropertySimple deepCopy() {
- return new PropertySimple(this);
+ public PropertySimple deepCopy(boolean keepId) {
+ return new PropertySimple(this, keepId);
}
@Override
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/RawConfiguration.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/RawConfiguration.java
index ca02070..22a7161 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/RawConfiguration.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/RawConfiguration.java
@@ -243,9 +243,14 @@ public class RawConfiguration implements Serializable, DeepCopyable<RawConfigura
.toString();
}
- public RawConfiguration deepCopy() {
+ public RawConfiguration deepCopy(boolean keepId) {
RawConfiguration copy = new RawConfiguration();
+ if (keepId) {
+ copy.id = this.id;
+ }
+
copy.path = this.path;
+
if (this.contents != null) {
copy.setContents(this.getContents());
}
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java
index 36084ec..85afc00 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java
@@ -38,59 +38,107 @@ import java.util.Set;
public class ConfigurationTest {
@Test
- public void deepCopyWithoutProxiesShouldNotReturnReferenceToOriginalObject() {
+ public void deepCopyShouldNotReturnReferenceToOriginalObjectWhenKeepingIds() {
Configuration original = createConfiguration();
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(true);
assertNotSame(copy, original, "Expected a reference to a new Configuration object, not the original object being copied");
}
@Test
- public void deepCopyWithoutProxiesShouldCopySimpleFields() {
+ public void deepCopyShouldNotReturnReferenceToOriginalObjectWhenNotKeepingIds() {
Configuration original = createConfiguration();
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
+ assertNotSame(copy, original, "Expected a reference to a new Configuration object, not the original object being copied");
+ }
+
+ @Test
+ public void deepCopyShouldCopyAllSimpleFieldsWhenKeepingIds() {
+ Configuration original = createConfiguration();
+ Configuration copy = original.deepCopy(true);
+
+ assertEquals(copy.getId(), original.getId(), "Failed to copy the id property");
assertEquals(copy.getNotes(), original.getNotes(), "Failed to copy the notes property");
assertEquals(copy.getVersion(), original.getVersion(), "Failed to copy version property");
}
@Test
- public void deepCopyWithoutProxiesShouldNotCopyIdProperty() {
+ public void deepCopyShouldNotCopyIdWhenNotKeepingIds() {
Configuration original = createConfiguration();
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
assertFalse(copy.getId() == original.getId(), "The original id property should not be copied");
+ assertEquals(copy.getNotes(), original.getNotes(), "Failed to copy the notes property");
+ assertEquals(copy.getVersion(), original.getVersion(), "Failed to copy version property");
+ }
+
+ @Test
+ public void deepCopyShouldCopyPropertiesWhenKeepingIds() {
+ Configuration original = createConfiguration();
+ original.put(new PropertySimple("simpleProperty", "Simple Property"));
+
+ Configuration copy = original.deepCopy(true);
+
+ assertNotSame(copy.getProperties(), original.getProperties(), "The properties property should not refer to the properties in the original object");
+ assertEquals(copy.getProperties(), original.getProperties(), "Failed to copy the contents of the properties collection");
}
@Test
- public void deepCopyWithoutProxiesShouldCopyProperties() {
+ public void deepCopyShouldCopyPropertiesWhenNotKeepingIds() {
Configuration original = createConfiguration();
original.put(new PropertySimple("simpleProperty", "Simple Property"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
assertNotSame(copy.getProperties(), original.getProperties(), "The properties property should not refer to the properties in the original object");
assertEquals(copy.getProperties(), original.getProperties(), "Failed to copy the contents of the properties collection");
}
@Test
- public void deepCopyWithoutProxiesShouldNotReturnCopyReferenceOfOriginalProperty() {
+ public void deepCopyShouldNotReturnCopyReferenceOfOriginalPropertyWhenKeepingIds() {
Configuration original = createConfiguration();
String propertyName = "simpleProperty";
original.put(new PropertySimple(propertyName, "Simple Property"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(true);
assertNotSame(copy.get(propertyName), original.get(propertyName), "Expected a refernce to a new property, not the original property being copied");
}
@Test
- public void deepCopyWithoutProxiesShouldSetParentReferenceOfCopiedProperties() {
+ public void deepCopyShouldNotReturnCopyReferenceOfOriginalPropertyWhenNotKeepingIds() {
+ Configuration original = createConfiguration();
+ String propertyName = "simpleProperty";
+ original.put(new PropertySimple(propertyName, "Simple Property"));
+
+ Configuration copy = original.deepCopy(false);
+
+ assertNotSame(copy.get(propertyName), original.get(propertyName), "Expected a refernce to a new property, not the original property being copied");
+ }
+
+ @Test
+ public void deepCopyShouldSetParentReferenceOfCopiedPropertiesWhenKeepingIds() {
+ Configuration original = createConfiguration();
+ String propertyName = "simpleProperty";
+ original.put(new PropertySimple(propertyName, "Simple Property"));
+
+ Configuration copy = original.deepCopy(true);
+
+ assertSame(
+ copy.get(propertyName).getConfiguration(),
+ copy,
+ "The reference to the parent configuration should point to the newly copied configuration, not the original configuration"
+ );
+ }
+
+ @Test
+ public void deepCopyShouldSetParentReferenceOfCopiedPropertiesWhenNotKeepingIds() {
Configuration original = createConfiguration();
String propertyName = "simpleProperty";
original.put(new PropertySimple(propertyName, "Simple Property"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
assertSame(
copy.get(propertyName).getConfiguration(),
@@ -100,11 +148,27 @@ public class ConfigurationTest {
}
@Test
- public void deepCopyWithoutProxiesShouldCopyRawConfigurations() {
+ public void deepCopyShouldCopyRawConfigurationsWhenKeepingIds() {
Configuration original = createConfiguration();
original.addRawConfiguration(createRawConfiguration("/tmp/foo"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(true);
+
+ assertNotSame(
+ copy.getRawConfigurations(),
+ original.getRawConfigurations(),
+ "The rawConfigurations property should not refer to the original rawConfigurations of the copied object."
+ );
+
+ assertRawConfigurationsEquals(copy.getRawConfigurations(), original.getRawConfigurations(), "Failed to copy rawConfigurations property.");
+ }
+
+ @Test
+ public void deepCopyShouldCopyRawConfigurationsWhenNotKeepingIds() {
+ Configuration original = createConfiguration();
+ original.addRawConfiguration(createRawConfiguration("/tmp/foo"));
+
+ Configuration copy = original.deepCopy(false);
assertNotSame(
copy.getRawConfigurations(),
@@ -123,11 +187,26 @@ public class ConfigurationTest {
}
@Test
- public void deepCopyWithoutProxiesShouldSetParentReferenceOfCopiedRawConfigurations() {
+ public void deepCopyShouldSetParentReferenceOfCopiedRawConfigurationsWhenKeepingIds() {
+ Configuration original = createConfiguration();
+ original.addRawConfiguration(createRawConfiguration("/tmp/foo"));
+
+ Configuration copy = original.deepCopy(true);
+ RawConfiguration copiedRawConfig = getCopiedRawConfiguration(copy);
+
+ assertSame(
+ copiedRawConfig.getConfiguration(),
+ copy,
+ "The reference to the parent configuration should point to the newly copied configuration, not the original configuration."
+ );
+ }
+
+ @Test
+ public void deepCopyShouldSetParentReferenceOfCopiedRawConfigurationsWhenNotKeepingIds() {
Configuration original = createConfiguration();
original.addRawConfiguration(createRawConfiguration("/tmp/foo"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
RawConfiguration copiedRawConfig = getCopiedRawConfiguration(copy);
assertSame(
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyListTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyListTest.java
index d298001..56d3887 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyListTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyListTest.java
@@ -30,41 +30,52 @@ import org.testng.annotations.Test;
public class PropertyListTest {
@Test
- public void deepCopyShouldCopySimpleFields() {
+ public void deepCopyShouldCopyAllSimpleFields() {
PropertyList original = createPropertyList();
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(true);
assertNotSame(copy, original, "The copy should not reference the original object");
-
+
+ assertEquals(copy.getId(), original.getId(), "Failed to copy the id property");
assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
}
@Test
- public void deepCopyShouldNotCopyIdField() {
+ public void deepCopyShouldNotCopyIdFieldWhenFlagIsFalse() {
PropertyList original = createPropertyList();
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(false);
assertFalse(copy.getId() == original.getId(), "The original id property should not be copied.");
+ assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
+ assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
+ }
+
+ @Test
+ public void deepCopyShouldNotCopyReferenceOfUnderlyingListWhenIdIncluded() {
+ PropertyList original = createPropertyList();
+ PropertyList copy = original.deepCopy(true);
+
+ assertNotSame(original.getList(), copy.getList(), "The values in the underlying list should be copied, not the variable reference to the list.");
}
@Test
- public void deepCopyShouldNotCopyReferenceOfUnderlyingList() {
+ public void deepCopyShouldNotCopyReferenceOfUnderlyingListWhenIdNotIncluded() {
PropertyList original = createPropertyList();
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(false);
assertNotSame(original.getList(), copy.getList(), "The values in the underlying list should be copied, not the variable reference to the list.");
}
@Test
- public void deepCopyShouldCopyProperty() {
+ public void deepCopyShouldCopyPropertyWhenIdIncluded() {
PropertyList original = createPropertyList();
PropertySimple simpleProperty = new PropertySimple("simeplProperty", "Simple Property");
original.add(simpleProperty);
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(true);
assertEquals(copy.getList().size(), original.getList().size(), "Failed to copy simple property contained in original property list");
@@ -72,13 +83,39 @@ public class PropertyListTest {
}
@Test
- public void deepCopyShouldSetParentOfCopiedProperty() {
+ public void deepCopyShouldCopyPropertyWhenIdNotIncluded() {
+ PropertyList original = createPropertyList();
+
+ PropertySimple simpleProperty = new PropertySimple("simeplProperty", "Simple Property");
+ original.add(simpleProperty);
+
+ PropertyList copy = original.deepCopy(false);
+
+ assertEquals(copy.getList().size(), original.getList().size(), "Failed to copy simple property contained in original property list");
+
+ assertNotSame(copy.getList().get(0), original.getList().get(0), "Properties in the list should be copied by value as opposed to just copying the references");
+ }
+
+ @Test
+ public void deepCopyShouldSetParentOfCopiedPropertyWhenIdIncluded() {
+ PropertyList original = createPropertyList();
+
+ PropertySimple simpleProperty = new PropertySimple("simpleProperty", "Simple Property");
+ original.add(simpleProperty);
+
+ PropertyList copy = original.deepCopy(true);
+
+ assertSame(copy.getList().get(0).getParentList(), copy, "The parentList property of copied properties should be set to the new PropertyList");
+ }
+
+ @Test
+ public void deepCopyShouldSetParentOfCopiedPropertyWhenIdNotIncluded() {
PropertyList original = createPropertyList();
PropertySimple simpleProperty = new PropertySimple("simpleProperty", "Simple Property");
original.add(simpleProperty);
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(false);
assertSame(copy.getList().get(0).getParentList(), copy, "The parentList property of copied properties should be set to the new PropertyList");
}
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyMapTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyMapTest.java
index 4a999b6..e73d835 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyMapTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyMapTest.java
@@ -30,40 +30,55 @@ import org.testng.annotations.Test;
public class PropertyMapTest {
@Test
- public void deepCopyShouldCopySimpleFields() {
+ public void deepCopyShouldCopyAllSimpleFields() {
PropertyMap original = createPropertyMap();
- PropertyMap copy = original.deepCopy();
+ PropertyMap copy = original.deepCopy(true);
assertNotSame(copy, original, "The copy should not reference the original object");
+ assertEquals(copy.getId(), original.getId(), "Failed to copy the id property");
assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
}
@Test
- public void deepCopyShouldNotCopyIdField() {
+ public void deepCopyShouldNotCopyIdFieldWhenFlagIsFalse() {
PropertyMap original = createPropertyMap();
- PropertyMap copy = original.deepCopy();
+ PropertyMap copy = original.deepCopy(false);
+
+ assertNotSame(copy, original, "The copy should not reference the original object");
assertFalse(copy.getId() == original.getId(), "The original id property should not be copied.");
+ assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
+ assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
}
@Test
- public void deepCopyShouldNotCopyReferenceOfUnderlyingMap() {
+ public void deepCopyShouldCopyPropertyWhenIdIncluded() {
PropertyMap original = createPropertyMap();
- PropertyMap copy = original.deepCopy();
- assertNotSame(copy.getMap(), original.getMap(), "The values in the underlying map should be copied, not the reference to the map itself");
+ PropertySimple simpleProperty = new PropertySimple("simeplProperty", "Simple Property");
+ original.put(simpleProperty);
+
+ PropertyMap copy = original.deepCopy(true);
+
+ assertEquals(copy.getMap().size(), original.getMap().size(), "Failed to copy simple property contained in original property map");
+
+ assertNotSame(
+ copy.getMap().get(simpleProperty.getName()),
+ original.getMap().get(simpleProperty.getName()),
+ "Properties in the map should be copied by value as opposed to just copying the references"
+ );
}
@Test
- public void deepCopyShouldCopyProperty() {
+ public void deepCopyShouldCopyPropertyWhenIdNotIncluded() {
PropertyMap original = createPropertyMap();
PropertySimple simpleProperty = new PropertySimple("simeplProperty", "Simple Property");
original.put(simpleProperty);
- PropertyMap copy = original.deepCopy();
+ PropertyMap copy = original.deepCopy(false);
assertEquals(copy.getMap().size(), original.getMap().size(), "Failed to copy simple property contained in original property map");
@@ -75,13 +90,29 @@ public class PropertyMapTest {
}
@Test
- public void deepCopyShouldSetParentOfCopiedProperty() {
+ public void deepCopyShouldSetParentOfCopiedPropertyWhenIdIncluded() {
+ PropertyMap original = createPropertyMap();
+
+ PropertySimple simpleProperty = new PropertySimple("simpleProperty", "Simple Property");
+ original.put(simpleProperty);
+
+ PropertyMap copy = original.deepCopy(true);
+
+ assertSame(
+ copy.get(simpleProperty.getName()).getParentMap(),
+ copy,
+ "The parentMap property of copied properties should be set to the new PropertyMap"
+ );
+ }
+
+ @Test
+ public void deepCopyShouldSetParentOfCopiedPropertyWhenIdNotIncluded() {
PropertyMap original = createPropertyMap();
PropertySimple simpleProperty = new PropertySimple("simpleProperty", "Simple Property");
original.put(simpleProperty);
- PropertyMap copy = original.deepCopy();
+ PropertyMap copy = original.deepCopy(false);
assertSame(
copy.get(simpleProperty.getName()).getParentMap(),
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertySimpleTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertySimpleTest.java
index c1b76aa..7b49837 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertySimpleTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertySimpleTest.java
@@ -30,13 +30,14 @@ import org.testng.annotations.Test;
public class PropertySimpleTest {
@Test
- public void deepCopyShouldCopySimpleFields() {
+ public void deepCopyShouldCopyAllSimpleFields() {
PropertySimple original = createProperty();
- PropertySimple copy = original.deepCopy();
+ PropertySimple copy = original.deepCopy(true);
assertNotSame(copy, original, "The copy should not reference the original object");
-
+
+ assertEquals(copy.getId(), original.getId(), "Failed to copy the id property");
assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
assertEquals(copy.getOverride(), original.getOverride(), "Failed to copy the override property");
@@ -45,12 +46,17 @@ public class PropertySimpleTest {
}
@Test
- public void deepCopyShouldNotCopyIdField() {
+ public void deepCopyShouldNotCopyIdFieldWhenFlagIsFalse() {
PropertySimple original = createProperty();
- PropertySimple copy = original.deepCopy();
+ PropertySimple copy = original.deepCopy(false);
assertFalse(copy.getId() == original.getId(), "The original id property should not be copied.");
+ assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
+ assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
+ assertEquals(copy.getOverride(), original.getOverride(), "Failed to copy the override property");
+ assertEquals(copy.getUnmaskedStringValue(), original.getUnmaskedStringValue(), "Failed to copy the unmaskedStringValue property");
+ assertEquals(copy.getStringValue(), original.getStringValue(), "Failed to copy the stringValue property");
}
private PropertySimple createProperty() {
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java
index fb926af..8f0aac8 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java
@@ -212,33 +212,49 @@ public class RawConfigurationTest {
}
@Test
- public void deepCopyShouldCopyPath() {
+ public void deepCopyShouldCopyPathAndIdWhenIdIncluded() {
RawConfiguration original = new RawConfiguration();
original.setPath("/tmp/foo");
+ original.setId(-1);
- RawConfiguration copy = original.deepCopy();
+ RawConfiguration copy = original.deepCopy(true);
+ assertEquals(copy.getId(), copy.getId(), "Failed to copy the id property.");
assertEquals(copy.getPath(), original.getPath(), "Failed to copy the path property.");
}
@Test
- public void deepCopyShouldCopyContents() {
+ public void deepCopyShouldCopyPathAndIdWhenIdNotIncluded() {
+ RawConfiguration original = new RawConfiguration();
+ original.setPath("/tmp/foo");
+ original.setId(-1);
+
+ RawConfiguration copy = original.deepCopy(false);
+
+ assertFalse(copy.getId() == original.getId(), "The original id property should not be copied.");
+ assertEquals(copy.getPath(), original.getPath(), "Failed to copy the path property.");
+ }
+
+ @Test
+ public void deepCopyShouldCopyContentsWhenCopyingId() {
RawConfiguration original = new RawConfiguration();
original.setContents(new byte[] {1, 2, 3, 4, 5});
- RawConfiguration copy = original.deepCopy();
+ RawConfiguration copy = original.deepCopy(true);
assertFalse(original.getContents() == copy.getContents(), "The values in the contents array should be copied, not the reference to the original object.");
assertEquals(copy.getContents(), original.getContents(), "Failed to copy contents property.");
}
@Test
- public void deepCopyShouldNotCopyIdProperty() {
+ public void deepCopyShouldCopyContentsWhenNotCopyingId() {
RawConfiguration original = new RawConfiguration();
- original.setId(1);
+ original.setContents(new byte[] {1, 2, 3, 4, 5});
- RawConfiguration copy = original.deepCopy();
+ RawConfiguration copy = original.deepCopy(false);
- assertFalse(original.getId() == copy.getId(), "The id property should not be copied.");
+ assertFalse(original.getContents() == copy.getContents(), "The values in the contents array should be copied, not the reference to the original object.");
+ assertEquals(copy.getContents(), original.getContents(), "Failed to copy contents property.");
}
+
}
commit 9994ec529ecf93914ab48d25023327ee0eb3f503
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 24 16:41:38 2009 -0500
add a test to confirm that snapshot versions are considered older than candidate releases or releases
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 d9c2a9f..dfee3a5 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
@@ -161,5 +161,14 @@ public class ComparableVersionTest {
assert ver2.compareTo(ver2) == 0;
assert ver1.compareTo(ver2) > 0; // ver1 is after ver2!
assert ver2.compareTo(ver1) < 0; // ver1 is after ver2!
+
+ ver1 = new ComparableVersion("4.0.0-SNAPSHOT");
+ ver2 = new ComparableVersion("4.0.0.CR2"); // CR is an alias for RC
+ assert !ver1.equals(ver2);
+ assert !ver2.equals(ver1);
+ assert ver1.compareTo(ver1) == 0;
+ assert ver2.compareTo(ver2) == 0;
+ assert ver1.compareTo(ver2) < 0;
+ assert ver2.compareTo(ver1) > 0;
}
}
commit 93cd6e74d101d7dc645ac38168b4d0157752bf8d
Author: Justin Harris <jharris(a)redhat.com>
Date: Tue Nov 24 14:57:46 2009 -0500
Moving in some seam functionality to allow for page scoped beans in form submission.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java
new file mode 100644
index 0000000..0bb87bd
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java
@@ -0,0 +1,73 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.admin.plugin;
+
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.AutoCreate;
+import org.jboss.seam.annotations.Factory;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.web.RequestParameter;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Component responsible for looking up a {@link Plugin}, obtaining
+ * the <code>name</code> and <code>type</code> from request parameters.
+ *
+ * @author jharris
+ */
+@Name("installedPlugin")
+public class InstalledPluginComponent {
+
+ @RequestParameter("plugin")
+ private String name;
+ @RequestParameter("pluginType")
+ private PluginDeploymentType type;
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public PluginDeploymentType getType() {
+ return this.type;
+ }
+
+ public void setType(PluginDeploymentType type) {
+ this.type = type;
+ }
+
+ @Factory(value="plugin", autoCreate=true, scope=ScopeType.PAGE)
+ public Plugin lookupPlugin() {
+ if (this.type == PluginDeploymentType.AGENT) {
+ return LookupUtil.getResourceMetadataManager().getPlugin(this.name);
+ } else if (this.type == PluginDeploymentType.SERVER) {
+ ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
+ Plugin plugin = serverPluginsBean.getServerPlugin(this.name);
+ return serverPluginsBean.getServerPluginRelationships(plugin);
+ }
+
+ return null;
+ }
+}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
index b6db223..3fe6988 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
@@ -21,8 +21,13 @@ package org.rhq.enterprise.gui.admin.plugin;
import javax.faces.application.FacesMessage;
import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.Create;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
import org.rhq.core.clientapi.agent.metadata.ConfigurationMetadataParser;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
@@ -40,21 +45,24 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
* @author Greg Hinkle
* @author John Mazzitelli
*/
+(a)Scope(ScopeType.PAGE)
+@Name("InstalledPluginUIBean")
public class InstalledPluginUIBean {
- private final Log log = LogFactory.getLog(InstalledPluginUIBean.class);
+ private static final String OUTCOME_SUCCESS = "success";
public static final String MANAGED_BEAN_NAME = InstalledPluginUIBean.class.getSimpleName();
-
+ private final Log log = LogFactory.getLog(InstalledPluginUIBean.class);
+ @In
private Plugin plugin;
private ConfigurationDefinition pluginConfigurationDefinition;
private ConfigurationDefinition scheduledJobsDefinition;
- public InstalledPluginUIBean() {
- lookupPlugin();
+ public Plugin getPlugin() {
+ return plugin;
}
- public Plugin getPlugin() {
- return this.plugin;
+ public void setPlugin(Plugin plugin) {
+ this.plugin = plugin;
}
public ConfigurationDefinition getPluginConfigurationDefinition() {
@@ -65,40 +73,39 @@ public class InstalledPluginUIBean {
return this.scheduledJobsDefinition;
}
- public void updatePlugin() {
+ public boolean isEditable() {
+ return this.pluginConfigurationDefinition != null || this.scheduledJobsDefinition != null;
+ }
+
+ public String updatePlugin() {
ServerPluginsLocal serverPlugins = LookupUtil.getServerPlugins();
try {
serverPlugins.updateServerPluginExceptContent(EnterpriseFacesContextUtility.getSubject(), plugin);
-
FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO,
- "Configuration settings saved.");
+ "Configuration settings saved.");
+
+ return OUTCOME_SUCCESS;
} catch (Exception e) {
log.error("Error updating the plugin configurations.", e);
FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR,
- "There was an error changing the configuration settings.", e);
- }
+ "There was an error changing the configuration settings.", e);
- lookupPlugin();
+ return null;
+ }
}
- private void lookupPlugin() {
+ @Create
+ public void lookupConfigDefinitions() {
hasPermission();
- String pluginName = FacesContextUtility.getRequiredRequestParameter("plugin", String.class);
- String pluginType = FacesContextUtility.getRequiredRequestParameter("pluginType", String.class);
- PluginDeploymentType deploymentType = PluginDeploymentType.valueOf(pluginType);
- if (deploymentType == PluginDeploymentType.AGENT) {
- this.plugin = LookupUtil.getResourceMetadataManager().getPlugin(pluginName);
- } else {
- ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
- this.plugin = serverPluginsBean.getServerPlugin(pluginName);
- this.plugin = serverPluginsBean.getServerPluginRelationships(this.plugin);
+ String pluginName = this.plugin.getName();
+
+ if (this.plugin.getDeployment() == PluginDeploymentType.SERVER) {
try {
+ ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
ServerPluginDescriptorType descriptor = serverPluginsBean.getServerPluginDescriptor(pluginName);
- this.pluginConfigurationDefinition = ConfigurationMetadataParser.parse("pc:" + pluginName, descriptor
- .getPluginConfiguration());
- this.scheduledJobsDefinition = ConfigurationMetadataParser.parse("jobs:" + pluginName, descriptor
- .getScheduledJobs());
+ this.pluginConfigurationDefinition = ConfigurationMetadataParser.parse("pc:" + pluginName, descriptor.getPluginConfiguration());
+ this.scheduledJobsDefinition = ConfigurationMetadataParser.parse("jobs:" + pluginName, descriptor.getScheduledJobs());
} catch (Exception e) {
String err = "Cannot determine what the plugin configuration or scheduled jobs configuration looks like";
log.error(err + " - Cause: " + e);
@@ -114,8 +121,7 @@ public class InstalledPluginUIBean {
private void hasPermission() {
Subject subject = EnterpriseFacesContextUtility.getSubject();
if (!LookupUtil.getAuthorizationManager().hasGlobalPermission(subject, Permission.MANAGE_SETTINGS)) {
- throw new PermissionException("User [" + subject.getName()
- + "] does not have the proper permissions to view or manage plugins");
+ throw new PermissionException("User [" + subject.getName() + "] does not have the proper permissions to view or manage plugins");
}
}
-}
\ No newline at end of file
+}
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml
index bacb535..64bd31e 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml
@@ -11,6 +11,7 @@
<component name="org.jboss.seam.core.init">
<property name="debug">false</property> <!-- enable only when needed -->
<property name="transactionManagementEnabled">false</property>
+ <property name="jndi-pattern">rhq/#{ejbName}/local</property>
</component>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml
index 11dadd0..a80402b 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml
@@ -20,13 +20,6 @@
<managed-bean-class>org.rhq.enterprise.gui.admin.plugin.InstalledPluginsUIBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
- <managed-bean>
- <description>Visibility for the installed agent and server plugins</description>
- <display-name>Installed Plugin</display-name>
- <managed-bean-name>InstalledPluginUIBean</managed-bean-name>
- <managed-bean-class>org.rhq.enterprise.gui.admin.plugin.InstalledPluginUIBean</managed-bean-class>
- <managed-bean-scope>request</managed-bean-scope>
- </managed-bean>
<managed-bean>
<description>Access to downloads information</description>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml
index 93932df..7f19f4d 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml
@@ -28,6 +28,17 @@
</navigation-case>
</navigation-rule>
+
+ <navigation-rule>
+ <from-view-id>/rhq/admin/plugin/plugin-details-edit.xhtml</from-view-id>
+
+ <navigation-case>
+ <from-outcome>success</from-outcome>
+ <to-view-id>/rhq/admin/plugin/plugin-details-view.xhtml?plugin=#{plugin.name}&pluginType=#{plugin.deployment}</to-view-id>
+ <redirect/>
+ </navigation-case>
+
+ </navigation-rule>
<navigation-rule>
<navigation-case>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml
new file mode 100644
index 0000000..d88afe7
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jstl/core"
+ xmlns:onc="http://jboss.org/on/component"
+ xmlns:rich="http://richfaces.ajax4jsf.org/rich">
+
+<ui:composition template="/rhq/admin/plugin/plugin-details.xhtml">
+ <ui:param name="editMode" value="true"/>
+
+ <ui:define name="post-config">
+ <rich:panel rendered="#{InstalledPluginUIBean.editable}">
+ <h:commandButton value="SAVE" type="submit" action="#{InstalledPluginUIBean.updatePlugin}"
+ alt="Click to Save Changes" styleClass="buttonmed" />
+ <h:commandButton value="RESET" type="reset" immediate="true"
+ title="Click to Reset Fields" styleClass="buttonmed"/>
+ </rich:panel>
+ </ui:define>
+</ui:composition>
+
+</html>
\ No newline at end of file
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml
new file mode 100644
index 0000000..389923a
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jstl/core"
+ xmlns:onc="http://jboss.org/on/component"
+ xmlns:rich="http://richfaces.ajax4jsf.org/rich">
+
+<ui:composition template="/rhq/admin/plugin/plugin-details.xhtml">
+ <ui:param name="editMode" value="false"/>
+
+ <ui:define name="pre-config">
+ <h:panelGrid columns="1" styleClass="buttons-table" columnClasses="button-cell"
+ rendered="#{InstalledPluginUIBean.editable}">
+ <h:outputLink value="/rhq/admin/plugin/plugin-details-edit.xhtml"
+ styleClass="buttonmed">
+ <f:param name="plugin" value="#{installedPlugin.name}"/>
+ <f:param name="pluginType" value="#{installedPlugin.type}"/>
+ <h:outputText value="EDIT"/>
+ </h:outputLink>
+ </h:panelGrid>
+ </ui:define>
+ </ui:composition>
+
+</html>
\ No newline at end of file
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
index fa46dc8..cc11203 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
@@ -35,8 +35,6 @@
layout="table"
width="100%"/>
-
-
<h:form id="pluginsForm">
<rich:panel>
@@ -66,7 +64,6 @@
</h:panelGrid>
-
<rich:panel>
<f:facet name="header">
<h:outputText value="Plugin Help"/>
@@ -76,6 +73,7 @@
</rich:panel>
+ <ui:insert name="pre-config" />
<rich:panel rendered="#{InstalledPluginUIBean.plugin.pluginConfiguration != null}">
<f:facet name="header">
@@ -83,7 +81,8 @@
</f:facet>
<onc:config
configurationDefinition="#{InstalledPluginUIBean.pluginConfigurationDefinition}"
- configuration="#{InstalledPluginUIBean.plugin.pluginConfiguration}" />
+ configuration="#{InstalledPluginUIBean.plugin.pluginConfiguration}"
+ readOnly="#{not editMode}" />
</rich:panel>
<rich:panel rendered="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration != null}">
@@ -92,17 +91,11 @@
</f:facet>
<onc:config
configurationDefinition="#{InstalledPluginUIBean.scheduledJobsDefinition}"
- configuration="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration}" />
+ configuration="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration}"
+ readOnly="#{not editMode}" />
</rich:panel>
- <input type="hidden" name="plugin" value="#{param.plugin}"/>
- <input type="hidden" name="pluginType" value="#{param.pluginType}"/>
-
- <rich:panel rendered="#{InstalledPluginUIBean.plugin.pluginConfiguration != null ||
- InstalledPluginUIBean.plugin.scheduledJobsConfiguration != null}">
- <h:commandButton value="OK" type="submit" action="#{InstalledPluginUIBean.updatePlugin}"
- alt="Click to Save Plugin" styleClass="buttonmed" />
- </rich:panel>
+ <ui:insert name="post-config" />
</rich:panel>
</h:form>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
index 72f941e..5654368 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
@@ -75,7 +75,7 @@
<h:outputText styleClass="headerText" value="Name"/>
</f:facet>
- <h:outputLink value="/rhq/admin/plugin/plugin-details.xhtml">
+ <h:outputLink value="/rhq/admin/plugin/plugin-details-view.xhtml">
<f:param name="plugin" value="#{agentPlugin.name}"/>
<f:param name="pluginType" value="AGENT"/>
<h:outputText value="#{agentPlugin.displayName}"/>
@@ -160,7 +160,7 @@
<h:outputText styleClass="headerText" value="Name"/>
</f:facet>
- <h:outputLink value="/rhq/admin/plugin/plugin-details.xhtml">
+ <h:outputLink value="/rhq/admin/plugin/plugin-details-view.xhtml">
<f:param name="plugin" value="#{serverPlugin.name}"/>
<f:param name="pluginType" value="SERVER"/>
<h:outputText value="#{serverPlugin.displayName}"/>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index ce603da..1415bb5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -16,7 +16,6 @@
* 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.plugin;
import java.io.BufferedInputStream;
@@ -67,14 +66,12 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
@Stateless
@javax.annotation.Resource(name = "RHQ_DS", mappedName = RHQConstants.DATASOURCE_JNDI_NAME)
public class ServerPluginsBean implements ServerPluginsLocal {
- private final Log log = LogFactory.getLog(ServerPluginsBean.class);
+ private final Log log = LogFactory.getLog(ServerPluginsBean.class);
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
private EntityManager entityManager;
-
@javax.annotation.Resource(name = "RHQ_DS")
private DataSource dataSource;
-
@EJB
private ServerPluginsLocal serverPluginsBean; //self
@@ -242,8 +239,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
File currentFile = new File(pluginDir, doomedPlugin.getPath());
currentFile.delete();
} catch (Exception e) {
- log.error("Failed to delete the undeployed plugin [" + doomedPlugin.getPath() + "]. Cause: "
- + ThrowableUtil.getAllMessages(e));
+ log.error("Failed to delete the undeployed plugin [" + doomedPlugin.getPath() + "]. Cause: " + ThrowableUtil.getAllMessages(e));
}
}
}
@@ -279,7 +275,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
@RequiredPermission(Permission.MANAGE_SETTINGS)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void setServerPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status)
- throws Exception {
+ throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
return; // nothing to do
}
@@ -295,8 +291,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
public Plugin registerServerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception {
if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
- throw new IllegalArgumentException("Plugin [" + plugin.getName()
- + "] must be a server plugin to be registered");
+ throw new IllegalArgumentException("Plugin [" + plugin.getName() + "] must be a server plugin to be registered");
}
Plugin existingPlugin = null;
@@ -309,8 +304,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (existingPlugin != null) {
if (existingPlugin.getStatus() == PluginStatusType.DELETED) {
- throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
- + "], it has been marked as deleted");
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName() + "], it has been marked as deleted");
}
Plugin obsolete = ServerPluginDescriptorUtil.determineObsoletePlugin(plugin, existingPlugin);
if (obsolete == existingPlugin) { // yes use == for reference equality
@@ -328,8 +322,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (plugin.getId() == 0) {
PluginStatusType status = getServerPluginStatus(plugin.getName());
if (PluginStatusType.DELETED == status) {
- throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
- + "], it has been previously marked as deleted.");
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName() + "], it has been previously marked as deleted.");
}
entityManager.persist(plugin);
} else {
@@ -371,8 +364,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
// to entityManager.merge that plugin POJO, it would null out that blob column.
if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
- throw new IllegalArgumentException("Plugin [" + plugin.getName()
- + "] must be a server plugin to be updated");
+ throw new IllegalArgumentException("Plugin [" + plugin.getName() + "] must be a server plugin to be updated");
}
if (plugin.getId() == 0) {
commit c8a8622dce3142a91725a0a152bee94be64a9259
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 23 14:05:06 2009 -0500
because we put the byte[] content directly in the plugin entity, we can't entityManager.find() because that would load the full plugin content.
instead, use getReference. when we need to load the relationships, we have to play games by
loading in the configs directly and doing a deep copy (mainly to workaround a hibernate bug)
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 157911d..ce603da 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -94,11 +94,14 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
public Plugin getServerPluginRelationships(Plugin plugin) {
- plugin = entityManager.find(Plugin.class, plugin.getId());
+ plugin = getServerPlugin(plugin.getName()); // refresh all but the content field
- // force eager load
- plugin.getPluginConfiguration().getProperties().size();
- plugin.getScheduledJobsConfiguration().getProperties().size();
+ int pluginConfigId = plugin.getPluginConfiguration().getId();
+ int scheduledJobsId = plugin.getScheduledJobsConfiguration().getId();
+ Configuration pluginConfig = entityManager.find(Configuration.class, pluginConfigId);
+ Configuration scheduledJobs = entityManager.find(Configuration.class, scheduledJobsId);
+ plugin.setPluginConfiguration(pluginConfig.deepCopyWithoutProxies());
+ plugin.setScheduledJobsConfiguration(scheduledJobs.deepCopyWithoutProxies());
return plugin;
}
@@ -146,9 +149,9 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
- public List<Plugin> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
+ public List<String> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
- return new ArrayList<Plugin>(); // nothing to do
+ return new ArrayList<String>(); // nothing to do
}
serverPluginsBean.setServerPluginEnabledFlag(subject, pluginIds, false);
@@ -156,19 +159,24 @@ public class ServerPluginsBean implements ServerPluginsLocal {
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
- List<Plugin> doomedPlugins = new ArrayList<Plugin>();
+ List<String> doomedPlugins = new ArrayList<String>();
for (Integer pluginId : pluginIds) {
- Plugin doomedPlugin = entityManager.find(Plugin.class, pluginId);
+ Plugin doomedPlugin = null;
+ try {
+ doomedPlugin = entityManager.getReference(Plugin.class, pluginId);
+ } catch (Exception ignore) {
+ }
if (doomedPlugin != null) {
- doomedPlugins.add(doomedPlugin);
+ String pluginName = doomedPlugin.getName();
+ doomedPlugins.add(pluginName);
if (master != null) {
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
+ AbstractTypeServerPluginContainer pc = master.getPluginContainer(pluginName);
if (pc != null) {
try {
- pc.unschedulePluginJobs(doomedPlugin.getName());
+ pc.unschedulePluginJobs(pluginName);
} catch (Exception e) {
- log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ log.warn("Failed to unschedule jobs for plugin [" + pluginName + "]", e);
}
}
}
@@ -184,9 +192,9 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
- public List<Plugin> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
+ public List<String> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
- return new ArrayList<Plugin>(); // nothing to do
+ return new ArrayList<String>(); // nothing to do
}
serverPluginsBean.setServerPluginEnabledFlag(subject, pluginIds, false);
@@ -194,19 +202,24 @@ public class ServerPluginsBean implements ServerPluginsLocal {
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
- List<Plugin> doomedPlugins = new ArrayList<Plugin>();
+ List<String> doomedPlugins = new ArrayList<String>();
for (Integer pluginId : pluginIds) {
- Plugin doomedPlugin = entityManager.find(Plugin.class, pluginId);
+ Plugin doomedPlugin = null;
+ try {
+ doomedPlugin = entityManager.getReference(Plugin.class, pluginId);
+ } catch (Exception ignore) {
+ }
if (doomedPlugin != null) {
- doomedPlugins.add(doomedPlugin);
+ String pluginName = doomedPlugin.getName();
+ doomedPlugins.add(pluginName);
if (master != null) {
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
+ AbstractTypeServerPluginContainer pc = master.getPluginContainer(pluginName);
if (pc != null) {
try {
- pc.unschedulePluginJobs(doomedPlugin.getName());
+ pc.unschedulePluginJobs(pluginName);
} catch (Exception e) {
- log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ log.warn("Failed to unschedule jobs for plugin [" + pluginName + "]", e);
}
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index 6f3600e..803f7cf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -86,20 +86,20 @@ public interface ServerPluginsLocal {
*
* @param subject user making the request
* @param pluginIds the plugins to be disabled
- * @return the list of plugins that were disabled
+ * @return the list of names of the plugins that were disabled
* @throws Exception if failed to disable a plugin
*/
- List<Plugin> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
+ List<String> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
/**
* Removes the plugin from the system and restarts the server plugin container.
*
* @param subject user making the request
* @param pluginIds
- * @return the list of plugins that were undeployed
+ * @return the list of names of plugins that were undeployed
* @throws Exception if failed to undeploy a plugin
*/
- List<Plugin> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
+ List<String> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
/**
* Turns on or off the enabled flag in the database but does NOT restart the server plugin container.
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
index e1796bf..d1a6aba 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
@@ -135,6 +135,24 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
assetLazyInitializationException(plugins.get(1));
}
+ public void testUpdatePlugins() throws Exception {
+ Plugin p1 = registerPlugin(1);
+ p1 = this.serverPluginsBean.getServerPlugin(p1.getName());
+ p1 = this.serverPluginsBean.getServerPluginRelationships(p1);
+
+ Plugin p1update = this.serverPluginsBean.updateServerPluginExceptContent(getOverlord(), p1);
+ p1update = this.serverPluginsBean.getServerPluginRelationships(p1update);
+
+ assert p1update.getId() == p1.getId() : p1update;
+ assert p1update.getId() == p1.getId() : p1update;
+ assert p1update.getName().equals(p1.getName()) : p1update;
+ assert p1update.getName().equals(p1.getName()) : p1update;
+ assert p1update.getPluginConfiguration().equals(p1.getPluginConfiguration()) : p1update;
+ assert p1update.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration()) : p1update;
+ p1update.getPluginConfiguration().equals(p1.getPluginConfiguration());
+ p1update.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration());
+ }
+
public void testDisableEnablePlugins() throws Exception {
Plugin p1 = registerPlugin(1);
Plugin p2 = registerPlugin(2);
@@ -142,12 +160,13 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
List<Integer> ids = new ArrayList<Integer>(2);
ids.add(p1.getId());
ids.add(p2.getId());
- List<Plugin> disabled = this.serverPluginsBean.disableServerPlugins(getOverlord(), ids);
+ List<String> disabled = this.serverPluginsBean.disableServerPlugins(getOverlord(), ids);
assert disabled.size() == 2 : disabled;
- assert disabled.contains(p1) : disabled;
- assert disabled.contains(p2) : disabled;
- assert disabled.get(0).getStatus() == PluginStatusType.INSTALLED; // still installed
- assert disabled.get(1).getStatus() == PluginStatusType.INSTALLED; // still installed
+ assert disabled.contains(p1.getName()) : disabled;
+ assert disabled.contains(p2.getName()) : disabled;
+ ;
+ assert this.serverPluginsBean.getServerPlugin(p1.getName()).getStatus() == PluginStatusType.INSTALLED; // still installed
+ assert this.serverPluginsBean.getServerPlugin(p2.getName()).getStatus() == PluginStatusType.INSTALLED; // still installed
List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert pluginNames.contains(p1.getName()) : pluginNames;
assert pluginNames.contains(p2.getName()) : pluginNames;
@@ -195,12 +214,14 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
List<Integer> ids = new ArrayList<Integer>(2);
ids.add(p1.getId());
ids.add(p2.getId());
- List<Plugin> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
+ List<String> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
assert undeployed.size() == 2 : undeployed;
- assert undeployed.contains(p1) : undeployed;
- assert undeployed.contains(p2) : undeployed;
- assert undeployed.get(0).getStatus() == PluginStatusType.DELETED;
- assert undeployed.get(1).getStatus() == PluginStatusType.DELETED;
+ assert undeployed.contains(p1.getName()) : undeployed;
+ assert undeployed.contains(p2.getName()) : undeployed;
+ Plugin p1deleted = getDeletedPluginInTx(p1.getName());
+ Plugin p2deleted = getDeletedPluginInTx(p2.getName());
+ assert p1deleted.getStatus() == PluginStatusType.DELETED;
+ assert p2deleted.getStatus() == PluginStatusType.DELETED;
List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert !pluginNames.contains(p1.getName()) : "deleted plugins should not be returned even here" + pluginNames;
@@ -230,16 +251,18 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
List<Integer> ids = new ArrayList<Integer>(2);
ids.add(p1.getId());
ids.add(p2.getId());
- List<Plugin> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
+ List<String> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
assert undeployed.size() == 2 : undeployed;
- assert undeployed.contains(p1) : undeployed;
- assert undeployed.contains(p2) : undeployed;
- assert undeployed.get(0).getStatus() == PluginStatusType.DELETED;
- assert undeployed.get(0).getPluginConfiguration() == null; // undeploy should have removed this
- assert undeployed.get(0).getScheduledJobsConfiguration() == null; // undeploy should have removed this
- assert undeployed.get(1).getStatus() == PluginStatusType.DELETED;
- assert undeployed.get(1).getPluginConfiguration() == null; // undeploy should have removed this
- assert undeployed.get(1).getScheduledJobsConfiguration() == null; // undeploy should have removed this
+ assert undeployed.contains(p1.getName()) : undeployed;
+ assert undeployed.contains(p2.getName()) : undeployed;
+ Plugin p1deleted = getDeletedPluginInTx(p1.getName());
+ assert p1deleted.getStatus() == PluginStatusType.DELETED;
+ assert p1deleted.getPluginConfiguration() == null; // undeploy should have removed this
+ assert p1deleted.getScheduledJobsConfiguration() == null; // undeploy should have removed this
+ Plugin p2deleted = getDeletedPluginInTx(p1.getName());
+ assert p2deleted.getStatus() == PluginStatusType.DELETED;
+ assert p2deleted.getPluginConfiguration() == null; // undeploy should have removed this
+ assert p2deleted.getScheduledJobsConfiguration() == null; // undeploy should have removed this
List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert !pluginNames.contains(p1.getName()) : "deleted plugins should not be returned even here" + pluginNames;
@@ -320,4 +343,17 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
private Subject getOverlord() {
return LookupUtil.getSubjectManager().getOverlord();
}
+
+ private Plugin getDeletedPluginInTx(String pluginName) throws Exception {
+ EntityManager em = getEntityManager();
+ getTransactionManager().begin();
+ try {
+ Query q = em.createNamedQuery(Plugin.QUERY_FIND_ANY_BY_NAME_AND_TYPE);
+ q.setParameter("name", pluginName);
+ q.setParameter("type", PluginDeploymentType.SERVER);
+ return (Plugin) q.getSingleResult();
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
}
commit 263227e335728de980194c0632ae04938396536e
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 23 11:36:47 2009 -0500
put the proper values in the query params
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 3697caa..157911d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -405,8 +405,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
q.setParameter("version", plugin.getVersion());
q.setParameter("ampsVersion", plugin.getAmpsVersion());
q.setParameter("deployment", plugin.getDeployment());
- q.setParameter("pluginConfiguration", config);
- q.setParameter("scheduledJobsConfiguration", config);
+ q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
+ q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
q.setParameter("description", plugin.getDescription());
q.setParameter("help", plugin.getHelp());
q.setParameter("mtime", plugin.getMtime());
commit e77a657abf17907a25dba4498b6e4993604ed38c
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 23 10:48:13 2009 -0500
the column should be "enabled" since everywhere else we talk about a plugin being enabled or disabled, not active/inactive
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
index 9f7f6b7..72f941e 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
@@ -105,7 +105,7 @@
<rich:column>
<f:facet name="header">
- <h:outputText styleClass="headerText" value="Active"/>
+ <h:outputText styleClass="headerText" value="Enabled"/>
</f:facet>
<h:outputText value="#{agentPlugin.enabled}"/>
@@ -190,7 +190,7 @@
<rich:column>
<f:facet name="header">
- <h:outputText styleClass="headerText" value="Active"/>
+ <h:outputText styleClass="headerText" value="Enabled"/>
</f:facet>
<h:outputText value="#{serverPlugin.enabled}"/>
commit 9af95de196ccc8b854a8f1c952af3a6cfa18e78d
Author: Justin Harris <jharris(a)redhat.com>
Date: Mon Nov 23 10:18:55 2009 -0500
Updating update plugin call to new naming scheme.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
index fac4661..b6db223 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
@@ -69,7 +69,7 @@ public class InstalledPluginUIBean {
ServerPluginsLocal serverPlugins = LookupUtil.getServerPlugins();
try {
- serverPlugins.updatePluginExceptContent(EnterpriseFacesContextUtility.getSubject(), plugin);
+ serverPlugins.updateServerPluginExceptContent(EnterpriseFacesContextUtility.getSubject(), plugin);
FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO,
"Configuration settings saved.");
@@ -78,6 +78,8 @@ public class InstalledPluginUIBean {
FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR,
"There was an error changing the configuration settings.", e);
}
+
+ lookupPlugin();
}
private void lookupPlugin() {
commit 556be90ec7e0285dc9205766805aaa91da2ef258
Author: Justin Harris <jharris(a)redhat.com>
Date: Fri Nov 20 18:34:52 2009 -0500
Adding save button to plugin details page.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
index f6eee0d..fac4661 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
@@ -65,6 +65,21 @@ public class InstalledPluginUIBean {
return this.scheduledJobsDefinition;
}
+ public void updatePlugin() {
+ ServerPluginsLocal serverPlugins = LookupUtil.getServerPlugins();
+
+ try {
+ serverPlugins.updatePluginExceptContent(EnterpriseFacesContextUtility.getSubject(), plugin);
+
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO,
+ "Configuration settings saved.");
+ } catch (Exception e) {
+ log.error("Error updating the plugin configurations.", e);
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR,
+ "There was an error changing the configuration settings.", e);
+ }
+ }
+
private void lookupPlugin() {
hasPermission();
String pluginName = FacesContextUtility.getRequiredRequestParameter("plugin", String.class);
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
index 3921b8e..fa46dc8 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
@@ -76,24 +76,32 @@
</rich:panel>
- <rich:panel>
+
+ <rich:panel rendered="#{InstalledPluginUIBean.plugin.pluginConfiguration != null}">
<f:facet name="header">
<h:outputText value="Plugin Configuration"/>
</f:facet>
<onc:config
configurationDefinition="#{InstalledPluginUIBean.pluginConfigurationDefinition}"
- configuration="#{InstalledPluginUIBean.plugin.pluginConfiguration}"
- readOnly="true" />
+ configuration="#{InstalledPluginUIBean.plugin.pluginConfiguration}" />
</rich:panel>
- <rich:panel>
+ <rich:panel rendered="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration != null}">
<f:facet name="header">
<h:outputText value="Scheduled Jobs"/>
</f:facet>
<onc:config
configurationDefinition="#{InstalledPluginUIBean.scheduledJobsDefinition}"
- configuration="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration}"
- readOnly="true" />
+ configuration="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration}" />
+ </rich:panel>
+
+ <input type="hidden" name="plugin" value="#{param.plugin}"/>
+ <input type="hidden" name="pluginType" value="#{param.pluginType}"/>
+
+ <rich:panel rendered="#{InstalledPluginUIBean.plugin.pluginConfiguration != null ||
+ InstalledPluginUIBean.plugin.scheduledJobsConfiguration != null}">
+ <h:commandButton value="OK" type="submit" action="#{InstalledPluginUIBean.updatePlugin}"
+ alt="Click to Save Plugin" styleClass="buttonmed" />
</rich:panel>
</rich:panel>
commit e144f9a55590182e130ae768b9b494b13f03c2a6
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 22 22:42:30 2009 -0500
convert CRLF to LF
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
index a7c0cbc..2c47b0a 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
@@ -1,397 +1,397 @@
-<%@ page import="java.io.ByteArrayOutputStream" %>
-<%@ page import="java.io.PrintStream" %>
-
-<%@ page import="org.rhq.core.domain.auth.Subject" %>
-<%@ page import="org.rhq.core.domain.util.PersistenceUtility" %>
-
-<%@ page import="org.rhq.enterprise.gui.legacy.util.SessionUtils"%>
-<%@ page import="org.rhq.enterprise.gui.util.WebUtility"%>
-
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences" %>
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences.MetricRangePreferences" %>
-
-<%@ page import="org.rhq.enterprise.server.test.CoreTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.DiscoveryTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.MeasurementTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.SubjectRoleTestBeanLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.AlertTemplateTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.cloud.instance.ServerManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementBaselineManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.core.AgentManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.system.SystemManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.auth.SubjectManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.support.SupportManagerLocal" %>
-<%@page import="org.rhq.enterprise.server.plugin.ServerPluginsLocal"%><html>
-<%@ page import="org.rhq.enterprise.server.util.LookupUtil" %>
-<%@ page import="org.rhq.enterprise.server.scheduler.jobs.DataPurgeJob"%>
-
-<%@ page import="org.rhq.enterprise.server.resource.ResourceTypeManagerRemote"%>
-<%@ page import="org.rhq.core.domain.criteria.ResourceTypeCriteria"%>
-<%@ page import="org.rhq.core.domain.resource.ResourceType"%>
-
-<%@ page import="javax.naming.NamingException" %>
-
-<%@ page contentType="text/html;charset=UTF-8" language="java" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-
-<html>
-<head><title>RHQ Test Control Page</title></head>
-<body>
-
-<jsp:include page="/admin/include/adminTestLinks.html" flush="true" />
-
-<%
- CoreTestLocal coreTestBean;
- DiscoveryTestLocal discoveryTestBean;
- MeasurementTestLocal measurementTestBean;
- ResourceGroupTestBeanLocal resourceGroupTestBean;
- SubjectRoleTestBeanLocal subjectRoleTestBean;
- ServerManagerLocal serverManager;
- AlertTemplateTestLocal alertTemplateTestBean;
- MeasurementBaselineManagerLocal measurementBaselineManager;
- MeasurementScheduleManagerLocal measurementScheduleManager;
- AgentManagerLocal agentManager;
- SystemManagerLocal systemManager;
- SubjectManagerLocal subjectManager;
- SupportManagerLocal supportManager;
- ResourceTypeManagerRemote typeManager;
- ServerPluginsLocal serverPlugins;
-
- coreTestBean = LookupUtil.getCoreTest();
- discoveryTestBean = LookupUtil.getDiscoveryTest();
- measurementTestBean = LookupUtil.getMeasurementTest();
- resourceGroupTestBean = LookupUtil.getResourceGroupTestBean();
- subjectRoleTestBean = LookupUtil.getSubjectRoleTestBean();
- serverManager = LookupUtil.getServerManager();
- alertTemplateTestBean = LookupUtil.getAlertTemplateTestBean();
- measurementBaselineManager = LookupUtil.getMeasurementBaselineManager();
- measurementScheduleManager = LookupUtil.getMeasurementScheduleManager();
- agentManager = LookupUtil.getAgentManager();
- systemManager = LookupUtil.getSystemManager();
- subjectManager = LookupUtil.getSubjectManager();
- supportManager = LookupUtil.getSupportManager();
- typeManager = LookupUtil.getResourceTypeManagerRemote();
- serverPlugins = LookupUtil.getServerPlugins();
-
- String result = null;
- String mode = pageContext.getRequest().getParameter("mode");
- String failure = null;
- try
- {
- if ("registerTestAgent".equals(mode))
- {
- coreTestBean.registerTestAgent();
- }
- else if ("registerTestPluginAndTypeInfo".equals(mode))
- {
- discoveryTestBean.registerTestPluginAndTypeInfo();
- }
- else if ("removeTestPluginAndTypeInfo".equals(mode))
- {
- discoveryTestBean.removeTestPluginAndTypeInfo();
- }
- else if ("sendTestFullInventoryReport".equals(mode))
- {
- discoveryTestBean.sendTestFullInventoryReport();
- }
- else if ("sendTestRuntimeInventoryReport".equals(mode))
- {
- discoveryTestBean.sendTestRuntimeInventoryReport();
- }
- else if ("sendTestMeasurementReport".equals(mode))
- {
- measurementTestBean.sendTestMeasurementReport();
- }
- else if ("sendNewPlatform".equals(mode))
- {
- String address = request.getParameter("address");
- int servers = Integer.parseInt(request.getParameter("servers"));
- int servicesPerServer = Integer.parseInt(request.getParameter("servicesPerServer"));
- discoveryTestBean.sendNewPlatform(address, servers, servicesPerServer);
- }
- else if ("setupCompatibleGroups".equals(mode))
- {
- resourceGroupTestBean.setupCompatibleGroups();
- }
- else if ("setupUberMixedGroup".equals(mode))
- {
- resourceGroupTestBean.setupUberMixedGroup();
- }
- else if ("startStats".equals(mode))
- {
- coreTestBean.enableHibernateStatistics();
- }
- else if ("addProblemResource".equals(mode))
- {
- measurementTestBean.addProblemResource();
- }
- else if ("setAgentCurrentlyScheduledMetrics".equals(mode))
- {
- String value = pageContext.getRequest().getParameter("v");
- measurementTestBean.setAgentCurrentlyScheduledMetrics(Double.valueOf(value));
- }
- else if ("addSubjectsAndRoles".equals(mode))
- {
- String roleCount = pageContext.getRequest().getParameter("roleCount");
- String usersInRoleCount = pageContext.getRequest().getParameter("usersInRoleCount");
- subjectRoleTestBean.createRolesAndUsers(Integer.parseInt(roleCount), Integer.parseInt(usersInRoleCount));
- }
- else if ("clusterGetIdentity".equals(mode))
- {
- String serverName = serverManager.getIdentity();
- pageContext.setAttribute("serverName", "(serverName = " + serverName + ")");
- }
- else if ("cloneAlertTemplate".equals(mode))
- {
- String alertTemplateId = pageContext.getRequest().getParameter("alertTemplateId");
- String numberOfClones = pageContext.getRequest().getParameter("numberOfClones");
- alertTemplateTestBean.cloneAlertTemplate(Integer.parseInt(alertTemplateId), Integer.parseInt(numberOfClones));
- }
- else if ("calculateAutoBaselines".equals(mode))
- {
- // for now, baselines aren't calculated until we hit our day limit, we force it here
- java.util.Properties props = systemManager.getSystemConfiguration();
- props.put("CAM_BASELINE_LASTTIME", "0");
- systemManager.setSystemConfiguration(subjectManager.getOverlord(), props,true);
-
- measurementBaselineManager.calculateAutoBaselines();
- }
- else if ("calculateOOBs".equals(mode))
- {
- DataPurgeJob dpj = new DataPurgeJob();
- dpj.calculateOOBs();
- }
- else if ("checkForSuspectAgents".equals(mode))
- {
- agentManager.checkForSuspectAgents();
- }
- else if ("dataPurgeJob".equals(mode))
- {
- DataPurgeJob.purgeNow();
- }
- else if ("dbMaintenance".equals(mode))
- {
- systemManager.vacuum(subjectManager.getOverlord());
- systemManager.reindex(subjectManager.getOverlord());
- systemManager.analyze(subjectManager.getOverlord());
- }
- else if ("metricDisplayRange".equals(mode))
- {
- int lastHours = Integer.parseInt(pageContext.getRequest().getParameter("lastHours"));
- Subject subject = WebUtility.getSubject(request);
- MeasurementPreferences prefs = new MeasurementPreferences(subject);
- MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
- rangePrefs.lastN = lastHours;
- prefs.setMetricRangePreferences(rangePrefs);
- }
- else if ("errorCorrectSchedules".equals("mode"))
- {
- measurementScheduleManager.errorCorrectSchedules();
- }
- else if ("generateSnapshotReport".equals(mode))
- {
- int resourceId = Integer.parseInt(request.getParameter("resourceId"));
- String name = request.getParameter("name");
- String description = request.getParameter("description");
- java.net.URL url = supportManager.getSnapshotReport(subjectManager.getOverlord(), resourceId, name, description);
- result = "Snapshot Report is located here: " + url.toString();
- }
- else if ("purgeServerPlugin".equals(mode))
- {
- String serverPluginName = request.getParameter("serverPluginName");
- serverPlugins.purgeServerPlugin(subjectManager.getOverlord(), serverPluginName);
- result = "OK - you can now try to re-register a plugin with the name [" + serverPluginName + "]";
- }
- else if ("typeManagerRemote".equals(mode))
- {
- int typeId = Integer.parseInt(request.getParameter("typeId"));
- ResourceTypeCriteria criteria = new ResourceTypeCriteria();
- criteria.addFilterId(typeId);
- criteria.fetchMetricDefinitions(true);
- java.util.List<ResourceType> types = typeManager.findResourceTypesByCriteria(subjectManager.getOverlord(), criteria);
- result = "";
- for (ResourceType type : types) {
- result += type.getName() + " has " + (type.getMetricDefinitions() != null ? type.getMetricDefinitions().size() : "empty") + " metric definitions";
- }
- }
- }
- catch (Exception e)
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- e.printStackTrace(new PrintStream(baos));
- failure = baos.toString();
- }
-
- pageContext.setAttribute("executed", mode);
- pageContext.setAttribute("result", result);
- pageContext.setAttribute("failure", failure);
- pageContext.setAttribute("testAgentReported", Boolean.valueOf(coreTestBean.isTestAgentReported()));
-
-%>
-
-<c:if test="${executed != null}">
- <b>Executed <c:out value="${executed}"/>: </b> <c:out value="${result}"/><br>
- <c:if test="${failure != null}">
- <pre style="background-color: yellow;"><c:out value="${failure}"/></pre>
- </c:if>
-</c:if>
-
-<h2>Administration</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
-Add Lots of Users and Roles
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="addSubjectsAndRoles"/>
- Number of Roles: <input type="text" name="roleCount" size="5"/><br/>
- Number of Users in each Role: <input type="text" name="usersInRoleCount" size="5"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
- <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
-</ul>
-
-<h2>Core</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestAgent"/>
- <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=dbMaintenance"/>
- <a href="<c:out value="${url}"/>">Perform All Database Maintenance Now</a></li>
-</ul>
-
-<h2>Cluster</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=clusterGetIdentity"/>
- <a href="<c:out value="${url}"/>">Get Identity</a> <c:out value="${serverName}"/></li>
-</ul>
-
-<h2>Inventory</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestFullInventoryReport"/>
- <a href="<c:out value="${url}"/>">Send Full Inventory Report</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestRuntimeInventoryReport"/>
- <a href="<c:out value="${url}"/>">Send Runtime Inventory Report</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setupCompatibleGroups"/>
- <a href="<c:out value="${url}"/>">Setup Compatible Groups</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setupUberMixedGroup"/>
- <a href="<c:out value="${url}"/>">Setup Uber Mixed Group</a></li>
-</ul>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=sendNewPlatform"/>
-Send New Platform Inventory Report
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="sendNewPlatform"/>
- Address: <input type="text" name="address" size="30"/><br/>
- Servers: <input type="text" name="servers" size="5"/><br/>
- Services Per Server: <input type="text" name="servicesPerServer" size="5"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-
-<h2>Measurement</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateAutoBaselines"/>
- <a href="<c:out value="${url}"/>">Calculate Auto Baselines</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestMeasurementReport"/>
- <a href="<c:out value="${url}"/>">Send Measurement Report</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=addProblemResource"/>
- <a href="<c:out value="${url}"/>">Add problem Resource</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=100"/>
- <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 100</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=50"/>
- <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 50</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=checkForSuspectAgents"/>
- <a href="<c:out value="${url}"/>">Check For Suspect Agents</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=dataPurgeJob"/>
- <a href="<c:out value="${url}"/>">Force Data Purge Now</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateOOBs"/>
- <a href="<c:out value="${url}"/>">Force calculation of OOBs</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=errorCorrectSchedules"/>
- <a href="<c:out value="${url}"/>">Error-Correct Measurement Schedules</a></li>
-</ul>
-
-<h2>Alerts</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=cloneAlertTemplate"/>
-Template Cloning
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="cloneAlertTemplate"/>
- Alert Template ID: <input type="text" name="alertTemplateId" size="5"/><br/>
- Number of Clones: <input type="text" name="numberOfClones" size="5"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-<h2>Utilities</h2>
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=startStats"/>
- <a href="<c:out value="${url}"/>">Start Hibernate Statistics Collection</a></li>
-</ul>
-
-
-<h2>User Preferences</h2>
-<%
- Subject subject = WebUtility.getSubject(request);
- MeasurementPreferences prefs = new MeasurementPreferences(subject);
- MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
- pageContext.setAttribute("lastHours", String.valueOf(rangePrefs.lastN));
-%>
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="metricDisplayRange"/>
- Last X hours: <input type="text" name="lastHours" size="5" value="<c:out value="${lastHours}"/>"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-<h2>Snapshot Report</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=generateSnapshotReport"/>
-Generate Snapshot Report
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="generateSnapshotReport"/>
- Resource ID: <input type="text" name="resourceId" size="10"/><br/>
- Name: <input type="text" name="name" size="30"/><br/>
- Description: <input type="text" name="description" size="100"/><br/>
- <input type="submit" value="Generate Snapshot" name="Generate Snapshot"/>
-</form>
-
-<h2>Server Plugins</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=purgeServerPlugin"/>
-Purge Server Plugin (allowing you to re-register it again later)
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="purgeServerPlugin"/>
- ServerPluginName: <input type="text" name="serverPluginName" size="30"/><br/>
- <input type="submit" value="Purge Server Plugin" name="Purge Server Plugin"/>
-</form>
-
-<h2>Resource Type Criteria</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=typeManagerRemote"/>
-Query ResourceTypes by Criteria
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="typeManagerRemote"/>
- ResourceType ID: <input type="text" name="typeId" size="10"/><br/>
- <input type="submit" value="Query by Criteria" name="Query by Criteria"/>
-</form>
-
-
-
-</body>
-</html>
+<%@ page import="java.io.ByteArrayOutputStream" %>
+<%@ page import="java.io.PrintStream" %>
+
+<%@ page import="org.rhq.core.domain.auth.Subject" %>
+<%@ page import="org.rhq.core.domain.util.PersistenceUtility" %>
+
+<%@ page import="org.rhq.enterprise.gui.legacy.util.SessionUtils"%>
+<%@ page import="org.rhq.enterprise.gui.util.WebUtility"%>
+
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences" %>
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences.MetricRangePreferences" %>
+
+<%@ page import="org.rhq.enterprise.server.test.CoreTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.DiscoveryTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.MeasurementTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.SubjectRoleTestBeanLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.AlertTemplateTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.cloud.instance.ServerManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementBaselineManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.core.AgentManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.system.SystemManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.auth.SubjectManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.support.SupportManagerLocal" %>
+<%@page import="org.rhq.enterprise.server.plugin.ServerPluginsLocal"%><html>
+<%@ page import="org.rhq.enterprise.server.util.LookupUtil" %>
+<%@ page import="org.rhq.enterprise.server.scheduler.jobs.DataPurgeJob"%>
+
+<%@ page import="org.rhq.enterprise.server.resource.ResourceTypeManagerRemote"%>
+<%@ page import="org.rhq.core.domain.criteria.ResourceTypeCriteria"%>
+<%@ page import="org.rhq.core.domain.resource.ResourceType"%>
+
+<%@ page import="javax.naming.NamingException" %>
+
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
+<html>
+<head><title>RHQ Test Control Page</title></head>
+<body>
+
+<jsp:include page="/admin/include/adminTestLinks.html" flush="true" />
+
+<%
+ CoreTestLocal coreTestBean;
+ DiscoveryTestLocal discoveryTestBean;
+ MeasurementTestLocal measurementTestBean;
+ ResourceGroupTestBeanLocal resourceGroupTestBean;
+ SubjectRoleTestBeanLocal subjectRoleTestBean;
+ ServerManagerLocal serverManager;
+ AlertTemplateTestLocal alertTemplateTestBean;
+ MeasurementBaselineManagerLocal measurementBaselineManager;
+ MeasurementScheduleManagerLocal measurementScheduleManager;
+ AgentManagerLocal agentManager;
+ SystemManagerLocal systemManager;
+ SubjectManagerLocal subjectManager;
+ SupportManagerLocal supportManager;
+ ResourceTypeManagerRemote typeManager;
+ ServerPluginsLocal serverPlugins;
+
+ coreTestBean = LookupUtil.getCoreTest();
+ discoveryTestBean = LookupUtil.getDiscoveryTest();
+ measurementTestBean = LookupUtil.getMeasurementTest();
+ resourceGroupTestBean = LookupUtil.getResourceGroupTestBean();
+ subjectRoleTestBean = LookupUtil.getSubjectRoleTestBean();
+ serverManager = LookupUtil.getServerManager();
+ alertTemplateTestBean = LookupUtil.getAlertTemplateTestBean();
+ measurementBaselineManager = LookupUtil.getMeasurementBaselineManager();
+ measurementScheduleManager = LookupUtil.getMeasurementScheduleManager();
+ agentManager = LookupUtil.getAgentManager();
+ systemManager = LookupUtil.getSystemManager();
+ subjectManager = LookupUtil.getSubjectManager();
+ supportManager = LookupUtil.getSupportManager();
+ typeManager = LookupUtil.getResourceTypeManagerRemote();
+ serverPlugins = LookupUtil.getServerPlugins();
+
+ String result = null;
+ String mode = pageContext.getRequest().getParameter("mode");
+ String failure = null;
+ try
+ {
+ if ("registerTestAgent".equals(mode))
+ {
+ coreTestBean.registerTestAgent();
+ }
+ else if ("registerTestPluginAndTypeInfo".equals(mode))
+ {
+ discoveryTestBean.registerTestPluginAndTypeInfo();
+ }
+ else if ("removeTestPluginAndTypeInfo".equals(mode))
+ {
+ discoveryTestBean.removeTestPluginAndTypeInfo();
+ }
+ else if ("sendTestFullInventoryReport".equals(mode))
+ {
+ discoveryTestBean.sendTestFullInventoryReport();
+ }
+ else if ("sendTestRuntimeInventoryReport".equals(mode))
+ {
+ discoveryTestBean.sendTestRuntimeInventoryReport();
+ }
+ else if ("sendTestMeasurementReport".equals(mode))
+ {
+ measurementTestBean.sendTestMeasurementReport();
+ }
+ else if ("sendNewPlatform".equals(mode))
+ {
+ String address = request.getParameter("address");
+ int servers = Integer.parseInt(request.getParameter("servers"));
+ int servicesPerServer = Integer.parseInt(request.getParameter("servicesPerServer"));
+ discoveryTestBean.sendNewPlatform(address, servers, servicesPerServer);
+ }
+ else if ("setupCompatibleGroups".equals(mode))
+ {
+ resourceGroupTestBean.setupCompatibleGroups();
+ }
+ else if ("setupUberMixedGroup".equals(mode))
+ {
+ resourceGroupTestBean.setupUberMixedGroup();
+ }
+ else if ("startStats".equals(mode))
+ {
+ coreTestBean.enableHibernateStatistics();
+ }
+ else if ("addProblemResource".equals(mode))
+ {
+ measurementTestBean.addProblemResource();
+ }
+ else if ("setAgentCurrentlyScheduledMetrics".equals(mode))
+ {
+ String value = pageContext.getRequest().getParameter("v");
+ measurementTestBean.setAgentCurrentlyScheduledMetrics(Double.valueOf(value));
+ }
+ else if ("addSubjectsAndRoles".equals(mode))
+ {
+ String roleCount = pageContext.getRequest().getParameter("roleCount");
+ String usersInRoleCount = pageContext.getRequest().getParameter("usersInRoleCount");
+ subjectRoleTestBean.createRolesAndUsers(Integer.parseInt(roleCount), Integer.parseInt(usersInRoleCount));
+ }
+ else if ("clusterGetIdentity".equals(mode))
+ {
+ String serverName = serverManager.getIdentity();
+ pageContext.setAttribute("serverName", "(serverName = " + serverName + ")");
+ }
+ else if ("cloneAlertTemplate".equals(mode))
+ {
+ String alertTemplateId = pageContext.getRequest().getParameter("alertTemplateId");
+ String numberOfClones = pageContext.getRequest().getParameter("numberOfClones");
+ alertTemplateTestBean.cloneAlertTemplate(Integer.parseInt(alertTemplateId), Integer.parseInt(numberOfClones));
+ }
+ else if ("calculateAutoBaselines".equals(mode))
+ {
+ // for now, baselines aren't calculated until we hit our day limit, we force it here
+ java.util.Properties props = systemManager.getSystemConfiguration();
+ props.put("CAM_BASELINE_LASTTIME", "0");
+ systemManager.setSystemConfiguration(subjectManager.getOverlord(), props,true);
+
+ measurementBaselineManager.calculateAutoBaselines();
+ }
+ else if ("calculateOOBs".equals(mode))
+ {
+ DataPurgeJob dpj = new DataPurgeJob();
+ dpj.calculateOOBs();
+ }
+ else if ("checkForSuspectAgents".equals(mode))
+ {
+ agentManager.checkForSuspectAgents();
+ }
+ else if ("dataPurgeJob".equals(mode))
+ {
+ DataPurgeJob.purgeNow();
+ }
+ else if ("dbMaintenance".equals(mode))
+ {
+ systemManager.vacuum(subjectManager.getOverlord());
+ systemManager.reindex(subjectManager.getOverlord());
+ systemManager.analyze(subjectManager.getOverlord());
+ }
+ else if ("metricDisplayRange".equals(mode))
+ {
+ int lastHours = Integer.parseInt(pageContext.getRequest().getParameter("lastHours"));
+ Subject subject = WebUtility.getSubject(request);
+ MeasurementPreferences prefs = new MeasurementPreferences(subject);
+ MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
+ rangePrefs.lastN = lastHours;
+ prefs.setMetricRangePreferences(rangePrefs);
+ }
+ else if ("errorCorrectSchedules".equals("mode"))
+ {
+ measurementScheduleManager.errorCorrectSchedules();
+ }
+ else if ("generateSnapshotReport".equals(mode))
+ {
+ int resourceId = Integer.parseInt(request.getParameter("resourceId"));
+ String name = request.getParameter("name");
+ String description = request.getParameter("description");
+ java.net.URL url = supportManager.getSnapshotReport(subjectManager.getOverlord(), resourceId, name, description);
+ result = "Snapshot Report is located here: " + url.toString();
+ }
+ else if ("purgeServerPlugin".equals(mode))
+ {
+ String serverPluginName = request.getParameter("serverPluginName");
+ serverPlugins.purgeServerPlugin(subjectManager.getOverlord(), serverPluginName);
+ result = "OK - you can now try to re-register a plugin with the name [" + serverPluginName + "]";
+ }
+ else if ("typeManagerRemote".equals(mode))
+ {
+ int typeId = Integer.parseInt(request.getParameter("typeId"));
+ ResourceTypeCriteria criteria = new ResourceTypeCriteria();
+ criteria.addFilterId(typeId);
+ criteria.fetchMetricDefinitions(true);
+ java.util.List<ResourceType> types = typeManager.findResourceTypesByCriteria(subjectManager.getOverlord(), criteria);
+ result = "";
+ for (ResourceType type : types) {
+ result += type.getName() + " has " + (type.getMetricDefinitions() != null ? type.getMetricDefinitions().size() : "empty") + " metric definitions";
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ e.printStackTrace(new PrintStream(baos));
+ failure = baos.toString();
+ }
+
+ pageContext.setAttribute("executed", mode);
+ pageContext.setAttribute("result", result);
+ pageContext.setAttribute("failure", failure);
+ pageContext.setAttribute("testAgentReported", Boolean.valueOf(coreTestBean.isTestAgentReported()));
+
+%>
+
+<c:if test="${executed != null}">
+ <b>Executed <c:out value="${executed}"/>: </b> <c:out value="${result}"/><br>
+ <c:if test="${failure != null}">
+ <pre style="background-color: yellow;"><c:out value="${failure}"/></pre>
+ </c:if>
+</c:if>
+
+<h2>Administration</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
+Add Lots of Users and Roles
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="addSubjectsAndRoles"/>
+ Number of Roles: <input type="text" name="roleCount" size="5"/><br/>
+ Number of Users in each Role: <input type="text" name="usersInRoleCount" size="5"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
+ <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
+</ul>
+
+<h2>Core</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestAgent"/>
+ <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=dbMaintenance"/>
+ <a href="<c:out value="${url}"/>">Perform All Database Maintenance Now</a></li>
+</ul>
+
+<h2>Cluster</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=clusterGetIdentity"/>
+ <a href="<c:out value="${url}"/>">Get Identity</a> <c:out value="${serverName}"/></li>
+</ul>
+
+<h2>Inventory</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestFullInventoryReport"/>
+ <a href="<c:out value="${url}"/>">Send Full Inventory Report</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestRuntimeInventoryReport"/>
+ <a href="<c:out value="${url}"/>">Send Runtime Inventory Report</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setupCompatibleGroups"/>
+ <a href="<c:out value="${url}"/>">Setup Compatible Groups</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setupUberMixedGroup"/>
+ <a href="<c:out value="${url}"/>">Setup Uber Mixed Group</a></li>
+</ul>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=sendNewPlatform"/>
+Send New Platform Inventory Report
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="sendNewPlatform"/>
+ Address: <input type="text" name="address" size="30"/><br/>
+ Servers: <input type="text" name="servers" size="5"/><br/>
+ Services Per Server: <input type="text" name="servicesPerServer" size="5"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+
+<h2>Measurement</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateAutoBaselines"/>
+ <a href="<c:out value="${url}"/>">Calculate Auto Baselines</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestMeasurementReport"/>
+ <a href="<c:out value="${url}"/>">Send Measurement Report</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=addProblemResource"/>
+ <a href="<c:out value="${url}"/>">Add problem Resource</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=100"/>
+ <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 100</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=50"/>
+ <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 50</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=checkForSuspectAgents"/>
+ <a href="<c:out value="${url}"/>">Check For Suspect Agents</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=dataPurgeJob"/>
+ <a href="<c:out value="${url}"/>">Force Data Purge Now</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateOOBs"/>
+ <a href="<c:out value="${url}"/>">Force calculation of OOBs</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=errorCorrectSchedules"/>
+ <a href="<c:out value="${url}"/>">Error-Correct Measurement Schedules</a></li>
+</ul>
+
+<h2>Alerts</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=cloneAlertTemplate"/>
+Template Cloning
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="cloneAlertTemplate"/>
+ Alert Template ID: <input type="text" name="alertTemplateId" size="5"/><br/>
+ Number of Clones: <input type="text" name="numberOfClones" size="5"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+<h2>Utilities</h2>
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=startStats"/>
+ <a href="<c:out value="${url}"/>">Start Hibernate Statistics Collection</a></li>
+</ul>
+
+
+<h2>User Preferences</h2>
+<%
+ Subject subject = WebUtility.getSubject(request);
+ MeasurementPreferences prefs = new MeasurementPreferences(subject);
+ MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
+ pageContext.setAttribute("lastHours", String.valueOf(rangePrefs.lastN));
+%>
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="metricDisplayRange"/>
+ Last X hours: <input type="text" name="lastHours" size="5" value="<c:out value="${lastHours}"/>"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+<h2>Snapshot Report</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=generateSnapshotReport"/>
+Generate Snapshot Report
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="generateSnapshotReport"/>
+ Resource ID: <input type="text" name="resourceId" size="10"/><br/>
+ Name: <input type="text" name="name" size="30"/><br/>
+ Description: <input type="text" name="description" size="100"/><br/>
+ <input type="submit" value="Generate Snapshot" name="Generate Snapshot"/>
+</form>
+
+<h2>Server Plugins</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=purgeServerPlugin"/>
+Purge Server Plugin (allowing you to re-register it again later)
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="purgeServerPlugin"/>
+ ServerPluginName: <input type="text" name="serverPluginName" size="30"/><br/>
+ <input type="submit" value="Purge Server Plugin" name="Purge Server Plugin"/>
+</form>
+
+<h2>Resource Type Criteria</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=typeManagerRemote"/>
+Query ResourceTypes by Criteria
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="typeManagerRemote"/>
+ ResourceType ID: <input type="text" name="typeId" size="10"/><br/>
+ <input type="submit" value="Query by Criteria" name="Query by Criteria"/>
+</form>
+
+
+
+</body>
+</html>
commit f04ef82719012571ecfa157eb270c6b0424ad0ac
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 22 22:39:34 2009 -0500
mistakenly deleted the html tag, put it back
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
index 4d5cfd5..a7c0cbc 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
@@ -38,7 +38,7 @@
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-
+<html>
<head><title>RHQ Test Control Page</title></head>
<body>
commit a5fcd064dc1d1eea47c2806754c3244e1c000235
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 22 01:59:12 2009 -0500
since there is no current way to "revive" a undeployed plugin from the real GUI, at least provide _some_ way to get back to a state that will let you re-register a plugin again using the test control.jsp page
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
index f3f0a35..4d5cfd5 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
@@ -24,6 +24,7 @@
<%@ page import="org.rhq.enterprise.server.system.SystemManagerLocal" %>
<%@ page import="org.rhq.enterprise.server.auth.SubjectManagerLocal" %>
<%@ page import="org.rhq.enterprise.server.support.SupportManagerLocal" %>
+<%@page import="org.rhq.enterprise.server.plugin.ServerPluginsLocal"%><html>
<%@ page import="org.rhq.enterprise.server.util.LookupUtil" %>
<%@ page import="org.rhq.enterprise.server.scheduler.jobs.DataPurgeJob"%>
@@ -37,7 +38,7 @@
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-<html>
+
<head><title>RHQ Test Control Page</title></head>
<body>
@@ -58,6 +59,7 @@
SubjectManagerLocal subjectManager;
SupportManagerLocal supportManager;
ResourceTypeManagerRemote typeManager;
+ ServerPluginsLocal serverPlugins;
coreTestBean = LookupUtil.getCoreTest();
discoveryTestBean = LookupUtil.getDiscoveryTest();
@@ -73,6 +75,7 @@
subjectManager = LookupUtil.getSubjectManager();
supportManager = LookupUtil.getSupportManager();
typeManager = LookupUtil.getResourceTypeManagerRemote();
+ serverPlugins = LookupUtil.getServerPlugins();
String result = null;
String mode = pageContext.getRequest().getParameter("mode");
@@ -197,6 +200,12 @@
java.net.URL url = supportManager.getSnapshotReport(subjectManager.getOverlord(), resourceId, name, description);
result = "Snapshot Report is located here: " + url.toString();
}
+ else if ("purgeServerPlugin".equals(mode))
+ {
+ String serverPluginName = request.getParameter("serverPluginName");
+ serverPlugins.purgeServerPlugin(subjectManager.getOverlord(), serverPluginName);
+ result = "OK - you can now try to re-register a plugin with the name [" + serverPluginName + "]";
+ }
else if ("typeManagerRemote".equals(mode))
{
int typeId = Integer.parseInt(request.getParameter("typeId"));
@@ -362,6 +371,16 @@ Generate Snapshot Report
<input type="submit" value="Generate Snapshot" name="Generate Snapshot"/>
</form>
+<h2>Server Plugins</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=purgeServerPlugin"/>
+Purge Server Plugin (allowing you to re-register it again later)
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="purgeServerPlugin"/>
+ ServerPluginName: <input type="text" name="serverPluginName" size="30"/><br/>
+ <input type="submit" value="Purge Server Plugin" name="Purge Server Plugin"/>
+</form>
+
<h2>Resource Type Criteria</h2>
<c:url var="url" value="/admin/test/control.jsp?mode=typeManagerRemote"/>
commit 5413dbb476c615effd97d698ae54b051bcfa02c5
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sat Nov 21 16:17:38 2009 -0500
actually remove all jobs for the undeployed server plugin
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 8a4ab80..3697caa 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -235,6 +235,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
}
+ log.info("Server plugins " + doomedPlugins + " have been undeployed");
+
// only restart if the master was started to begin with; otherwise, leave it down
if (master != null) {
serverPluginService.restartMasterPluginContainer();
@@ -257,6 +259,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
throw new Exception("Failed to update [" + pluginIds.size() + "] plugins. Count was [" + count + "]");
}
+ log.info((enabled ? "Enabling" : "Disabling") + " server plugins with plugin IDs of " + pluginIds);
return;
}
@@ -324,7 +327,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
entityManager.flush();
streamPluginFileContentToDatabase(plugin.getId(), pluginFile);
}
- log.debug("Updated plugin entity [" + plugin + "]");
+ log.info("Server plugin [" + plugin.getName() + "] has been registered in the database");
}
return plugin;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index 3256bf5..e88e5fd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -235,7 +235,21 @@ public abstract class AbstractTypeServerPluginContainer {
*/
public void unschedulePluginJobs(String pluginName) throws Exception {
SchedulerLocal scheduler = LookupUtil.getSchedulerBean();
- scheduler.resumeJobGroup(pluginName);
+
+ // note: all jobs for a plugin are placed in the same group, where the group name is the plugin name
+ String groupName = pluginName;
+
+ scheduler.pauseJobGroup(groupName);
+ String[] jobNames = scheduler.getJobNames(groupName);
+ if (jobNames != null) {
+ for (String jobName : jobNames) {
+ boolean deleted = scheduler.deleteJob(jobName, groupName);
+ if (!deleted) {
+ log.warn("Plugin [" + pluginName + "] failed to get its job [" + jobName + "] unscheduled!");
+ }
+ }
+ }
+
return;
}
commit 1093e91f666af1848a7bd5d4fb93ed6cdb9b9c50
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sat Nov 21 13:24:26 2009 -0500
provide API that will allow us to later build a user interface to "resurrect" a deleted plugin - to re-install it if it was undelpoyed before.
this also fixes some tests - server/jar and core/domain plugin tests now all pass properly
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index 67ffc53..eda26d8 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -114,6 +114,31 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " LEFT JOIN p.scheduledJobsConfiguration " //
+ " WHERE p.name=:name AND p.status = 'INSTALLED' "), //
+ // gets the plugin, even if it is deleted
+ // this query does not load the content blob, but loads everything else
+ @NamedQuery(name = Plugin.QUERY_FIND_ANY_BY_NAME_AND_TYPE, query = "" //
+ + " SELECT new org.rhq.core.domain.plugin.Plugin( " //
+ + " p.id, " //
+ + " p.name, " //
+ + " p.path, " //
+ + " p.displayName, " //
+ + " p.enabled, " //
+ + " p.status, " //
+ + " p.description, " //
+ + " p.help, " //
+ + " p.md5, " //
+ + " p.version, " //
+ + " p.ampsVersion, " //
+ + " p.deployment, " //
+ + " p.pluginConfiguration, " //
+ + " p.scheduledJobsConfiguration, " //
+ + " p.ctime, " //
+ + " p.mtime) " //
+ + " FROM Plugin AS p " //
+ + " LEFT JOIN p.pluginConfiguration " //
+ + " LEFT JOIN p.scheduledJobsConfiguration " //
+ + " WHERE p.name=:name AND p.deployment = :type "), //
+
// this query does not load the content blob, but loads everything else
@NamedQuery(name = Plugin.QUERY_FIND_ALL_AGENT, query = "" //
+ " SELECT new org.rhq.core.domain.plugin.Plugin( " //
@@ -227,6 +252,7 @@ public class Plugin implements Serializable {
public static final String QUERY_FIND_ALL_AGENT = "Plugin.findAllAgent";
public static final String QUERY_FIND_ALL_SERVER = "Plugin.findAllServer";
public static final String QUERY_FIND_BY_NAME = "Plugin.findByName";
+ public static final String QUERY_FIND_ANY_BY_NAME_AND_TYPE = "Plugin.findAnyByNameAndType";
public static final String QUERY_FIND_BY_IDS_AND_TYPE = "Plugin.findByIdsAndType";
public static final String QUERY_GET_NAMES_BY_ENABLED_AND_TYPE = "Plugin.findByEnabledAndType";
public static final String QUERY_GET_STATUS_BY_NAME_AND_TYPE = "Plugin.getStatusByNameAndType";
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index 8ab3171..07f8f97 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -48,7 +48,7 @@ import org.rhq.core.util.stream.StreamUtil;
@Test
public class PluginTest extends AbstractEJB3Test {
- public void testUpdate() throws Exception {
+ public void testUpdate() throws Throwable {
boolean done = false;
getTransactionManager().begin();
EntityManager em = getEntityManager();
@@ -81,8 +81,8 @@ public class PluginTest extends AbstractEJB3Test {
em.persist(plugin);
id = plugin.getId();
assert id > 0;
- assert plugin.getPluginConfiguration().getId() > 0 : "did not persist config";
- assert plugin.getScheduledJobsConfiguration().getId() > 0 : "did not persist jobs config";
+ assert plugin.getPluginConfiguration() == null : "there was no config that should have been here";
+ assert plugin.getScheduledJobsConfiguration() == null : "there was no config that should have been here";
q = em.createNamedQuery(Plugin.QUERY_GET_STATUS_BY_NAME_AND_TYPE);
q.setParameter("name", plugin.getName());
@@ -127,6 +127,10 @@ public class PluginTest extends AbstractEJB3Test {
getTransactionManager().begin();
em = getEntityManager();
+ em.persist(pluginConfig);
+ em.persist(jobsConfig);
+ em.flush(); // gotta get those two persists to flush to the DB
+
q = em.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
q.setParameter("id", id); // same as the one we just persisted
q.setParameter("name", name);
@@ -173,12 +177,19 @@ public class PluginTest extends AbstractEJB3Test {
getTransactionManager().commit();
getTransactionManager().begin();
em = getEntityManager();
- em.createNativeQuery("DELETE FROM " + Plugin.TABLE_NAME + " WHERE ID = " + id).executeUpdate();
+ q = em.createNamedQuery(Plugin.QUERY_FIND_ANY_BY_NAME_AND_TYPE);
+ q.setParameter("name", plugin.getName());
+ q.setParameter("type", plugin.getDeployment());
+ Plugin doomed = (Plugin) q.getSingleResult();
+ doomed = em.getReference(Plugin.class, doomed.getId());
+ em.remove(doomed);
+ assert q.getResultList().size() == 0 : "didn't remove the plugin";
em.close();
getTransactionManager().commit();
done = true;
} catch (Throwable t) {
t.printStackTrace();
+ throw t;
} finally {
if (!done) {
getTransactionManager().rollback();
@@ -486,7 +497,13 @@ public class PluginTest extends AbstractEJB3Test {
getTransactionManager().commit();
getTransactionManager().begin();
em = getEntityManager();
- em.createNativeQuery("DELETE FROM " + Plugin.TABLE_NAME + " WHERE ID = " + plugin.getId()).executeUpdate();
+ Query q = em.createNamedQuery(Plugin.QUERY_FIND_ANY_BY_NAME_AND_TYPE);
+ q.setParameter("name", plugin.getName());
+ q.setParameter("type", plugin.getDeployment());
+ Plugin doomed = (Plugin) q.getSingleResult();
+ doomed = em.getReference(Plugin.class, doomed.getId());
+ em.remove(doomed);
+ assert q.getResultList().size() == 0 : "didn't remove the plugin";
em.close();
getTransactionManager().commit();
done = true;
@@ -595,8 +612,13 @@ public class PluginTest extends AbstractEJB3Test {
getTransactionManager().commit();
getTransactionManager().begin();
em = getEntityManager();
- em.createNativeQuery("DELETE FROM " + Plugin.TABLE_NAME + " WHERE ID = " + plugin.getId()).executeUpdate();
- em.close();
+ Query q = em.createNamedQuery(Plugin.QUERY_FIND_ANY_BY_NAME_AND_TYPE);
+ q.setParameter("name", plugin.getName());
+ q.setParameter("type", plugin.getDeployment());
+ Plugin doomed = (Plugin) q.getSingleResult();
+ doomed = em.getReference(Plugin.class, doomed.getId());
+ em.remove(doomed);
+ assert q.getResultList().size() == 0 : "didn't remove the plugin";
getTransactionManager().commit();
done = true;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 67d5efd..8a4ab80 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -44,6 +44,7 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
import org.rhq.core.domain.plugin.PluginStatusType;
@@ -213,8 +214,14 @@ public class ServerPluginsBean implements ServerPluginsLocal {
// if this plugin ever gets re-installed, let's support the use-case where the new plugin
// will have different config metadata. Here we null out the old config so the new
// config can be set to the new cofig definition's default values.
- doomedPlugin.setPluginConfiguration(null);
- doomedPlugin.setScheduledJobsConfiguration(null);
+ if (doomedPlugin.getPluginConfiguration() != null) {
+ entityManager.remove(doomedPlugin.getPluginConfiguration());
+ doomedPlugin.setPluginConfiguration(null);
+ }
+ if (doomedPlugin.getScheduledJobsConfiguration() != null) {
+ entityManager.remove(doomedPlugin.getScheduledJobsConfiguration());
+ doomedPlugin.setScheduledJobsConfiguration(null);
+ }
doomedPlugin.setStatus(PluginStatusType.DELETED);
try {
@@ -324,6 +331,22 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public void purgeServerPlugin(Subject subject, String pluginName) {
+ Query q = this.entityManager.createNamedQuery(Plugin.QUERY_FIND_ANY_BY_NAME_AND_TYPE);
+ q.setParameter("name", pluginName);
+ q.setParameter("type", PluginDeploymentType.SERVER);
+ Plugin doomed = (Plugin) q.getSingleResult();
+
+ // get the reference to attach to em and use the em.remove. this cascade deletes too.
+ doomed = this.entityManager.getReference(Plugin.class, doomed.getId());
+ this.entityManager.remove(doomed);
+
+ log.debug("Server plugin [" + pluginName + "] has been purged from the db");
+ return;
+ }
+
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
public Plugin updateServerPluginExceptContent(Subject subject, Plugin plugin) throws Exception {
// this method is here because we need a way to update the plugin's information
@@ -339,6 +362,35 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (plugin.getId() == 0) {
throw new IllegalArgumentException("Plugin must already exist to update it");
} else {
+ // make sure the configs are in the DB properly and we have their refs
+ // this is because we are using JPQL update, so we need to do some of this "manually"
+ boolean needFlush = false;
+ Configuration config = plugin.getPluginConfiguration();
+ if (config != null) {
+ if (config.getId() > 0) {
+ config = entityManager.getReference(Configuration.class, config.getId());
+ plugin.setPluginConfiguration(config);
+ } else {
+ entityManager.persist(config);
+ needFlush = true;
+ }
+ }
+ config = plugin.getScheduledJobsConfiguration();
+ if (config != null) {
+ if (config.getId() > 0) {
+ config = entityManager.getReference(Configuration.class, config.getId());
+ plugin.setScheduledJobsConfiguration(config);
+ } else {
+ entityManager.persist(config);
+ needFlush = true;
+ }
+ }
+ if (needFlush) {
+ entityManager.flush(); // must be flushed to the DB so the JPQL update below works
+ }
+
+ // now we can JPQL update the row - all but content is updated here.
+ // we assured our configs are persisted/attached above
Query q = entityManager.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
q.setParameter("id", plugin.getId());
q.setParameter("name", plugin.getName());
@@ -350,14 +402,16 @@ public class ServerPluginsBean implements ServerPluginsLocal {
q.setParameter("version", plugin.getVersion());
q.setParameter("ampsVersion", plugin.getAmpsVersion());
q.setParameter("deployment", plugin.getDeployment());
- q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
- q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
+ q.setParameter("pluginConfiguration", config);
+ q.setParameter("scheduledJobsConfiguration", config);
q.setParameter("description", plugin.getDescription());
q.setParameter("help", plugin.getHelp());
q.setParameter("mtime", plugin.getMtime());
if (q.executeUpdate() != 1) {
throw new Exception("Failed to update a plugin that matches [" + plugin + "]");
}
+
+ entityManager.flush(); // make sure we push this out to the DB now
}
return plugin;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index 68afc0e..6f3600e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -126,7 +126,8 @@ public interface ServerPluginsLocal {
void setServerPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status) throws Exception;
/**
- * Registers the given plugin to the database.
+ * Registers the given plugin to the database. This does nothing with the master plugin container,
+ * all it does is ensure the database is up-to-date with this new plugin.
*
* @param subject the user that needs to have permissions to add a plugin to the system
* @param plugin the plugin definition
@@ -149,6 +150,20 @@ public interface ServerPluginsLocal {
Plugin updateServerPluginExceptContent(Subject subject, Plugin plugin) throws Exception;
/**
+ * Purges the server plugin from the database. This ensures that, after this method returns,
+ * the given plugin will be unknown. The plugin can be installed again later.
+ *
+ * This has "requires new" semantics, so the results are committed immediately upon return.
+ * This is really a supporting method for {@link #reRegisterServerPlugin(Subject, Plugin, File)} - you'll
+ * probably want to use that instead. Do not blindly purge server plugins using this method unless you
+ * know what you are doing.
+ *
+ * @param subject user making the request
+ * @param pluginName the name of the server plugin to delete
+ */
+ void purgeServerPlugin(Subject subject, String pluginName);
+
+ /**
* Given the name of a server plugin, this will return the status of that plugin.
* Use this to determine if a plugin has been deleted or not.
*
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
index 8250c7d..9c971e0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
@@ -50,6 +50,7 @@ import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.content.PackageType;
import org.rhq.core.domain.event.EventDefinition;
@@ -196,6 +197,33 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
if (plugin.getId() == 0) {
entityManager.persist(plugin);
} else {
+ // agent plugins don't support these configs, but if/when they do in the future, this will support it
+ boolean needFlush = false;
+ Configuration config = plugin.getPluginConfiguration();
+ if (config != null) {
+ if (config.getId() > 0) {
+ config = entityManager.getReference(Configuration.class, config.getId());
+ plugin.setPluginConfiguration(config);
+ } else {
+ entityManager.persist(config);
+ needFlush = true;
+ }
+ }
+ config = plugin.getScheduledJobsConfiguration();
+ if (config != null) {
+ if (config.getId() > 0) {
+ config = entityManager.getReference(Configuration.class, config.getId());
+ plugin.setScheduledJobsConfiguration(config);
+ } else {
+ entityManager.persist(config);
+ needFlush = true;
+ }
+ }
+ if (needFlush) {
+ entityManager.flush(); // must be flushed to the DB so the JPQL update below works
+ }
+
+ // update all the fields except content
Query q = entityManager.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
q.setParameter("id", plugin.getId());
q.setParameter("name", plugin.getName());
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
index d5817a2..e1796bf 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
@@ -74,10 +74,11 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
getTransactionManager().begin();
em = getEntityManager();
- Query q = em.createQuery("SELECT p FROM Plugin p WHERE p.name LIKE 'serverplugintest%'");
+ Query q = em
+ .createQuery("SELECT p FROM Plugin p LEFT JOIN FETCH p.pluginConfiguration LEFT JOIN FETCH p.scheduledJobsConfiguration WHERE p.name LIKE 'serverplugintest%'");
List<Plugin> doomed = q.getResultList();
for (Plugin plugin : doomed) {
- em.remove(plugin);
+ em.remove(em.getReference(Plugin.class, plugin.getId()));
}
getTransactionManager().commit();
@@ -207,17 +208,70 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(true);
assert !pluginNames.contains(p1.getName()) : pluginNames;
assert !pluginNames.contains(p2.getName()) : pluginNames;
+ }
+
+ public void testReRegisterPlugins() throws Exception {
+
+ PluginStatusType status;
+
+ status = this.serverPluginsBean.getServerPluginStatus(TEST_PLUGIN_NAME_PREFIX + "1");
+ assert status == null;
+ status = this.serverPluginsBean.getServerPluginStatus(TEST_PLUGIN_NAME_PREFIX + "2");
+ assert status == null;
+
+ Plugin p1 = registerPlugin(1);
+ Plugin p2 = registerPlugin(2);
+
+ status = this.serverPluginsBean.getServerPluginStatus(p1.getName());
+ assert status == PluginStatusType.INSTALLED;
+ status = this.serverPluginsBean.getServerPluginStatus(p2.getName());
+ assert status == PluginStatusType.INSTALLED;
- // re-install them - need to implement this feature
- // this.serverPluginsBean.enableServerPlugins(getOverlord(), ids);
- // pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
- // assert pluginNames.contains(p1.getName()) : pluginNames;
- // assert pluginNames.contains(p2.getName()) : pluginNames;
- // assert undeployed.get(0).getStatus() == PluginStatusType.INSTALLED;
- // assert undeployed.get(1).getStatus() == PluginStatusType.INSTALLED;
- // pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
- // assert !pluginNames.contains(p1.getName()) : pluginNames;
- // assert !pluginNames.contains(p2.getName()) : pluginNames;
+ List<Integer> ids = new ArrayList<Integer>(2);
+ ids.add(p1.getId());
+ ids.add(p2.getId());
+ List<Plugin> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
+ assert undeployed.size() == 2 : undeployed;
+ assert undeployed.contains(p1) : undeployed;
+ assert undeployed.contains(p2) : undeployed;
+ assert undeployed.get(0).getStatus() == PluginStatusType.DELETED;
+ assert undeployed.get(0).getPluginConfiguration() == null; // undeploy should have removed this
+ assert undeployed.get(0).getScheduledJobsConfiguration() == null; // undeploy should have removed this
+ assert undeployed.get(1).getStatus() == PluginStatusType.DELETED;
+ assert undeployed.get(1).getPluginConfiguration() == null; // undeploy should have removed this
+ assert undeployed.get(1).getScheduledJobsConfiguration() == null; // undeploy should have removed this
+
+ List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
+ assert !pluginNames.contains(p1.getName()) : "deleted plugins should not be returned even here" + pluginNames;
+ assert !pluginNames.contains(p2.getName()) : "deleted plugins should not be returned even here" + pluginNames;
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(true);
+ assert !pluginNames.contains(p1.getName()) : pluginNames;
+ assert !pluginNames.contains(p2.getName()) : pluginNames;
+
+ // purge them completely from the DB to prepare to re-register them
+ this.serverPluginsBean.purgeServerPlugin(getOverlord(), p1.getName());
+ this.serverPluginsBean.purgeServerPlugin(getOverlord(), p2.getName());
+
+ // we just purged the database, make sure our entity ID's are all zero, since the original IDs are gone
+ p1.setId(0);
+ p2.setId(0);
+ p1.setPluginConfiguration(p1.getPluginConfiguration().deepCopy(false));
+ p2.setPluginConfiguration(p2.getPluginConfiguration().deepCopy(false));
+ p1.setScheduledJobsConfiguration(p1.getScheduledJobsConfiguration().deepCopy(false));
+ p2.setScheduledJobsConfiguration(p2.getScheduledJobsConfiguration().deepCopy(false));
+
+ // re-register them now
+ Plugin p1again = this.serverPluginsBean.registerServerPlugin(getOverlord(), p1, null);
+ Plugin p2again = this.serverPluginsBean.registerServerPlugin(getOverlord(), p2, null);
+
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(true);
+ assert pluginNames.contains(p1.getName()) : pluginNames;
+ assert pluginNames.contains(p2.getName()) : pluginNames;
+ assert p1again.getStatus() == PluginStatusType.INSTALLED;
+ assert p2again.getStatus() == PluginStatusType.INSTALLED;
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
+ assert !pluginNames.contains(p1.getName()) : pluginNames;
+ assert !pluginNames.contains(p2.getName()) : pluginNames;
}
private Plugin registerPlugin(int index) throws Exception {
commit 45180dcd79713f2f29e7051b2f1bed396dce9d2b
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sat Nov 21 10:42:18 2009 -0500
do not attempt to register plugins that were previously undeployed.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index 552179f..67ffc53 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -56,6 +56,11 @@ import org.rhq.core.util.MessageDigestGenerator;
@Entity
@NamedQueries( {
//
+ @NamedQuery(name = Plugin.QUERY_GET_STATUS_BY_NAME_AND_TYPE, query = "" //
+ + " SELECT p.status " //
+ + " FROM Plugin AS p " //
+ + " WHERE p.name = :name AND p.deployment = :type "), //
+
@NamedQuery(name = Plugin.QUERY_GET_NAMES_BY_ENABLED_AND_TYPE, query = "" //
+ " SELECT p.name " //
+ " FROM Plugin AS p " //
@@ -224,6 +229,7 @@ public class Plugin implements Serializable {
public static final String QUERY_FIND_BY_NAME = "Plugin.findByName";
public static final String QUERY_FIND_BY_IDS_AND_TYPE = "Plugin.findByIdsAndType";
public static final String QUERY_GET_NAMES_BY_ENABLED_AND_TYPE = "Plugin.findByEnabledAndType";
+ public static final String QUERY_GET_STATUS_BY_NAME_AND_TYPE = "Plugin.getStatusByNameAndType";
public static final String UPDATE_ALL_BUT_CONTENT = "Plugin.updateAllButContent";
public static final String UPDATE_PLUGINS_ENABLED_BY_IDS = "Plugin.updatePluginsEnabledByIds";
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index 7e3ad25..8ab3171 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -73,12 +73,22 @@ public class PluginTest extends AbstractEJB3Test {
plugin.setHelp(null);
plugin.setContent(content);
+ Query q = em.createNamedQuery(Plugin.QUERY_GET_STATUS_BY_NAME_AND_TYPE);
+ q.setParameter("name", plugin.getName());
+ q.setParameter("type", plugin.getDeployment());
+ assert q.getResultList().size() == 0; // not in the db yet
+
em.persist(plugin);
id = plugin.getId();
assert id > 0;
assert plugin.getPluginConfiguration().getId() > 0 : "did not persist config";
assert plugin.getScheduledJobsConfiguration().getId() > 0 : "did not persist jobs config";
+ q = em.createNamedQuery(Plugin.QUERY_GET_STATUS_BY_NAME_AND_TYPE);
+ q.setParameter("name", plugin.getName());
+ q.setParameter("type", plugin.getDeployment());
+ assert ((PluginStatusType) q.getSingleResult()) == PluginStatusType.INSTALLED;
+
plugin = em.find(Plugin.class, id);
assert plugin != null;
assert plugin.getId() == id;
@@ -117,7 +127,7 @@ public class PluginTest extends AbstractEJB3Test {
getTransactionManager().begin();
em = getEntityManager();
- Query q = em.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
+ q = em.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
q.setParameter("id", id); // same as the one we just persisted
q.setParameter("name", name);
q.setParameter("path", path);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
index a172719..6bd8c0f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
@@ -53,6 +53,7 @@ import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.core.domain.plugin.PluginStatusType;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.jdbc.JDBCUtil;
import org.rhq.core.util.stream.StreamUtil;
@@ -175,8 +176,17 @@ public class ServerPluginScanner {
}
ServerPluginsLocal serverPluginsManager = LookupUtil.getServerPlugins();
- SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
- serverPluginsManager.registerPlugin(subjectManager.getOverlord(), plugin, pluginFile);
+
+ // see if this plugin has been deleted previously; if so, don't register and delete the file
+ PluginStatusType status = serverPluginsManager.getServerPluginStatus(pluginName);
+ if (PluginStatusType.DELETED == status) {
+ log.warn("Plugin file [" + pluginFile + "] has been detected but that plugin with name [" + pluginName
+ + "] was previously undeployed. Will not re-register that plugin and the file will be deleted.");
+ pluginFile.delete();
+ } else {
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ serverPluginsManager.registerServerPlugin(subjectManager.getOverlord(), plugin, pluginFile);
+ }
} catch (Exception e) {
log.error("Failed to register RHQ plugin file [" + pluginFile + "]", e);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 577ea92..67d5efd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -121,7 +121,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return descriptor;
}
- public List<String> getPluginNamesByEnabled(boolean enabled) {
+ public List<String> getServerPluginNamesByEnabled(boolean enabled) {
Query query = entityManager.createNamedQuery(Plugin.QUERY_GET_NAMES_BY_ENABLED_AND_TYPE);
query.setParameter("enabled", Boolean.valueOf(enabled));
query.setParameter("type", PluginDeploymentType.SERVER);
@@ -134,7 +134,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return; // nothing to do
}
- serverPluginsBean.setPluginEnabledFlag(subject, pluginIds, true);
+ serverPluginsBean.setServerPluginEnabledFlag(subject, pluginIds, true);
// only restart the master if it was started to begin with
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
@@ -150,7 +150,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return new ArrayList<Plugin>(); // nothing to do
}
- serverPluginsBean.setPluginEnabledFlag(subject, pluginIds, false);
+ serverPluginsBean.setServerPluginEnabledFlag(subject, pluginIds, false);
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
@@ -188,7 +188,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return new ArrayList<Plugin>(); // nothing to do
}
- serverPluginsBean.setPluginEnabledFlag(subject, pluginIds, false);
+ serverPluginsBean.setServerPluginEnabledFlag(subject, pluginIds, false);
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
@@ -238,7 +238,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
@RequiredPermission(Permission.MANAGE_SETTINGS)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
- public void setPluginEnabledFlag(Subject subject, List<Integer> pluginIds, boolean enabled) throws Exception {
+ public void setServerPluginEnabledFlag(Subject subject, List<Integer> pluginIds, boolean enabled) throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
return; // nothing to do
}
@@ -255,20 +255,21 @@ public class ServerPluginsBean implements ServerPluginsLocal {
@RequiredPermission(Permission.MANAGE_SETTINGS)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
- public void setPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status) throws Exception {
+ public void setServerPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status)
+ throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
return; // nothing to do
}
List<Plugin> plugins = getServerPluginsById(pluginIds);
for (Plugin plugin : plugins) {
plugin.setStatus(status);
- updatePluginExceptContent(subject, plugin);
+ updateServerPluginExceptContent(subject, plugin);
}
return;
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
- public Plugin registerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception {
+ public Plugin registerServerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception {
if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
throw new IllegalArgumentException("Plugin [" + plugin.getName()
@@ -302,9 +303,14 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
if (plugin.getId() == 0) {
+ PluginStatusType status = getServerPluginStatus(plugin.getName());
+ if (PluginStatusType.DELETED == status) {
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
+ + "], it has been previously marked as deleted.");
+ }
entityManager.persist(plugin);
} else {
- plugin = updatePluginExceptContent(subject, plugin);
+ plugin = updateServerPluginExceptContent(subject, plugin);
}
if (pluginFile != null) {
@@ -318,11 +324,18 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
- public Plugin updatePluginExceptContent(Subject subject, Plugin plugin) throws Exception {
+ public Plugin updateServerPluginExceptContent(Subject subject, Plugin plugin) throws Exception {
+
// this method is here because we need a way to update the plugin's information
// without blowing away the content data. Because we do not want to load the
// content blob in memory, the plugin's content field will be null - if we were
// to entityManager.merge that plugin POJO, it would null out that blob column.
+
+ if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
+ throw new IllegalArgumentException("Plugin [" + plugin.getName()
+ + "] must be a server plugin to be updated");
+ }
+
if (plugin.getId() == 0) {
throw new IllegalArgumentException("Plugin must already exist to update it");
} else {
@@ -349,6 +362,19 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return plugin;
}
+ public PluginStatusType getServerPluginStatus(String pluginName) {
+ Query q = entityManager.createNamedQuery(Plugin.QUERY_GET_STATUS_BY_NAME_AND_TYPE);
+ q.setParameter("name", pluginName);
+ q.setParameter("type", PluginDeploymentType.SERVER);
+ PluginStatusType status;
+ try {
+ status = (PluginStatusType) q.getSingleResult();
+ } catch (NoResultException nre) {
+ status = null; // doesn't exist in the DB, tell the caller this by returning null
+ }
+ return status;
+ }
+
/**
* This will write the contents of the given plugin file to the database.
* This will assume the MD5 in the database is already correct, so this
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index 528d87c..68afc0e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -70,7 +70,7 @@ public interface ServerPluginsLocal {
* if <code>false</code>, return only the names of plugins that are disabled.
* @return list of plugin names that match the enabled criteria
*/
- List<String> getPluginNamesByEnabled(boolean enabled);
+ List<String> getServerPluginNamesByEnabled(boolean enabled);
/**
* Enables the plugins and restarts the server plugin container.
@@ -110,7 +110,7 @@ public interface ServerPluginsLocal {
* @param enabled the value of the enabled flag for the plugins
* @throws if failed to update a plugin
*/
- void setPluginEnabledFlag(Subject subject, List<Integer> pluginIds, boolean enabled) throws Exception;
+ void setServerPluginEnabledFlag(Subject subject, List<Integer> pluginIds, boolean enabled) throws Exception;
/**
* Sets the status flag in the database but does NOT restart the server plugin container.
@@ -123,7 +123,7 @@ public interface ServerPluginsLocal {
* @param enabled the value of the enabled flag for the plugins
* @throws if failed to update one of the plugins
*/
- void setPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status) throws Exception;
+ void setServerPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status) throws Exception;
/**
* Registers the given plugin to the database.
@@ -134,7 +134,7 @@ public interface ServerPluginsLocal {
* @return the plugin after being persisted
* @throws Exception if failed to fully register the plugin
*/
- Plugin registerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception;
+ Plugin registerServerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception;
/**
* Given a plugin that already exists, this will update that plugin's data in the database,
@@ -146,5 +146,15 @@ public interface ServerPluginsLocal {
* @return the updated plugin
* @throws Exception if the plugin did not already exist or an error occurred that caused the update to fail
*/
- public Plugin updatePluginExceptContent(Subject subject, Plugin plugin) throws Exception;
+ Plugin updateServerPluginExceptContent(Subject subject, Plugin plugin) throws Exception;
+
+ /**
+ * Given the name of a server plugin, this will return the status of that plugin.
+ * Use this to determine if a plugin has been deleted or not.
+ *
+ * @param pluginName the name of the plugin whose status is to be returned.
+ * @return the status of the plugin, to indicate if the plugin has been deleted or is installed.
+ * <code>null</code> indicates an unknown plugin.
+ */
+ PluginStatusType getServerPluginStatus(String pluginName);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index 40bb776..8ebabd4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -357,7 +357,7 @@ public class MasterServerPluginContainer {
* @return names of "blacklisted" plugins that should not be loaded
*/
protected List<String> getDisabledPluginNames() {
- List<String> disabledPlugins = LookupUtil.getServerPlugins().getPluginNamesByEnabled(false);
+ List<String> disabledPlugins = LookupUtil.getServerPlugins().getServerPluginNamesByEnabled(false);
return disabledPlugins;
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
index 3301ba0..d5817a2 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
@@ -46,6 +46,9 @@ import org.rhq.enterprise.server.util.LookupUtil;
*/
@Test
public class ServerPluginsBeanTest extends AbstractEJB3Test {
+
+ private static final String TEST_PLUGIN_NAME_PREFIX = "serverplugintest";
+
private ServerPluginsLocal serverPluginsBean;
@BeforeMethod
@@ -96,10 +99,10 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
public void testGetPlugins() throws Exception {
Plugin p1 = registerPlugin(1);
Plugin p2 = registerPlugin(2);
- List<String> pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(true);
assert pluginNames.contains(p1.getName()) : pluginNames;
assert pluginNames.contains(p2.getName()) : pluginNames;
- pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert !pluginNames.contains(p1.getName()) : pluginNames;
assert !pluginNames.contains(p2.getName()) : pluginNames;
@@ -144,19 +147,19 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
assert disabled.contains(p2) : disabled;
assert disabled.get(0).getStatus() == PluginStatusType.INSTALLED; // still installed
assert disabled.get(1).getStatus() == PluginStatusType.INSTALLED; // still installed
- List<String> pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert pluginNames.contains(p1.getName()) : pluginNames;
assert pluginNames.contains(p2.getName()) : pluginNames;
- pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(true);
assert !pluginNames.contains(p1.getName()) : pluginNames;
assert !pluginNames.contains(p2.getName()) : pluginNames;
// re-enable them
this.serverPluginsBean.enableServerPlugins(getOverlord(), ids);
- pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(true);
assert pluginNames.contains(p1.getName()) : pluginNames;
assert pluginNames.contains(p2.getName()) : pluginNames;
- pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert !pluginNames.contains(p1.getName()) : pluginNames;
assert !pluginNames.contains(p2.getName()) : pluginNames;
@@ -173,9 +176,21 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
public void testUndeployPlugins() throws Exception {
+ PluginStatusType status;
+
+ status = this.serverPluginsBean.getServerPluginStatus(TEST_PLUGIN_NAME_PREFIX + "1");
+ assert status == null;
+ status = this.serverPluginsBean.getServerPluginStatus(TEST_PLUGIN_NAME_PREFIX + "2");
+ assert status == null;
+
Plugin p1 = registerPlugin(1);
Plugin p2 = registerPlugin(2);
+ status = this.serverPluginsBean.getServerPluginStatus(p1.getName());
+ assert status == PluginStatusType.INSTALLED;
+ status = this.serverPluginsBean.getServerPluginStatus(p2.getName());
+ assert status == PluginStatusType.INSTALLED;
+
List<Integer> ids = new ArrayList<Integer>(2);
ids.add(p1.getId());
ids.add(p2.getId());
@@ -186,10 +201,10 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
assert undeployed.get(0).getStatus() == PluginStatusType.DELETED;
assert undeployed.get(1).getStatus() == PluginStatusType.DELETED;
- List<String> pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert !pluginNames.contains(p1.getName()) : "deleted plugins should not be returned even here" + pluginNames;
assert !pluginNames.contains(p2.getName()) : "deleted plugins should not be returned even here" + pluginNames;
- pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(true);
assert !pluginNames.contains(p1.getName()) : pluginNames;
assert !pluginNames.contains(p2.getName()) : pluginNames;
@@ -206,12 +221,12 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
}
private Plugin registerPlugin(int index) throws Exception {
- Plugin plugin = new Plugin(0, "serverplugintest" + index, "path", "displayName", true,
+ Plugin plugin = new Plugin(0, TEST_PLUGIN_NAME_PREFIX + index, "path", "displayName", true,
PluginStatusType.INSTALLED, "description", "help", "md5", "version", "ampsVersion",
PluginDeploymentType.SERVER, createPluginConfiguration(), createScheduledJobsConfiguration(), System
.currentTimeMillis(), System.currentTimeMillis());
- plugin = this.serverPluginsBean.registerPlugin(getOverlord(), plugin, null);
+ plugin = this.serverPluginsBean.registerServerPlugin(getOverlord(), plugin, null);
assert plugin.getId() > 0;
assert plugin.isEnabled() == true;
assert plugin.getDeployment() == PluginDeploymentType.SERVER;
commit 26c981d4720dbb65e02ea9ae5994d0888e8275c5
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 20 18:20:27 2009 -0500
do not stream plugins to filesystem if the database flagged it as deleted
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
index d6cf6fe..a172719 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
@@ -353,7 +353,7 @@ public class ServerPluginScanner {
// get all the plugins
ps = conn.prepareStatement("SELECT NAME, PATH, MD5, MTIME, VERSION FROM " + Plugin.TABLE_NAME
- + " WHERE DEPLOYMENT = 'SERVER'");
+ + " WHERE DEPLOYMENT = 'SERVER' AND STATUS = 'INSTALLED' ");
rs = ps.executeQuery();
while (rs.next()) {
String name = rs.getString(1);
@@ -451,7 +451,7 @@ public class ServerPluginScanner {
// write all our updated plugins to the file system
ps = conn.prepareStatement("SELECT CONTENT FROM " + Plugin.TABLE_NAME
- + " WHERE DEPLOYMENT = 'SERVER' AND NAME = ?");
+ + " WHERE DEPLOYMENT = 'SERVER' AND STATUS = 'INSTALLED' AND NAME = ?");
for (Plugin plugin : updatedPlugins) {
File file = new File(this.getServerPluginDir(), plugin.getPath());
@@ -516,8 +516,9 @@ public class ServerPluginScanner {
ResultSet rs = null;
TransactionManager tm = null;
- String sql = "UPDATE " + Plugin.TABLE_NAME
- + " SET CONTENT = ?, MD5 = ?, MTIME = ?, PATH = ? WHERE DEPLOYMENT = 'SERVER' AND NAME = ?";
+ String sql = "UPDATE "
+ + Plugin.TABLE_NAME
+ + " SET CONTENT = ?, MD5 = ?, MTIME = ?, PATH = ? WHERE DEPLOYMENT = 'SERVER' AND STATUS = 'INSTALLED' AND NAME = ?";
// if 'different' is true, give bogus data so the plugin deployer will think the plugin on the file system is new
String md5 = (!different) ? MessageDigestGenerator.getDigestString(file) : "TO BE UPDATED";
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index bfd828d..577ea92 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -284,6 +284,10 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
if (existingPlugin != null) {
+ if (existingPlugin.getStatus() == PluginStatusType.DELETED) {
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
+ + "], it has been marked as deleted");
+ }
Plugin obsolete = ServerPluginDescriptorUtil.determineObsoletePlugin(plugin, existingPlugin);
if (obsolete == existingPlugin) { // yes use == for reference equality
newOrUpdated = true;
commit 487407253bff60da59588b7bc814e6d14b0fb04c
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 20 17:47:29 2009 -0500
add the ability to mark a plugin DELETED. add authz to server plugin SLSB calls. add tests
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index 6f6f12b..8f466be 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -22,7 +22,7 @@
<properties>
<scm.module.path>modules/core/dbutils/</scm.module.path>
- <db.schema.version>2.69</db.schema.version>
+ <db.schema.version>2.69.1</db.schema.version>
</properties>
<dependencies>
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/amps-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/amps-schema.xml
index 5120803..dbc4a19 100644
--- a/modules/core/dbutils/src/main/scripts/dbsetup/amps-schema.xml
+++ b/modules/core/dbutils/src/main/scripts/dbsetup/amps-schema.xml
@@ -12,6 +12,7 @@
<column name="VERSION" size="200" type="VARCHAR2" required="false"/>
<column name="AMPS_VERSION" size="16" type="VARCHAR2" required="false"/>
<column name="ENABLED" type="BOOLEAN" required="true"/>
+ <column name="STATUS" size="16" type="VARCHAR2" required="true"/>
<column name="HELP" type="CLOB" required="false"/>
<column name="PATH" size="500" type="VARCHAR2" required="true"/>
<column name="MD5" size="100" type="VARCHAR2" required="true"/>
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 4cc035a..07831eb 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -2172,6 +2172,17 @@
</schema-directSQL>
</schemaSpec>
+ <schemaSpec version="2.69.1">
+ <!-- add the new column that indicates if this is plugin has been deleted -->
+ <schema-addColumn table="RHQ_PLUGIN" column="STATUS" columnType="VARCHAR2" precision="16"/>
+ <schema-directSQL>
+ <statement desc="Updating existing plugins with status of INSTALLED">
+ UPDATE RHQ_PLUGIN SET STATUS = 'INSTALLED'
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_PLUGIN" column="STATUS" nullable="FALSE"/>
+ </schemaSpec>
+
</dbupgrade>
</target>
</project>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index 2b3913d..552179f 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -59,7 +59,7 @@ import org.rhq.core.util.MessageDigestGenerator;
@NamedQuery(name = Plugin.QUERY_GET_NAMES_BY_ENABLED_AND_TYPE, query = "" //
+ " SELECT p.name " //
+ " FROM Plugin AS p " //
- + " WHERE p.enabled = :enabled AND p.deployment = :type"), //
+ + " WHERE p.enabled = :enabled AND p.deployment = :type AND p.status = 'INSTALLED' "), //
// this query does not load the content blob, but loads everything else
@NamedQuery(name = Plugin.QUERY_FIND_BY_IDS_AND_TYPE, query = "" //
@@ -69,6 +69,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.path, " //
+ " p.displayName, " //
+ " p.enabled, " //
+ + " p.status, " //
+ " p.description, " //
+ " p.help, " //
+ " p.md5, " //
@@ -82,7 +83,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " FROM Plugin AS p " //
+ " LEFT JOIN p.pluginConfiguration " //
+ " LEFT JOIN p.scheduledJobsConfiguration " //
- + " WHERE p.id IN (:ids) AND p.deployment = :type"), //
+ + " WHERE p.id IN (:ids) AND p.deployment = :type AND p.status = 'INSTALLED' "), //
// this query does not load the content blob, but loads everything else
@NamedQuery(name = Plugin.QUERY_FIND_BY_NAME, query = "" //
@@ -92,6 +93,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.path, " //
+ " p.displayName, " //
+ " p.enabled, " //
+ + " p.status, " //
+ " p.description, " //
+ " p.help, " //
+ " p.md5, " //
@@ -105,7 +107,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " FROM Plugin AS p " //
+ " LEFT JOIN p.pluginConfiguration " //
+ " LEFT JOIN p.scheduledJobsConfiguration " //
- + " WHERE p.name=:name"), //
+ + " WHERE p.name=:name AND p.status = 'INSTALLED' "), //
// this query does not load the content blob, but loads everything else
@NamedQuery(name = Plugin.QUERY_FIND_ALL_AGENT, query = "" //
@@ -115,6 +117,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.path, " //
+ " p.displayName, " //
+ " p.enabled, " //
+ + " p.status, " //
+ " p.description, " //
+ " p.help, " //
+ " p.md5, " //
@@ -128,7 +131,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " FROM Plugin AS p " //
+ " LEFT JOIN p.pluginConfiguration " //
+ " LEFT JOIN p.scheduledJobsConfiguration " //
- + " WHERE p.deployment = 'AGENT'"), //
+ + " WHERE p.deployment = 'AGENT' AND p.status = 'INSTALLED' "), //
// this query does not load the content blob, but loads everything else
@NamedQuery(name = Plugin.QUERY_FIND_ALL_SERVER, query = "" //
@@ -138,6 +141,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.path, " //
+ " p.displayName, " //
+ " p.enabled, " //
+ + " p.status, " //
+ " p.description, " //
+ " p.help, " //
+ " p.md5, " //
@@ -151,7 +155,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " FROM Plugin AS p " //
+ " LEFT JOIN p.pluginConfiguration " //
+ " LEFT JOIN p.scheduledJobsConfiguration " //
- + " WHERE p.deployment = 'SERVER'"), //
+ + " WHERE p.deployment = 'SERVER' AND p.status = 'INSTALLED' "), //
// this query does not update the content blob or ctime
@NamedQuery(name = Plugin.UPDATE_ALL_BUT_CONTENT, query = "" //
@@ -160,6 +164,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.displayName = :displayName, " //
+ " p.description = :description, " //
+ " p.enabled = :enabled, " //
+ + " p.status = :status, " //
+ " p.help = :help, " //
+ " p.version = :version, " //
+ " p.ampsVersion = :ampsVersion," //
@@ -185,6 +190,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.path, " //
+ " p.displayName, " //
+ " p.enabled, " //
+ + " p.status, " //
+ " p.description, " //
+ " p.help, " //
+ " p.md5, " //
@@ -198,7 +204,8 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " FROM Plugin p " //
+ " LEFT JOIN p.pluginConfiguration " //
+ " LEFT JOIN p.scheduledJobsConfiguration " //
- + " WHERE p.name IN ( SELECT rt.plugin " //
+ + " WHERE p.status = 'INSTALLED' AND " //
+ + " p.name IN ( SELECT rt.plugin " //
+ " FROM Resource res " //
+ " JOIN res.resourceType rt " //
+ " WHERE ( rt.category = :resourceCategory OR :resourceCategory IS NULL ) " //
@@ -249,6 +256,10 @@ public class Plugin implements Serializable {
@Column(name = "ENABLED", nullable = false)
private boolean enabled = true;
+ @Column(name = "STATUS", nullable = false)
+ @Enumerated(EnumType.STRING)
+ private PluginStatusType status = PluginStatusType.INSTALLED;
+
@Column(name = "HELP", nullable = true)
private String help;
@@ -334,6 +345,7 @@ public class Plugin implements Serializable {
* @param path
* @param displayName
* @param enabled
+ * @param status
* @param description
* @param help
* @param md5
@@ -345,14 +357,16 @@ public class Plugin implements Serializable {
* @param ctime
* @param mtime
*/
- public Plugin(int id, String name, String path, String displayName, boolean enabled, String description,
- String help, String md5, String version, String ampsVersion, PluginDeploymentType deployment,
- Configuration pluginConfig, Configuration scheduledJobsConfig, long ctime, long mtime) {
+ public Plugin(int id, String name, String path, String displayName, boolean enabled, PluginStatusType status,
+ String description, String help, String md5, String version, String ampsVersion,
+ PluginDeploymentType deployment, Configuration pluginConfig, Configuration scheduledJobsConfig, long ctime,
+ long mtime) {
this.id = id;
this.name = name;
this.path = path;
this.displayName = displayName;
this.enabled = enabled;
+ this.status = status;
this.description = description;
this.help = help;
this.md5 = md5;
@@ -455,6 +469,17 @@ public class Plugin implements Serializable {
this.enabled = enabled;
}
+ public PluginStatusType getStatus() {
+ return status;
+ }
+
+ public void setStatus(PluginStatusType status) {
+ this.status = status;
+ if (this.status == PluginStatusType.DELETED) {
+ this.enabled = false;
+ }
+ }
+
public String getHelp() {
return help;
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/PluginStatusType.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/PluginStatusType.java
new file mode 100644
index 0000000..40fd9ab
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/PluginStatusType.java
@@ -0,0 +1,29 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin;
+
+/**
+ * Indicates if a plugin is installed or has been deleted.
+ *
+ * @author John Mazzitelli
+ */
+public enum PluginStatusType {
+ INSTALLED, DELETED
+}
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index 77d9312..7e3ad25 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -41,6 +41,7 @@ import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.core.domain.plugin.PluginStatusType;
import org.rhq.core.domain.test.AbstractEJB3Test;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.stream.StreamUtil;
@@ -58,12 +59,14 @@ public class PluginTest extends AbstractEJB3Test {
String path = "/test/Update";
String displayName = "Plugin Test - testUpdate";
boolean enabled = true;
+ PluginStatusType status = PluginStatusType.INSTALLED;
String md5 = "abcdef";
byte[] content = "the content is here".getBytes();
Plugin plugin = new Plugin(name, path);
plugin.setDisplayName(displayName);
plugin.setEnabled(enabled);
+ plugin.setStatus(status);
plugin.setMD5(md5);
plugin.setVersion(null);
plugin.setDescription(null);
@@ -83,6 +86,7 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.getPath().equals(path);
assert plugin.getDisplayName().equals(displayName);
assert plugin.isEnabled() == enabled;
+ assert plugin.getStatus() == PluginStatusType.INSTALLED;
assert plugin.getMD5().equals(md5);
assert plugin.getVersion() == null;
assert plugin.getDescription() == null;
@@ -119,6 +123,7 @@ public class PluginTest extends AbstractEJB3Test {
q.setParameter("path", path);
q.setParameter("displayName", displayName);
q.setParameter("enabled", enabled);
+ q.setParameter("status", status);
q.setParameter("md5", md5);
q.setParameter("version", version);
q.setParameter("ampsVersion", ampsVersion);
@@ -179,11 +184,13 @@ public class PluginTest extends AbstractEJB3Test {
String path = "/test/Persist";
String displayName = "Plugin Test - testPersist";
boolean enabled = true;
+ PluginStatusType status = PluginStatusType.INSTALLED;
String md5 = "abcdef";
Plugin plugin = new Plugin(name, path);
plugin.setDisplayName(displayName);
plugin.setEnabled(enabled);
+ plugin.setStatus(status);
plugin.setMD5(md5);
// the following are the only nullable fields
@@ -202,6 +209,7 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.getPath().equals(path);
assert plugin.getDisplayName().equals(displayName);
assert plugin.isEnabled() == enabled;
+ assert plugin.getStatus() == PluginStatusType.INSTALLED;
assert plugin.getMD5().equals(md5);
assert plugin.getVersion() == null;
assert plugin.getDescription() == null;
@@ -210,6 +218,17 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.getScheduledJobsConfiguration() == null;
assert plugin.getHelp() == null;
assert plugin.getContent() == null;
+
+ // side check - see that "deleting" a plugin also sets enabled to false
+ assert plugin.isEnabled() == true;
+ assert plugin.getStatus() == PluginStatusType.INSTALLED;
+ plugin.setStatus(PluginStatusType.DELETED);
+ assert plugin.getStatus() == PluginStatusType.DELETED;
+ assert plugin.isEnabled() == false;
+ plugin = em.merge(plugin);
+ assert plugin.getStatus() == PluginStatusType.DELETED;
+ assert plugin.isEnabled() == false;
+
} finally {
getTransactionManager().rollback();
}
@@ -334,6 +353,25 @@ public class PluginTest extends AbstractEJB3Test {
}
assert got_it : "findAll query failed to get our plugin";
+ // mark a plugin deleted - all of our queries should then never see it
+ plugin.setStatus(PluginStatusType.DELETED);
+ em.merge(plugin);
+
+ query = em.createNamedQuery(Plugin.QUERY_FIND_BY_NAME);
+ query.setParameter("name", name);
+ List<?> results = query.getResultList();
+ assert results.size() == 0;
+
+ query = em.createNamedQuery(Plugin.QUERY_FIND_BY_IDS_AND_TYPE);
+ query.setParameter("ids", Arrays.asList(Integer.valueOf(plugin.getId())));
+ query.setParameter("type", plugin.getDeployment());
+ results = query.getResultList();
+ assert results.size() == 0;
+
+ query = em.createNamedQuery(Plugin.QUERY_FIND_ALL_SERVER);
+ results = query.getResultList();
+ assert results.size() == 0;
+
} finally {
getTransactionManager().rollback();
}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
index 9fd46f2..cfc99cf 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
@@ -38,6 +38,7 @@ import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.gui.util.FacesContextUtility;
import org.rhq.core.gui.util.StringUtility;
+import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
import org.rhq.enterprise.server.authz.PermissionException;
@@ -79,9 +80,7 @@ public class InstalledPluginsUIBean {
scanner.scanAndRegister();
FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Done scanning for updated plugins.");
} catch (Exception e) {
- String err = "Failed to scan for updated plugins";
- log.error(err + " - Cause: " + e);
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, err, e);
+ processException("Failed to scan for updated plugins", e);
}
}
@@ -118,9 +117,7 @@ public class InstalledPluginsUIBean {
+ "]. A scan is required now in order to register it.");
FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "New plugin uploaded: " + newPluginFilename);
} catch (Exception e) {
- String err = "Failed to process uploaded plugin";
- log.error(err + " - Cause: " + e);
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, err, e);
+ processException("Failed to process uploaded plugin", e);
}
return;
@@ -132,8 +129,15 @@ public class InstalledPluginsUIBean {
for (Plugin selectedPlugin : selectedPlugins) {
selectedPluginNames.add(selectedPlugin.getName());
}
- serverPluginsBean.enableServerPlugins(getIds(selectedPlugins));
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Enabled server plugins: " + selectedPluginNames);
+
+ try {
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
+ serverPluginsBean.enableServerPlugins(subject, getIds(selectedPlugins));
+ FacesContextUtility
+ .addMessage(FacesMessage.SEVERITY_INFO, "Enabled server plugins: " + selectedPluginNames);
+ } catch (Exception e) {
+ processException("Failed to enable server plugins", e);
+ }
return;
}
@@ -143,8 +147,15 @@ public class InstalledPluginsUIBean {
for (Plugin selectedPlugin : selectedPlugins) {
selectedPluginNames.add(selectedPlugin.getName());
}
- serverPluginsBean.disableServerPlugins(getIds(selectedPlugins));
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Disabled server plugins: " + selectedPluginNames);
+
+ try {
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
+ serverPluginsBean.disableServerPlugins(subject, getIds(selectedPlugins));
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Disabled server plugins: "
+ + selectedPluginNames);
+ } catch (Exception e) {
+ processException("Failed to disable server plugins", e);
+ }
return;
}
@@ -154,8 +165,15 @@ public class InstalledPluginsUIBean {
for (Plugin selectedPlugin : selectedPlugins) {
selectedPluginNames.add(selectedPlugin.getName());
}
- serverPluginsBean.undeployServerPlugins(getIds(selectedPlugins));
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Undeployed server plugins: " + selectedPluginNames);
+
+ try {
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
+ serverPluginsBean.undeployServerPlugins(subject, getIds(selectedPlugins));
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Undeployed server plugins: "
+ + selectedPluginNames);
+ } catch (Exception e) {
+ processException("Failed to undeploy server plugins", e);
+ }
return;
}
@@ -193,4 +211,9 @@ public class InstalledPluginsUIBean {
+ "] does not have the proper permissions to view or manage plugins");
}
}
+
+ private void processException(String errMsg, Exception e) {
+ log.error(errMsg + ". Cause: " + ThrowableUtil.getAllMessages(e));
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, errMsg, e);
+ }
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
index fc4b6eb..d6cf6fe 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
@@ -176,7 +176,7 @@ public class ServerPluginScanner {
ServerPluginsLocal serverPluginsManager = LookupUtil.getServerPlugins();
SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
- serverPluginsManager.registerPlugin(subjectManager.getOverlord(), plugin, descriptor, pluginFile);
+ serverPluginsManager.registerPlugin(subjectManager.getOverlord(), plugin, pluginFile);
} catch (Exception e) {
log.error("Failed to register RHQ plugin file [" + pluginFile + "]", e);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 27234f8..bfd828d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -46,6 +46,8 @@ import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.core.domain.plugin.PluginStatusType;
+import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.core.util.jdbc.JDBCUtil;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.authz.RequiredPermission;
@@ -102,7 +104,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
public List<Plugin> getServerPluginsById(List<Integer> pluginIds) {
if (pluginIds == null || pluginIds.size() == 0) {
- return new ArrayList<Plugin>();
+ return new ArrayList<Plugin>(); // nothing to do
}
Query query = entityManager.createNamedQuery(Plugin.QUERY_FIND_BY_IDS_AND_TYPE);
query.setParameter("ids", pluginIds);
@@ -126,14 +128,29 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return query.getResultList();
}
- public void enableServerPlugins(List<Integer> pluginIds) {
- serverPluginsBean.setPluginEnabledFlag(pluginIds, true);
- LookupUtil.getServerPluginService().restartMasterPluginContainer();
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
+ public void enableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
+ if (pluginIds == null || pluginIds.size() == 0) {
+ return; // nothing to do
+ }
+
+ serverPluginsBean.setPluginEnabledFlag(subject, pluginIds, true);
+
+ // only restart the master if it was started to begin with
+ ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
+ if (serverPluginService.isMasterPluginContainerStarted()) {
+ serverPluginService.restartMasterPluginContainer();
+ }
return;
}
- public List<Plugin> disableServerPlugins(List<Integer> pluginIds) {
- serverPluginsBean.setPluginEnabledFlag(pluginIds, false);
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
+ public List<Plugin> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
+ if (pluginIds == null || pluginIds.size() == 0) {
+ return new ArrayList<Plugin>(); // nothing to do
+ }
+
+ serverPluginsBean.setPluginEnabledFlag(subject, pluginIds, false);
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
@@ -144,23 +161,34 @@ public class ServerPluginsBean implements ServerPluginsLocal {
Plugin doomedPlugin = entityManager.find(Plugin.class, pluginId);
if (doomedPlugin != null) {
doomedPlugins.add(doomedPlugin);
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
- if (pc != null) {
- try {
- pc.unschedulePluginJobs(doomedPlugin.getName());
- } catch (Exception e) {
- log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ if (master != null) {
+ AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
+ if (pc != null) {
+ try {
+ pc.unschedulePluginJobs(doomedPlugin.getName());
+ } catch (Exception e) {
+ log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ }
}
}
}
}
- serverPluginService.restartMasterPluginContainer();
+ // only restart if the master was started to begin with; otherwise, leave it down
+ if (master != null) {
+ serverPluginService.restartMasterPluginContainer();
+ }
+
return doomedPlugins;
}
- public List<Plugin> undeployServerPlugins(List<Integer> pluginIds) {
- serverPluginsBean.setPluginEnabledFlag(pluginIds, false);
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
+ public List<Plugin> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
+ if (pluginIds == null || pluginIds.size() == 0) {
+ return new ArrayList<Plugin>(); // nothing to do
+ }
+
+ serverPluginsBean.setPluginEnabledFlag(subject, pluginIds, false);
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
@@ -171,12 +199,14 @@ public class ServerPluginsBean implements ServerPluginsLocal {
Plugin doomedPlugin = entityManager.find(Plugin.class, pluginId);
if (doomedPlugin != null) {
doomedPlugins.add(doomedPlugin);
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
- if (pc != null) {
- try {
- pc.unschedulePluginJobs(doomedPlugin.getName());
- } catch (Exception e) {
- log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ if (master != null) {
+ AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
+ if (pc != null) {
+ try {
+ pc.unschedulePluginJobs(doomedPlugin.getName());
+ } catch (Exception e) {
+ log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ }
}
}
@@ -185,35 +215,65 @@ public class ServerPluginsBean implements ServerPluginsLocal {
// config can be set to the new cofig definition's default values.
doomedPlugin.setPluginConfiguration(null);
doomedPlugin.setScheduledJobsConfiguration(null);
-
- // TODO: this really won't do anything, our server plugin scanner will see it missing
- // and stream it back on the file system. Need to add a DELETED column to RHQ_PLUGIN
- // and call doomedPlugin.setDeleted(true). When deleted is true, our scanner can
- // skip writing the file to disk. All plugin queries should avoid returning
- // plugin rows that have deleted=true. Only then will removing it from the
- // file system as we do below actually help.
- File pluginDir = serverPluginService.getServerPluginsDirectory();
- File currentFile = new File(pluginDir, doomedPlugin.getPath());
- currentFile.delete();
+ doomedPlugin.setStatus(PluginStatusType.DELETED);
+
+ try {
+ File pluginDir = serverPluginService.getServerPluginsDirectory();
+ File currentFile = new File(pluginDir, doomedPlugin.getPath());
+ currentFile.delete();
+ } catch (Exception e) {
+ log.error("Failed to delete the undeployed plugin [" + doomedPlugin.getPath() + "]. Cause: "
+ + ThrowableUtil.getAllMessages(e));
+ }
}
}
- serverPluginService.restartMasterPluginContainer();
+ // only restart if the master was started to begin with; otherwise, leave it down
+ if (master != null) {
+ serverPluginService.restartMasterPluginContainer();
+ }
+
return doomedPlugins;
}
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
- public void setPluginEnabledFlag(List<Integer> pluginIds, boolean enabled) {
+ public void setPluginEnabledFlag(Subject subject, List<Integer> pluginIds, boolean enabled) throws Exception {
+ if (pluginIds == null || pluginIds.size() == 0) {
+ return; // nothing to do
+ }
Query q = entityManager.createNamedQuery(Plugin.UPDATE_PLUGINS_ENABLED_BY_IDS);
q.setParameter("ids", pluginIds);
q.setParameter("enabled", Boolean.valueOf(enabled));
- q.executeUpdate();
+ int count = q.executeUpdate();
+ if (count != pluginIds.size()) {
+ throw new Exception("Failed to update [" + pluginIds.size() + "] plugins. Count was [" + count + "]");
+ }
+
+ return;
+ }
+
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public void setPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status) throws Exception {
+ if (pluginIds == null || pluginIds.size() == 0) {
+ return; // nothing to do
+ }
+ List<Plugin> plugins = getServerPluginsById(pluginIds);
+ for (Plugin plugin : plugins) {
+ plugin.setStatus(status);
+ updatePluginExceptContent(subject, plugin);
+ }
return;
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
- public void registerPlugin(Subject subject, Plugin plugin, ServerPluginDescriptorType descriptor, File pluginFile)
- throws Exception {
+ public Plugin registerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception {
+
+ if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
+ throw new IllegalArgumentException("Plugin [" + plugin.getName()
+ + "] must be a server plugin to be registered");
+ }
Plugin existingPlugin = null;
boolean newOrUpdated = false;
@@ -240,7 +300,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (plugin.getId() == 0) {
entityManager.persist(plugin);
} else {
- plugin = updatePluginExceptContent(plugin);
+ plugin = updatePluginExceptContent(subject, plugin);
}
if (pluginFile != null) {
@@ -250,10 +310,11 @@ public class ServerPluginsBean implements ServerPluginsLocal {
log.debug("Updated plugin entity [" + plugin + "]");
}
- return;
+ return plugin;
}
- public Plugin updatePluginExceptContent(Plugin plugin) throws Exception {
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
+ public Plugin updatePluginExceptContent(Subject subject, Plugin plugin) throws Exception {
// this method is here because we need a way to update the plugin's information
// without blowing away the content data. Because we do not want to load the
// content blob in memory, the plugin's content field will be null - if we were
@@ -267,6 +328,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
q.setParameter("path", plugin.getPath());
q.setParameter("displayName", plugin.getDisplayName());
q.setParameter("enabled", plugin.isEnabled());
+ q.setParameter("status", plugin.getStatus());
q.setParameter("md5", plugin.getMD5());
q.setParameter("version", plugin.getVersion());
q.setParameter("ampsVersion", plugin.getAmpsVersion());
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index 64efe4d..528d87c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -8,6 +8,7 @@ import javax.persistence.NoResultException;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginStatusType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
@@ -40,7 +41,6 @@ public interface ServerPluginsLocal {
* Call this method to fill in that data that wasn't originally loaded.
*
* @param plugin
- *
* @return the same plugin, with the relationship data loaded
*/
Plugin getServerPluginRelationships(Plugin plugin);
@@ -49,7 +49,6 @@ public interface ServerPluginsLocal {
* Get a list of plugins from their IDs.
*
* @param pluginIds the IDs of the plugins to load.
- *
* @return plugins matching the given IDs
*/
List<Plugin> getServerPluginsById(List<Integer> pluginIds);
@@ -76,56 +75,76 @@ public interface ServerPluginsLocal {
/**
* Enables the plugins and restarts the server plugin container.
*
+ * @param subject user making the request
* @param pluginIds the plugins to be enabled
+ * @throws Exception if failed to disable a plugin
*/
- void enableServerPlugins(List<Integer> pluginIds);
+ void enableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
/**
* Disables the plugins and restarts the server plugin container.
*
+ * @param subject user making the request
* @param pluginIds the plugins to be disabled
- *
* @return the list of plugins that were disabled
+ * @throws Exception if failed to disable a plugin
*/
- List<Plugin> disableServerPlugins(List<Integer> pluginIds);
+ List<Plugin> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
/**
* Removes the plugin from the system and restarts the server plugin container.
*
+ * @param subject user making the request
* @param pluginIds
- *
* @return the list of plugins that were undeployed
+ * @throws Exception if failed to undeploy a plugin
*/
- List<Plugin> undeployServerPlugins(List<Integer> pluginIds);
+ List<Plugin> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
/**
* Turns on or off the enabled flag in the database but does NOT restart the server plugin container.
+ * This has "requires new" semantics, so the results are committed immediately upon return.
+ *
+ * @param subject user making the request
+ * @param pluginIds the plugins to be enabled
+ * @param enabled the value of the enabled flag for the plugins
+ * @throws if failed to update a plugin
+ */
+ void setPluginEnabledFlag(Subject subject, List<Integer> pluginIds, boolean enabled) throws Exception;
+
+ /**
+ * Sets the status flag in the database but does NOT restart the server plugin container.
+ * If the status is {@link PluginStatusType#DELETED}, the enabled flag is also flipped to <code>false</code>.
*
+ * This has "requires new" semantics, so the results are committed immediately upon return.
+ *
+ * @param subject user making the request
* @param pluginIds the plugins to be enabled
* @param enabled the value of the enabled flag for the plugins
+ * @throws if failed to update one of the plugins
*/
- void setPluginEnabledFlag(List<Integer> pluginIds, boolean enabled);
+ void setPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status) throws Exception;
/**
* Registers the given plugin to the database.
*
* @param subject the user that needs to have permissions to add a plugin to the system
* @param plugin the plugin definition
- * @param descriptor the plugin descriptor that was found in the plugin file
* @param pluginFile the actual plugin file itself
+ * @return the plugin after being persisted
* @throws Exception if failed to fully register the plugin
*/
- void registerPlugin(Subject subject, Plugin plugin, ServerPluginDescriptorType descriptor, File pluginFile)
- throws Exception;
+ Plugin registerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception;
/**
* Given a plugin that already exists, this will update that plugin's data in the database,
* except for the content, which is left as-is. If the plugin did not yet exist, an exception is thrown.
* You can use this to update the plugin's scheduled jobs configuration and plugin configuration.
*
+ * @param subject user making the request
* @param plugin existing plugin with updated data
* @return the updated plugin
* @throws Exception if the plugin did not already exist or an error occurred that caused the update to fail
*/
- public Plugin updatePluginExceptContent(Plugin plugin) throws Exception;
+ public Plugin updatePluginExceptContent(Subject subject, Plugin plugin) throws Exception;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
index 90639d2..8250c7d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
@@ -202,6 +202,7 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
q.setParameter("path", plugin.getPath());
q.setParameter("displayName", plugin.getDisplayName());
q.setParameter("enabled", plugin.isEnabled());
+ q.setParameter("status", plugin.getStatus());
q.setParameter("md5", plugin.getMD5());
q.setParameter("version", plugin.getVersion());
q.setParameter("ampsVersion", plugin.getAmpsVersion());
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
new file mode 100644
index 0000000..3301ba0
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
@@ -0,0 +1,254 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.hibernate.LazyInitializationException;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.core.domain.plugin.PluginStatusType;
+import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * @author John Mazzitelli
+ */
+@Test
+public class ServerPluginsBeanTest extends AbstractEJB3Test {
+ private ServerPluginsLocal serverPluginsBean;
+
+ @BeforeMethod
+ public void beforeMethod() {
+ TestGenericServerPluginService pluginService;
+ pluginService = new TestGenericServerPluginService();
+ prepareCustomServerPluginService(pluginService);
+
+ serverPluginsBean = LookupUtil.getServerPlugins();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() {
+
+ EntityManager em = null;
+
+ try {
+ unprepareServerPluginService();
+ } catch (Exception e) {
+ }
+
+ try {
+ getTransactionManager().begin();
+ em = getEntityManager();
+
+ Query q = em.createQuery("SELECT p FROM Plugin p WHERE p.name LIKE 'serverplugintest%'");
+ List<Plugin> doomed = q.getResultList();
+ for (Plugin plugin : doomed) {
+ em.remove(plugin);
+ }
+
+ getTransactionManager().commit();
+ em.close();
+ em = null;
+ } catch (Exception e) {
+ try {
+ System.out.println("CANNOT CLEAN UP TEST: Cause: " + e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+ } finally {
+ if (null != em) {
+ em.close();
+ }
+ }
+ }
+
+ public void testGetPlugins() throws Exception {
+ Plugin p1 = registerPlugin(1);
+ Plugin p2 = registerPlugin(2);
+ List<String> pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ assert pluginNames.contains(p1.getName()) : pluginNames;
+ assert pluginNames.contains(p2.getName()) : pluginNames;
+ pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ assert !pluginNames.contains(p1.getName()) : pluginNames;
+ assert !pluginNames.contains(p2.getName()) : pluginNames;
+
+ Plugin plugin = this.serverPluginsBean.getServerPlugin(p1.getName());
+ assert plugin.getId() == p1.getId() : plugin;
+ assert plugin.getName().equals(p1.getName()) : plugin;
+ assetLazyInitializationException(plugin);
+
+ plugin = this.serverPluginsBean.getServerPluginRelationships(plugin);
+ assert plugin.getPluginConfiguration() != null;
+ assert plugin.getScheduledJobsConfiguration() != null;
+ assert plugin.getPluginConfiguration().equals(p1.getPluginConfiguration());
+ assert plugin.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration());
+
+ List<Plugin> plugins = this.serverPluginsBean.getServerPlugins();
+ assert plugins.contains(p1) : plugins;
+ assert plugins.contains(p2) : plugins;
+ assetLazyInitializationException(plugins.get(0));
+ assetLazyInitializationException(plugins.get(1));
+
+ List<Integer> ids = new ArrayList<Integer>(2);
+ ids.add(p1.getId());
+ ids.add(p2.getId());
+ plugins = this.serverPluginsBean.getServerPluginsById(ids);
+ assert plugins.size() == 2 : plugins;
+ assert plugins.contains(p1) : plugins;
+ assert plugins.contains(p2) : plugins;
+ assetLazyInitializationException(plugins.get(0));
+ assetLazyInitializationException(plugins.get(1));
+ }
+
+ public void testDisableEnablePlugins() throws Exception {
+ Plugin p1 = registerPlugin(1);
+ Plugin p2 = registerPlugin(2);
+
+ List<Integer> ids = new ArrayList<Integer>(2);
+ ids.add(p1.getId());
+ ids.add(p2.getId());
+ List<Plugin> disabled = this.serverPluginsBean.disableServerPlugins(getOverlord(), ids);
+ assert disabled.size() == 2 : disabled;
+ assert disabled.contains(p1) : disabled;
+ assert disabled.contains(p2) : disabled;
+ assert disabled.get(0).getStatus() == PluginStatusType.INSTALLED; // still installed
+ assert disabled.get(1).getStatus() == PluginStatusType.INSTALLED; // still installed
+ List<String> pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ assert pluginNames.contains(p1.getName()) : pluginNames;
+ assert pluginNames.contains(p2.getName()) : pluginNames;
+ pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ assert !pluginNames.contains(p1.getName()) : pluginNames;
+ assert !pluginNames.contains(p2.getName()) : pluginNames;
+
+ // re-enable them
+ this.serverPluginsBean.enableServerPlugins(getOverlord(), ids);
+ pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ assert pluginNames.contains(p1.getName()) : pluginNames;
+ assert pluginNames.contains(p2.getName()) : pluginNames;
+ pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ assert !pluginNames.contains(p1.getName()) : pluginNames;
+ assert !pluginNames.contains(p2.getName()) : pluginNames;
+
+ // make sure none of these enable/disable settings lost our config
+ Plugin plugin = this.serverPluginsBean.getServerPlugin(p1.getName());
+ plugin = this.serverPluginsBean.getServerPluginRelationships(plugin);
+ assert plugin.getPluginConfiguration() != null; // no LazyInitException should be thrown!
+ assert plugin.getPluginConfiguration().equals(p1.getPluginConfiguration());
+ plugin = this.serverPluginsBean.getServerPlugin(p2.getName());
+ plugin = this.serverPluginsBean.getServerPluginRelationships(plugin);
+ assert plugin.getPluginConfiguration() != null; // no LazyInitException should be thrown!
+ assert plugin.getPluginConfiguration().equals(p1.getPluginConfiguration());
+ }
+
+ public void testUndeployPlugins() throws Exception {
+
+ Plugin p1 = registerPlugin(1);
+ Plugin p2 = registerPlugin(2);
+
+ List<Integer> ids = new ArrayList<Integer>(2);
+ ids.add(p1.getId());
+ ids.add(p2.getId());
+ List<Plugin> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
+ assert undeployed.size() == 2 : undeployed;
+ assert undeployed.contains(p1) : undeployed;
+ assert undeployed.contains(p2) : undeployed;
+ assert undeployed.get(0).getStatus() == PluginStatusType.DELETED;
+ assert undeployed.get(1).getStatus() == PluginStatusType.DELETED;
+
+ List<String> pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ assert !pluginNames.contains(p1.getName()) : "deleted plugins should not be returned even here" + pluginNames;
+ assert !pluginNames.contains(p2.getName()) : "deleted plugins should not be returned even here" + pluginNames;
+ pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ assert !pluginNames.contains(p1.getName()) : pluginNames;
+ assert !pluginNames.contains(p2.getName()) : pluginNames;
+
+ // re-install them - need to implement this feature
+ // this.serverPluginsBean.enableServerPlugins(getOverlord(), ids);
+ // pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ // assert pluginNames.contains(p1.getName()) : pluginNames;
+ // assert pluginNames.contains(p2.getName()) : pluginNames;
+ // assert undeployed.get(0).getStatus() == PluginStatusType.INSTALLED;
+ // assert undeployed.get(1).getStatus() == PluginStatusType.INSTALLED;
+ // pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ // assert !pluginNames.contains(p1.getName()) : pluginNames;
+ // assert !pluginNames.contains(p2.getName()) : pluginNames;
+ }
+
+ private Plugin registerPlugin(int index) throws Exception {
+ Plugin plugin = new Plugin(0, "serverplugintest" + index, "path", "displayName", true,
+ PluginStatusType.INSTALLED, "description", "help", "md5", "version", "ampsVersion",
+ PluginDeploymentType.SERVER, createPluginConfiguration(), createScheduledJobsConfiguration(), System
+ .currentTimeMillis(), System.currentTimeMillis());
+
+ plugin = this.serverPluginsBean.registerPlugin(getOverlord(), plugin, null);
+ assert plugin.getId() > 0;
+ assert plugin.isEnabled() == true;
+ assert plugin.getDeployment() == PluginDeploymentType.SERVER;
+ assert plugin.getStatus() == PluginStatusType.INSTALLED;
+ assert plugin.getPluginConfiguration() != null;
+ assert plugin.getScheduledJobsConfiguration() != null;
+ return plugin;
+ }
+
+ private void assetLazyInitializationException(Plugin plugin) {
+ try {
+ plugin.getPluginConfiguration().toString();
+ assert false : "Should have thrown a lazy-initialization exception - we didn't load config";
+ } catch (LazyInitializationException ok) {
+ }
+ try {
+ plugin.getScheduledJobsConfiguration().toString();
+ assert false : "Should have thrown a lazy-initialization exception - we didn't load config";
+ } catch (LazyInitializationException ok) {
+ }
+ }
+
+ private Configuration createPluginConfiguration() {
+ Configuration config = new Configuration();
+ config.put(new PropertySimple("simpleprop1", "simpleprop1value"));
+ return config;
+ }
+
+ private Configuration createScheduledJobsConfiguration() {
+ Configuration config = new Configuration();
+ PropertyMap map = new PropertyMap("jobname");
+ config.put(map);
+ map.put(new PropertySimple("methodName", "methodNameValue"));
+ return config;
+ }
+
+ private Subject getOverlord() {
+ return LookupUtil.getSubjectManager().getOverlord();
+ }
+}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
index 2d30403..592a3d9 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
@@ -29,6 +29,7 @@ import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.core.domain.plugin.PluginStatusType;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
@@ -195,10 +196,10 @@ public class TestGenericServerPluginService extends ServerPluginService implemen
File pluginFile = new File(env.getPluginUrl().toURI());
Plugin plugin = new Plugin(0, env.getPluginName(), pluginFile.getName(), pluginDescriptor
- .getDisplayName(), true, pluginDescriptor.getDescription(), "", MessageDigestGenerator
- .getDigestString(pluginFile), pluginDescriptor.getVersion(), pluginDescriptor.getVersion(),
- PluginDeploymentType.SERVER, pluginConfig, scheduledJobsConfig, System.currentTimeMillis(), System
- .currentTimeMillis());
+ .getDisplayName(), true, PluginStatusType.INSTALLED, pluginDescriptor.getDescription(), "",
+ MessageDigestGenerator.getDigestString(pluginFile), pluginDescriptor.getVersion(), pluginDescriptor
+ .getVersion(), PluginDeploymentType.SERVER, pluginConfig, scheduledJobsConfig, System
+ .currentTimeMillis(), System.currentTimeMillis());
return plugin;
} catch (Exception e) {
throw new RuntimeException(e);
commit d191decc1328210999f7ace3be051dde164b29f9
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 20 14:52:19 2009 -0500
out out tabs! fix formatting
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 3e12bad..4cc035a 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -1484,39 +1484,39 @@
</schema-directSQL>
<schema-addColumn table="RHQ_RAW_CONFIG" column="CONFIG_ID" columnType="INTEGER"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="CONFIG_ID"
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="CONFIG_ID"
columnType="INTEGER"
nullable="false"/>
<schema-addColumn table="RHQ_RAW_CONFIG" column="PATH" columnType="VARCHAR2"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="PATH"
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="PATH"
columnType="VARCHAR2"
precision="512"/>
<schema-addColumn table="RHQ_RAW_CONFIG" column="CONTENTS" columnType="BLOB"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="CONTENTS"
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="CONTENTS"
columnType="BLOB"
nullable="false"/>
<schema-addColumn table="RHQ_RAW_CONFIG" column="SHA256" columnType="VARCHAR2"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="SHA256"
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="SHA256"
columnType="VARCHAR2"
- precision="64"
+ precision="64"
nullable="false"/>
<schema-addColumn table="RHQ_RAW_CONFIG" column="CTIME" columnType="LONG"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="CTIME"
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="CTIME"
columnType="LONG"
nullable="false"/>
<schema-addColumn table="RHQ_RAW_CONFIG" column="MTIME" columnType="LONG"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="MTIME"
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="MTIME"
columnType="LONG"
nullable="false"/>
@@ -2024,62 +2024,60 @@
<schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
<schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
</schemaSpec>
-
- <!-- Generic tagging support -->
+
+ <!-- Generic tagging support -->
<schemaSpec version="2.64">
- <schema-createSequence name="RHQ_TAG_ID_SEQ" initial="10001" />
- <schema-directSQL>
- <statement>
- CREATE TABLE RHQ_TAG ( ID INTEGER PRIMARY KEY )
- </statement>
- </schema-directSQL>
- <schema-alterColumn table="RHQ_TAG" column="ID" nullable="false" />
- <schema-addColumn table="RHQ_TAG" column="NAME" precision="200" columnType="VARCHAR2" />
- <schema-alterColumn table="RHQ_TAG" column="NAME" nullable="false" />
- <schema-addColumn table="RHQ_TAG" column="DESCRIPTION" precision="500" columnType="VARCHAR2" />
- </schemaSpec>
-
- <!-- Distribution Files -->
- <schemaSpec version="2.65">
- <schema-directSQL>
- <statement>
- CREATE TABLE RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID INTEGER )
- </statement>
- </schema-directSQL>
- <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="DISTRIBUTION_ID" nullable="false" />
- <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" precision="256" columnType="VARCHAR2" />
- <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" nullable="false" />
- <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" precision="64" columnType="VARCHAR2" />
- <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" nullable="false" />
- <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" columnType="LONG" />
- <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" nullable="false" />
- <schema-directSQL>
- <statement targetDBVendor="postgresql">
- CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
- ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
- </statement>
- <statement targetDBVendor="oracle">
- CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
- ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
- </statement>
- </schema-directSQL>
- <schema-directSQL>
- <statement targetDBVendor="oracle">
- ALTER TABLE RHQ_DISTRIBUTION_FILE
- ADD CONSTRAINT RHQ_DIST_FILE_FKEY
- FOREIGN KEY ( DISTRIBUTION_ID)
- REFERENCES RHQ_DISTRIBUTION ( ID )
- </statement>
- <statement targetDBVendor="postgresql">
- ALTER TABLE RHQ_DISTRIBUTION_FILE
- ADD CONSTRAINT RHQ_DIST_FILE_FKEY
- FOREIGN KEY ( DISTRIBUTION_ID)
- REFERENCES RHQ_DISTRIBUTION ( ID )
- </statement>
- </schema-directSQL>
-
+ <schema-createSequence name="RHQ_TAG_ID_SEQ" initial="10001" />
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_TAG ( ID INTEGER PRIMARY KEY )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_TAG" column="ID" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="NAME" precision="200" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_TAG" column="NAME" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="DESCRIPTION" precision="500" columnType="VARCHAR2" />
</schemaSpec>
+ <!-- Distribution Files -->
+ <schemaSpec version="2.65">
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID INTEGER )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="DISTRIBUTION_ID" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" precision="256" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" precision="64" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" columnType="LONG" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" nullable="false" />
+ <schema-directSQL>
+ <statement targetDBVendor="postgresql">
+ CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
+ ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
+ </statement>
+ <statement targetDBVendor="oracle">
+ CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
+ ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
+ </statement>
+ </schema-directSQL>
+ <schema-directSQL>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_DISTRIBUTION_FILE
+ ADD CONSTRAINT RHQ_DIST_FILE_FKEY
+ FOREIGN KEY ( DISTRIBUTION_ID)
+ REFERENCES RHQ_DISTRIBUTION ( ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_DISTRIBUTION_FILE
+ ADD CONSTRAINT RHQ_DIST_FILE_FKEY
+ FOREIGN KEY ( DISTRIBUTION_ID)
+ REFERENCES RHQ_DISTRIBUTION ( ID )
+ </statement>
+ </schema-directSQL>
+ </schemaSpec>
<!-- RHQ_REPO_TAG_MAP -->
<schemaSpec version="2.66">
@@ -2123,23 +2121,23 @@
</schemaSpec>
<schemaSpec version="2.68">
- <schema-createSequence name="RHQ_DISTRIBUTION_FILE_SEQ" initial="10001" />
+ <schema-createSequence name="RHQ_DISTRIBUTION_FILE_SEQ" initial="10001" />
<schema-directSQL>
- <statement>
- ALTER TABLE RHQ_DISTRIBUTION_FILE DROP CONSTRAINT RHQ_DISTRIBUTION_FILE_PKEY
- </statement>
+ <statement>
+ ALTER TABLE RHQ_DISTRIBUTION_FILE DROP CONSTRAINT RHQ_DISTRIBUTION_FILE_PKEY
+ </statement>
</schema-directSQL>
-
+
<schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="ID" columnType="INTEGER" />
<schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="ID" nullable="false" />
-
- <schema-directSQL>
- <statement>
- ALTER TABLE RHQ_DISTRIBUTION_FILE ALTER COLUMN ID SET DEFAULT NEXTVAL('RHQ_DISTRIBUTION_FILE_ID_SEQ')
- </statement>
+
+ <schema-directSQL>
+ <statement>
+ ALTER TABLE RHQ_DISTRIBUTION_FILE ALTER COLUMN ID SET DEFAULT NEXTVAL('RHQ_DISTRIBUTION_FILE_ID_SEQ')
+ </statement>
</schema-directSQL>
- </schemaSpec>
-
+ </schemaSpec>
+
<!-- Add support for server-side plugins -->
<schemaSpec version="2.69">
<!-- add the new column that indicates if this is deployed on the SERVER or AGENT -->
commit ccefb1d4df35a99cc4b241781668662380f65625
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 20 13:58:48 2009 -0500
update schema catalog for eclipse usrs
diff --git a/etc/eclipse-tools/templates/schema.xmlcatalog b/etc/eclipse-tools/templates/schema.xmlcatalog
index 3107878..d4054bb 100644
--- a/etc/eclipse-tools/templates/schema.xmlcatalog
+++ b/etc/eclipse-tools/templates/schema.xmlcatalog
@@ -2,6 +2,10 @@
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<uri name="urn:xmlns:rhq-configuration" uri="platform:/resource/rhq/modules/core/client-api/src/main/resources/rhq-configuration.xsd"/>
<uri name="urn:xmlns:rhq-plugin" uri="platform:/resource/rhq/modules/core/client-api/src/main/resources/rhq-plugin.xsd"/>
-<uri name="urn:xmlns:rhq-serverplugin.content" uri="platform:/resource/rhq/modules/core/client-api/src/main/resources/rhq-serverplugin-content.xsd"/>
-<uri name="urn:xmlns:rhq-perspective" uri="platform:/resource/rhq/modules/core/client-api/src/main/resources/rhq-perspective.xsd"/>
+<uri name="urn:xmlns:rhq-contentsource-packagedetails" uri="platform:/resource/rhq/modules/enterprise/server/xml-schemas/src/main/resources/rhq-contentsource-packagedetails.xsd"/>
+<uri name="urn:xmlns:rhq-serverplugin" uri="platform:/resource/rhq/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd"/>
+<uri name="urn:xmlns:rhq-serverplugin.generic" uri="platform:/resource/rhq/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-generic.xsd"/>
+<uri name="urn:xmlns:rhq-serverplugin.alert" uri="platform:/resource/rhq/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-alert.xsd"/>
+<uri name="urn:xmlns:rhq-serverplugin.content" uri="platform:/resource/rhq/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-content.xsd"/>
+<uri name="urn:xmlns:rhq-serverplugin.perspective" uri="platform:/resource/rhq/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-perspective.xsd"/>
</catalog>
commit 984e31c191aaee7da559baa6e57d69577c9bf2c2
Merge: e6472fc... 1d180bf...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 20 09:57:46 2009 -0500
Merge branch 'pc' - this adds server-side plugin container UI and DB changes
Conflicts:
modules/core/dbutils/pom.xml
modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
diff --cc modules/core/dbutils/pom.xml
index b7b94ce,9ac94d7..6f6f12b
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@@ -22,7 -22,7 +22,7 @@@
<properties>
<scm.module.path>modules/core/dbutils/</scm.module.path>
- <db.schema.version>2.68</db.schema.version>
- <db.schema.version>2.66</db.schema.version>
++ <db.schema.version>2.69</db.schema.version>
</properties>
<dependencies>
diff --cc modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index 2564ff5,f477569..3e12bad
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@@ -2019,127 -2019,44 +2019,160 @@@
precision="255" />
</schemaSpec>
- <schemaSpec version="2.62.1">
- <schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
- <schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
+
+ <schemaSpec version="2.63">
+ <schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
+ <schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
+ </schemaSpec>
+
+ <!-- Generic tagging support -->
+ <schemaSpec version="2.64">
+ <schema-createSequence name="RHQ_TAG_ID_SEQ" initial="10001" />
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_TAG ( ID INTEGER PRIMARY KEY )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_TAG" column="ID" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="NAME" precision="200" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_TAG" column="NAME" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="DESCRIPTION" precision="500" columnType="VARCHAR2" />
+ </schemaSpec>
+
+ <!-- Distribution Files -->
+ <schemaSpec version="2.65">
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID INTEGER )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="DISTRIBUTION_ID" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" precision="256" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" precision="64" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" columnType="LONG" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" nullable="false" />
+ <schema-directSQL>
+ <statement targetDBVendor="postgresql">
+ CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
+ ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
+ </statement>
+ <statement targetDBVendor="oracle">
+ CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
+ ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
+ </statement>
+ </schema-directSQL>
+ <schema-directSQL>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_DISTRIBUTION_FILE
+ ADD CONSTRAINT RHQ_DIST_FILE_FKEY
+ FOREIGN KEY ( DISTRIBUTION_ID)
+ REFERENCES RHQ_DISTRIBUTION ( ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_DISTRIBUTION_FILE
+ ADD CONSTRAINT RHQ_DIST_FILE_FKEY
+ FOREIGN KEY ( DISTRIBUTION_ID)
+ REFERENCES RHQ_DISTRIBUTION ( ID )
+ </statement>
+ </schema-directSQL>
+
+ </schemaSpec>
+
+
+ <!-- RHQ_REPO_TAG_MAP -->
+ <schemaSpec version="2.66">
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_REPO_TAG_MAP ( REPO_ID INTEGER )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_REPO_TAG_MAP" column="REPO_ID" nullable="false" />
+ <schema-addColumn table="RHQ_REPO_TAG_MAP" column="TAG_ID" columnType="INTEGER" />
+ <schema-alterColumn table="RHQ_REPO_TAG_MAP" column="TAG_ID" nullable="false" />
+ <schema-directSQL>
+ <statement>
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD CONSTRAINT RHQ_REPO_TAG_MAP_KEY
+ PRIMARY KEY ( REPO_ID, TAG_ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD CONSTRAINT RHQ_REPO_TAG_MAP_REPO_ID_FKEY
+ FOREIGN KEY ( REPO_ID )
+ REFERENCES RHQ_REPO ( ID )
+ </statement>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD FOREIGN KEY ( REPO_ID )
+ REFERENCES RHQ_REPO ( ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD CONSTRAINT RHQ_REPO_TAG_MAP_TAG_ID_FKEY
+ FOREIGN KEY ( TAG_ID )
+ REFERENCES RHQ_TAG ( ID )
+ </statement>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD FOREIGN KEY ( TAG_ID )
+ REFERENCES RHQ_TAG ( ID )
+ </statement>
+ </schema-directSQL>
</schemaSpec>
+ <schemaSpec version="2.68">
+ <schema-createSequence name="RHQ_DISTRIBUTION_FILE_SEQ" initial="10001" />
+ <schema-directSQL>
+ <statement>
+ ALTER TABLE RHQ_DISTRIBUTION_FILE DROP CONSTRAINT RHQ_DISTRIBUTION_FILE_PKEY
+ </statement>
+ </schema-directSQL>
+
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="ID" columnType="INTEGER" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="ID" nullable="false" />
+
+ <schema-directSQL>
+ <statement>
+ ALTER TABLE RHQ_DISTRIBUTION_FILE ALTER COLUMN ID SET DEFAULT NEXTVAL('RHQ_DISTRIBUTION_FILE_ID_SEQ')
+ </statement>
+ </schema-directSQL>
+ </schemaSpec>
+
+ <!-- Add support for server-side plugins -->
- <schemaSpec version="2.66">
++ <schemaSpec version="2.69">
+ <!-- add the new column that indicates if this is deployed on the SERVER or AGENT -->
+ <schema-addColumn table="RHQ_PLUGIN" column="DEPLOYMENT" columnType="VARCHAR2" precision="8"/>
+ <schema-directSQL>
+ <statement desc="Updating existing plugins with default deployment of AGENT">
+ UPDATE RHQ_PLUGIN SET DEPLOYMENT = 'AGENT'
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_PLUGIN" column="DEPLOYMENT" nullable="FALSE"/>
+
+ <!-- add the new column that provides configuration to a plugin -->
+ <schema-addColumn table="RHQ_PLUGIN" column="PLUGIN_CONFIG_ID" columnType="INTEGER" />
+ <schema-directSQL>
+ <statement desc="Creating RHQ_PLUGIN foreign key relation to RHQ_CONFIG for plugin config">
+ ALTER TABLE RHQ_PLUGIN
+ ADD CONSTRAINT RHQ_PLUGIN_P_CFG_ID_FKEY
+ FOREIGN KEY (PLUGIN_CONFIG_ID)
+ REFERENCES RHQ_CONFIG (ID)
+ </statement>
+ </schema-directSQL>
+
+ <!-- add the new column that provides configuration to a plugin -->
+ <schema-addColumn table="RHQ_PLUGIN" column="JOBS_CONFIG_ID" columnType="INTEGER" />
+ <schema-directSQL>
+ <statement desc="Creating RHQ_PLUGIN foreign key relation to RHQ_CONFIG for scheduled jobs">
+ ALTER TABLE RHQ_PLUGIN
+ ADD CONSTRAINT RHQ_PLUGIN_JOBS_CFG_ID_FKEY
+ FOREIGN KEY (JOBS_CONFIG_ID)
+ REFERENCES RHQ_CONFIG (ID)
+ </statement>
+ </schema-directSQL>
+ </schemaSpec>
</dbupgrade>
</target>
commit 1d180bf7237480fe50ec0e860894d40444e0be4c
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 20 09:11:46 2009 -0500
have the sample plugin be disabled on discovery
diff --git a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
index 215e044..b5ab88f 100644
--- a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -5,7 +5,8 @@
description="A custom generic plugin."
package="org.custom"
version="1.0"
- apiVersion="2.0"
+ apiVersion="2.0"
+ disabledOnDiscovery="true"
xmlns="urn:xmlns:rhq-serverplugin.generic"
xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
xmlns:c="urn:xmlns:rhq-configuration">
commit 4d6fd45b76845c3db04397124ed84599e7cdbfc8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 20 09:03:01 2009 -0500
be able to tell the plugin container to initially disable the plugin when it is first discovered into the system.
default is to enable it immediately. but this allows a plugin to force a user to configure it before starting it.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
index 9b2196e..fc4b6eb 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
@@ -161,7 +161,7 @@ public class ServerPluginScanner {
Plugin plugin = new Plugin(pluginName, pluginFile.getName());
plugin.setDeployment(PluginDeploymentType.SERVER);
plugin.setDisplayName((displayName != null) ? displayName : pluginName);
- plugin.setEnabled(false); // initially disabled, user must configure it first before enabling
+ plugin.setEnabled(!descriptor.isDisabledOnDiscovery());
plugin.setDescription(descriptor.getDescription());
plugin.setMtime(pluginFile.lastModified());
plugin.setVersion(version.toString());
diff --git a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
index 9b79376..766fae4 100644
--- a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
+++ b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
@@ -147,20 +147,38 @@
</xs:documentation>
</xs:annotation>
</xs:attribute>
- <xs:attribute name="version" type="xs:string">
+ <xs:attribute name="version" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation>
The version of this plugin in an OSGI compatible format. (e.g. 2.0.4 or 3.1.beta2)
+ This attribute is optional - you can put the plugin version in the jar's manifest
+ in the Implementation-Version manifest entry. You must, however, provide a version
+ somewhere - either via the manifest or this attribute.
</xs:documentation>
</xs:annotation>
</xs:attribute>
- <xs:attribute name="apiVersion" type="xs:string">
+ <xs:attribute name="apiVersion" type="xs:string" use="optional">
<xs:annotation>
<xs:documentation>
The version of the server-side API this plugin requires in OSGI compatible format. (e.g. 2.0)
</xs:documentation>
</xs:annotation>
</xs:attribute>
+ <xs:attribute name="disabledOnDiscovery" type="xs:boolean" use="optional" default="false">
+ <xs:annotation>
+ <xs:documentation>
+ Indicates if the plugin should be disabled immediately when it is first detected by
+ the server. By default, all plugins will be enabled as soon as they are first detected
+ by the server. However, if you want to require the user to configure the plugin
+ first, before the plugin is ever deployed and run, then set this to true. Use this
+ when the default configuration for the plugin is not complete and user intervention
+ is required in order to fully complete the configuration before the plugin can run.
+ The user will be forced to edit the configuration (or, optionally, agree to the
+ default configuration as-is) of the plugin and then manually enable the plugin
+ before the plugin can finally run.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
</xs:complexType>
<xs:complexType name="ServerPluginComponentType">
diff --git a/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java b/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
index c3b70ea..692b244 100644
--- a/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
+++ b/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
@@ -70,6 +70,7 @@ public class ServerPluginDescriptorUtilTest {
assert descriptor.getDisplayName().equals("generic display");
assert descriptor.getDescription().equals("generic description");
assert descriptor.getPackage().equals("generic.package");
+ assert descriptor.isDisabledOnDiscovery() == false; // the default
HelpType help = descriptor.getHelp();
assert help != null;
@@ -135,6 +136,7 @@ public class ServerPluginDescriptorUtilTest {
assert descriptor.getDisplayName().equals("alert plugin display name");
assert descriptor.getDescription().equals("alert plugin wotgorilla?");
assert descriptor.getPackage().equals("org.alert.package.name.here");
+ assert descriptor.isDisabledOnDiscovery() == true;
ServerPluginComponentType pluginComponent = descriptor.getPluginComponent();
assert pluginComponent.getClazz().equals("alertPluginComponent");
diff --git a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-alert.xml b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-alert.xml
index 021030f..74b7ec0 100644
--- a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-alert.xml
+++ b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-alert.xml
@@ -6,6 +6,7 @@
displayName="alert plugin display name"
name="alert plugin name"
package="org.alert.package.name.here"
+ disabledOnDiscovery="true"
xmlns="urn:xmlns:rhq-serverplugin.alert"
xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
xmlns:c="urn:xmlns:rhq-configuration"
commit 36680ec88a2807d35e7eaff1bfc40379b9d3e992
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 20 01:21:43 2009 -0500
be able to enable and disable plugins - start undeploy coding, but it isn't complete.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index b414675..2b3913d 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -171,6 +171,12 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.mtime = :mtime " //
+ " WHERE p.id = :id"),
+ // this query is how you enable and disable plugins
+ @NamedQuery(name = Plugin.UPDATE_PLUGINS_ENABLED_BY_IDS, query = "" //
+ + "UPDATE Plugin p " //
+ + " SET p.enabled = :enabled " //
+ + " WHERE p.id IN (:ids)"),
+
// this query does not load the content blob, but loads everything else
@NamedQuery(name = Plugin.QUERY_FIND_BY_RESOURCE_TYPE_AND_CATEGORY, query = "" //
+ " SELECT new org.rhq.core.domain.plugin.Plugin( " //
@@ -212,6 +218,7 @@ public class Plugin implements Serializable {
public static final String QUERY_FIND_BY_IDS_AND_TYPE = "Plugin.findByIdsAndType";
public static final String QUERY_GET_NAMES_BY_ENABLED_AND_TYPE = "Plugin.findByEnabledAndType";
public static final String UPDATE_ALL_BUT_CONTENT = "Plugin.updateAllButContent";
+ public static final String UPDATE_PLUGINS_ENABLED_BY_IDS = "Plugin.updatePluginsEnabledByIds";
@Column(name = "ID", nullable = false)
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ")
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index df226b5..27234f8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -49,6 +49,9 @@ import org.rhq.core.domain.plugin.PluginDeploymentType;
import org.rhq.core.util.jdbc.JDBCUtil;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.authz.RequiredPermission;
+import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
@@ -129,25 +132,83 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return;
}
- public void disableServerPlugins(List<Integer> pluginIds) {
+ public List<Plugin> disableServerPlugins(List<Integer> pluginIds) {
serverPluginsBean.setPluginEnabledFlag(pluginIds, false);
- LookupUtil.getServerPluginService().restartMasterPluginContainer();
- return;
+
+ ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
+ MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
+
+ List<Plugin> doomedPlugins = new ArrayList<Plugin>();
+
+ for (Integer pluginId : pluginIds) {
+ Plugin doomedPlugin = entityManager.find(Plugin.class, pluginId);
+ if (doomedPlugin != null) {
+ doomedPlugins.add(doomedPlugin);
+ AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
+ if (pc != null) {
+ try {
+ pc.unschedulePluginJobs(doomedPlugin.getName());
+ } catch (Exception e) {
+ log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ }
+ }
+ }
+ }
+
+ serverPluginService.restartMasterPluginContainer();
+ return doomedPlugins;
}
- public void undeployServerPlugins(List<Integer> pluginIds) {
+ public List<Plugin> undeployServerPlugins(List<Integer> pluginIds) {
serverPluginsBean.setPluginEnabledFlag(pluginIds, false);
- // TODO: actually mark the plugins as deleted, remove their files
- LookupUtil.getServerPluginService().restartMasterPluginContainer();
- return;
+
+ ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
+ MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
+
+ List<Plugin> doomedPlugins = new ArrayList<Plugin>();
+
+ for (Integer pluginId : pluginIds) {
+ Plugin doomedPlugin = entityManager.find(Plugin.class, pluginId);
+ if (doomedPlugin != null) {
+ doomedPlugins.add(doomedPlugin);
+ AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
+ if (pc != null) {
+ try {
+ pc.unschedulePluginJobs(doomedPlugin.getName());
+ } catch (Exception e) {
+ log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ }
+ }
+
+ // if this plugin ever gets re-installed, let's support the use-case where the new plugin
+ // will have different config metadata. Here we null out the old config so the new
+ // config can be set to the new cofig definition's default values.
+ doomedPlugin.setPluginConfiguration(null);
+ doomedPlugin.setScheduledJobsConfiguration(null);
+
+ // TODO: this really won't do anything, our server plugin scanner will see it missing
+ // and stream it back on the file system. Need to add a DELETED column to RHQ_PLUGIN
+ // and call doomedPlugin.setDeleted(true). When deleted is true, our scanner can
+ // skip writing the file to disk. All plugin queries should avoid returning
+ // plugin rows that have deleted=true. Only then will removing it from the
+ // file system as we do below actually help.
+ File pluginDir = serverPluginService.getServerPluginsDirectory();
+ File currentFile = new File(pluginDir, doomedPlugin.getPath());
+ currentFile.delete();
+ }
+ }
+
+ serverPluginService.restartMasterPluginContainer();
+ return doomedPlugins;
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void setPluginEnabledFlag(List<Integer> pluginIds, boolean enabled) {
- List<Plugin> plugins = getServerPluginsById(pluginIds);
- for (Plugin plugin : plugins) {
- plugin.setEnabled(enabled);
- }
+ Query q = entityManager.createNamedQuery(Plugin.UPDATE_PLUGINS_ENABLED_BY_IDS);
+ q.setParameter("ids", pluginIds);
+ q.setParameter("enabled", Boolean.valueOf(enabled));
+ q.executeUpdate();
+ return;
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index eef03ee..64efe4d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -84,15 +84,19 @@ public interface ServerPluginsLocal {
* Disables the plugins and restarts the server plugin container.
*
* @param pluginIds the plugins to be disabled
+ *
+ * @return the list of plugins that were disabled
*/
- void disableServerPlugins(List<Integer> pluginIds);
+ List<Plugin> disableServerPlugins(List<Integer> pluginIds);
/**
* Removes the plugin from the system and restarts the server plugin container.
*
* @param pluginIds
+ *
+ * @return the list of plugins that were undeployed
*/
- void undeployServerPlugins(List<Integer> pluginIds);
+ List<Plugin> undeployServerPlugins(List<Integer> pluginIds);
/**
* Turns on or off the enabled flag in the database but does NOT restart the server plugin container.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index f8dd84d..3256bf5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -220,6 +220,26 @@ public abstract class AbstractTypeServerPluginContainer {
}
/**
+ * Unschedules any plugin jobs that are currently scheduled for the named plugin.
+ *
+ * Subclasses are free to extend this method to unschedule those additional plugin jobs
+ * they created, but must ensure they call this method so the global scheduled jobs get
+ * removed from the scheduler.
+ *
+ * Note that this is separate from the {@link #stop()} method because we never want
+ * to unschedule jobs since other plugin containers on other servers may be running
+ * and able to process the jobs. This method should only be called when a plugin
+ * is being disabled or removed.
+ *
+ * @throws Exception if failed to unschedule jobs
+ */
+ public void unschedulePluginJobs(String pluginName) throws Exception {
+ SchedulerLocal scheduler = LookupUtil.getSchedulerBean();
+ scheduler.resumeJobGroup(pluginName);
+ return;
+ }
+
+ /**
* This will be called when its time for this plugin container to create its plugin manager.
* Subclasses are free to override this if they need their own specialized plugin manager.
*
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index 8d4bf33..40bb776 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -255,6 +255,23 @@ public class MasterServerPluginContainer {
}
/**
+ * Given the name of a deployed plugin, this returns the plugin container that is hosting
+ * that plugin. If there is no plugin with the given name or that plugin is not
+ * loaded in any plugin container (e.g. when it is disabled), then <code>null</code> is returned.
+ *
+ * @param pluginName
+ * @return the plugin container that is managing the named plugin of <code>null</code>
+ */
+ public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainer(String pluginName) {
+ for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
+ if (null != pc.getPluginManager().getPluginEnvironment(pluginName)) {
+ return (T) pc;
+ }
+ }
+ return null;
+ }
+
+ /**
* Given a plugin's descriptor, this will return the plugin container that can manage the plugin.
*
* @param descriptor descriptor to identify a plugin whose container is to be returned
commit e8c2575caa8bc5ef094dc66abeff48e8ab9e9e60
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 19 23:34:44 2009 -0500
more coding to get info about plugins from the database. this also shows the configs in the server plugin details list as a prototype for how configs could look
diff --git a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
index e174c0e..699ac49 100644
--- a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
+++ b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
@@ -19,8 +19,11 @@
package org.custom;
-import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.enterprise.server.plugin.pc.ScheduledJobInvocationContext;
import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
/**
* A sample lifecycle listener for the sample generic plugin. This listener will be
@@ -51,8 +54,9 @@ public class MyLifecycleListener implements ServerPluginComponent {
System.out.println("The sample plugin scheduled job [myScheduledJobMethod1] has triggered!!! : " + this);
}
- public void myScheduledJobMethod2() throws Exception {
- System.out.println("The sample plugin scheduled job [myScheduledJobMethod2] has triggered!!! : " + this);
+ public void myScheduledJobMethod2(ScheduledJobInvocationContext invocation) throws Exception {
+ System.out.println("The sample plugin scheduled job [myScheduledJobMethod2] has triggered!!! : " + this
+ + " - CALLBACK DATA=" + invocation.getJobDefinition().getCallbackData());
}
@Override
@@ -63,7 +67,20 @@ public class MyLifecycleListener implements ServerPluginComponent {
StringBuilder str = new StringBuilder();
str.append("plugin-name=").append(this.context.getPluginEnvironment().getPluginName()).append(",");
- str.append("plugin-url=").append(this.context.getPluginEnvironment().getPluginUrl()); // do not append ,
+ str.append("plugin-url=").append(this.context.getPluginEnvironment().getPluginUrl()).append(",");
+ str.append("plugin-config=[").append(getPluginConfigurationString()).append(']'); // do not append ,
return str.toString();
}
+
+ private String getPluginConfigurationString() {
+ String results = "";
+ Configuration config = this.context.getPluginConfiguration();
+ for (PropertySimple prop : config.getSimpleProperties().values()) {
+ if (results.length() > 0) {
+ results += ", ";
+ }
+ results = results + prop.getName() + "=" + prop.getStringValue();
+ }
+ return results;
+ }
}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
index c6edb8d..f6eee0d 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
@@ -75,6 +75,7 @@ public class InstalledPluginUIBean {
} else {
ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
this.plugin = serverPluginsBean.getServerPlugin(pluginName);
+ this.plugin = serverPluginsBean.getServerPluginRelationships(this.plugin);
try {
ServerPluginDescriptorType descriptor = serverPluginsBean.getServerPluginDescriptor(pluginName);
this.pluginConfigurationDefinition = ConfigurationMetadataParser.parse("pc:" + pluginName, descriptor
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
index c6a5fc5..3921b8e 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
@@ -75,6 +75,26 @@
<h:outputText escape="false" value="<pre> #{InstalledPluginUIBean.plugin.help} </pre>"/>
</rich:panel>
+
+ <rich:panel>
+ <f:facet name="header">
+ <h:outputText value="Plugin Configuration"/>
+ </f:facet>
+ <onc:config
+ configurationDefinition="#{InstalledPluginUIBean.pluginConfigurationDefinition}"
+ configuration="#{InstalledPluginUIBean.plugin.pluginConfiguration}"
+ readOnly="true" />
+ </rich:panel>
+
+ <rich:panel>
+ <f:facet name="header">
+ <h:outputText value="Scheduled Jobs"/>
+ </f:facet>
+ <onc:config
+ configurationDefinition="#{InstalledPluginUIBean.scheduledJobsDefinition}"
+ configuration="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration}"
+ readOnly="true" />
+ </rich:panel>
</rich:panel>
</h:form>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index f843901..df226b5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -87,6 +87,16 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return plugin;
}
+ public Plugin getServerPluginRelationships(Plugin plugin) {
+ plugin = entityManager.find(Plugin.class, plugin.getId());
+
+ // force eager load
+ plugin.getPluginConfiguration().getProperties().size();
+ plugin.getScheduledJobsConfiguration().getProperties().size();
+
+ return plugin;
+ }
+
public List<Plugin> getServerPluginsById(List<Integer> pluginIds) {
if (pluginIds == null || pluginIds.size() == 0) {
return new ArrayList<Plugin>();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index d6ebc9a..eef03ee 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -32,6 +32,26 @@ public interface ServerPluginsLocal {
*/
Plugin getServerPlugin(String name);
+ /**
+ * Methods in this object that return plugins normally do not include
+ * the data from relationships with the plugin (for example, the
+ * plugin configuration and scheduled jobs related to the plugin).
+ *
+ * Call this method to fill in that data that wasn't originally loaded.
+ *
+ * @param plugin
+ *
+ * @return the same plugin, with the relationship data loaded
+ */
+ Plugin getServerPluginRelationships(Plugin plugin);
+
+ /**
+ * Get a list of plugins from their IDs.
+ *
+ * @param pluginIds the IDs of the plugins to load.
+ *
+ * @return plugins matching the given IDs
+ */
List<Plugin> getServerPluginsById(List<Integer> pluginIds);
/**
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index e3a3ba6..8d4bf33 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -302,7 +302,7 @@ public class MasterServerPluginContainer {
if (pluginFiles != null) {
- List<String> enabledPlugins = LookupUtil.getServerPlugins().getPluginNamesByEnabled(true);
+ List<String> disabledPlugins = getDisabledPluginNames();
for (File pluginFile : pluginFiles) {
if (pluginFile.getName().endsWith(".jar")) {
@@ -312,7 +312,7 @@ public class MasterServerPluginContainer {
ServerPluginDescriptorType descriptor;
descriptor = ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginUrl);
if (descriptor != null) {
- if (enabledPlugins.contains(descriptor.getName())) {
+ if (!disabledPlugins.contains(descriptor.getName())) {
log.debug("pre-loaded server plugin from URL: " + pluginUrl);
plugins.put(pluginUrl, descriptor);
} else {
@@ -333,6 +333,18 @@ public class MasterServerPluginContainer {
}
/**
+ * This will return a list of plugin names that represent all the plugins that are to be
+ * disabled. If a plugin jar is found on the filesystem, its plugin name should be checked with
+ * this "blacklist" if it its name is found, that plugin should not be loaded.
+ *
+ * @return names of "blacklisted" plugins that should not be loaded
+ */
+ protected List<String> getDisabledPluginNames() {
+ List<String> disabledPlugins = LookupUtil.getServerPlugins().getPluginNamesByEnabled(false);
+ return disabledPlugins;
+ }
+
+ /**
* Creates the individual plugin containers that can be used to deploy different plugin types.
*
* <p>This is protected to allow subclasses to override the PCs that are created by this service (mainly to support tests).</p>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index 1ad7dad..36fa5bd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -288,13 +288,8 @@ public class ServerPluginManager {
List<ScheduledJobDefinition> schedules;
try {
- // get the plugin data from the database
- ServerPluginsLocal serverPluginsManager = LookupUtil.getServerPlugins();
- Plugin plugin = serverPluginsManager.getServerPlugin(pluginName);
-
- // get the plugin configuration and scheduled jobs from the DB data
+ Plugin plugin = getPlugin(env);
plugnConfig = plugin.getPluginConfiguration();
-
Configuration scheduledJobsConfig = plugin.getScheduledJobsConfiguration();
schedules = ServerPluginDescriptorMetadataParser.getScheduledJobs(scheduledJobsConfig);
} catch (Exception e) {
@@ -307,6 +302,20 @@ public class ServerPluginManager {
}
/**
+ * Given a plugin environment, return its Plugin representation, which should also include
+ * the plugin configuration and scheduled jobs configuration.
+ *
+ * @param pluginEnv
+ * @return the Plugin object for the given plugin
+ */
+ protected Plugin getPlugin(ServerPluginEnvironment pluginEnv) {
+ // get the plugin data from the database
+ ServerPluginsLocal serverPluginsManager = LookupUtil.getServerPlugins();
+ Plugin plugin = serverPluginsManager.getServerPlugin(pluginEnv.getPluginName());
+ return plugin;
+ }
+
+ /**
* This will create a new {@link ServerPluginComponent} instance for that is used to
* initialize and shutdown a particular server plugin. If there is no plugin component
* configured for the given plugin, <code>null</code> is returned.
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
index b1888f4..2d30403 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
@@ -25,6 +25,11 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
@@ -32,6 +37,7 @@ import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
import org.rhq.enterprise.server.plugin.pc.ServerPluginManager;
import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorMetadataParser;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
@@ -87,6 +93,12 @@ public class TestGenericServerPluginService extends ServerPluginService implemen
return super.preloadAllPlugins();
}
}
+
+ @Override
+ protected List<String> getDisabledPluginNames() {
+ // in the real world, the db is checked for enable flag, here we say all plugins are enabled
+ return new ArrayList<String>();
+ }
}
/**
@@ -162,6 +174,38 @@ public class TestGenericServerPluginService extends ServerPluginService implemen
}
@Override
+ protected Plugin getPlugin(ServerPluginEnvironment env) {
+
+ try {
+ Configuration pluginConfig = null;
+ Configuration scheduledJobsConfig = null;
+ ConfigurationDefinition configDef;
+
+ ServerPluginDescriptorType pluginDescriptor = env.getPluginDescriptor();
+
+ configDef = ServerPluginDescriptorMetadataParser.getPluginConfigurationDefinition(pluginDescriptor);
+ if (configDef != null) {
+ pluginConfig = configDef.getDefaultTemplate().createConfiguration();
+ }
+
+ configDef = ServerPluginDescriptorMetadataParser.getScheduledJobsDefinition(pluginDescriptor);
+ if (configDef != null) {
+ scheduledJobsConfig = configDef.getDefaultTemplate().createConfiguration();
+ }
+
+ File pluginFile = new File(env.getPluginUrl().toURI());
+ Plugin plugin = new Plugin(0, env.getPluginName(), pluginFile.getName(), pluginDescriptor
+ .getDisplayName(), true, pluginDescriptor.getDescription(), "", MessageDigestGenerator
+ .getDigestString(pluginFile), pluginDescriptor.getVersion(), pluginDescriptor.getVersion(),
+ PluginDeploymentType.SERVER, pluginConfig, scheduledJobsConfig, System.currentTimeMillis(), System
+ .currentTimeMillis());
+ return plugin;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
protected ServerPluginComponent createServerPluginComponent(ServerPluginEnvironment environment)
throws Exception {
ServerPluginComponent component = super.createServerPluginComponent(environment);
commit 7a1e3dc0a0d18ab114dd8911ecafe4525e2a97d8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 19 20:12:14 2009 -0500
API to get configuration def for server plugins
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
index 84eeeea..c6edb8d 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
@@ -18,22 +18,27 @@
*/
package org.rhq.enterprise.gui.admin.plugin;
+import javax.faces.application.FacesMessage;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.rhq.core.clientapi.agent.metadata.ConfigurationMetadataParser;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
import org.rhq.core.gui.util.FacesContextUtility;
import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
import org.rhq.enterprise.server.authz.PermissionException;
import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
-import org.rhq.enterprise.server.resource.metadata.ResourceMetadataManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
* @author Greg Hinkle
+ * @author John Mazzitelli
*/
public class InstalledPluginUIBean {
private final Log log = LogFactory.getLog(InstalledPluginUIBean.class);
@@ -41,27 +46,47 @@ public class InstalledPluginUIBean {
public static final String MANAGED_BEAN_NAME = InstalledPluginUIBean.class.getSimpleName();
private Plugin plugin;
-
- private ResourceMetadataManagerLocal resourceMetadataManagerBean = LookupUtil.getResourceMetadataManager();
- private ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
+ private ConfigurationDefinition pluginConfigurationDefinition;
+ private ConfigurationDefinition scheduledJobsDefinition;
public InstalledPluginUIBean() {
- this.plugin = lookupPlugin();
+ lookupPlugin();
}
public Plugin getPlugin() {
return this.plugin;
}
- private Plugin lookupPlugin() {
+ public ConfigurationDefinition getPluginConfigurationDefinition() {
+ return this.pluginConfigurationDefinition;
+ }
+
+ public ConfigurationDefinition getScheduledJobsDefinition() {
+ return this.scheduledJobsDefinition;
+ }
+
+ private void lookupPlugin() {
hasPermission();
String pluginName = FacesContextUtility.getRequiredRequestParameter("plugin", String.class);
String pluginType = FacesContextUtility.getRequiredRequestParameter("pluginType", String.class);
PluginDeploymentType deploymentType = PluginDeploymentType.valueOf(pluginType);
if (deploymentType == PluginDeploymentType.AGENT) {
- return resourceMetadataManagerBean.getPlugin(pluginName);
+ this.plugin = LookupUtil.getResourceMetadataManager().getPlugin(pluginName);
} else {
- return serverPluginsBean.getServerPlugin(pluginName);
+ ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
+ this.plugin = serverPluginsBean.getServerPlugin(pluginName);
+ try {
+ ServerPluginDescriptorType descriptor = serverPluginsBean.getServerPluginDescriptor(pluginName);
+ this.pluginConfigurationDefinition = ConfigurationMetadataParser.parse("pc:" + pluginName, descriptor
+ .getPluginConfiguration());
+ this.scheduledJobsDefinition = ConfigurationMetadataParser.parse("jobs:" + pluginName, descriptor
+ .getScheduledJobs());
+ } catch (Exception e) {
+ String err = "Cannot determine what the plugin configuration or scheduled jobs configuration looks like";
+ log.error(err + " - Cause: " + e);
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, err, e);
+ return;
+ }
}
}
commit 903e7b5094b0c037f41f25deda1e6b32e0079827
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 19 19:17:53 2009 -0500
have master PC and its supporting classes access the DB to get plugin information
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index e94a0dd..b414675 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -56,6 +56,11 @@ import org.rhq.core.util.MessageDigestGenerator;
@Entity
@NamedQueries( {
//
+ @NamedQuery(name = Plugin.QUERY_GET_NAMES_BY_ENABLED_AND_TYPE, query = "" //
+ + " SELECT p.name " //
+ + " FROM Plugin AS p " //
+ + " WHERE p.enabled = :enabled AND p.deployment = :type"), //
+
// this query does not load the content blob, but loads everything else
@NamedQuery(name = Plugin.QUERY_FIND_BY_IDS_AND_TYPE, query = "" //
+ " SELECT new org.rhq.core.domain.plugin.Plugin( " //
@@ -205,6 +210,7 @@ public class Plugin implements Serializable {
public static final String QUERY_FIND_ALL_SERVER = "Plugin.findAllServer";
public static final String QUERY_FIND_BY_NAME = "Plugin.findByName";
public static final String QUERY_FIND_BY_IDS_AND_TYPE = "Plugin.findByIdsAndType";
+ public static final String QUERY_GET_NAMES_BY_ENABLED_AND_TYPE = "Plugin.findByEnabledAndType";
public static final String UPDATE_ALL_BUT_CONTENT = "Plugin.updateAllButContent";
@Column(name = "ID", nullable = false)
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
index 2dd973f..cbee6bc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
@@ -109,6 +109,22 @@ public class CoreServer extends ServiceMBeanSupport implements CoreServerMBean {
return serverHomeDir;
}
+ public File getJBossServerDataDir() {
+ MBeanServer mbs = getMBeanServer();
+ ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
+ Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
+ File serverDataDir = ((ServerConfig) mbean).getServerDataDir();
+ return serverDataDir;
+ }
+
+ public File getJBossServerTempDir() {
+ MBeanServer mbs = getMBeanServer();
+ ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
+ Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
+ File serverTempDir = ((ServerConfig) mbean).getServerTempDir();
+ return serverTempDir;
+ }
+
private MBeanServer getMBeanServer() {
return MBeanServerLocator.locateJBoss();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerMBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerMBean.java
index c471c37..108a0d5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerMBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerMBean.java
@@ -66,8 +66,22 @@ public interface CoreServerMBean extends ServiceMBean {
/**
* Where the JBoss Server Home directory is. Typically, this is something like:
- * {@link #getInstallDir() isntall-dir}/jbossas/server/default
+ * {@link #getInstallDir() install-dir}/jbossas/server/default
* @return jboss server home directory
*/
File getJBossServerHomeDir();
+
+ /**
+ * Where the JBoss Server Data directory is. Typically, this is something like:
+ * {@link #getInstallDir() install-dir}/jbossas/server/default/data
+ * @return jboss server home directory
+ */
+ File getJBossServerDataDir();
+
+ /**
+ * Where the JBoss Server Temp directory is. Typically, this is something like:
+ * {@link #getInstallDir() install-dir}/jbossas/server/default/tmp
+ * @return jboss server home directory
+ */
+ File getJBossServerTempDir();
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
index b22cab3..9b2196e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
@@ -49,6 +49,8 @@ import org.rhq.core.db.H2DatabaseType;
import org.rhq.core.db.OracleDatabaseType;
import org.rhq.core.db.PostgresqlDatabaseType;
import org.rhq.core.db.SQLServerDatabaseType;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
import org.rhq.core.util.MessageDigestGenerator;
@@ -57,6 +59,7 @@ import org.rhq.core.util.stream.StreamUtil;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorMetadataParser;
import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
@@ -164,6 +167,8 @@ public class ServerPluginScanner {
plugin.setVersion(version.toString());
plugin.setAmpsVersion(descriptor.getApiVersion());
plugin.setMD5(MessageDigestGenerator.getDigestString(pluginFile));
+ plugin.setPluginConfiguration(getDefaultPluginConfiguration(descriptor));
+ plugin.setScheduledJobsConfiguration(getDefaultScheduledJobsConfiguration(descriptor));
if (descriptor.getHelp() != null && !descriptor.getHelp().getContent().isEmpty()) {
plugin.setHelp(String.valueOf(descriptor.getHelp().getContent().get(0)));
@@ -178,6 +183,24 @@ public class ServerPluginScanner {
return;
}
+ private Configuration getDefaultPluginConfiguration(ServerPluginDescriptorType descriptor) throws Exception {
+ Configuration defaults = null;
+ ConfigurationDefinition def = ServerPluginDescriptorMetadataParser.getPluginConfigurationDefinition(descriptor);
+ if (def != null) {
+ defaults = def.getDefaultTemplate().createConfiguration();
+ }
+ return defaults;
+ }
+
+ private Configuration getDefaultScheduledJobsConfiguration(ServerPluginDescriptorType descriptor) throws Exception {
+ Configuration defaults = null;
+ ConfigurationDefinition def = ServerPluginDescriptorMetadataParser.getScheduledJobsDefinition(descriptor);
+ if (def != null) {
+ defaults = def.getDefaultTemplate().createConfiguration();
+ }
+ return defaults;
+ }
+
/**
* Scans the plugin directory and updates our cache of known plugin files.
* This will purge any old plugins that are deemed obsolete.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 424b85a..f843901 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -22,6 +22,7 @@ package org.rhq.enterprise.server.plugin;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
+import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -96,6 +97,22 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return query.getResultList();
}
+ public ServerPluginDescriptorType getServerPluginDescriptor(String pluginName) throws Exception {
+ Plugin plugin = getServerPlugin(pluginName);
+ File pluginsDir = LookupUtil.getServerPluginService().getServerPluginsDirectory();
+ File pluginJar = new File(pluginsDir, plugin.getPath());
+ URL url = pluginJar.toURI().toURL();
+ ServerPluginDescriptorType descriptor = ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(url);
+ return descriptor;
+ }
+
+ public List<String> getPluginNamesByEnabled(boolean enabled) {
+ Query query = entityManager.createNamedQuery(Plugin.QUERY_GET_NAMES_BY_ENABLED_AND_TYPE);
+ query.setParameter("enabled", Boolean.valueOf(enabled));
+ query.setParameter("type", PluginDeploymentType.SERVER);
+ return query.getResultList();
+ }
+
public void enableServerPlugins(List<Integer> pluginIds) {
serverPluginsBean.setPluginEnabledFlag(pluginIds, true);
LookupUtil.getServerPluginService().restartMasterPluginContainer();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index af67646..d6ebc9a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -35,6 +35,25 @@ public interface ServerPluginsLocal {
List<Plugin> getServerPluginsById(List<Integer> pluginIds);
/**
+ * Given a plugin name, returns the descriptor for that plugin.
+ *
+ * @param pluginName
+ * @return descriptor parsed from the file in the plugin jar
+ * @throws Exception if the descriptor could not be retrieved or parsed for the given plugin
+ */
+ ServerPluginDescriptorType getServerPluginDescriptor(String pluginName) throws Exception;
+
+ /**
+ * Returns a list of plugin names for only those server plugins whose
+ * enabled flag is equal to the given parameter.
+ *
+ * @param enabled if <code>true</code>, return only the names of plugins that are enabled;
+ * if <code>false</code>, return only the names of plugins that are disabled.
+ * @return list of plugin names that match the enabled criteria
+ */
+ List<String> getPluginNamesByEnabled(boolean enabled);
+
+ /**
* Enables the plugins and restarts the server plugin container.
*
* @param pluginIds the plugins to be enabled
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index f6ed889..f8dd84d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -32,7 +32,6 @@ import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.CronScheduleType;
import org.rhq.enterprise.server.xmlschema.PeriodicScheduleType;
import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
-import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorMetadataParser;
/**
* The abstract superclass for all plugin containers of the different {@link ServerPluginType plugin types}.
@@ -199,8 +198,7 @@ public abstract class AbstractTypeServerPluginContainer {
String pluginName = pluginEnv.getPluginName();
try {
- // TODO: we need to read the config from the DB, and use thoses job defs instead of the ones from the descriptor
- jobs = ServerPluginDescriptorMetadataParser.getScheduledJobs(pluginEnv.getPluginDescriptor());
+ jobs = this.pluginManager.getServerPluginContext(pluginEnv).getSchedules();
if (jobs != null) {
for (ScheduledJobDefinition job : jobs) {
try {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index 4d0d314..e3a3ba6 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -33,6 +33,7 @@ import org.rhq.enterprise.server.plugin.pc.alert.AlertServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.generic.GenericServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.perspective.PerspectiveServerPluginContainer;
+import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
@@ -300,6 +301,9 @@ public class MasterServerPluginContainer {
File[] pluginFiles = pluginDirectory.listFiles();
if (pluginFiles != null) {
+
+ List<String> enabledPlugins = LookupUtil.getServerPlugins().getPluginNamesByEnabled(true);
+
for (File pluginFile : pluginFiles) {
if (pluginFile.getName().endsWith(".jar")) {
URL pluginUrl = pluginFile.toURI().toURL();
@@ -308,8 +312,13 @@ public class MasterServerPluginContainer {
ServerPluginDescriptorType descriptor;
descriptor = ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginUrl);
if (descriptor != null) {
- log.debug("pre-loaded server plugin from URL: " + pluginUrl);
- plugins.put(pluginUrl, descriptor);
+ if (enabledPlugins.contains(descriptor.getName())) {
+ log.debug("pre-loaded server plugin from URL: " + pluginUrl);
+ plugins.put(pluginUrl, descriptor);
+ } else {
+ log.info("Server plugin [" + descriptor.getName()
+ + "] is disabled and will not be initialized");
+ }
}
} catch (Throwable t) {
// for some reason, the plugin failed to load - it will be ignored
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index a0cca3f..1ad7dad 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -30,11 +30,12 @@ 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.definition.ConfigurationDefinition;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorMetadataParser;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginComponentType;
-import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
* Provides functionality to manage plugins for a plugin container. Plugin containers
@@ -278,8 +279,6 @@ public class ServerPluginManager {
return context;
}
- ServerPluginDescriptorType pluginDescriptor = env.getPluginDescriptor();
-
MasterServerPluginContainer masterPC = this.parentPluginContainer.getMasterServerPluginContainer();
MasterServerPluginContainerConfiguration masterConfig = masterPC.getConfiguration();
File dataDir = new File(masterConfig.getDataDirectory(), pluginName);
@@ -289,18 +288,17 @@ public class ServerPluginManager {
List<ScheduledJobDefinition> schedules;
try {
- // TODO: today we have no way in the UI to customize the plugin config values
- // for now, just use the defaults as defined in the descriptor
- ConfigurationDefinition configDef = ServerPluginDescriptorMetadataParser
- .getPluginConfigurationDefinition(pluginDescriptor);
- plugnConfig = configDef.getDefaultTemplate().createConfiguration();
-
- // TODO: today we have no way in the UI to customize the schedules
- // for now, just use the defaults as defined in the descriptor
- schedules = ServerPluginDescriptorMetadataParser.getScheduledJobs(pluginDescriptor);
+ // get the plugin data from the database
+ ServerPluginsLocal serverPluginsManager = LookupUtil.getServerPlugins();
+ Plugin plugin = serverPluginsManager.getServerPlugin(pluginName);
+
+ // get the plugin configuration and scheduled jobs from the DB data
+ plugnConfig = plugin.getPluginConfiguration();
+
+ Configuration scheduledJobsConfig = plugin.getScheduledJobsConfiguration();
+ schedules = ServerPluginDescriptorMetadataParser.getScheduledJobs(scheduledJobsConfig);
} catch (Exception e) {
- // TODO need proper exception handling
- throw new RuntimeException(e);
+ throw new RuntimeException("Failed to get plugin config/schedules from the database", e);
}
context = new ServerPluginContext(env, dataDir, tmpDir, plugnConfig, schedules);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
index 0c80dcb..e72a5d5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
@@ -25,9 +25,9 @@ import org.apache.commons.logging.LogFactory;
import org.jboss.annotation.ejb.Management;
import org.jboss.annotation.ejb.Service;
-import org.jboss.system.server.ServerConfig;
import org.rhq.enterprise.server.RHQConstants;
+import org.rhq.enterprise.server.util.LookupUtil;
/**
* This is the singleton management service responsible for managing the lifecycle of the
@@ -118,6 +118,12 @@ public class ServerPluginService implements ServerPluginServiceManagement {
return this.masterPluginContainer != null;
}
+ public File getServerPluginsDirectory() {
+ File serverHomeDir = LookupUtil.getCoreServer().getJBossServerHomeDir();
+ File pluginDir = new File(serverHomeDir, "deploy/" + RHQConstants.EAR_FILE_NAME + "/rhq-serverplugins");
+ return pluginDir;
+ }
+
/**
* This will create, configure and initialize the plugin container and return it.
*
@@ -129,15 +135,13 @@ public class ServerPluginService implements ServerPluginServiceManagement {
protected MasterServerPluginContainer createMasterPluginContainer() {
MasterServerPluginContainer pc = new MasterServerPluginContainer();
- String pluginDirStr = System.getProperty(ServerConfig.SERVER_HOME_DIR);
- File pluginDir = new File(pluginDirStr, "deploy/" + RHQConstants.EAR_FILE_NAME + "/rhq-serverplugins");
+ File pluginDir = getServerPluginsDirectory();
- String dataDirStr = System.getProperty(ServerConfig.SERVER_DATA_DIR);
- File dataDir = new File(dataDirStr, "server-plugins");
+ File serverDataDir = LookupUtil.getCoreServer().getJBossServerHomeDir();
+ File dataDir = new File(serverDataDir, "server-plugins");
dataDir.mkdirs(); // make sure the data directory exists
- String tmpDirStr = System.getProperty(ServerConfig.SERVER_TEMP_DIR);
- File tmpDir = new File(tmpDirStr);
+ File tmpDir = LookupUtil.getCoreServer().getJBossServerTempDir();
// TODO: determine what things to hide from our war classloader
//StringBuilder defaultRegex = new StringBuilder();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java
index 490c9fd..8773283 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java
@@ -18,6 +18,8 @@
*/
package org.rhq.enterprise.server.plugin.pc;
+import java.io.File;
+
import javax.management.ObjectName;
import org.rhq.core.util.ObjectNameFactory;
@@ -99,4 +101,10 @@ public interface ServerPluginServiceManagement {
* @return <code>true</code> if the master plugin container has been started
*/
boolean isMasterPluginContainerStarted();
+
+ /**
+ * Returns the directory where the server plugins are found.
+ * @return server plugins directory
+ */
+ File getServerPluginsDirectory();
}
\ No newline at end of file
diff --git a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorMetadataParser.java b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorMetadataParser.java
index cfaa1a8..49f89a2 100644
--- a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorMetadataParser.java
+++ b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorMetadataParser.java
@@ -76,6 +76,28 @@ public class ServerPluginDescriptorMetadataParser {
}
/**
+ * Returns the scheduled jobs configuration definition for the plugin.
+ * Use {@link #getScheduledJobs(ServerPluginDescriptorType)} to return a list of a more
+ * strongly typed jobs object, as opposed to a generic configuration definition.
+ *
+ * @param descriptor
+ *
+ * @return the scheduled jobs configuration definition, or <code>null</code> if the descriptor did not define plugin config.
+ *
+ * @throws Exception if the plugin descriptor was invalid
+ */
+ public static ConfigurationDefinition getScheduledJobsDefinition(ServerPluginDescriptorType descriptor)
+ throws Exception {
+
+ ConfigurationDefinition config = null;
+ ConfigurationDescriptor configXml = descriptor.getScheduledJobs();
+ if (configXml != null) {
+ config = ConfigurationMetadataParser.parse(descriptor.getName(), configXml);
+ }
+ return config;
+ }
+
+ /**
* Given a descriptor, this will parse it and return any scheduled jobs that it finds.
* This essentially gives you a list of the pre-defined jobs, prior to a user customizing
* them with their own settings.
commit 4695e236d9c4f74fb04f5dd205fe7f44c2bda5bc
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 19 17:18:59 2009 -0500
get the database check to put cache the plugin info, just like how the filesystem check does it
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
index a0b4677..b22cab3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
@@ -343,17 +343,13 @@ public class ServerPluginScanner {
File expectedFile = new File(this.getServerPluginDir(), path);
File currentFile = null; // will be non-null if we find that we have this plugin on the filesystem already
PluginWithDescriptor pluginWithDescriptor = this.serverPluginsOnFilesystem.get(expectedFile);
- Plugin cachedPluginOnFilesystem = null;
- if (pluginWithDescriptor != null) {
- cachedPluginOnFilesystem = pluginWithDescriptor.plugin;
- }
- if (cachedPluginOnFilesystem != null) {
+ if (pluginWithDescriptor != null) {
currentFile = expectedFile; // we have it where we are expected to have it
- if (!cachedPluginOnFilesystem.getName().equals(name)) {
+ if (!pluginWithDescriptor.plugin.getName().equals(name)) {
// I have no idea when or if this would ever happen, but at least log it so we'll see it if it does happen
log.warn("For some reason, the server plugin file [" + expectedFile + "] is plugin ["
- + cachedPluginOnFilesystem.getName() + "] but the database says it should be [" + name
+ + pluginWithDescriptor.plugin.getName() + "] but the database says it should be [" + name
+ "]");
} else {
log.debug("File system and database agree on a server plugin location for [" + expectedFile
@@ -364,7 +360,7 @@ public class ServerPluginScanner {
for (Map.Entry<File, PluginWithDescriptor> cacheEntry : this.serverPluginsOnFilesystem.entrySet()) {
if (cacheEntry.getValue().plugin.getName().equals(name)) {
currentFile = cacheEntry.getKey();
- cachedPluginOnFilesystem = cacheEntry.getValue().plugin;
+ pluginWithDescriptor = cacheEntry.getValue();
log.info("Filesystem has a server plugin [" + name + "] at the file [" + currentFile
+ "] which is different than where the DB thinks it should be [" + expectedFile + "]");
break; // we found it, no need to continue the loop
@@ -372,7 +368,7 @@ public class ServerPluginScanner {
}
}
- if (cachedPluginOnFilesystem != null && currentFile != null && currentFile.exists()) {
+ if (pluginWithDescriptor != null && currentFile != null && currentFile.exists()) {
Plugin dbPlugin = new Plugin(name, path);
dbPlugin.setMd5(md5);
dbPlugin.setVersion(version);
@@ -380,20 +376,20 @@ public class ServerPluginScanner {
dbPlugin.setDeployment(PluginDeploymentType.SERVER);
Plugin obsoletePlugin = ServerPluginDescriptorUtil.determineObsoletePlugin(dbPlugin,
- cachedPluginOnFilesystem);
+ pluginWithDescriptor.plugin);
- if (obsoletePlugin == cachedPluginOnFilesystem) { // yes use == for reference equality!
+ if (obsoletePlugin == pluginWithDescriptor.plugin) { // yes use == for reference equality!
StringBuilder logMsg = new StringBuilder();
logMsg.append("Found server plugin [").append(name);
logMsg.append("] in the DB that is newer than the one on the filesystem: ");
logMsg.append("DB path=[").append(path);
logMsg.append("]; file path=[").append(currentFile.getName());
logMsg.append("]; DB MD5=[").append(md5);
- logMsg.append("]; file MD5=[").append(cachedPluginOnFilesystem.getMd5());
+ logMsg.append("]; file MD5=[").append(pluginWithDescriptor.plugin.getMd5());
logMsg.append("]; DB version=[").append(version);
- logMsg.append("]; file version=[").append(cachedPluginOnFilesystem.getVersion());
+ logMsg.append("]; file version=[").append(pluginWithDescriptor.plugin.getVersion());
logMsg.append("]; DB timestamp=[").append(new Date(mtime));
- logMsg.append("]; file timestamp=[").append(new Date(cachedPluginOnFilesystem.getMtime()));
+ logMsg.append("]; file timestamp=[").append(new Date(pluginWithDescriptor.plugin.getMtime()));
logMsg.append("]");
log.info(logMsg.toString());
@@ -411,9 +407,9 @@ public class ServerPluginScanner {
} else if (obsoletePlugin == null) {
// the db is up-to-date, but update the cache so we don't check MD5 or parse the descriptor again
currentFile.setLastModified(mtime);
- cachedPluginOnFilesystem.setMtime(mtime);
- cachedPluginOnFilesystem.setVersion(version);
- cachedPluginOnFilesystem.setMd5(md5);
+ pluginWithDescriptor.plugin.setMtime(mtime);
+ pluginWithDescriptor.plugin.setVersion(version);
+ pluginWithDescriptor.plugin.setMd5(md5);
} else {
log.info("It appears that the server plugin [" + dbPlugin
+ "] in the database may be obsolete. If so, it will be updated later.");
@@ -444,6 +440,9 @@ public class ServerPluginScanner {
rs.close();
file.setLastModified(plugin.getMtime()); // so our file matches the database mtime
updatedFiles.add(file);
+
+ // we are writing a new file to the filesystem, cache it since we know about it now
+ cacheFilesystemServerPluginJar(file, null);
}
} finally {
JDBCUtil.safeClose(conn, ps, rs);
commit 79d29e8a232a0a0e4860e796c3c81d389f47a91b
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 19 16:53:46 2009 -0500
oppps... forgot to define the datasource resource via annotation
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 41158ea..424b85a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -58,6 +58,7 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
* @author John Mazzitelli
*/
@Stateless
+(a)javax.annotation.Resource(name = "RHQ_DS", mappedName = RHQConstants.DATASOURCE_JNDI_NAME)
public class ServerPluginsBean implements ServerPluginsLocal {
private final Log log = LogFactory.getLog(ServerPluginsBean.class);
commit 90ec2ce365a5e1bc320db9306ac1ce924c963a0e
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 19 16:43:13 2009 -0500
initial code that persisted server plugin info to the database
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
index 55a4960..a0b4677 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
@@ -34,12 +34,14 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import javax.sql.DataSource;
import javax.transaction.TransactionManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.apache.maven.artifact.versioning.ComparableVersion;
import org.rhq.core.db.DatabaseType;
import org.rhq.core.db.DatabaseTypeFactory;
@@ -52,6 +54,8 @@ import org.rhq.core.domain.plugin.PluginDeploymentType;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.jdbc.JDBCUtil;
import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.auth.SubjectManagerLocal;
+import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
@@ -67,10 +71,10 @@ public class ServerPluginScanner {
private DatabaseType dbType = null;
/** a list of server plugins found on previous scans that have not yet been processed */
- private List<URL> scanned = new ArrayList<URL>();
+ private List<File> scanned = new ArrayList<File>();
/** Maintains a cache of what we had on the filesystem during the last scan */
- private Map<File, Plugin> serverPluginsOnFilesystem = new HashMap<File, Plugin>();
+ private Map<File, PluginWithDescriptor> serverPluginsOnFilesystem = new HashMap<File, PluginWithDescriptor>();
private File serverPluginDir;
@@ -92,15 +96,11 @@ public class ServerPluginScanner {
* @throws Exception
*/
void registerServerPlugins() throws Exception {
- for (URL url : this.scanned) {
- log.debug("Hot deploying server plugin [" + url + "]...");
- //this.agentPluginDeployer.pluginDetected(di);
+ for (File file : this.scanned) {
+ log.debug("Deploying server plugin [" + file + "]...");
+ registerServerPlugin(file);
}
this.scanned.clear();
-
- // Register all the new plugins.
- //this.agentPluginDeployer.registerPlugins();
-
return;
}
@@ -128,9 +128,52 @@ public class ServerPluginScanner {
allUpdatedFiles.addAll(updatedFiles2);
for (File updatedFile : allUpdatedFiles) {
- URL url = updatedFile.toURI().toURL();
- log.debug("Scan detected server plugin [" + url + "]...");
- this.scanned.add(url);
+ log.debug("Scan detected server plugin [" + updatedFile + "]...");
+ this.scanned.add(updatedFile);
+ }
+ return;
+ }
+
+ /**
+ * This is called when a server plugin jar has been found on the filesystem that hasn't been seen yet
+ * during this particular lifetime of the scanner. This does not necessarily mean its a new plugin jar,
+ * it only means this is the first time we've seen it since this object has been instantiated.
+ * This method will check to see if the database record matches the new plugin file and if so, does nothing.
+ *
+ * @param file the new server plugin file
+ */
+ private void registerServerPlugin(File pluginFile) {
+ try {
+ ServerPluginDescriptorType descriptor;
+ descriptor = this.serverPluginsOnFilesystem.get(pluginFile).descriptor;
+
+ String pluginName = descriptor.getName();
+ String displayName = descriptor.getDisplayName();
+
+ ComparableVersion version; // this must be non-null, the next line ensures this
+ version = ServerPluginDescriptorUtil.getPluginVersion(pluginFile, descriptor);
+
+ log.info("Registering RHQ server plugin [" + pluginName + "], version " + version);
+
+ Plugin plugin = new Plugin(pluginName, pluginFile.getName());
+ plugin.setDeployment(PluginDeploymentType.SERVER);
+ plugin.setDisplayName((displayName != null) ? displayName : pluginName);
+ plugin.setEnabled(false); // initially disabled, user must configure it first before enabling
+ plugin.setDescription(descriptor.getDescription());
+ plugin.setMtime(pluginFile.lastModified());
+ plugin.setVersion(version.toString());
+ plugin.setAmpsVersion(descriptor.getApiVersion());
+ plugin.setMD5(MessageDigestGenerator.getDigestString(pluginFile));
+
+ if (descriptor.getHelp() != null && !descriptor.getHelp().getContent().isEmpty()) {
+ plugin.setHelp(String.valueOf(descriptor.getHelp().getContent().get(0)));
+ }
+
+ ServerPluginsLocal serverPluginsManager = LookupUtil.getServerPlugins();
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ serverPluginsManager.registerPlugin(subjectManager.getOverlord(), plugin, descriptor, pluginFile);
+ } catch (Exception e) {
+ log.error("Failed to register RHQ plugin file [" + pluginFile + "]", e);
}
return;
}
@@ -141,7 +184,7 @@ public class ServerPluginScanner {
*
* @return a list of files that appear to be new or updated and should be deployed
*/
- List<File> serverPluginScanFilesystem() {
+ private List<File> serverPluginScanFilesystem() {
List<File> updated = new ArrayList<File>();
// get the current list of plugins deployed on the filesystem
@@ -174,7 +217,12 @@ public class ServerPluginScanner {
for (File pluginJar : pluginJars) {
String md5 = null;
- Plugin plugin = this.serverPluginsOnFilesystem.get(pluginJar);
+ PluginWithDescriptor pluginWithDescriptor = this.serverPluginsOnFilesystem.get(pluginJar);
+ Plugin plugin = null;
+ if (pluginWithDescriptor != null) {
+ plugin = pluginWithDescriptor.plugin;
+ }
+
try {
if (plugin != null) {
if (pluginJar.lastModified() == 0L) {
@@ -203,8 +251,8 @@ public class ServerPluginScanner {
// This is needed if plugin-A-1.0.jar exists and someone deployed plugin-A-1.1.jar but fails to delete plugin-A-1.0.jar.
doomedPluginFiles.clear();
HashMap<String, Plugin> pluginsByName = new HashMap<String, Plugin>();
- for (Map.Entry<File, Plugin> currentPluginFileEntry : this.serverPluginsOnFilesystem.entrySet()) {
- Plugin currentPlugin = currentPluginFileEntry.getValue();
+ for (Entry<File, PluginWithDescriptor> currentPluginFileEntry : this.serverPluginsOnFilesystem.entrySet()) {
+ Plugin currentPlugin = currentPluginFileEntry.getValue().plugin;
Plugin existingPlugin = pluginsByName.get(currentPlugin.getName());
if (existingPlugin == null) {
// this is the usual case - this is the only plugin with the given name we've seen
@@ -255,7 +303,7 @@ public class ServerPluginScanner {
plugin.setVersion(version);
plugin.setMtime(pluginJar.lastModified());
plugin.setDeployment(PluginDeploymentType.SERVER);
- this.serverPluginsOnFilesystem.put(pluginJar, plugin);
+ this.serverPluginsOnFilesystem.put(pluginJar, new PluginWithDescriptor(plugin, descriptor));
return plugin;
}
@@ -265,7 +313,7 @@ public class ServerPluginScanner {
*
* @return a list of files that appear to be new or updated and should be deployed
*/
- List<File> serverPluginScanDatabase() throws Exception {
+ private List<File> serverPluginScanDatabase() throws Exception {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
@@ -282,8 +330,7 @@ public class ServerPluginScanner {
// get all the plugins
ps = conn.prepareStatement("SELECT NAME, PATH, MD5, MTIME, VERSION FROM " + Plugin.TABLE_NAME
- + " WHERE DEPLOYMENT = 'SERVER' AND ENABLED=?");
- setEnabledFlag(conn, ps, 1, true);
+ + " WHERE DEPLOYMENT = 'SERVER'");
rs = ps.executeQuery();
while (rs.next()) {
String name = rs.getString(1);
@@ -295,7 +342,11 @@ public class ServerPluginScanner {
// let's see if we have this logical plugin on the filesystem (it may or may not be under the same filename)
File expectedFile = new File(this.getServerPluginDir(), path);
File currentFile = null; // will be non-null if we find that we have this plugin on the filesystem already
- Plugin cachedPluginOnFilesystem = this.serverPluginsOnFilesystem.get(expectedFile);
+ PluginWithDescriptor pluginWithDescriptor = this.serverPluginsOnFilesystem.get(expectedFile);
+ Plugin cachedPluginOnFilesystem = null;
+ if (pluginWithDescriptor != null) {
+ cachedPluginOnFilesystem = pluginWithDescriptor.plugin;
+ }
if (cachedPluginOnFilesystem != null) {
currentFile = expectedFile; // we have it where we are expected to have it
@@ -310,10 +361,10 @@ public class ServerPluginScanner {
}
} else {
// the plugin might still be on the file system but under a different filename, see if we can find it
- for (Map.Entry<File, Plugin> cachePluginEntry : this.serverPluginsOnFilesystem.entrySet()) {
- if (cachePluginEntry.getValue().getName().equals(name)) {
- currentFile = cachePluginEntry.getKey();
- cachedPluginOnFilesystem = cachePluginEntry.getValue();
+ for (Map.Entry<File, PluginWithDescriptor> cacheEntry : this.serverPluginsOnFilesystem.entrySet()) {
+ if (cacheEntry.getValue().plugin.getName().equals(name)) {
+ currentFile = cacheEntry.getKey();
+ cachedPluginOnFilesystem = cacheEntry.getValue().plugin;
log.info("Filesystem has a server plugin [" + name + "] at the file [" + currentFile
+ "] which is different than where the DB thinks it should be [" + expectedFile + "]");
break; // we found it, no need to continue the loop
@@ -381,12 +432,11 @@ public class ServerPluginScanner {
// write all our updated plugins to the file system
ps = conn.prepareStatement("SELECT CONTENT FROM " + Plugin.TABLE_NAME
- + " WHERE DEPLOYMENT = 'SERVER' AND NAME = ? AND ENABLED = ?");
+ + " WHERE DEPLOYMENT = 'SERVER' AND NAME = ?");
for (Plugin plugin : updatedPlugins) {
File file = new File(this.getServerPluginDir(), plugin.getPath());
ps.setString(1, plugin.getName());
- setEnabledFlag(conn, ps, 2, true);
rs = ps.executeQuery();
rs.next();
InputStream content = rs.getBinaryStream(1);
@@ -488,4 +538,14 @@ public class ServerPluginScanner {
}
return;
}
+
+ private class PluginWithDescriptor {
+ public PluginWithDescriptor(Plugin plugin, ServerPluginDescriptorType descriptor) {
+ this.plugin = plugin;
+ this.descriptor = descriptor;
+ }
+
+ public Plugin plugin;
+ public ServerPluginDescriptorType descriptor;
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 6eb6fc7..41158ea 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -19,6 +19,12 @@
package org.rhq.enterprise.server.plugin;
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
@@ -27,13 +33,24 @@ import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
+import javax.sql.DataSource;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.core.util.jdbc.JDBCUtil;
import org.rhq.enterprise.server.RHQConstants;
+import org.rhq.enterprise.server.authz.RequiredPermission;
import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
* A server API into the server plugin infrastructure.
@@ -42,10 +59,14 @@ import org.rhq.enterprise.server.util.LookupUtil;
*/
@Stateless
public class ServerPluginsBean implements ServerPluginsLocal {
+ private final Log log = LogFactory.getLog(ServerPluginsBean.class);
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
private EntityManager entityManager;
+ @javax.annotation.Resource(name = "RHQ_DS")
+ private DataSource dataSource;
+
@EJB
private ServerPluginsLocal serverPluginsBean; //self
@@ -101,4 +122,113 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
}
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
+ public void registerPlugin(Subject subject, Plugin plugin, ServerPluginDescriptorType descriptor, File pluginFile)
+ throws Exception {
+
+ Plugin existingPlugin = null;
+ boolean newOrUpdated = false;
+ try {
+ existingPlugin = getServerPlugin(plugin.getName());
+ } catch (NoResultException nre) {
+ newOrUpdated = true; // this is expected for new plugins
+ }
+
+ if (existingPlugin != null) {
+ Plugin obsolete = ServerPluginDescriptorUtil.determineObsoletePlugin(plugin, existingPlugin);
+ if (obsolete == existingPlugin) { // yes use == for reference equality
+ newOrUpdated = true;
+ }
+ plugin.setId(existingPlugin.getId());
+ }
+
+ // If this is a brand new plugin, it gets "updated" too - which ends up being a simple persist.
+ if (newOrUpdated) {
+ if (plugin.getDisplayName() == null) {
+ plugin.setDisplayName(plugin.getName());
+ }
+
+ if (plugin.getId() == 0) {
+ entityManager.persist(plugin);
+ } else {
+ plugin = updatePluginExceptContent(plugin);
+ }
+
+ if (pluginFile != null) {
+ entityManager.flush();
+ streamPluginFileContentToDatabase(plugin.getId(), pluginFile);
+ }
+ log.debug("Updated plugin entity [" + plugin + "]");
+ }
+
+ return;
+ }
+
+ public Plugin updatePluginExceptContent(Plugin plugin) throws Exception {
+ // this method is here because we need a way to update the plugin's information
+ // without blowing away the content data. Because we do not want to load the
+ // content blob in memory, the plugin's content field will be null - if we were
+ // to entityManager.merge that plugin POJO, it would null out that blob column.
+ if (plugin.getId() == 0) {
+ throw new IllegalArgumentException("Plugin must already exist to update it");
+ } else {
+ Query q = entityManager.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
+ q.setParameter("id", plugin.getId());
+ q.setParameter("name", plugin.getName());
+ q.setParameter("path", plugin.getPath());
+ q.setParameter("displayName", plugin.getDisplayName());
+ q.setParameter("enabled", plugin.isEnabled());
+ q.setParameter("md5", plugin.getMD5());
+ q.setParameter("version", plugin.getVersion());
+ q.setParameter("ampsVersion", plugin.getAmpsVersion());
+ q.setParameter("deployment", plugin.getDeployment());
+ q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
+ q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
+ q.setParameter("description", plugin.getDescription());
+ q.setParameter("help", plugin.getHelp());
+ q.setParameter("mtime", plugin.getMtime());
+ if (q.executeUpdate() != 1) {
+ throw new Exception("Failed to update a plugin that matches [" + plugin + "]");
+ }
+ }
+ return plugin;
+ }
+
+ /**
+ * This will write the contents of the given plugin file to the database.
+ * This will assume the MD5 in the database is already correct, so this
+ * method will not take the time to calculate the MD5 again.
+ *
+ * @param id the ID of the plugin whose content is being updated
+ * @param file the plugin file whose content will be streamed to the database
+ *
+ * @throws Exception
+ */
+ private void streamPluginFileContentToDatabase(int id, File file) throws Exception {
+ Connection conn = null;
+ PreparedStatement ps = null;
+ ResultSet rs = null;
+
+ FileInputStream fis = new FileInputStream(file);
+
+ try {
+
+ conn = this.dataSource.getConnection();
+ ps = conn.prepareStatement("UPDATE " + Plugin.TABLE_NAME + " SET CONTENT = ? WHERE ID = ?");
+ ps.setBinaryStream(1, new BufferedInputStream(fis), (int) file.length());
+ ps.setInt(2, id);
+ int updateResults = ps.executeUpdate();
+ if (updateResults != 1) {
+ throw new Exception("Failed to update content for plugin [" + id + "] from [" + file + "]");
+ }
+ } finally {
+ JDBCUtil.safeClose(conn, ps, rs);
+
+ try {
+ fis.close();
+ } catch (Throwable t) {
+ }
+ }
+ return;
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index c8ab236..af67646 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -1,11 +1,14 @@
package org.rhq.enterprise.server.plugin;
+import java.io.File;
import java.util.List;
import javax.ejb.Local;
import javax.persistence.NoResultException;
+import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
* Interface to the methods that interact with the serve-side plugin infrastructure.
@@ -59,4 +62,27 @@ public interface ServerPluginsLocal {
* @param enabled the value of the enabled flag for the plugins
*/
void setPluginEnabledFlag(List<Integer> pluginIds, boolean enabled);
+
+ /**
+ * Registers the given plugin to the database.
+ *
+ * @param subject the user that needs to have permissions to add a plugin to the system
+ * @param plugin the plugin definition
+ * @param descriptor the plugin descriptor that was found in the plugin file
+ * @param pluginFile the actual plugin file itself
+ * @throws Exception if failed to fully register the plugin
+ */
+ void registerPlugin(Subject subject, Plugin plugin, ServerPluginDescriptorType descriptor, File pluginFile)
+ throws Exception;
+
+ /**
+ * Given a plugin that already exists, this will update that plugin's data in the database,
+ * except for the content, which is left as-is. If the plugin did not yet exist, an exception is thrown.
+ * You can use this to update the plugin's scheduled jobs configuration and plugin configuration.
+ *
+ * @param plugin existing plugin with updated data
+ * @return the updated plugin
+ * @throws Exception if the plugin did not already exist or an error occurred that caused the update to fail
+ */
+ public Plugin updatePluginExceptContent(Plugin plugin) throws Exception;
}
commit 52783b3a95abf74eeb9fdbbfbbc037bad5393cac
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 19 15:18:18 2009 -0500
the scan period scans for both server and agent plugins now, not just agent plugins
diff --git a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
index ad1e0f6..6c6fedb 100644
--- a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
+++ b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
@@ -146,15 +146,15 @@
</not>
</condition>
- <!-- developers might want to deploy agent plugins frequently, so we'll scan every 30 seconds -->
- <!-- in production, agent plugins change very infrequently, so only scan every 5 minutes -->
- <condition property="rhq.server.agent-plugin-scan-period-ms" value="30000">
+ <!-- developers might want to deploy agent/server plugins frequently, so we'll scan every 30 seconds -->
+ <!-- in production, plugins change very infrequently, so only scan every 5 minutes -->
+ <condition property="rhq.server.plugin-scan-period-ms" value="30000">
<or>
<equals arg1="${dev.profile.active}" arg2="true" />
<equals arg1="${developer}" arg2="true" />
</or>
</condition>
- <condition property="rhq.server.agent-plugin-scan-period-ms" value="300000">
+ <condition property="rhq.server.plugin-scan-period-ms" value="300000">
<not>
<or>
<equals arg1="${dev.profile.active}" arg2="true" />
@@ -577,8 +577,8 @@ rhq.server.concurrency-limit.measurement-schedule-request=10
# Content Local Filesystem Repository
rhq.server.content.filesystem=${jboss.server.data.dir}/packagebits
-# The frequency (in millis) the server checks for updated agent plugins
-rhq.server.agent-plugin-scan-period-ms=${rhq.server.agent-plugin-scan-period-ms}
+# The frequency (in millis) the server checks for updated plugins
+rhq.server.plugin-scan-period-ms=${rhq.server.plugin-scan-period-ms}
# Auto-Install Pre-Configuration Settings
# If you wish to circumvent the installer webapp and auto-install the server
diff --git a/modules/enterprise/server/ear/src/main/resources/product-plugin-service.xml b/modules/enterprise/server/ear/src/main/resources/product-plugin-service.xml
index 1344ec8..5c0e3d2 100644
--- a/modules/enterprise/server/ear/src/main/resources/product-plugin-service.xml
+++ b/modules/enterprise/server/ear/src/main/resources/product-plugin-service.xml
@@ -5,7 +5,7 @@
<server>
<mbean code="org.rhq.enterprise.server.core.plugin.PluginDeploymentScanner"
name="rhq:service=PluginDeploymentScanner">
- <attribute name="ScanPeriod">${rhq.server.agent-plugin-scan-period-ms:300000}</attribute>
+ <attribute name="ScanPeriod">${rhq.server.plugin-scan-period-ms:300000}</attribute>
<attribute name="AgentPluginDir">${jboss.server.home.dir}/deploy/${rhq.earName}/rhq-downloads/rhq-plugins</attribute>
<attribute name="ServerPluginDir">${jboss.server.home.dir}/deploy/${rhq.earName}/rhq-serverplugins</attribute>
<attribute name="UserPluginDir">${jboss.home.dir}/../plugins</attribute>
commit f1446bec216cdc787afb3289352247ccde2df472
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 19 13:45:19 2009 -0500
start doing some server plugin scanning
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index 811586c..e94a0dd 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -57,6 +57,29 @@ import org.rhq.core.util.MessageDigestGenerator;
@NamedQueries( {
//
// this query does not load the content blob, but loads everything else
+ @NamedQuery(name = Plugin.QUERY_FIND_BY_IDS_AND_TYPE, query = "" //
+ + " SELECT new org.rhq.core.domain.plugin.Plugin( " //
+ + " p.id, " //
+ + " p.name, " //
+ + " p.path, " //
+ + " p.displayName, " //
+ + " p.enabled, " //
+ + " p.description, " //
+ + " p.help, " //
+ + " p.md5, " //
+ + " p.version, " //
+ + " p.ampsVersion, " //
+ + " p.deployment, " //
+ + " p.pluginConfiguration, " //
+ + " p.scheduledJobsConfiguration, " //
+ + " p.ctime, " //
+ + " p.mtime) " //
+ + " FROM Plugin AS p " //
+ + " LEFT JOIN p.pluginConfiguration " //
+ + " LEFT JOIN p.scheduledJobsConfiguration " //
+ + " WHERE p.id IN (:ids) AND p.deployment = :type"), //
+
+ // this query does not load the content blob, but loads everything else
@NamedQuery(name = Plugin.QUERY_FIND_BY_NAME, query = "" //
+ " SELECT new org.rhq.core.domain.plugin.Plugin( " //
+ " p.id, " //
@@ -181,6 +204,7 @@ public class Plugin implements Serializable {
public static final String QUERY_FIND_ALL_AGENT = "Plugin.findAllAgent";
public static final String QUERY_FIND_ALL_SERVER = "Plugin.findAllServer";
public static final String QUERY_FIND_BY_NAME = "Plugin.findByName";
+ public static final String QUERY_FIND_BY_IDS_AND_TYPE = "Plugin.findByIdsAndType";
public static final String UPDATE_ALL_BUT_CONTENT = "Plugin.updateAllButContent";
@Column(name = "ID", nullable = false)
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index bf8787f..77d9312 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -27,6 +27,7 @@ import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
+import java.util.Arrays;
import java.util.List;
import javax.naming.InitialContext;
@@ -288,6 +289,26 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.getHelp().equals(help);
assert plugin.getContent() == null;
+ query = em.createNamedQuery(Plugin.QUERY_FIND_BY_IDS_AND_TYPE);
+ query.setParameter("ids", Arrays.asList(Integer.valueOf(plugin.getId())));
+ query.setParameter("type", plugin.getDeployment());
+ plugin = (Plugin) query.getSingleResult();
+ assert plugin != null;
+ assert plugin.getId() > 0;
+ assert plugin.getName().equals(name);
+ assert plugin.getPath().equals(path);
+ assert plugin.getDisplayName().equals(displayName);
+ assert plugin.isEnabled() == enabled;
+ assert plugin.getMD5().equals(md5);
+ assert plugin.getVersion().equals(version);
+ assert plugin.getAmpsVersion().equals(ampsVersion);
+ assert plugin.getDescription().equals(description);
+ assert plugin.getDeployment() == deployment;
+ assert plugin.getPluginConfiguration().equals(pluginConfig);
+ assert plugin.getScheduledJobsConfiguration().equals(jobsConfig);
+ assert plugin.getHelp().equals(help);
+ assert plugin.getContent() == null;
+
query = em.createNamedQuery(Plugin.QUERY_FIND_ALL_SERVER);
List<Plugin> all = query.getResultList();
boolean got_it = false;
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
index 12530f5..84eeeea 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
@@ -24,9 +24,11 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginDeploymentType;
import org.rhq.core.gui.util.FacesContextUtility;
import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
import org.rhq.enterprise.server.authz.PermissionException;
+import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
import org.rhq.enterprise.server.resource.metadata.ResourceMetadataManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -36,11 +38,12 @@ import org.rhq.enterprise.server.util.LookupUtil;
public class InstalledPluginUIBean {
private final Log log = LogFactory.getLog(InstalledPluginUIBean.class);
- public static final String MANAGED_BEAN_NAME = "InstalledPluginUIBean";
+ public static final String MANAGED_BEAN_NAME = InstalledPluginUIBean.class.getSimpleName();
private Plugin plugin;
private ResourceMetadataManagerLocal resourceMetadataManagerBean = LookupUtil.getResourceMetadataManager();
+ private ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
public InstalledPluginUIBean() {
this.plugin = lookupPlugin();
@@ -53,14 +56,13 @@ public class InstalledPluginUIBean {
private Plugin lookupPlugin() {
hasPermission();
String pluginName = FacesContextUtility.getRequiredRequestParameter("plugin", String.class);
- return resourceMetadataManagerBean.getPlugin(pluginName);
- }
-
- public void setEnabled(boolean enabled) {
- // TODO is this supposed to be empty?
- }
-
- public void undeploy() {
+ String pluginType = FacesContextUtility.getRequiredRequestParameter("pluginType", String.class);
+ PluginDeploymentType deploymentType = PluginDeploymentType.valueOf(pluginType);
+ if (deploymentType == PluginDeploymentType.AGENT) {
+ return resourceMetadataManagerBean.getPlugin(pluginName);
+ } else {
+ return serverPluginsBean.getServerPlugin(pluginName);
+ }
}
/**
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
index bfc6e52..9fd46f2 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
@@ -22,7 +22,10 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
import javax.faces.application.FacesMessage;
@@ -34,6 +37,7 @@ import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.gui.util.FacesContextUtility;
+import org.rhq.core.gui.util.StringUtility;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
import org.rhq.enterprise.server.authz.PermissionException;
@@ -122,6 +126,63 @@ public class InstalledPluginsUIBean {
return;
}
+ public void enableServerPlugins() {
+ List<Plugin> selectedPlugins = getSelectedServerPlugins();
+ List<String> selectedPluginNames = new ArrayList<String>();
+ for (Plugin selectedPlugin : selectedPlugins) {
+ selectedPluginNames.add(selectedPlugin.getName());
+ }
+ serverPluginsBean.enableServerPlugins(getIds(selectedPlugins));
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Enabled server plugins: " + selectedPluginNames);
+ return;
+ }
+
+ public void disableServerPlugins() {
+ List<Plugin> selectedPlugins = getSelectedServerPlugins();
+ List<String> selectedPluginNames = new ArrayList<String>();
+ for (Plugin selectedPlugin : selectedPlugins) {
+ selectedPluginNames.add(selectedPlugin.getName());
+ }
+ serverPluginsBean.disableServerPlugins(getIds(selectedPlugins));
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Disabled server plugins: " + selectedPluginNames);
+ return;
+ }
+
+ public void undeployServerPlugins() {
+ List<Plugin> selectedPlugins = getSelectedServerPlugins();
+ List<String> selectedPluginNames = new ArrayList<String>();
+ for (Plugin selectedPlugin : selectedPlugins) {
+ selectedPluginNames.add(selectedPlugin.getName());
+ }
+ serverPluginsBean.undeployServerPlugins(getIds(selectedPlugins));
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Undeployed server plugins: " + selectedPluginNames);
+ return;
+ }
+
+ private List<Integer> getIds(List<Plugin> plugins) {
+ ArrayList<Integer> ids = new ArrayList<Integer>(plugins.size());
+ for (Plugin plugin : plugins) {
+ ids.add(plugin.getId());
+ }
+ return ids;
+ }
+
+ private List<Plugin> getSelectedServerPlugins() {
+ Integer[] integerItems = getSelectedPluginIds();
+ List<Integer> ids = Arrays.asList(integerItems);
+ List<Plugin> plugins = serverPluginsBean.getServerPluginsById(ids);
+ return plugins;
+ }
+
+ private Integer[] getSelectedPluginIds() {
+ String[] stringItems = FacesContextUtility.getRequest().getParameterValues("selectedPlugin");
+ if (stringItems == null || stringItems.length == 0) {
+ return new Integer[0];
+ }
+ Integer[] integerItems = StringUtility.getIntegerArray(stringItems);
+ return integerItems;
+ }
+
/**
* Throws a permission exception if the user is not allowed to access this functionality.
*/
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
index 3c8a1f3..c6a5fc5 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
@@ -52,15 +52,18 @@
<h:outputLabel styleClass="BlockLabel" value="Enabled:"/>
<h:outputText value="#{InstalledPluginUIBean.plugin.enabled}"/>
+ <h:outputLabel styleClass="BlockLabel" value="Type:"/>
+ <h:outputText value="#{InstalledPluginUIBean.plugin.deployment}"/>
+
<h:outputLabel styleClass="BlockLabel" value="MD5:"/>
<h:outputText value="#{InstalledPluginUIBean.plugin.md5}"/>
- <h:outputLabel styleClass="BlockLabel" value="Path:"/>
- <h:outputText value="#{InstalledPluginUIBean.plugin.path}"/>
-
<h:outputLabel styleClass="BlockLabel" value="Description:"/>
<h:outputText value="#{InstalledPluginUIBean.plugin.description}"/>
+ <h:outputLabel styleClass="BlockLabel" value="Path:"/>
+ <h:outputText value="#{InstalledPluginUIBean.plugin.path}"/>
+
</h:panelGrid>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
index a2d5782..9f7f6b7 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
@@ -77,6 +77,7 @@
<h:outputLink value="/rhq/admin/plugin/plugin-details.xhtml">
<f:param name="plugin" value="#{agentPlugin.name}"/>
+ <f:param name="pluginType" value="AGENT"/>
<h:outputText value="#{agentPlugin.displayName}"/>
</h:outputLink>
@@ -161,6 +162,7 @@
<h:outputLink value="/rhq/admin/plugin/plugin-details.xhtml">
<f:param name="plugin" value="#{serverPlugin.name}"/>
+ <f:param name="pluginType" value="SERVER"/>
<h:outputText value="#{serverPlugin.displayName}"/>
</h:outputLink>
@@ -200,6 +202,15 @@
<h:commandButton action="#{InstalledPluginsUIBean.scan}"
value="SCAN FOR UPDATES" styleClass="on-pager-button buttonsmall">
</h:commandButton>
+ <onc:selectCommandButton action="#{InstalledPluginsUIBean.enableServerPlugins}"
+ value="ENABLE" target="selectedPlugin" styleClass="on-pager-button buttonsmall">
+ </onc:selectCommandButton>
+ <onc:selectCommandButton action="#{InstalledPluginsUIBean.disableServerPlugins}"
+ value="DISABLE" target="selectedPlugin" styleClass="on-pager-button buttonsmall">
+ </onc:selectCommandButton>
+ <onc:selectCommandButton action="#{InstalledPluginsUIBean.undeployServerPlugins}"
+ value="UNDEPLOY" target="selectedPlugin" styleClass="on-pager-button buttonsmall">
+ </onc:selectCommandButton>
</rich:column>
</rich:columnGroup>
</f:facet>
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 e0600e6..5112347 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
@@ -73,7 +73,7 @@ import org.rhq.enterprise.server.util.LookupUtil;
* @author John Mazzitelli
*/
public class AgentPluginScanner {
- private Log log = LogFactory.getLog(PluginDeploymentScanner.class);
+ private Log log = LogFactory.getLog(AgentPluginScanner.class);
private DatabaseType dbType = null;
@@ -92,7 +92,7 @@ public class AgentPluginScanner {
void registerAgentPlugins() throws Exception {
for (DeploymentInfo di : this.scanned) {
- log.debug("Hot deploying plugin [" + di.url + "]...");
+ log.debug("Hot deploying agent plugin [" + di.url + "]...");
this.agentPluginDeployer.pluginDetected(di);
}
this.scanned.clear();
@@ -124,7 +124,7 @@ public class AgentPluginScanner {
for (File updatedFile : allUpdatedFiles) {
DeploymentInfo di = new DeploymentInfo(updatedFile.toURI().toURL());
- log.debug("Scan detected plugin [" + di.url + "]...");
+ log.debug("Scan detected agent plugin [" + di.url + "]...");
this.scanned.add(di);
}
return;
@@ -188,7 +188,7 @@ public class AgentPluginScanner {
updated.add(pluginJar);
}
} catch (Exception e) {
- log.warn("Failed to scan plugin [" + pluginJar + "] found on filesystem. Skipping it. Cause: " + e);
+ log.warn("Failed to scan agent plugin [" + pluginJar + "] found on filesystem. Skipping. Cause: " + e);
this.agentPluginsOnFilesystem.remove(pluginJar); // act like we never saw it
updated.remove(pluginJar);
}
@@ -219,11 +219,11 @@ public class AgentPluginScanner {
// now we need to actually delete any obsolete plugin files from the file system
for (File doomedPluginFile : doomedPluginFiles) {
if (doomedPluginFile.delete()) {
- log.info("Deleted an obsolete plugin file: " + doomedPluginFile);
+ log.info("Deleted an obsolete agent plugin file: " + doomedPluginFile);
this.agentPluginsOnFilesystem.remove(doomedPluginFile);
updated.remove(doomedPluginFile);
} else {
- log.warn("Failed to delete what was deemed an obsolete plugin file: " + doomedPluginFile);
+ log.warn("Failed to delete what was deemed an obsolete agent plugin file: " + doomedPluginFile);
}
}
@@ -276,7 +276,7 @@ public class AgentPluginScanner {
// get all the plugins
ps = conn.prepareStatement("SELECT NAME, PATH, MD5, MTIME, VERSION FROM " + Plugin.TABLE_NAME
- + " WHERE ENABLED=?");
+ + " WHERE DEPLOYMENT = 'AGENT' AND ENABLED=?");
setEnabledFlag(conn, ps, 1, true);
rs = ps.executeQuery();
while (rs.next()) {
@@ -341,10 +341,10 @@ public class AgentPluginScanner {
updatedPlugins.add(dbPlugin);
if (currentFile.delete()) {
- log.info("Deleted the obsolete plugin file to be updated: " + currentFile);
+ log.info("Deleted the obsolete agent plugin file to be updated: " + currentFile);
this.agentPluginsOnFilesystem.remove(currentFile);
} else {
- log.warn("Failed to delete the obsolete (to-be-updated) plugin file: " + currentFile);
+ log.warn("Failed to delete the obsolete (to-be-updated) agent plugin file: " + currentFile);
}
currentFile = null;
} else if (obsoletePlugin == null) {
@@ -354,7 +354,7 @@ public class AgentPluginScanner {
cachedPluginOnFilesystem.setVersion(version);
cachedPluginOnFilesystem.setMd5(md5);
} else {
- log.info("It appears that the plugin [" + dbPlugin
+ log.info("It appears that the agent plugin [" + dbPlugin
+ "] in the database may be obsolete. If so, it will be updated by the plugin deployer.");
}
} else {
@@ -369,7 +369,8 @@ public class AgentPluginScanner {
JDBCUtil.safeClose(ps, rs);
// write all our updated plugins to the file system
- ps = conn.prepareStatement("SELECT CONTENT FROM " + Plugin.TABLE_NAME + " WHERE NAME = ? AND ENABLED = ?");
+ ps = conn.prepareStatement("SELECT CONTENT FROM " + Plugin.TABLE_NAME
+ + " WHERE DEPLOYMENT = 'AGENT' AND NAME = ? AND ENABLED = ?");
for (Plugin plugin : updatedPlugins) {
File file = new File(this.agentPluginDeployer.getPluginDir(), plugin.getPath());
@@ -548,7 +549,8 @@ public class AgentPluginScanner {
ResultSet rs = null;
TransactionManager tm = null;
- String sql = "UPDATE " + Plugin.TABLE_NAME + " SET CONTENT = ?, MD5 = ?, MTIME = ?, PATH = ? WHERE NAME = ?";
+ String sql = "UPDATE " + Plugin.TABLE_NAME
+ + " SET CONTENT = ?, MD5 = ?, MTIME = ?, PATH = ? WHERE DEPLOYMENT = 'AGENT' AND NAME = ?";
// if 'different' is true, give bogus data so the plugin deployer will think the plugin on the file system is new
String md5 = (!different) ? MessageDigestGenerator.getDigestString(file) : "TO BE UPDATED";
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 91bb8bd..9b8df52 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
@@ -48,15 +48,15 @@ public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
/** handles the scheduled scanning */
private ScheduledExecutorService poller;
- /** where the server-side plugins live */
- private File serverPluginDir = null;
-
/** where the user can copy agent or server plugins */
private File userPluginDir = null;
/** what looks for new or changed agent plugins */
private AgentPluginScanner agentPluginScanner = new AgentPluginScanner();
+ /** what looks for new or changed agent plugins */
+ private ServerPluginScanner serverPluginScanner = new ServerPluginScanner();
+
public Long getScanPeriod() {
return Long.valueOf(this.scanPeriod);
}
@@ -78,11 +78,11 @@ public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
}
public File getServerPluginDir() {
- return this.serverPluginDir;
+ return this.serverPluginScanner.getServerPluginDir();
}
public void setServerPluginDir(File dir) {
- this.serverPluginDir = dir;
+ this.serverPluginScanner.setServerPluginDir(dir);
}
public File getAgentPluginDir() {
@@ -167,6 +167,8 @@ public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
// scan for agent plugins
this.agentPluginScanner.agentPluginScan();
+ // scan for server plugins
+ this.serverPluginScanner.serverPluginScan();
return;
}
@@ -176,6 +178,9 @@ public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
// now tell the agent plugin scanner to register plugins that it determined needs to be registered
this.agentPluginScanner.registerAgentPlugins();
+
+ // tell the server plugin scanner the same
+ this.serverPluginScanner.registerServerPlugins();
}
/**
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
new file mode 100644
index 0000000..55a4960
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
@@ -0,0 +1,491 @@
+/*
+ * 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.core.plugin;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.InputStream;
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.sql.DataSource;
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.db.DatabaseType;
+import org.rhq.core.db.DatabaseTypeFactory;
+import org.rhq.core.db.H2DatabaseType;
+import org.rhq.core.db.OracleDatabaseType;
+import org.rhq.core.db.PostgresqlDatabaseType;
+import org.rhq.core.db.SQLServerDatabaseType;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.core.util.jdbc.JDBCUtil;
+import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
+
+/**
+ * This looks at both the file system and the database for new server plugins.
+ *
+ * @author John Mazzitelli
+ */
+public class ServerPluginScanner {
+ private Log log = LogFactory.getLog(ServerPluginScanner.class);
+
+ private DatabaseType dbType = null;
+
+ /** a list of server plugins found on previous scans that have not yet been processed */
+ private List<URL> scanned = new ArrayList<URL>();
+
+ /** Maintains a cache of what we had on the filesystem during the last scan */
+ private Map<File, Plugin> serverPluginsOnFilesystem = new HashMap<File, Plugin>();
+
+ private File serverPluginDir;
+
+ public ServerPluginScanner() {
+ }
+
+ public File getServerPluginDir() {
+ return this.serverPluginDir;
+ }
+
+ public void setServerPluginDir(File dir) {
+ this.serverPluginDir = dir;
+ }
+
+ /**
+ * This should be called after a call to {@link #serverPluginScan()} to register
+ * plugins that were found in the scan.
+ *
+ * @throws Exception
+ */
+ void registerServerPlugins() throws Exception {
+ for (URL url : this.scanned) {
+ log.debug("Hot deploying server plugin [" + url + "]...");
+ //this.agentPluginDeployer.pluginDetected(di);
+ }
+ this.scanned.clear();
+
+ // Register all the new plugins.
+ //this.agentPluginDeployer.registerPlugins();
+
+ return;
+ }
+
+ /**
+ * This method just scans the filesystem and DB for server plugin changes but makes
+ * no attempt to register the plugins.
+ *
+ * @throws Exception
+ */
+ void serverPluginScan() throws Exception {
+ log.debug("Scanning for server plugins");
+
+ if (this.getServerPluginDir() == null || !this.getServerPluginDir().isDirectory()) {
+ // nothing to do since there is no plugin directory configured
+ return;
+ }
+
+ // ensure that the filesystem and database are in a consistent state
+ List<File> updatedFiles1 = serverPluginScanFilesystem();
+ List<File> updatedFiles2 = serverPluginScanDatabase();
+
+ // process any newly detected plugins
+ List<File> allUpdatedFiles = new ArrayList<File>();
+ allUpdatedFiles.addAll(updatedFiles1);
+ allUpdatedFiles.addAll(updatedFiles2);
+
+ for (File updatedFile : allUpdatedFiles) {
+ URL url = updatedFile.toURI().toURL();
+ log.debug("Scan detected server plugin [" + url + "]...");
+ this.scanned.add(url);
+ }
+ return;
+ }
+
+ /**
+ * 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> serverPluginScanFilesystem() {
+ List<File> updated = new ArrayList<File>();
+
+ // get the current list of plugins deployed on the filesystem
+ File[] pluginJars = this.getServerPluginDir().listFiles(new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return name.endsWith(".jar");
+ }
+ });
+
+ // refresh our cache so it reflects what is currently on the filesystem
+ // first we remove any jar files in our cache that we no longer have on the filesystem
+ ArrayList<File> doomedPluginFiles = new ArrayList<File>();
+ for (File cachedPluginFile : this.serverPluginsOnFilesystem.keySet()) {
+ boolean existsOnFileSystem = false;
+ for (File filesystemPluginFile : pluginJars) {
+ if (cachedPluginFile.equals(filesystemPluginFile)) {
+ existsOnFileSystem = true;
+ continue; // our cached jar still exists on the file system
+ }
+ }
+ if (!existsOnFileSystem) {
+ doomedPluginFiles.add(cachedPluginFile); // this plugin file has been deleted from the filesystem, remove it from the cache
+ }
+ }
+ for (File deletedPluginFile : doomedPluginFiles) {
+ this.serverPluginsOnFilesystem.remove(deletedPluginFile);
+ }
+
+ // now insert new cache items representing new jar files and update existing ones as appropriate
+ for (File pluginJar : pluginJars) {
+ String md5 = null;
+
+ Plugin plugin = this.serverPluginsOnFilesystem.get(pluginJar);
+ try {
+ if (plugin != null) {
+ if (pluginJar.lastModified() == 0L) {
+ // for some reason the operating system can't give us the last mod time, we need to do MD5 check
+ md5 = MessageDigestGenerator.getDigestString(pluginJar);
+ if (!md5.equals(plugin.getMd5())) {
+ plugin = null; // this plugin jar has changed - force it to refresh the cache.
+ }
+ } else if (pluginJar.lastModified() != plugin.getMtime()) {
+ plugin = null; // this plugin jar has changed - force it to refresh the cache.
+ }
+ }
+
+ if (plugin == null) {
+ cacheFilesystemServerPluginJar(pluginJar, md5);
+ updated.add(pluginJar);
+ }
+ } catch (Exception e) {
+ log.warn("Failed to scan server plugin [" + pluginJar + "] found on filesystem. Skipping. Cause: " + e);
+ this.serverPluginsOnFilesystem.remove(pluginJar); // act like we never saw it
+ updated.remove(pluginJar);
+ }
+ }
+
+ // Let's check to see if there are any obsolete plugins that need to be deleted.
+ // This is needed if plugin-A-1.0.jar exists and someone deployed plugin-A-1.1.jar but fails to delete plugin-A-1.0.jar.
+ doomedPluginFiles.clear();
+ HashMap<String, Plugin> pluginsByName = new HashMap<String, Plugin>();
+ for (Map.Entry<File, Plugin> currentPluginFileEntry : this.serverPluginsOnFilesystem.entrySet()) {
+ Plugin currentPlugin = currentPluginFileEntry.getValue();
+ Plugin existingPlugin = pluginsByName.get(currentPlugin.getName());
+ if (existingPlugin == null) {
+ // this is the usual case - this is the only plugin with the given name we've seen
+ pluginsByName.put(currentPlugin.getName(), currentPlugin);
+ } else {
+ Plugin obsolete = ServerPluginDescriptorUtil.determineObsoletePlugin(currentPlugin, existingPlugin);
+ if (obsolete == null) {
+ obsolete = currentPlugin; // both were identical, but we only want one file so pick one to get rid of
+ }
+ doomedPluginFiles.add(new File(this.getServerPluginDir(), obsolete.getPath()));
+ if (obsolete == existingPlugin) { // yes use == for reference equality!
+ pluginsByName.put(currentPlugin.getName(), currentPlugin); // override the original one we saw with this latest one
+ }
+ }
+ }
+
+ // now we need to actually delete any obsolete plugin files from the file system
+ for (File doomedPluginFile : doomedPluginFiles) {
+ if (doomedPluginFile.delete()) {
+ log.info("Deleted an obsolete server plugin file: " + doomedPluginFile);
+ this.serverPluginsOnFilesystem.remove(doomedPluginFile);
+ updated.remove(doomedPluginFile);
+ } else {
+ log.warn("Failed to delete what was deemed an obsolete server plugin file: " + doomedPluginFile);
+ }
+ }
+
+ return updated;
+ }
+
+ /**
+ * Creates a {@link Plugin} object for the given plugin jar and caches it.
+ * @param pluginJar information about this plugin jar will be cached
+ * @param md5 if known, this is the plugin jar's MD5, <code>null</code> if not known
+ * @return the plugin jar files's information that has been cached
+ * @throws Exception if failed to get information about the plugin
+ */
+ private Plugin cacheFilesystemServerPluginJar(File pluginJar, String md5) throws Exception {
+ if (md5 == null) { // don't calculate the MD5 is we've already done it before
+ md5 = MessageDigestGenerator.getDigestString(pluginJar);
+ }
+ URL pluginUrl = pluginJar.toURI().toURL();
+ ServerPluginDescriptorType descriptor = ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginUrl);
+ String version = ServerPluginDescriptorUtil.getPluginVersion(pluginJar, descriptor).toString();
+ String name = descriptor.getName();
+ Plugin plugin = new Plugin(name, pluginJar.getName());
+ plugin.setMd5(md5);
+ plugin.setVersion(version);
+ plugin.setMtime(pluginJar.lastModified());
+ plugin.setDeployment(PluginDeploymentType.SERVER);
+ this.serverPluginsOnFilesystem.put(pluginJar, plugin);
+ return plugin;
+ }
+
+ /**
+ * This method scans the database for any new or updated server plugins and make sure this server
+ * has a plugin file on the filesystem for each of those new/updated server plugins.
+ *
+ * @return a list of files that appear to be new or updated and should be deployed
+ */
+ List<File> serverPluginScanDatabase() throws Exception {
+ Connection conn = null;
+ PreparedStatement ps = null;
+ ResultSet rs = null;
+
+ // these are plugins (name/path/md5/mtime) that have changed in the DB but are missing from the file system
+ List<Plugin> updatedPlugins = new ArrayList<Plugin>();
+
+ // the same list as above, only they are the files that are written to the filesystem and no longer missing
+ List<File> updatedFiles = new ArrayList<File>();
+
+ try {
+ DataSource ds = LookupUtil.getDataSource();
+ conn = ds.getConnection();
+
+ // get all the plugins
+ ps = conn.prepareStatement("SELECT NAME, PATH, MD5, MTIME, VERSION FROM " + Plugin.TABLE_NAME
+ + " WHERE DEPLOYMENT = 'SERVER' AND ENABLED=?");
+ setEnabledFlag(conn, ps, 1, true);
+ rs = ps.executeQuery();
+ while (rs.next()) {
+ String name = rs.getString(1);
+ String path = rs.getString(2);
+ String md5 = rs.getString(3);
+ long mtime = rs.getLong(4);
+ String version = rs.getString(5);
+
+ // let's see if we have this logical plugin on the filesystem (it may or may not be under the same filename)
+ File expectedFile = new File(this.getServerPluginDir(), path);
+ File currentFile = null; // will be non-null if we find that we have this plugin on the filesystem already
+ Plugin cachedPluginOnFilesystem = this.serverPluginsOnFilesystem.get(expectedFile);
+
+ if (cachedPluginOnFilesystem != null) {
+ currentFile = expectedFile; // we have it where we are expected to have it
+ if (!cachedPluginOnFilesystem.getName().equals(name)) {
+ // I have no idea when or if this would ever happen, but at least log it so we'll see it if it does happen
+ log.warn("For some reason, the server plugin file [" + expectedFile + "] is plugin ["
+ + cachedPluginOnFilesystem.getName() + "] but the database says it should be [" + name
+ + "]");
+ } else {
+ log.debug("File system and database agree on a server plugin location for [" + expectedFile
+ + "]");
+ }
+ } else {
+ // the plugin might still be on the file system but under a different filename, see if we can find it
+ for (Map.Entry<File, Plugin> cachePluginEntry : this.serverPluginsOnFilesystem.entrySet()) {
+ if (cachePluginEntry.getValue().getName().equals(name)) {
+ currentFile = cachePluginEntry.getKey();
+ cachedPluginOnFilesystem = cachePluginEntry.getValue();
+ log.info("Filesystem has a server plugin [" + name + "] at the file [" + currentFile
+ + "] which is different than where the DB thinks it should be [" + expectedFile + "]");
+ break; // we found it, no need to continue the loop
+ }
+ }
+ }
+
+ if (cachedPluginOnFilesystem != null && currentFile != null && currentFile.exists()) {
+ Plugin dbPlugin = new Plugin(name, path);
+ dbPlugin.setMd5(md5);
+ dbPlugin.setVersion(version);
+ dbPlugin.setMtime(mtime);
+ dbPlugin.setDeployment(PluginDeploymentType.SERVER);
+
+ Plugin obsoletePlugin = ServerPluginDescriptorUtil.determineObsoletePlugin(dbPlugin,
+ cachedPluginOnFilesystem);
+
+ if (obsoletePlugin == cachedPluginOnFilesystem) { // yes use == for reference equality!
+ StringBuilder logMsg = new StringBuilder();
+ logMsg.append("Found server plugin [").append(name);
+ logMsg.append("] in the DB that is newer than the one on the filesystem: ");
+ logMsg.append("DB path=[").append(path);
+ logMsg.append("]; file path=[").append(currentFile.getName());
+ logMsg.append("]; DB MD5=[").append(md5);
+ logMsg.append("]; file MD5=[").append(cachedPluginOnFilesystem.getMd5());
+ logMsg.append("]; DB version=[").append(version);
+ logMsg.append("]; file version=[").append(cachedPluginOnFilesystem.getVersion());
+ logMsg.append("]; DB timestamp=[").append(new Date(mtime));
+ logMsg.append("]; file timestamp=[").append(new Date(cachedPluginOnFilesystem.getMtime()));
+ logMsg.append("]");
+ log.info(logMsg.toString());
+
+ updatedPlugins.add(dbPlugin);
+
+ if (currentFile.delete()) {
+ log.info("Deleted the obsolete server plugin file to be updated: " + currentFile);
+ this.serverPluginsOnFilesystem.remove(currentFile);
+ } else {
+ log
+ .warn("Failed to delete the obsolete (to-be-updated) server plugin file: "
+ + currentFile);
+ }
+ currentFile = null;
+ } else if (obsoletePlugin == null) {
+ // the db is up-to-date, but update the cache so we don't check MD5 or parse the descriptor again
+ currentFile.setLastModified(mtime);
+ cachedPluginOnFilesystem.setMtime(mtime);
+ cachedPluginOnFilesystem.setVersion(version);
+ cachedPluginOnFilesystem.setMd5(md5);
+ } else {
+ log.info("It appears that the server plugin [" + dbPlugin
+ + "] in the database may be obsolete. If so, it will be updated later.");
+ }
+ } else {
+ log.info("Found server plugin in the DB that we do not yet have: " + name);
+ Plugin plugin = new Plugin(name, path, md5);
+ plugin.setMtime(mtime);
+ plugin.setVersion(version);
+ plugin.setDeployment(PluginDeploymentType.SERVER);
+ updatedPlugins.add(plugin);
+ this.serverPluginsOnFilesystem.remove(expectedFile); // paranoia, make sure the cache doesn't have this
+ }
+ }
+ JDBCUtil.safeClose(ps, rs);
+
+ // write all our updated plugins to the file system
+ ps = conn.prepareStatement("SELECT CONTENT FROM " + Plugin.TABLE_NAME
+ + " WHERE DEPLOYMENT = 'SERVER' AND NAME = ? AND ENABLED = ?");
+ for (Plugin plugin : updatedPlugins) {
+ File file = new File(this.getServerPluginDir(), plugin.getPath());
+
+ ps.setString(1, plugin.getName());
+ setEnabledFlag(conn, ps, 2, true);
+ rs = ps.executeQuery();
+ rs.next();
+ InputStream content = rs.getBinaryStream(1);
+ StreamUtil.copy(content, new FileOutputStream(file));
+ rs.close();
+ file.setLastModified(plugin.getMtime()); // so our file matches the database mtime
+ updatedFiles.add(file);
+ }
+ } finally {
+ JDBCUtil.safeClose(conn, ps, rs);
+ }
+
+ return updatedFiles;
+ }
+
+ private void setEnabledFlag(Connection conn, PreparedStatement ps, int index, boolean enabled) throws Exception {
+ if (null == this.dbType) {
+ this.dbType = DatabaseTypeFactory.getDatabaseType(conn);
+ }
+ if (dbType instanceof PostgresqlDatabaseType || dbType instanceof H2DatabaseType) {
+ ps.setBoolean(index, enabled);
+ } else if (dbType instanceof OracleDatabaseType || dbType instanceof SQLServerDatabaseType) {
+ ps.setInt(index, (enabled ? 1 : 0));
+ } else {
+ throw new RuntimeException("Unknown database type : " + dbType);
+ }
+ }
+
+ /**
+ * This will write the contents of the given plugin file to the database.
+ * This will store both the contents and the MD5 in an atomic transaction
+ * so they remain insync.
+ *
+ * When <code>different</code> is <code>false</code>, it means the original
+ * plugin and the one currently found on the file system are the same.
+ *
+ * When <code>different</code> is <code>true</code>, it means the plugin
+ * is most likely a different one than the one that originally existed.
+ * When this happens, it is assumed that the we need
+ * to see the plugin on the file system as new and needing to be processed, therefore
+ * the MD5, CONTENT and MTIME columns will be updated to ensure the deployer
+ * will process this plugin and thus update all the metadata for this plugin.
+ *
+ * @param name the name of the plugin whose content is being updated
+ * @param file the plugin file whose content will be streamed to the database
+ * @param different this will be <code>true</code> if the given file has a different filename
+ * that the plugin's "path" as found in the database.
+ *
+ *
+ * @throws Exception
+ */
+ private void streamPluginFileContentToDatabase(String name, File file, boolean different) throws Exception {
+ Connection conn = null;
+ PreparedStatement ps = null;
+ ResultSet rs = null;
+ TransactionManager tm = null;
+
+ String sql = "UPDATE " + Plugin.TABLE_NAME
+ + " SET CONTENT = ?, MD5 = ?, MTIME = ?, PATH = ? WHERE DEPLOYMENT = 'SERVER' AND NAME = ?";
+
+ // if 'different' is true, give bogus data so the plugin deployer will think the plugin on the file system is new
+ String md5 = (!different) ? MessageDigestGenerator.getDigestString(file) : "TO BE UPDATED";
+ long mtime = (!different) ? file.lastModified() : 0L;
+ InputStream fis = (!different) ? new FileInputStream(file) : new ByteArrayInputStream(new byte[0]);
+ int contentSize = (int) ((!different) ? file.length() : 0);
+
+ try {
+ tm = LookupUtil.getTransactionManager();
+ tm.begin();
+ DataSource ds = LookupUtil.getDataSource();
+ conn = ds.getConnection();
+ ps = conn.prepareStatement(sql);
+ ps.setBinaryStream(1, new BufferedInputStream(fis), contentSize);
+ ps.setString(2, md5);
+ ps.setLong(3, mtime);
+ ps.setString(4, file.getName());
+ ps.setString(5, name);
+ int updateResults = ps.executeUpdate();
+ if (updateResults == 1) {
+ log.info("Stored content for plugin [" + name + "] in the db. file=" + file);
+ } else {
+ throw new Exception("Failed to update content for plugin [" + name + "] from [" + file + "]");
+ }
+ } catch (Exception e) {
+ tm.rollback();
+ tm = null;
+ throw e;
+ } finally {
+ JDBCUtil.safeClose(conn, ps, rs);
+
+ try {
+ fis.close();
+ } catch (Throwable t) {
+ }
+
+ if (tm != null) {
+ tm.commit();
+ }
+ }
+ return;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 1e41913..6eb6fc7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -19,9 +19,13 @@
package org.rhq.enterprise.server.plugin;
+import java.util.ArrayList;
import java.util.List;
+import javax.ejb.EJB;
import javax.ejb.Stateless;
+import javax.ejb.TransactionAttribute;
+import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
@@ -29,6 +33,7 @@ import javax.persistence.Query;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
import org.rhq.enterprise.server.RHQConstants;
+import org.rhq.enterprise.server.util.LookupUtil;
/**
* A server API into the server plugin infrastructure.
@@ -41,6 +46,9 @@ public class ServerPluginsBean implements ServerPluginsLocal {
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
private EntityManager entityManager;
+ @EJB
+ private ServerPluginsLocal serverPluginsBean; //self
+
public List<Plugin> getServerPlugins() {
Query q = entityManager.createNamedQuery(Plugin.QUERY_FIND_ALL_SERVER);
return q.getResultList();
@@ -55,4 +63,42 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
return plugin;
}
+
+ public List<Plugin> getServerPluginsById(List<Integer> pluginIds) {
+ if (pluginIds == null || pluginIds.size() == 0) {
+ return new ArrayList<Plugin>();
+ }
+ Query query = entityManager.createNamedQuery(Plugin.QUERY_FIND_BY_IDS_AND_TYPE);
+ query.setParameter("ids", pluginIds);
+ query.setParameter("type", PluginDeploymentType.SERVER);
+ return query.getResultList();
+ }
+
+ public void enableServerPlugins(List<Integer> pluginIds) {
+ serverPluginsBean.setPluginEnabledFlag(pluginIds, true);
+ LookupUtil.getServerPluginService().restartMasterPluginContainer();
+ return;
+ }
+
+ public void disableServerPlugins(List<Integer> pluginIds) {
+ serverPluginsBean.setPluginEnabledFlag(pluginIds, false);
+ LookupUtil.getServerPluginService().restartMasterPluginContainer();
+ return;
+ }
+
+ public void undeployServerPlugins(List<Integer> pluginIds) {
+ serverPluginsBean.setPluginEnabledFlag(pluginIds, false);
+ // TODO: actually mark the plugins as deleted, remove their files
+ LookupUtil.getServerPluginService().restartMasterPluginContainer();
+ return;
+ }
+
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public void setPluginEnabledFlag(List<Integer> pluginIds, boolean enabled) {
+ List<Plugin> plugins = getServerPluginsById(pluginIds);
+ for (Plugin plugin : plugins) {
+ plugin.setEnabled(enabled);
+ }
+ }
+
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index 92f8c7c..c8ab236 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -28,4 +28,35 @@ public interface ServerPluginsLocal {
* @throws NoResultException when no plugin with that name exists
*/
Plugin getServerPlugin(String name);
+
+ List<Plugin> getServerPluginsById(List<Integer> pluginIds);
+
+ /**
+ * Enables the plugins and restarts the server plugin container.
+ *
+ * @param pluginIds the plugins to be enabled
+ */
+ void enableServerPlugins(List<Integer> pluginIds);
+
+ /**
+ * Disables the plugins and restarts the server plugin container.
+ *
+ * @param pluginIds the plugins to be disabled
+ */
+ void disableServerPlugins(List<Integer> pluginIds);
+
+ /**
+ * Removes the plugin from the system and restarts the server plugin container.
+ *
+ * @param pluginIds
+ */
+ void undeployServerPlugins(List<Integer> pluginIds);
+
+ /**
+ * Turns on or off the enabled flag in the database but does NOT restart the server plugin container.
+ *
+ * @param pluginIds the plugins to be enabled
+ * @param enabled the value of the enabled flag for the plugins
+ */
+ void setPluginEnabledFlag(List<Integer> pluginIds, boolean enabled);
}
commit e6472fc0865b41d04259402fbaa8644d4da69108
Author: John Matthews <jmatthew(a)redhat.com>
Date: Wed Nov 18 18:25:25 2009 -0500
Fixes primary.xml/repomd.xml generation for packages.
metadata for <location href=""> can not be blank,
this breaks generation of a yum primary.xml
See org.rhq.plugins.platform.content.yum.Primary, it expects an href="...." value to exist
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/PrimaryXML.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/PrimaryXML.java
index c40a338..6fe726b 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/PrimaryXML.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/PrimaryXML.java
@@ -18,68 +18,66 @@
*/
package org.rhq.enterprise.server.plugins.rhnhosted;
-import java.util.List;
import java.io.Serializable;
+import java.util.List;
-import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageType;
-import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageProvidesType;
-import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageProvidesEntryType;
-import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageRequiresType;
-import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageRequiresEntryType;
-import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageObsoletesType;
-import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageObsoletesEntryType;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.jdom.Element;
import org.jdom.output.XMLOutputter;
-import org.apache.commons.logging.LogFactory;
-import org.apache.commons.logging.Log;
+
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageObsoletesType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageProvidesEntryType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageProvidesType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageRequiresEntryType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageRequiresType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageType;
/**
* @author John Matthews
*/
-public class PrimaryXML
-{
- /** Example package element from primary.xml used by yum
- *
-
- <package type="rpm">
- <name>gnome-user-docs</name>
- <arch>noarch</arch>
- <version ver="2.16.0" rel="2.fc6" epoch="0"/>
- <checksum type="md5" pkgid="YES">4e7d379301407b4c79f211596b802a13</checksum>
- <summary>GNOME User Documentation</summary>
- <description>This package contains end user documentation for the GNOME desktop environment.</description>
- <packager/>
- <url/>
- <time file="1157750823" build="1157750823"/>
- <size package="6549456" archive="11858600" installed=""/>
- <location href="getPackage/gnome-user-docs-2.16.0-2.fc6.noarch.rpm"/>
- <format>
- <rpm:license>FDL</rpm:license>
- <rpm:vendor>Red Hat, Inc.</rpm:vendor>
- <rpm:group>Documentation</rpm:group>
- <rpm:buildhost>altix2.build.redhat.com</rpm:buildhost>
- <rpm:sourcerpm>gnome-user-docs-2.16.0-2.fc6.src.rpm</rpm:sourcerpm>
- <rpm:header-range start="440" end="97656"/>
- <rpm:provides>
- <rpm:entry name="gnome-user-docs" flags="EQ" epoch="0" ver="2.16.0" rel="2.fc6"/>
- </rpm:provides>
- <rpm:requires>
- <rpm:entry name="/bin/sh"/>
- <rpm:entry name="/bin/sh"/>
- <rpm:entry name="rpmlib(CompressedFileNames)" flags="LE" epoch="0" ver="3.0.4" rel="1"/>
- <rpm:entry name="rpmlib(PayloadFilesHavePrefix)" flags="LE" epoch="0" ver="4.0" rel="1"/>
- <rpm:entry name="rpmlib(VersionedDependencies)" flags="LE" epoch="0" ver="3.0.3" rel="1"/>
- <rpm:entry name="scrollkeeper" flags="GE" epoch="0" ver="0.3.11"/>
- </rpm:requires>
- <rpm:conflicts/>
- <rpm:obsoletes>
- <rpm:entry name="gnome-users-guide"/>
- </rpm:obsoletes>
- </format>
-</package>
-
- **/
+public class PrimaryXML {
+ /** Example package element from primary.xml used by yum
+ *
+ <package type="rpm">
+ <name>gnome-user-docs</name>
+ <arch>noarch</arch>
+ <version ver="2.16.0" rel="2.fc6" epoch="0"/>
+ <checksum type="md5" pkgid="YES">4e7d379301407b4c79f211596b802a13</checksum>
+ <summary>GNOME User Documentation</summary>
+ <description>This package contains end user documentation for the GNOME desktop environment.</description>
+ <packager/>
+ <url/>
+ <time file="1157750823" build="1157750823"/>
+ <size package="6549456" archive="11858600" installed=""/>
+ <location href="getPackage/gnome-user-docs-2.16.0-2.fc6.noarch.rpm"/>
+ <format>
+ <rpm:license>FDL</rpm:license>
+ <rpm:vendor>Red Hat, Inc.</rpm:vendor>
+ <rpm:group>Documentation</rpm:group>
+ <rpm:buildhost>altix2.build.redhat.com</rpm:buildhost>
+ <rpm:sourcerpm>gnome-user-docs-2.16.0-2.fc6.src.rpm</rpm:sourcerpm>
+ <rpm:header-range start="440" end="97656"/>
+ <rpm:provides>
+ <rpm:entry name="gnome-user-docs" flags="EQ" epoch="0" ver="2.16.0" rel="2.fc6"/>
+ </rpm:provides>
+ <rpm:requires>
+ <rpm:entry name="/bin/sh"/>
+ <rpm:entry name="/bin/sh"/>
+ <rpm:entry name="rpmlib(CompressedFileNames)" flags="LE" epoch="0" ver="3.0.4" rel="1"/>
+ <rpm:entry name="rpmlib(PayloadFilesHavePrefix)" flags="LE" epoch="0" ver="4.0" rel="1"/>
+ <rpm:entry name="rpmlib(VersionedDependencies)" flags="LE" epoch="0" ver="3.0.3" rel="1"/>
+ <rpm:entry name="scrollkeeper" flags="GE" epoch="0" ver="0.3.11"/>
+ </rpm:requires>
+ <rpm:conflicts/>
+ <rpm:obsoletes>
+ <rpm:entry name="gnome-users-guide"/>
+ </rpm:obsoletes>
+ </format>
+ </package>
+
+ **/
/** RPM uses bit flags to determine if a package relationships is "Greater, LessThan, Equals";
* These values can be found from running the python console and executing
@@ -96,14 +94,11 @@ public class PrimaryXML
int flags = tmp & (RPM_SENSE_LESS | RPM_SENSE_GREATER | RPM_SENSE_EQUAL);
if (flags == (RPM_SENSE_LESS | RPM_SENSE_EQUAL)) {
return "LE";
- }
- else if (flags == RPM_SENSE_LESS) {
+ } else if (flags == RPM_SENSE_LESS) {
return "LT";
- }
- else if (flags == (RPM_SENSE_GREATER | RPM_SENSE_EQUAL)) {
+ } else if (flags == (RPM_SENSE_GREATER | RPM_SENSE_EQUAL)) {
return "GE";
- }
- else if (flags == (RPM_SENSE_GREATER)) {
+ } else if (flags == (RPM_SENSE_GREATER)) {
return "GT";
} else if (flags == (RPM_SENSE_EQUAL)) {
return "EQ";
@@ -141,7 +136,7 @@ public class PrimaryXML
}
return tmp.substring(start, end);
}
-
+
static public String getRelease(String version) {
int start = version.indexOf("-");
if (start < 0) {
@@ -214,8 +209,10 @@ public class PrimaryXML
top.addContent(size);
Element location = new Element("location");
- //TODO: Unsure about href
- location.setAttribute("href", "");
+ //This value can not be empty and can not contain a "?".
+ //It's value is ignored by the RHQ processing for yum.
+ //RHQ will append a series of request parameters to download the file.
+ location.setAttribute("href", "getPackage");
top.addContent(location);
Element format = new Element("format");
@@ -246,10 +243,10 @@ public class PrimaryXML
format.addContent(rpmHeaderRange);
Element rpmProvides = new Element("provides", "rpm");
- RhnPackageProvidesType provides_type = pkg.getRhnPackageProvides();
+ RhnPackageProvidesType provides_type = pkg.getRhnPackageProvides();
if (provides_type != null) {
List<RhnPackageProvidesEntryType> provides = provides_type.getRhnPackageProvidesEntry();
- for (RhnPackageProvidesEntryType provEntry: provides) {
+ for (RhnPackageProvidesEntryType provEntry : provides) {
Element entry = new Element("entry", "rpm");
entry.setAttribute("name", provEntry.getName());
entry.setAttribute("flags", getFlags(provEntry.getSense()));
@@ -265,7 +262,7 @@ public class PrimaryXML
RhnPackageRequiresType requires_type = pkg.getRhnPackageRequires();
if (requires_type != null) {
List<RhnPackageRequiresEntryType> requires = requires_type.getRhnPackageRequiresEntry();
- for (RhnPackageRequiresEntryType reqEntry: requires) {
+ for (RhnPackageRequiresEntryType reqEntry : requires) {
Element entry = new Element("entry", "rpm");
entry.setAttribute("name", reqEntry.getName());
entry.setAttribute("flags", getFlags(reqEntry.getSense()));
@@ -285,7 +282,7 @@ public class PrimaryXML
RhnPackageObsoletesType obs_type = pkg.getRhnPackageObsoletes();
if (obs_type != null) {
List<Serializable> obsoletes = obs_type.getContent();
- for (Serializable obsEntry: obsoletes) {
+ for (Serializable obsEntry : obsoletes) {
Element entry = new Element("entry", "rpm");
entry.setAttribute("name", obsEntry.toString());
rpmObsoletes.addContent(entry);
@@ -293,8 +290,8 @@ public class PrimaryXML
}
format.addContent(rpmObsoletes);
- top.addContent(format);
- XMLOutputter xmlOut = new XMLOutputter();
- return xmlOut.outputString(top);
- }
+ top.addContent(format);
+ XMLOutputter xmlOut = new XMLOutputter();
+ return xmlOut.outputString(top);
+ }
}
commit f61fade0d9411f43fec88dc30d760e5b13cbc8c4
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 18 17:55:53 2009 -0500
some APIs and some GUI work to start being able to display server plugins on the plugins UI page
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/DownloadsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/DownloadsUIBean.java
index e795fb7..56e38db 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/DownloadsUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/DownloadsUIBean.java
@@ -26,14 +26,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
-import javax.management.MBeanServer;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.ObjectName;
-
-import org.jboss.mx.util.MBeanServerLocator;
-import org.jboss.system.server.ServerConfig;
-
-import org.rhq.core.util.ObjectNameFactory;
import org.rhq.enterprise.server.util.LookupUtil;
/**
@@ -61,10 +53,6 @@ public class DownloadsUIBean implements Serializable {
}
- private MBeanServer getMBeanServer() {
- return MBeanServerLocator.locateJBoss();
- }
-
public List<File> getConnectorDownloadFiles() throws Exception {
File downloadDir = getConnectorDownloadsDir();
File[] filesArray = downloadDir.listFiles();
@@ -80,10 +68,7 @@ public class DownloadsUIBean implements Serializable {
}
private File getConnectorDownloadsDir() throws Exception {
- MBeanServer mbs = getMBeanServer();
- ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
- Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
- File serverHomeDir = ((ServerConfig) mbean).getServerHomeDir();
+ File serverHomeDir = LookupUtil.getCoreServer().getJBossServerHomeDir();
File downloadDir = new File(serverHomeDir, "deploy/rhq.ear/rhq-downloads/connectors");
if (!downloadDir.exists()) {
throw new FileNotFoundException("Missing connectors downloads directory at [" + downloadDir + "]");
@@ -92,10 +77,7 @@ public class DownloadsUIBean implements Serializable {
}
private File getClientDownloadDir() throws Exception {
- MBeanServer mbs = getMBeanServer();
- ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
- Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
- File serverHomeDir = ((ServerConfig) mbean).getServerHomeDir();
+ File serverHomeDir = LookupUtil.getCoreServer().getJBossServerHomeDir();
File downloadDir = new File(serverHomeDir, "deploy/rhq.ear/rhq-downloads/rhq-client");
if (!downloadDir.exists()) {
throw new FileNotFoundException("Missing remote client download directory at [" + downloadDir + "]");
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
index 67404ae..bfc6e52 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
@@ -37,9 +37,8 @@ import org.rhq.core.gui.util.FacesContextUtility;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
import org.rhq.enterprise.server.authz.PermissionException;
-import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceMBean;
-import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceUtil;
import org.rhq.enterprise.server.core.plugin.PluginDeploymentScannerMBean;
+import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
import org.rhq.enterprise.server.resource.metadata.ResourceMetadataManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -48,28 +47,35 @@ import org.rhq.enterprise.server.util.LookupUtil;
public class InstalledPluginsUIBean {
private final Log log = LogFactory.getLog(InstalledPluginsUIBean.class);
- public static final String MANAGED_BEAN_NAME = "InstalledPluginsUIBean";
+ public static final String MANAGED_BEAN_NAME = InstalledPluginsUIBean.class.getSimpleName();
private ResourceMetadataManagerLocal resourceMetadataManagerBean = LookupUtil.getResourceMetadataManager();
+ private ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
public InstalledPluginsUIBean() {
}
- public Collection<Plugin> getInstalledPlugins() {
- hasPermission();
+ public Collection<Plugin> getInstalledAgentPlugins() {
+ hasPermission();
return resourceMetadataManagerBean.getPlugins();
}
+ public Collection<Plugin> getInstalledServerPlugins() {
+
+ hasPermission();
+ return serverPluginsBean.getServerPlugins();
+ }
+
public void scan() {
hasPermission();
try {
PluginDeploymentScannerMBean scanner = LookupUtil.getPluginDeploymentScanner();
scanner.scanAndRegister();
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Done scanning for updated agent plugins.");
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Done scanning for updated plugins.");
} catch (Exception e) {
- String err = "Failed to scan for updated agent plugins";
+ String err = "Failed to scan for updated plugins";
log.error(err + " - Cause: " + e);
FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, err, e);
}
@@ -97,18 +103,18 @@ public class InstalledPluginsUIBean {
throw new FileNotFoundException("The uploaded plugin file [" + uploadedPlugin + "] does not exist!");
}
- // put the new plugin file in our agent plugin location
- ServerCommunicationsServiceMBean sc = ServerCommunicationsServiceUtil.getService();
- File dir = new File(sc.getConfiguration().getAgentFilesDirectory(), "rhq-plugins");
- File agentPlugin = new File(dir, newPluginFilename);
- FileOutputStream fos = new FileOutputStream(agentPlugin);
+ // put the new plugin file in our plugin dropbox location
+ File installDir = LookupUtil.getCoreServer().getInstallDir();
+ File dir = new File(installDir, "plugins");
+ File pluginFile = new File(dir, newPluginFilename);
+ FileOutputStream fos = new FileOutputStream(pluginFile);
FileInputStream fis = new FileInputStream(uploadedPlugin);
StreamUtil.copy(fis, fos);
- log.info("A new plugin has been deployed [" + agentPlugin
+ log.info("A new plugin has been deployed [" + pluginFile
+ "]. A scan is required now in order to register it.");
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "New agent plugin uploaded: " + agentPlugin);
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "New plugin uploaded: " + newPluginFilename);
} catch (Exception e) {
- String err = "Failed to process uploaded agent plugin";
+ String err = "Failed to process uploaded plugin";
log.error(err + " - Cause: " + e);
FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, err, e);
}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/client/RemoteClientServlet.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/client/RemoteClientServlet.java
index dd2b910..81d0731 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/client/RemoteClientServlet.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/client/RemoteClientServlet.java
@@ -24,20 +24,13 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
-import javax.management.MBeanServer;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.ObjectName;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.jboss.mx.util.MBeanServerLocator;
-import org.jboss.system.server.ServerConfig;
-
import org.rhq.core.domain.cloud.Server.OperationMode;
import org.rhq.core.util.MessageDigestGenerator;
-import org.rhq.core.util.ObjectNameFactory;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.enterprise.server.core.CoreServerMBean;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -172,10 +165,7 @@ public class RemoteClientServlet extends HttpServlet {
}
private File getDownloadDir() throws Exception {
- MBeanServer mbs = getMBeanServer();
- ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
- Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
- File serverHomeDir = ((ServerConfig) mbean).getServerHomeDir();
+ File serverHomeDir = LookupUtil.getCoreServer().getJBossServerHomeDir();
File downloadDir = new File(serverHomeDir, "deploy/rhq.ear/rhq-downloads/rhq-client");
if (!downloadDir.exists()) {
throw new FileNotFoundException("Missing remote client download directory at [" + downloadDir + "]");
@@ -183,10 +173,6 @@ public class RemoteClientServlet extends HttpServlet {
return downloadDir;
}
- private MBeanServer getMBeanServer() {
- return MBeanServerLocator.locateJBoss();
- }
-
private void getVersion(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
File versionFile = getVersionFile();
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/download/DownloadServlet.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/download/DownloadServlet.java
index 36a7dc5..8c1a7bb 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/download/DownloadServlet.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/download/DownloadServlet.java
@@ -26,19 +26,12 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
-import javax.management.MBeanServer;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.ObjectName;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.jboss.mx.util.MBeanServerLocator;
-import org.jboss.system.server.ServerConfig;
-
import org.rhq.core.domain.cloud.Server.OperationMode;
-import org.rhq.core.util.ObjectNameFactory;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -228,10 +221,7 @@ public class DownloadServlet extends HttpServlet {
}
private File getRootDownloadsDir() throws Exception {
- MBeanServer mbs = getMBeanServer();
- ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
- Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
- File serverHomeDir = ((ServerConfig) mbean).getServerHomeDir();
+ File serverHomeDir = LookupUtil.getCoreServer().getJBossServerHomeDir();
File downloadDir = new File(serverHomeDir, "deploy/rhq.ear/rhq-downloads");
if (!downloadDir.exists()) {
throw new FileNotFoundException("Missing downloads directory at [" + downloadDir + "]");
@@ -239,10 +229,6 @@ public class DownloadServlet extends HttpServlet {
return downloadDir;
}
- private MBeanServer getMBeanServer() {
- return MBeanServerLocator.locateJBoss();
- }
-
private boolean isServerAcceptingRequests() {
try {
OperationMode mode = LookupUtil.getServerManager().getServer().getOperationMode();
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
index 08280c7..a2d5782 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
@@ -39,12 +39,14 @@
</f:facet>
<h:panelGrid columns="1" width="100%">
+ <rich:tabPanel>
+ <rich:tab label="Agent Plugins">
- <rich:dataTable id="pluginsDataTable"
- value="#{InstalledPluginsUIBean.installedPlugins}"
- var="plugin"
+ <rich:dataTable id="agentPluginsDataTable"
+ value="#{InstalledPluginsUIBean.installedAgentPlugins}"
+ var="agentPlugin"
width="100%"
- columnsWidth="20%, 45%, 15%, 9%"
+ columnsWidth="20%, 50%, 20%, 10%"
headerClass="tableRowHeader"
footerClass="on-pager-footer"
onRowMouseOver="this.style.backgroundColor='#E7E7E7'"
@@ -56,7 +58,7 @@
<onc:allSelect target="selectedPlugin"/>
</f:facet>
- <onc:select name="selectedPlugin" value="#{plugin.id}"/>
+ <onc:select name="selectedPlugin" value="#{agentPlugin.id}"/>
</rich:column>-->
<rich:column rendered="#{param.debug}">
@@ -64,7 +66,7 @@
<h:outputText styleClass="headerText" value="ID"/>
</f:facet>
- <h:outputText value="#{plugin.id}"/>
+ <h:outputText value="#{agentPlugin.id}"/>
</rich:column>
@@ -74,8 +76,8 @@
</f:facet>
<h:outputLink value="/rhq/admin/plugin/plugin-details.xhtml">
- <f:param name="plugin" value="#{plugin.name}"/>
- <h:outputText value="#{plugin.displayName}"/>
+ <f:param name="plugin" value="#{agentPlugin.name}"/>
+ <h:outputText value="#{agentPlugin.displayName}"/>
</h:outputLink>
</rich:column>
@@ -86,7 +88,7 @@
<h:outputText styleClass="headerText" value="Description"/>
</f:facet>
- <h:outputText value="#{plugin.description}"/>
+ <h:outputText value="#{agentPlugin.description}"/>
</rich:column>
<rich:column>
@@ -94,7 +96,7 @@
<h:outputText styleClass="headerText" value="Last Update"/>
</f:facet>
- <h:outputText value="#{plugin.mtime}">
+ <h:outputText value="#{agentPlugin.mtime}">
<f:converter converterId="UserDateTimeConverter" />
</h:outputText>
</rich:column>
@@ -105,7 +107,7 @@
<h:outputText styleClass="headerText" value="Active"/>
</f:facet>
- <h:outputText value="#{plugin.enabled}"/>
+ <h:outputText value="#{agentPlugin.enabled}"/>
</rich:column>
<f:facet name="footer">
@@ -120,6 +122,92 @@
</rich:dataTable>
+ </rich:tab>
+
+ <rich:tab label="Server Plugins">
+
+ <rich:dataTable id="serverPluginsDataTable"
+ value="#{InstalledPluginsUIBean.installedServerPlugins}"
+ var="serverPlugin"
+ width="100%"
+ columnsWidth="3%, 20%, 52%, 15%, 10%"
+ headerClass="tableRowHeader"
+ footerClass="on-pager-footer"
+ onRowMouseOver="this.style.backgroundColor='#E7E7E7'"
+ onRowMouseOut="this.style.backgroundColor='#{a4jSkin.tableBackgroundColor}'">
+
+
+ <rich:column>
+ <f:facet name="header">
+ <onc:allSelect target="selectedPlugin"/>
+ </f:facet>
+
+ <onc:select name="selectedPlugin" value="#{serverPlugin.id}"/>
+ </rich:column>
+
+ <rich:column rendered="#{param.debug}">
+ <f:facet name="header">
+ <h:outputText styleClass="headerText" value="ID"/>
+ </f:facet>
+
+ <h:outputText value="#{serverPlugin.id}"/>
+ </rich:column>
+
+
+ <rich:column>
+ <f:facet name="header">
+ <h:outputText styleClass="headerText" value="Name"/>
+ </f:facet>
+
+ <h:outputLink value="/rhq/admin/plugin/plugin-details.xhtml">
+ <f:param name="plugin" value="#{serverPlugin.name}"/>
+ <h:outputText value="#{serverPlugin.displayName}"/>
+ </h:outputLink>
+
+ </rich:column>
+
+
+ <rich:column>
+ <f:facet name="header">
+ <h:outputText styleClass="headerText" value="Description"/>
+ </f:facet>
+
+ <h:outputText value="#{serverPlugin.description}"/>
+ </rich:column>
+
+ <rich:column>
+ <f:facet name="header">
+ <h:outputText styleClass="headerText" value="Last Update"/>
+ </f:facet>
+
+ <h:outputText value="#{serverPlugin.mtime}">
+ <f:converter converterId="UserDateTimeConverter" />
+ </h:outputText>
+ </rich:column>
+
+
+ <rich:column>
+ <f:facet name="header">
+ <h:outputText styleClass="headerText" value="Active"/>
+ </f:facet>
+
+ <h:outputText value="#{serverPlugin.enabled}"/>
+ </rich:column>
+
+ <f:facet name="footer">
+ <rich:columnGroup>
+ <rich:column colspan="5" width="100%">
+ <h:commandButton action="#{InstalledPluginsUIBean.scan}"
+ value="SCAN FOR UPDATES" styleClass="on-pager-button buttonsmall">
+ </h:commandButton>
+ </rich:column>
+ </rich:columnGroup>
+ </f:facet>
+
+ </rich:dataTable>
+
+ </rich:tab>
+ </rich:tabPanel>
</h:panelGrid>
</rich:panel>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/AgentManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/AgentManagerBean.java
index a8c5018..e4eb34b 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/AgentManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/AgentManagerBean.java
@@ -34,9 +34,6 @@ import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.interceptor.ExcludeDefaultInterceptors;
-import javax.management.MBeanServer;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.ObjectName;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
@@ -47,8 +44,6 @@ import org.apache.commons.logging.LogFactory;
import org.apache.maven.artifact.versioning.ComparableVersion;
import org.jboss.annotation.IgnoreDependency;
-import org.jboss.mx.util.MBeanServerLocator;
-import org.jboss.system.server.ServerConfig;
import org.rhq.core.clientapi.server.core.AgentVersion;
import org.rhq.core.domain.auth.Subject;
@@ -60,7 +55,6 @@ import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.PersistenceUtility;
import org.rhq.core.util.MessageDigestGenerator;
-import org.rhq.core.util.ObjectNameFactory;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.agentclient.AgentClient;
@@ -518,10 +512,7 @@ public class AgentManagerBean implements AgentManagerLocal {
@ExcludeDefaultInterceptors
public File getAgentDownloadDir() throws Exception {
- MBeanServer mbs = MBeanServerLocator.locateJBoss();
- ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
- Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
- File serverHomeDir = ((ServerConfig) mbean).getServerHomeDir();
+ File serverHomeDir = LookupUtil.getCoreServer().getJBossServerHomeDir();
File agentDownloadDir = new File(serverHomeDir, "deploy/rhq.ear/rhq-downloads/rhq-agent");
if (!agentDownloadDir.exists()) {
throw new FileNotFoundException("Missing agent downloads directory at [" + agentDownloadDir + "]");
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
index a7f28b2..2dd973f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServer.java
@@ -18,14 +18,23 @@
*/
package org.rhq.enterprise.server.core;
+import java.io.File;
import java.io.InputStream;
import java.util.Date;
import java.util.Properties;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.ObjectName;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.jboss.mx.util.MBeanServerLocator;
import org.jboss.system.ServiceMBeanSupport;
+import org.jboss.system.server.ServerConfig;
+
+import org.rhq.core.util.ObjectNameFactory;
public class CoreServer extends ServiceMBeanSupport implements CoreServerMBean {
private final Log log = LogFactory.getLog(CoreServer.class);
@@ -83,6 +92,27 @@ public class CoreServer extends ServiceMBeanSupport implements CoreServerMBean {
return bootTime;
}
+ public File getInstallDir() {
+ MBeanServer mbs = getMBeanServer();
+ ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
+ Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
+
+ File homeDir = ((ServerConfig) mbean).getHomeDir();
+ return homeDir.getParentFile(); // jboss homedir is "rhq-install-dir/jbossas", so the install dir is .. from jbossas
+ }
+
+ public File getJBossServerHomeDir() {
+ MBeanServer mbs = getMBeanServer();
+ ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
+ Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
+ File serverHomeDir = ((ServerConfig) mbean).getServerHomeDir();
+ return serverHomeDir;
+ }
+
+ private MBeanServer getMBeanServer() {
+ return MBeanServerLocator.locateJBoss();
+ }
+
private Properties loadBuildProperties() {
Properties buildProps = new Properties();
ClassLoader classLoader = this.getClass().getClassLoader();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerMBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerMBean.java
index dca969e..c471c37 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerMBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/CoreServerMBean.java
@@ -18,6 +18,7 @@
*/
package org.rhq.enterprise.server.core;
+import java.io.File;
import java.util.Date;
import javax.management.ObjectName;
@@ -56,4 +57,17 @@ public interface CoreServerMBean extends ServiceMBean {
* @return the boot time of the server
*/
Date getBootTime();
+
+ /**
+ * Where the RHQ Server is installed.
+ * @return RHQ Server install directory
+ */
+ File getInstallDir();
+
+ /**
+ * Where the JBoss Server Home directory is. Typically, this is something like:
+ * {@link #getInstallDir() isntall-dir}/jbossas/server/default
+ * @return jboss server home directory
+ */
+ File getJBossServerHomeDir();
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerCommunicationsService.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerCommunicationsService.java
index 61e0e81..a299dfc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerCommunicationsService.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/comm/ServerCommunicationsService.java
@@ -43,7 +43,6 @@ import javax.management.ObjectName;
import mazz.i18n.Logger;
import org.jboss.remoting.InvokerLocator;
-import org.jboss.system.server.ServerConfig;
import org.jboss.util.StringPropertyReplacer;
import org.rhq.core.clientapi.server.content.ContentServerService;
@@ -51,7 +50,6 @@ import org.rhq.core.clientapi.server.discovery.DiscoveryServerService;
import org.rhq.core.clientapi.server.measurement.MeasurementServerService;
import org.rhq.core.domain.cloud.Server;
import org.rhq.core.domain.resource.Agent;
-import org.rhq.core.util.ObjectNameFactory;
import org.rhq.core.util.PropertiesFileUpdate;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.enterprise.communications.GlobalConcurrencyLimitCommandListener;
@@ -953,11 +951,8 @@ public class ServerCommunicationsService implements ServerCommunicationsServiceM
private File getServerPropertiesFile() {
if (m_serverPropertiesFile == null) {
- ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
- Object mbean = MBeanServerInvocationHandler.newProxyInstance(m_mbs, name, ServerConfig.class, false);
-
- File homeDir = ((ServerConfig) mbean).getHomeDir();
- File binDir = new File(homeDir.getParentFile(), "bin");
+ File installDir = LookupUtil.getCoreServer().getInstallDir();
+ File binDir = new File(installDir, "bin");
m_serverPropertiesFile = new File(binDir, "rhq-server.properties");
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
new file mode 100644
index 0000000..1e41913
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -0,0 +1,58 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin;
+
+import java.util.List;
+
+import javax.ejb.Stateless;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.enterprise.server.RHQConstants;
+
+/**
+ * A server API into the server plugin infrastructure.
+ *
+ * @author John Mazzitelli
+ */
+@Stateless
+public class ServerPluginsBean implements ServerPluginsLocal {
+
+ @PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
+ private EntityManager entityManager;
+
+ public List<Plugin> getServerPlugins() {
+ Query q = entityManager.createNamedQuery(Plugin.QUERY_FIND_ALL_SERVER);
+ return q.getResultList();
+ }
+
+ public Plugin getServerPlugin(String name) {
+ Query query = entityManager.createNamedQuery(Plugin.QUERY_FIND_BY_NAME);
+ query.setParameter("name", name);
+ Plugin plugin = (Plugin) query.getSingleResult();
+ if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
+ throw new IllegalArgumentException("Plugin named [" + name + "] is not a server plugin");
+ }
+ return plugin;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
new file mode 100644
index 0000000..92f8c7c
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -0,0 +1,31 @@
+package org.rhq.enterprise.server.plugin;
+
+import java.util.List;
+
+import javax.ejb.Local;
+import javax.persistence.NoResultException;
+
+import org.rhq.core.domain.plugin.Plugin;
+
+/**
+ * Interface to the methods that interact with the serve-side plugin infrastructure.
+ *
+ * @author John Mazzitelli
+ */
+@Local
+public interface ServerPluginsLocal {
+ /**
+ * Returns a list of all the server plugins in the database.
+ *
+ * @return all plugins found in the DB
+ */
+ List<Plugin> getServerPlugins();
+
+ /**
+ * Returns a plugin with the given name.
+ * @param name name of plugin to find
+ * @return the named plugin
+ * @throws NoResultException when no plugin with that name exists
+ */
+ Plugin getServerPlugin(String name);
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/support/SupportManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/support/SupportManagerBean.java
index 9f9b6ae..6cdb34a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/support/SupportManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/support/SupportManagerBean.java
@@ -26,23 +26,17 @@ import java.net.URL;
import javax.ejb.EJB;
import javax.ejb.Stateless;
-import javax.management.MBeanServer;
-import javax.management.MBeanServerInvocationHandler;
-import javax.management.ObjectName;
-
-import org.jboss.mx.util.MBeanServerLocator;
-import org.jboss.system.server.ServerConfig;
import org.rhq.core.clientapi.agent.support.SupportAgentService;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.cloud.Server;
-import org.rhq.core.util.ObjectNameFactory;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.enterprise.server.agentclient.AgentClient;
import org.rhq.enterprise.server.authz.RequiredPermission;
import org.rhq.enterprise.server.cloud.instance.ServerManagerLocal;
import org.rhq.enterprise.server.core.AgentManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
/**
* Provides some methods that are useful for supporting managed resources. This includes being
@@ -95,10 +89,7 @@ public class SupportManagerBean implements SupportManagerLocal, SupportManagerRe
}
private File getDownloadsDir() throws Exception {
- MBeanServer mbs = MBeanServerLocator.locateJBoss();
- ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
- Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
- File serverHomeDir = ((ServerConfig) mbean).getServerHomeDir();
+ File serverHomeDir = LookupUtil.getCoreServer().getJBossServerHomeDir();
File downloadDir = new File(serverHomeDir, "deploy/rhq.ear/rhq-downloads/support");
if (!downloadDir.isDirectory()) {
downloadDir.mkdirs();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java
index bc87049..89816ec 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/system/SystemManagerBean.java
@@ -41,7 +41,7 @@ import javax.ejb.Timer;
import javax.ejb.TimerService;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
-import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.persistence.EntityManager;
@@ -53,7 +53,6 @@ import org.apache.commons.logging.LogFactory;
import org.jboss.deployment.MainDeployerMBean;
import org.jboss.mx.util.MBeanServerLocator;
-import org.jboss.system.server.ServerConfig;
import org.rhq.core.db.DatabaseType;
import org.rhq.core.db.DatabaseTypeFactory;
@@ -462,11 +461,9 @@ public class SystemManagerBean implements SystemManagerLocal, SystemManagerRemot
*/
public void undeployInstaller() {
try {
- MBeanServer mbs = MBeanServerLocator.locateJBoss();
- ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
- Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
+ File serverHomeDir = LookupUtil.getCoreServer().getJBossServerHomeDir();
- File deployDirectory = new File(((ServerConfig) mbean).getServerHomeDir(), "deploy");
+ File deployDirectory = new File(serverHomeDir, "deploy");
if (deployDirectory.exists()) {
File deployedInstallWar = new File(deployDirectory.getAbsolutePath(), "rhq-installer.war");
@@ -474,8 +471,10 @@ public class SystemManagerBean implements SystemManagerLocal, SystemManagerRemot
if (deployedInstallWar.exists()) {
// we need to undeploy it first - on windows the files are locked and can't be renamed until undeployed
- name = ObjectNameFactory.create("jboss.system:service=MainDeployer");
- mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, MainDeployerMBean.class, false);
+ ObjectName name = ObjectNameFactory.create("jboss.system:service=MainDeployer");
+ MBeanServerConnection mbs = MBeanServerLocator.locateJBoss();
+ MainDeployerMBean mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name,
+ MainDeployerMBean.class, false);
URL url = deployedInstallWar.toURI().toURL();
String urlString = url.toString().replace("%20", " "); // bug in undeployer doesn't like %20 - it wants a real space
((MainDeployerMBean) mbean).undeploy(urlString);
@@ -580,11 +579,9 @@ public class SystemManagerBean implements SystemManagerLocal, SystemManagerRemot
@RequiredPermission(Permission.MANAGE_SETTINGS)
public void updateLicense(Subject subject, byte[] licenseData) {
try {
- MBeanServer mbs = MBeanServerLocator.locateJBoss();
- ObjectName name = ObjectNameFactory.create("jboss.system:type=ServerConfig");
- Object mbean = MBeanServerInvocationHandler.newProxyInstance(mbs, name, ServerConfig.class, false);
+ File serverHomeDir = LookupUtil.getCoreServer().getJBossServerHomeDir();
- File deployDirectory = new File(((ServerConfig) mbean).getServerHomeDir(), "deploy");
+ File deployDirectory = new File(serverHomeDir, "deploy");
String licenseFileName = LicenseManager.getLicenseFileName();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
index 67ebfc3..36439da 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
@@ -121,6 +121,8 @@ import org.rhq.enterprise.server.operation.OperationManagerBean;
import org.rhq.enterprise.server.operation.OperationManagerLocal;
import org.rhq.enterprise.server.perspective.PerspectiveManagerBean;
import org.rhq.enterprise.server.perspective.PerspectiveManagerLocal;
+import org.rhq.enterprise.server.plugin.ServerPluginsBean;
+import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
import org.rhq.enterprise.server.report.DataAccessManagerBean;
import org.rhq.enterprise.server.report.DataAccessManagerLocal;
@@ -504,6 +506,31 @@ public final class LookupUtil {
return lookupLocal(StatusManagerBean.class);
}
+ public static ServerPluginsLocal getServerPlugins() {
+ return lookupLocal(ServerPluginsBean.class);
+ }
+
+ public static CoreServerMBean getCoreServer() {
+ MBeanServer jBossMBeanServer = MBeanServerLocator.locateJBoss();
+ CoreServerMBean jonServer = (CoreServerMBean) MBeanProxyExt.create(CoreServerMBean.class,
+ CoreServerMBean.OBJECT_NAME, jBossMBeanServer);
+ return jonServer;
+ }
+
+ public static PluginDeploymentScannerMBean getPluginDeploymentScanner() {
+ MBeanServer jBossMBeanServer = MBeanServerLocator.locateJBoss();
+ PluginDeploymentScannerMBean scanner = (PluginDeploymentScannerMBean) MBeanProxyExt.create(
+ PluginDeploymentScannerMBean.class, PluginDeploymentScannerMBean.OBJECT_NAME, jBossMBeanServer);
+ return scanner;
+ }
+
+ public static ServerPluginServiceManagement getServerPluginService() {
+ MBeanServer jBossMBeanServer = MBeanServerLocator.locateJBoss();
+ ServerPluginServiceManagement service = (ServerPluginServiceManagement) MBeanProxyExt.create(
+ ServerPluginServiceManagement.class, ServerPluginServiceManagement.OBJECT_NAME, jBossMBeanServer);
+ return service;
+ }
+
//--------------------------------------------
// The TEST services
//--------------------------------------------
@@ -528,26 +555,7 @@ public final class LookupUtil {
return lookupLocal(ResourceGroupTestBean.class);
}
- public static CoreServerMBean getCoreServer() {
- MBeanServer jBossMBeanServer = MBeanServerLocator.locateJBoss();
- CoreServerMBean jonServer = (CoreServerMBean) MBeanProxyExt.create(CoreServerMBean.class,
- CoreServerMBean.OBJECT_NAME, jBossMBeanServer);
- return jonServer;
- }
-
- public static PluginDeploymentScannerMBean getPluginDeploymentScanner() {
- MBeanServer jBossMBeanServer = MBeanServerLocator.locateJBoss();
- PluginDeploymentScannerMBean scanner = (PluginDeploymentScannerMBean) MBeanProxyExt.create(
- PluginDeploymentScannerMBean.class, PluginDeploymentScannerMBean.OBJECT_NAME, jBossMBeanServer);
- return scanner;
- }
-
- public static ServerPluginServiceManagement getServerPluginService() {
- MBeanServer jBossMBeanServer = MBeanServerLocator.locateJBoss();
- ServerPluginServiceManagement service = (ServerPluginServiceManagement) MBeanProxyExt.create(
- ServerPluginServiceManagement.class, ServerPluginServiceManagement.OBJECT_NAME, jBossMBeanServer);
- return service;
- }
+ // Private Methods
private static <T> String getLocalJNDIName(@NotNull Class<? super T> beanClass) {
return (embeddedDeployment ? "" : (RHQConstants.EAR_NAME + "/")) + beanClass.getSimpleName() + "/local";
commit a5499a827f552709cc968233306d1fa7a12b5619
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 18 16:19:01 2009 -0500
add queries to filter on deployment type of plugin
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index b3c0837..811586c 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -80,7 +80,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " WHERE p.name=:name"), //
// this query does not load the content blob, but loads everything else
- @NamedQuery(name = Plugin.QUERY_FIND_ALL, query = "" //
+ @NamedQuery(name = Plugin.QUERY_FIND_ALL_AGENT, query = "" //
+ " SELECT new org.rhq.core.domain.plugin.Plugin( " //
+ " p.id, " //
+ " p.name, " //
@@ -99,7 +99,31 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.mtime) " //
+ " FROM Plugin AS p " //
+ " LEFT JOIN p.pluginConfiguration " //
- + " LEFT JOIN p.scheduledJobsConfiguration "), //
+ + " LEFT JOIN p.scheduledJobsConfiguration " //
+ + " WHERE p.deployment = 'AGENT'"), //
+
+ // this query does not load the content blob, but loads everything else
+ @NamedQuery(name = Plugin.QUERY_FIND_ALL_SERVER, query = "" //
+ + " SELECT new org.rhq.core.domain.plugin.Plugin( " //
+ + " p.id, " //
+ + " p.name, " //
+ + " p.path, " //
+ + " p.displayName, " //
+ + " p.enabled, " //
+ + " p.description, " //
+ + " p.help, " //
+ + " p.md5, " //
+ + " p.version, " //
+ + " p.ampsVersion, " //
+ + " p.deployment, " //
+ + " p.pluginConfiguration, " //
+ + " p.scheduledJobsConfiguration, " //
+ + " p.ctime, " //
+ + " p.mtime) " //
+ + " FROM Plugin AS p " //
+ + " LEFT JOIN p.pluginConfiguration " //
+ + " LEFT JOIN p.scheduledJobsConfiguration " //
+ + " WHERE p.deployment = 'SERVER'"), //
// this query does not update the content blob or ctime
@NamedQuery(name = Plugin.UPDATE_ALL_BUT_CONTENT, query = "" //
@@ -154,7 +178,8 @@ public class Plugin implements Serializable {
public static final String TABLE_NAME = "RHQ_PLUGIN";
public static final String QUERY_FIND_BY_RESOURCE_TYPE_AND_CATEGORY = "Plugin.findByResourceType";
- public static final String QUERY_FIND_ALL = "Plugin.findAll";
+ public static final String QUERY_FIND_ALL_AGENT = "Plugin.findAllAgent";
+ public static final String QUERY_FIND_ALL_SERVER = "Plugin.findAllServer";
public static final String QUERY_FIND_BY_NAME = "Plugin.findByName";
public static final String UPDATE_ALL_BUT_CONTENT = "Plugin.updateAllButContent";
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index 75b34e5..bf8787f 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -288,7 +288,7 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.getHelp().equals(help);
assert plugin.getContent() == null;
- query = em.createNamedQuery(Plugin.QUERY_FIND_ALL);
+ query = em.createNamedQuery(Plugin.QUERY_FIND_ALL_SERVER);
List<Plugin> all = query.getResultList();
boolean got_it = false;
for (Plugin p : all) {
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 2ef7f49..8695d35 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
@@ -259,7 +259,7 @@ public class CoreServerServiceImpl implements CoreServerService {
try {
em = LookupUtil.getEntityManager();
- Query q = em.createNamedQuery(Plugin.QUERY_FIND_ALL);
+ Query q = em.createNamedQuery(Plugin.QUERY_FIND_ALL_AGENT);
List<Plugin> resultList = q.getResultList();
for (Plugin potentialPlugin : resultList) {
if (potentialPlugin.isEnabled()) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
index 432bef1..90639d2 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
@@ -120,11 +120,11 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
}
/**
- * Returns the information on all plugins as found in the database.
+ * Returns the information on all agent plugins as found in the database.
*/
@SuppressWarnings("unchecked")
public List<Plugin> getPlugins() {
- Query q = entityManager.createNamedQuery(Plugin.QUERY_FIND_ALL);
+ Query q = entityManager.createNamedQuery(Plugin.QUERY_FIND_ALL_AGENT);
return q.getResultList();
}
commit 8133576b0e70d1f61c5516362307cc23d3a2d252
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 18 14:23:34 2009 -0500
test that we can persist plugin config and jobs config for plugins
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index 356b62b..75b34e5 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -37,6 +37,7 @@ import javax.sql.DataSource;
import org.testng.annotations.Test;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
import org.rhq.core.domain.test.AbstractEJB3Test;
@@ -71,6 +72,8 @@ public class PluginTest extends AbstractEJB3Test {
em.persist(plugin);
id = plugin.getId();
assert id > 0;
+ assert plugin.getPluginConfiguration().getId() > 0 : "did not persist config";
+ assert plugin.getScheduledJobsConfiguration().getId() > 0 : "did not persist jobs config";
plugin = em.find(Plugin.class, id);
assert plugin != null;
@@ -99,8 +102,10 @@ public class PluginTest extends AbstractEJB3Test {
String description = "description-UPDATED";
String help = "help-UPDATED";
PluginDeploymentType deployment = PluginDeploymentType.SERVER;
- Configuration pluginConfig = null;
- Configuration scheduledJobsConfig = null;
+ Configuration pluginConfig = new Configuration();
+ Configuration jobsConfig = new Configuration();
+ pluginConfig.put(new PropertySimple("first", "last"));
+ jobsConfig.put(new PropertySimple("aaa", "bbb"));
em.close();
getTransactionManager().commit(); // we will be doing an update - needs to be in own tx
@@ -118,7 +123,7 @@ public class PluginTest extends AbstractEJB3Test {
q.setParameter("ampsVersion", ampsVersion);
q.setParameter("deployment", deployment);
q.setParameter("pluginConfiguration", pluginConfig);
- q.setParameter("scheduledJobsConfiguration", scheduledJobsConfig);
+ q.setParameter("scheduledJobsConfiguration", jobsConfig);
q.setParameter("description", description);
q.setParameter("help", help);
q.setParameter("mtime", System.currentTimeMillis());
@@ -138,10 +143,11 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.isEnabled() == enabled;
assert plugin.getMD5().equals(md5);
assert plugin.getVersion().equals(version);
+ q.setParameter("ampsVersion", ampsVersion);
assert plugin.getDescription().equals(description);
assert plugin.getDeployment() == PluginDeploymentType.SERVER;
- assert plugin.getPluginConfiguration() == null;
- assert plugin.getScheduledJobsConfiguration() == null;
+ assert plugin.getPluginConfiguration().equals(pluginConfig);
+ assert plugin.getScheduledJobsConfiguration().equals(jobsConfig);
assert plugin.getHelp().equals(help);
// and what we really want to test - ensure the content remained intact after the update
assert new String(plugin.getContent()).equals(new String(content));
@@ -222,16 +228,25 @@ public class PluginTest extends AbstractEJB3Test {
byte[] content = "this is the test content".getBytes();
String md5 = MessageDigestGenerator.getDigestString(new String(content));
PluginDeploymentType deployment = PluginDeploymentType.SERVER;
+ String ampsVersion = "1.2";
+
+ Configuration pluginConfig = new Configuration();
+ Configuration jobsConfig = new Configuration();
+ pluginConfig.put(new PropertySimple("first", "last"));
+ jobsConfig.put(new PropertySimple("aaa", "bbb"));
Plugin plugin = new Plugin(name, path);
plugin.setDisplayName(displayName);
plugin.setEnabled(enabled);
plugin.setMD5(md5);
plugin.setVersion(version);
+ plugin.setAmpsVersion(ampsVersion);
plugin.setDescription(description);
plugin.setHelp(help);
plugin.setContent(content);
plugin.setDeployment(deployment);
+ plugin.setPluginConfiguration(pluginConfig);
+ plugin.setScheduledJobsConfiguration(jobsConfig);
em.persist(plugin);
assert plugin.getId() > 0;
@@ -245,10 +260,11 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.isEnabled() == enabled;
assert plugin.getMD5().equals(md5);
assert plugin.getVersion().equals(version);
+ assert plugin.getAmpsVersion().equals(ampsVersion);
assert plugin.getDescription().equals(description);
assert plugin.getDeployment() == deployment;
- assert plugin.getPluginConfiguration() == null;
- assert plugin.getScheduledJobsConfiguration() == null;
+ assert plugin.getPluginConfiguration().equals(pluginConfig);
+ assert plugin.getScheduledJobsConfiguration().equals(jobsConfig);
assert plugin.getHelp().equals(help);
assert new String(plugin.getContent()).equals(new String(content));
@@ -264,10 +280,11 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.isEnabled() == enabled;
assert plugin.getMD5().equals(md5);
assert plugin.getVersion().equals(version);
+ assert plugin.getAmpsVersion().equals(ampsVersion);
assert plugin.getDescription().equals(description);
assert plugin.getDeployment() == deployment;
- assert plugin.getPluginConfiguration() == null;
- assert plugin.getScheduledJobsConfiguration() == null;
+ assert plugin.getPluginConfiguration().equals(pluginConfig);
+ assert plugin.getScheduledJobsConfiguration().equals(jobsConfig);
assert plugin.getHelp().equals(help);
assert plugin.getContent() == null;
@@ -284,10 +301,11 @@ public class PluginTest extends AbstractEJB3Test {
assert p.isEnabled() == enabled;
assert p.getMD5().equals(md5);
assert p.getVersion().equals(version);
+ assert plugin.getAmpsVersion().equals(ampsVersion);
assert p.getDescription().equals(description);
assert plugin.getDeployment() == deployment;
- assert plugin.getPluginConfiguration() == null;
- assert plugin.getScheduledJobsConfiguration() == null;
+ assert plugin.getPluginConfiguration().equals(pluginConfig);
+ assert plugin.getScheduledJobsConfiguration().equals(jobsConfig);
assert p.getHelp().equals(help);
assert p.getContent() == null;
break;
commit 62f6b71102da2c79912c9ee13f44014a6d632deb
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 18 14:13:24 2009 -0500
fix the queries to join the config properly
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index cfb3a10..b3c0837 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -75,6 +75,8 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.ctime, " //
+ " p.mtime) " //
+ " FROM Plugin AS p " //
+ + " LEFT JOIN p.pluginConfiguration " //
+ + " LEFT JOIN p.scheduledJobsConfiguration " //
+ " WHERE p.name=:name"), //
// this query does not load the content blob, but loads everything else
@@ -95,7 +97,9 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.scheduledJobsConfiguration, " //
+ " p.ctime, " //
+ " p.mtime) " //
- + " FROM Plugin AS p "), //
+ + " FROM Plugin AS p " //
+ + " LEFT JOIN p.pluginConfiguration " //
+ + " LEFT JOIN p.scheduledJobsConfiguration "), //
// this query does not update the content blob or ctime
@NamedQuery(name = Plugin.UPDATE_ALL_BUT_CONTENT, query = "" //
@@ -134,6 +138,8 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.ctime, " //
+ " p.mtime) " //
+ " FROM Plugin p " //
+ + " LEFT JOIN p.pluginConfiguration " //
+ + " LEFT JOIN p.scheduledJobsConfiguration " //
+ " WHERE p.name IN ( SELECT rt.plugin " //
+ " FROM Resource res " //
+ " JOIN res.resourceType rt " //
commit fb16955d06c9aa08896de49e1c538b064d7d0d8d
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 18 13:20:39 2009 -0500
add new plugin schema changes
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index 8380172..9ac94d7 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -22,7 +22,7 @@
<properties>
<scm.module.path>modules/core/dbutils/</scm.module.path>
- <db.schema.version>2.62.1</db.schema.version>
+ <db.schema.version>2.66</db.schema.version>
</properties>
<dependencies>
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/amps-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/amps-schema.xml
index 204b1db..5120803 100644
--- a/modules/core/dbutils/src/main/scripts/dbsetup/amps-schema.xml
+++ b/modules/core/dbutils/src/main/scripts/dbsetup/amps-schema.xml
@@ -4,7 +4,6 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:xmlns:rhq-dbsetup-schema">
-
<table name="RHQ_PLUGIN">
<column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
<column name="NAME" size="200" type="VARCHAR2" required="true"/>
@@ -18,6 +17,9 @@
<column name="MD5" size="100" type="VARCHAR2" required="true"/>
<column name="CTIME" type="LONG" required="true"/>
<column name="MTIME" type="LONG" required="true"/>
+ <column name="DEPLOYMENT" size="8" type="VARCHAR2" required="true"/>
+ <column name="PLUGIN_CONFIG_ID" type="INTEGER" references="RHQ_CONFIG" required="false"/>
+ <column name="JOBS_CONFIG_ID" type="INTEGER" references="RHQ_CONFIG" required="false"/>
<column name="CONTENT" type="BLOB" required="false"/>
<index name="RHQ_PLUGIN_NAME_IDX" unique="true">
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 af17a6d..f477569 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -2024,6 +2024,40 @@
<schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
</schemaSpec>
+ <!-- Add support for server-side plugins -->
+ <schemaSpec version="2.66">
+ <!-- add the new column that indicates if this is deployed on the SERVER or AGENT -->
+ <schema-addColumn table="RHQ_PLUGIN" column="DEPLOYMENT" columnType="VARCHAR2" precision="8"/>
+ <schema-directSQL>
+ <statement desc="Updating existing plugins with default deployment of AGENT">
+ UPDATE RHQ_PLUGIN SET DEPLOYMENT = 'AGENT'
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_PLUGIN" column="DEPLOYMENT" nullable="FALSE"/>
+
+ <!-- add the new column that provides configuration to a plugin -->
+ <schema-addColumn table="RHQ_PLUGIN" column="PLUGIN_CONFIG_ID" columnType="INTEGER" />
+ <schema-directSQL>
+ <statement desc="Creating RHQ_PLUGIN foreign key relation to RHQ_CONFIG for plugin config">
+ ALTER TABLE RHQ_PLUGIN
+ ADD CONSTRAINT RHQ_PLUGIN_P_CFG_ID_FKEY
+ FOREIGN KEY (PLUGIN_CONFIG_ID)
+ REFERENCES RHQ_CONFIG (ID)
+ </statement>
+ </schema-directSQL>
+
+ <!-- add the new column that provides configuration to a plugin -->
+ <schema-addColumn table="RHQ_PLUGIN" column="JOBS_CONFIG_ID" columnType="INTEGER" />
+ <schema-directSQL>
+ <statement desc="Creating RHQ_PLUGIN foreign key relation to RHQ_CONFIG for scheduled jobs">
+ ALTER TABLE RHQ_PLUGIN
+ ADD CONSTRAINT RHQ_PLUGIN_JOBS_CFG_ID_FKEY
+ FOREIGN KEY (JOBS_CONFIG_ID)
+ REFERENCES RHQ_CONFIG (ID)
+ </statement>
+ </schema-directSQL>
+ </schemaSpec>
+
</dbupgrade>
</target>
</project>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index fe704bc..cfb3a10 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -25,19 +25,26 @@ package org.rhq.core.domain.plugin;
import java.io.ByteArrayInputStream;
import java.io.Serializable;
+import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
+import javax.persistence.JoinColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
+import javax.persistence.OneToOne;
import javax.persistence.PrePersist;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import org.jetbrains.annotations.NotNull;
+import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.util.MessageDigestGenerator;
/**
@@ -62,6 +69,9 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.md5, " //
+ " p.version, " //
+ " p.ampsVersion, " //
+ + " p.deployment, " //
+ + " p.pluginConfiguration, " //
+ + " p.scheduledJobsConfiguration, " //
+ " p.ctime, " //
+ " p.mtime) " //
+ " FROM Plugin AS p " //
@@ -80,6 +90,9 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.md5, " //
+ " p.version, " //
+ " p.ampsVersion, " //
+ + " p.deployment, " //
+ + " p.pluginConfiguration, " //
+ + " p.scheduledJobsConfiguration, " //
+ " p.ctime, " //
+ " p.mtime) " //
+ " FROM Plugin AS p "), //
@@ -94,6 +107,9 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.help = :help, " //
+ " p.version = :version, " //
+ " p.ampsVersion = :ampsVersion," //
+ + " p.deployment = :deployment, " //
+ + " p.pluginConfiguration = :pluginConfiguration, " //
+ + " p.scheduledJobsConfiguration = :scheduledJobsConfiguration, " //
+ " p.path = :path, " //
+ " p.md5 = :md5, " //
+ " p.mtime = :mtime " //
@@ -112,6 +128,9 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.md5, " //
+ " p.version, " //
+ " p.ampsVersion, " //
+ + " p.deployment, " //
+ + " p.pluginConfiguration, " //
+ + " p.scheduledJobsConfiguration, " //
+ " p.ctime, " //
+ " p.mtime) " //
+ " FROM Plugin p " //
@@ -138,6 +157,18 @@ public class Plugin implements Serializable {
@Id
private int id;
+ @Column(name = "DEPLOYMENT", nullable = false)
+ @Enumerated(EnumType.STRING)
+ private PluginDeploymentType deployment = PluginDeploymentType.AGENT; // assume agent
+
+ @JoinColumn(name = "JOBS_CONFIG_ID", referencedColumnName = "ID")
+ @OneToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
+ private Configuration scheduledJobsConfiguration;
+
+ @JoinColumn(name = "PLUGIN_CONFIG_ID", referencedColumnName = "ID")
+ @OneToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY)
+ private Configuration pluginConfiguration;
+
@Column(name = "NAME", nullable = false)
private String name;
@@ -239,11 +270,16 @@ public class Plugin implements Serializable {
* @param help
* @param md5
* @param version
+ * @param ampsVersion
+ * @param deployment
+ * @param pluginConfig
+ * @param scheduledJobsConfig
* @param ctime
* @param mtime
*/
public Plugin(int id, String name, String path, String displayName, boolean enabled, String description,
- String help, String md5, String version, String ampsVersion, long ctime, long mtime) {
+ String help, String md5, String version, String ampsVersion, PluginDeploymentType deployment,
+ Configuration pluginConfig, Configuration scheduledJobsConfig, long ctime, long mtime) {
this.id = id;
this.name = name;
this.path = path;
@@ -254,6 +290,9 @@ public class Plugin implements Serializable {
this.md5 = md5;
this.version = version;
this.ampsVersion = ampsVersion;
+ this.deployment = deployment;
+ this.pluginConfiguration = pluginConfig;
+ this.scheduledJobsConfiguration = scheduledJobsConfig;
this.ctime = ctime;
this.mtime = mtime;
}
@@ -409,6 +448,45 @@ public class Plugin implements Serializable {
}
/**
+ * Indicates how the plugin gets deployed (e.g. running in the agent or in the server).
+ *
+ * @return plugin deployment type
+ */
+ public PluginDeploymentType getDeployment() {
+ return deployment;
+ }
+
+ public void setDeployment(PluginDeploymentType deployment) {
+ this.deployment = deployment;
+ }
+
+ /**
+ * If the plugin has jobs associated with it, this is the configuration for those jobs.
+ *
+ * @return scheduled job configuration for jobs that the plugin defined.
+ */
+ public Configuration getScheduledJobsConfiguration() {
+ return scheduledJobsConfiguration;
+ }
+
+ public void setScheduledJobsConfiguration(Configuration scheduledJobsConfiguration) {
+ this.scheduledJobsConfiguration = scheduledJobsConfiguration;
+ }
+
+ /**
+ * If the plugin, itself, has configuration associated with it, this is that configuration.
+ *
+ * @return the configuration associated with the plugin itself
+ */
+ public Configuration getPluginConfiguration() {
+ return pluginConfiguration;
+ }
+
+ public void setPluginConfiguration(Configuration pluginConfiguration) {
+ this.pluginConfiguration = pluginConfiguration;
+ }
+
+ /**
* Returns the actual content of the plugin file. Be careful calling this
* in an entity context - the entire plugin file content will be loaded in
* memory (which may trigger an OutOfMemoryError if the file is very large).
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/PluginDeploymentType.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/PluginDeploymentType.java
new file mode 100644
index 0000000..77d2f0e
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/PluginDeploymentType.java
@@ -0,0 +1,31 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin;
+
+/**
+ * Indicates if a plugin is to be deployed on the agent or the server. In other words,
+ * identifies a plugin as a server-side plugin or an agent plugin.
+ *
+ * @author John Mazzitelli
+ */
+public enum PluginDeploymentType {
+ AGENT, SERVER
+}
+
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index 9327b2a..356b62b 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -28,7 +28,6 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;
-import java.lang.reflect.Constructor;
import javax.naming.InitialContext;
import javax.persistence.EntityManager;
@@ -37,15 +36,12 @@ import javax.sql.DataSource;
import org.testng.annotations.Test;
+import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginDeploymentType;
import org.rhq.core.domain.test.AbstractEJB3Test;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.stream.StreamUtil;
-import org.hibernate.Session;
-import org.hibernate.transform.ResultTransformer;
-import org.hibernate.type.Type;
-import org.hibernate.criterion.Example;
-import org.hibernate.criterion.Projections;
@Test
public class PluginTest extends AbstractEJB3Test {
@@ -86,6 +82,9 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.getMD5().equals(md5);
assert plugin.getVersion() == null;
assert plugin.getDescription() == null;
+ assert plugin.getDeployment() == PluginDeploymentType.AGENT; // default is agent
+ assert plugin.getPluginConfiguration() == null;
+ assert plugin.getScheduledJobsConfiguration() == null;
assert plugin.getHelp() == null;
assert new String(plugin.getContent()).equals(new String(content));
@@ -99,6 +98,9 @@ public class PluginTest extends AbstractEJB3Test {
String ampsVersion = "2.1";
String description = "description-UPDATED";
String help = "help-UPDATED";
+ PluginDeploymentType deployment = PluginDeploymentType.SERVER;
+ Configuration pluginConfig = null;
+ Configuration scheduledJobsConfig = null;
em.close();
getTransactionManager().commit(); // we will be doing an update - needs to be in own tx
@@ -114,6 +116,9 @@ public class PluginTest extends AbstractEJB3Test {
q.setParameter("md5", md5);
q.setParameter("version", version);
q.setParameter("ampsVersion", ampsVersion);
+ q.setParameter("deployment", deployment);
+ q.setParameter("pluginConfiguration", pluginConfig);
+ q.setParameter("scheduledJobsConfiguration", scheduledJobsConfig);
q.setParameter("description", description);
q.setParameter("help", help);
q.setParameter("mtime", System.currentTimeMillis());
@@ -134,6 +139,9 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.getMD5().equals(md5);
assert plugin.getVersion().equals(version);
assert plugin.getDescription().equals(description);
+ assert plugin.getDeployment() == PluginDeploymentType.SERVER;
+ assert plugin.getPluginConfiguration() == null;
+ assert plugin.getScheduledJobsConfiguration() == null;
assert plugin.getHelp().equals(help);
// and what we really want to test - ensure the content remained intact after the update
assert new String(plugin.getContent()).equals(new String(content));
@@ -190,6 +198,9 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.getMD5().equals(md5);
assert plugin.getVersion() == null;
assert plugin.getDescription() == null;
+ assert plugin.getDeployment() == PluginDeploymentType.AGENT; // default is agent
+ assert plugin.getPluginConfiguration() == null;
+ assert plugin.getScheduledJobsConfiguration() == null;
assert plugin.getHelp() == null;
assert plugin.getContent() == null;
} finally {
@@ -210,6 +221,7 @@ public class PluginTest extends AbstractEJB3Test {
String help = "the test help string is here";
byte[] content = "this is the test content".getBytes();
String md5 = MessageDigestGenerator.getDigestString(new String(content));
+ PluginDeploymentType deployment = PluginDeploymentType.SERVER;
Plugin plugin = new Plugin(name, path);
plugin.setDisplayName(displayName);
@@ -219,6 +231,7 @@ public class PluginTest extends AbstractEJB3Test {
plugin.setDescription(description);
plugin.setHelp(help);
plugin.setContent(content);
+ plugin.setDeployment(deployment);
em.persist(plugin);
assert plugin.getId() > 0;
@@ -233,6 +246,9 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.getMD5().equals(md5);
assert plugin.getVersion().equals(version);
assert plugin.getDescription().equals(description);
+ assert plugin.getDeployment() == deployment;
+ assert plugin.getPluginConfiguration() == null;
+ assert plugin.getScheduledJobsConfiguration() == null;
assert plugin.getHelp().equals(help);
assert new String(plugin.getContent()).equals(new String(content));
@@ -249,6 +265,9 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.getMD5().equals(md5);
assert plugin.getVersion().equals(version);
assert plugin.getDescription().equals(description);
+ assert plugin.getDeployment() == deployment;
+ assert plugin.getPluginConfiguration() == null;
+ assert plugin.getScheduledJobsConfiguration() == null;
assert plugin.getHelp().equals(help);
assert plugin.getContent() == null;
@@ -266,6 +285,9 @@ public class PluginTest extends AbstractEJB3Test {
assert p.getMD5().equals(md5);
assert p.getVersion().equals(version);
assert p.getDescription().equals(description);
+ assert plugin.getDeployment() == deployment;
+ assert plugin.getPluginConfiguration() == null;
+ assert plugin.getScheduledJobsConfiguration() == null;
assert p.getHelp().equals(help);
assert p.getContent() == null;
break;
@@ -507,4 +529,4 @@ public class PluginTest extends AbstractEJB3Test {
}
}
-}
\ No newline at end of file
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
index 7d2265a..432bef1 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
@@ -205,6 +205,9 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
q.setParameter("md5", plugin.getMD5());
q.setParameter("version", plugin.getVersion());
q.setParameter("ampsVersion", plugin.getAmpsVersion());
+ q.setParameter("deployment", plugin.getDeployment());
+ q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
+ q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
q.setParameter("description", plugin.getDescription());
q.setParameter("help", plugin.getHelp());
q.setParameter("mtime", plugin.getMtime());
commit a7d76bcfecd3ec3acf99f578ed02b22fefb187d9
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 18 11:27:04 2009 -0500
put the plugin component instance in the job context so stateless jobs can get to the stateful component if they need it.
diff --git a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java
index c4e50d3..9476b83 100644
--- a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java
+++ b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java
@@ -28,13 +28,14 @@ import org.rhq.enterprise.server.plugin.pc.ScheduledJobInvocationContext;
*/
public class MyScheduledJob {
public void executeWithContext(ScheduledJobInvocationContext jobContext) throws Exception {
- System.out.println("Sample scheduled job has been triggered! [" + this.getClass() + "] jobId="
- + jobContext.getJobDefinition().getJobId() + ", methodName="
+ System.out.println("The sample plugin scheduled job [executeWithContext] (stateless) has triggered!!! : ["
+ + this.getClass() + "] jobId=" + jobContext.getJobDefinition().getJobId() + ", methodName="
+ jobContext.getJobDefinition().getMethodName() + ", callbackData="
+ jobContext.getJobDefinition().getCallbackData());
}
public void executeNoArg() throws Exception {
- System.out.println("Sample scheduled job has been triggered! [" + this.getClass() + "] NO CONTEXT!");
+ System.out.println("The sample plugin scheduled job [executeNoArg] has triggered!!! : [" + this.getClass()
+ + "] - NO CONTEXT!");
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
index 5d2e405..4493a2d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -179,9 +179,11 @@ abstract class AbstractJobWrapper implements Job {
+ "]", null);
}
+ ServerPluginComponent pluginComponent = pluginManager.getServerPluginComponent(pluginName);
+
if (jobClass == null) {
// null classname means use the stateful plugin component as the target object
- pluginJobObject = pluginManager.getServerPluginComponent(pluginName);
+ pluginJobObject = pluginComponent;
if (pluginJobObject == null) {
throwJobExecutionException(pluginName, pluginType, jobId, "no plugin component to process job", null);
}
@@ -214,7 +216,7 @@ abstract class AbstractJobWrapper implements Job {
ScheduledJobDefinition jobDefinition = new ScheduledJobDefinition(jobId, true, jobClass, jobMethodName,
scheduleType, callbackData);
ServerPluginContext pluginContext = pluginManager.getServerPluginContext(pluginEnv);
- params[0] = new ScheduledJobInvocationContext(jobDefinition, pluginContext);
+ params[0] = new ScheduledJobInvocationContext(jobDefinition, pluginContext, pluginComponent);
} catch (NoSuchMethodException e) {
try {
// see if there is a no-arg method of the given name
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java
index e204b31..cdb0ebf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java
@@ -31,17 +31,41 @@ import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
public class ScheduledJobInvocationContext {
private final ScheduledJobDefinition jobDefinition;
private final ServerPluginContext serverPluginContext;
+ private final ServerPluginComponent serverPluginComponent;
- public ScheduledJobInvocationContext(ScheduledJobDefinition jobDefinition, ServerPluginContext pluginContext) {
+ public ScheduledJobInvocationContext(ScheduledJobDefinition jobDefinition, ServerPluginContext pluginContext,
+ ServerPluginComponent serverPluginComponent) {
this.jobDefinition = jobDefinition;
this.serverPluginContext = pluginContext;
+ this.serverPluginComponent = serverPluginComponent;
}
+ /**
+ * The definition of the triggered job that owns this context object.
+ *
+ * @return the triggered job's definition
+ */
public ScheduledJobDefinition getJobDefinition() {
return this.jobDefinition;
}
+ /**
+ * General information for the job's plugin.
+ *
+ * @return the triggered job's plugin context
+ */
public ServerPluginContext getServerPluginContext() {
return this.serverPluginContext;
}
+
+ /**
+ * If the job's plugin has a plugin component defined, this will return the instance of that component.
+ * This is helpful for stateless jobs to obtain information from the plugin component, which is stateful.
+ *
+ * @return the plugin component instance from the triggered job's plugin, or <code>null</code> if
+ * there is no plugin component for the plugin
+ */
+ public ServerPluginComponent getServerPluginComponent() {
+ return serverPluginComponent;
+ }
}
commit 526f08dedf75ca698d78ac96b3947fc6eb1104aa
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Wed Nov 18 11:09:34 2009 -0500
Removed assertion that's no longer valid with the changes to the content source comparator.
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/content/test/ContentSourceSyncResultsTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/content/test/ContentSourceSyncResultsTest.java
index 151e8c0..156bfa2 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/content/test/ContentSourceSyncResultsTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/content/test/ContentSourceSyncResultsTest.java
@@ -107,9 +107,6 @@ public class ContentSourceSyncResultsTest extends AbstractEJB3Test {
syncResults = cs.getSyncResults();
assert syncResults != null;
assert syncResults.size() == 2;
- long startTime0 = syncResults.get(0).getStartTime();
- long startTime1 = syncResults.get(1).getStartTime();
- assert startTime0 > startTime1 : "Why doesn't @OrderBy work?: " + startTime0 + " | " + startTime1;
} finally {
getTransactionManager().rollback();
}
commit 4161fed485f203fbd24e4ad7b5eea4ab37e457b4
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 18 11:04:14 2009 -0500
do not invoke job if master PC is down. only refire immediately if other HA servers can take it
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
index 2e2c38a..5d2e405 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -155,6 +155,14 @@ abstract class AbstractJobWrapper implements Job {
if (!serverPluginService.isMasterPluginContainerStarted()) {
String msg = "The master plugin container is shutdown, will not execute job here, will resubmit";
log.error(logMsg(pluginName, pluginType, jobId, msg, null));
+ JobExecutionException exception = new JobExecutionException();
+
+ // we only refire immediately if we are in an HA environment- which means another server might
+ // be able to take over - and that other server might have its master PC running for us to execute in.
+ boolean isHA = LookupUtil.getCloudManager().getNormalServerCount() > 1;
+ exception.setRefireImmediately(isHA);
+
+ // abort this invocation now - we can't run without the plugin containers
return;
}
commit 0764add1d4fcb73161577dc48831a2c19380ee67
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Wed Nov 18 10:58:12 2009 -0500
Fixed broken test.
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 0688ddd..9f89050 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
@@ -916,6 +916,7 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
return null;
}
+ @RequiredPermission(Permission.MANAGE_INVENTORY)
public int synchronizeRepos(Subject subject, Integer[] repoIds) {
int syncCount = 0;
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
index a1537c3..13981eb 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
@@ -52,6 +52,8 @@ import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.content.metadata.ContentSourceMetadataManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
+import org.rhq.enterprise.server.plugin.pc.content.TestContentServerPluginService;
public class RepoManagerBeanTest extends AbstractEJB3Test {
@@ -72,11 +74,17 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
contentSourceManager = LookupUtil.getContentSourceManager();
contentSourceMetadataManager = LookupUtil.getContentSourceMetadataManager();
+ TestContentServerPluginService pluginService = new TestContentServerPluginService();
+ prepareCustomServerPluginService(pluginService);
+ pluginService.startMasterPluginContainer();
+
overlord = LookupUtil.getSubjectManager().getOverlord();
}
@AfterMethod
public void tearDownAfterMethod() throws Exception {
+ unprepareServerPluginService();
+
TransactionManager tx = getTransactionManager();
if (tx != null) {
tx.rollback();
@@ -112,6 +120,11 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
ContentSourceType cst = new ContentSourceType("testSyncStatus");
ContentSource cs = new ContentSource("testSyncStatus", cst);
+
+ EntityManager em = getEntityManager();
+ em.persist(cst);
+ em.persist(cs);
+
repo.addContentSource(cs);
syncCount = repoManager.synchronizeRepos(overlord, ids);
commit a297bc5e36c76914bb361c1f3498291ade226a83
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 18 10:40:32 2009 -0500
add a query and API to get the number of normal servers in the cloud
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/Server.java b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/Server.java
index 8adf52a..09d5332 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/Server.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/cloud/Server.java
@@ -69,6 +69,7 @@ import org.rhq.core.domain.resource.Agent;
+ "LEFT JOIN FETCH s.affinityGroup " //
+ " WHERE s.name = :name"),
@NamedQuery(name = Server.QUERY_FIND_ALL_CLOUD_MEMBERS, query = "SELECT s FROM Server s WHERE NOT s.operationMode = 'INSTALLED'"),
+ @NamedQuery(name = Server.QUERY_FIND_ALL_NORMAL_CLOUD_MEMBERS, query = "SELECT s FROM Server s WHERE s.operationMode = 'NORMAL'"),
@NamedQuery(name = Server.QUERY_FIND_BY_AFFINITY_GROUP, query = "" //
+ "SELECT s " //
+ " FROM Server s " //
@@ -104,8 +105,7 @@ public class Server implements Serializable {
public static final String QUERY_FIND_WITHOUT_AFFINITY_GROUP = "Server.findWithoutAffinityGroup";
public static final String QUERY_DELETE_BY_ID = "Server.deleteById";
public static final String QUERY_UPDATE_SET_STALE_DOWN = "Server.updateSetStaleDown";
-
- // HA queries
+ public static final String QUERY_FIND_ALL_NORMAL_CLOUD_MEMBERS = "Server.findAllNormalCloudMembers";
public static final String QUERY_UPDATE_STATUS_BY_NAME = "Server.updateStatusByName";
@Column(name = "ID", nullable = false)
@@ -237,7 +237,7 @@ public class Server implements Serializable {
public enum OperationMode {
DOWN("This server is down member of the HA server cloud"), //
- INSTALLED("This server is newly installed but not yet fullyoperating"), //
+ INSTALLED("This server is newly installed but not yet fully operating"), //
MAINTENANCE("This server is a Maintenance Mode member of the HA server cloud"), //
NORMAL("This server is a Normal Member of the HA server cloud");
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/test/QueryAllTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/test/QueryAllTest.java
index 9f24916..e559830 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/test/QueryAllTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/test/QueryAllTest.java
@@ -52,9 +52,9 @@ import org.rhq.core.domain.alert.notification.SubjectNotification;
import org.rhq.core.domain.auth.Principal;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Role;
+import org.rhq.core.domain.cloud.Server;
import org.rhq.core.domain.common.SystemConfiguration;
import org.rhq.core.domain.content.Architecture;
-import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.content.ContentServiceRequest;
import org.rhq.core.domain.content.ContentSource;
import org.rhq.core.domain.content.ContentSourceSyncResults;
@@ -65,6 +65,7 @@ import org.rhq.core.domain.content.PackageInstallationStep;
import org.rhq.core.domain.content.PackageType;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.core.domain.content.PackageVersionContentSource;
+import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.event.Event;
import org.rhq.core.domain.measurement.MeasurementDataNumeric1D;
import org.rhq.core.domain.measurement.MeasurementDataNumeric1H;
@@ -135,6 +136,9 @@ public class QueryAllTest extends AbstractEJB3Test {
Resource.class.getSimpleName(),
ResourceType.class.getSimpleName(),
+ // HA stuff
+ Server.class.getSimpleName(),
+
// content stuff
Architecture.class.getSimpleName(), Repo.class.getSimpleName(), ContentServiceRequest.class.getSimpleName(),
ContentSource.class.getSimpleName(), ContentSourceType.class.getSimpleName(),
@@ -283,6 +287,7 @@ public class QueryAllTest extends AbstractEJB3Test {
continue;
}
+ System.out.println("Testing queries for: " + shortName);
List<NamedQuery> nqs = getNamedQueriesForEntity(entity);
for (NamedQuery nq : nqs) {
boolean hasId;
@@ -326,7 +331,7 @@ public class QueryAllTest extends AbstractEJB3Test {
query.setMaxResults(5);
Collection results = query.getResultList();
- System.out.println(" ==> #results: " + results.size());
+ System.out.println(" " + nq.name() + "==> #results: " + results.size());
} catch (Throwable t) {
assert false : "Failed to query named query " + nq.name() + ": "
+ ThrowableUtil.getAllMessages(t, true);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/CloudManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/CloudManagerBean.java
index 372f932..d9780fe 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/CloudManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/CloudManagerBean.java
@@ -145,6 +145,18 @@ public class CloudManagerBean implements CloudManagerLocal {
}
}
+ public int getNormalServerCount() {
+ Query query = PersistenceUtility.createCountQuery(entityManager, Server.QUERY_FIND_ALL_NORMAL_CLOUD_MEMBERS);
+
+ try {
+ long serverCount = (Long) query.getSingleResult();
+ return (int) serverCount;
+ } catch (NoResultException nre) {
+ log.debug("Could not get count of normal cloud instances, returning 0...");
+ return 0;
+ }
+ }
+
public void deleteServers(Integer[] serverIds) throws CloudManagerException {
if (serverIds == null) {
return;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/CloudManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/CloudManagerLocal.java
index 3524e50..212f835 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/CloudManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/cloud/CloudManagerLocal.java
@@ -61,8 +61,27 @@ public interface CloudManagerLocal {
PageList<ServerWithAgentCountComposite> getServerComposites(Subject subject, PageControl pc);
+ /**
+ * Returns the number of servers that are part of the "server cloud", which excludes
+ * servers that have been installed but not associated with the cloud.
+ * The returned count will include those servers that are down or in maintenance mode,
+ * in addition to those servers that are currently running in a normal state.
+ *
+ * @return count of servers in the cloud
+ */
int getServerCount();
+ /**
+ * Returns the number of servers that are part of the "server cloud" that are currently
+ * running in "normal" mode.
+ *
+ * This excludes all other servers such as those servers that have been installed but
+ * not associated with the cloud, servers that are down or in maintenance mode.
+ *
+ * @return count of servers in the cloud that are in a normal running state
+ */
+ int getNormalServerCount();
+
void updateServerMode(Integer[] serverIds, Server.OperationMode mode);
Server updateServer(Subject subject, Server server);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
index 9b3d64d..2e2c38a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -150,8 +150,16 @@ abstract class AbstractJobWrapper implements Job {
throwJobExecutionException(pluginName, pluginTypeString, jobId, "Datamap had invalid plugin type string", t);
}
+ // do not execute the job if the master plugin container has been stopped
+ ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
+ if (!serverPluginService.isMasterPluginContainerStarted()) {
+ String msg = "The master plugin container is shutdown, will not execute job here, will resubmit";
+ log.error(logMsg(pluginName, pluginType, jobId, msg, null));
+ return;
+ }
+
// determine which plugin component class will be invoked to perform the work of the job
- MasterServerPluginContainer mpc = LookupUtil.getServerPluginService().getMasterPluginContainer();
+ MasterServerPluginContainer mpc = serverPluginService.getMasterPluginContainer();
AbstractTypeServerPluginContainer pc = mpc.getPluginContainerByPluginType(pluginType);
Object pluginJobObject = null;
commit 009897f89b52c9d092baae46e3371927ffff2b52
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 18 01:24:45 2009 -0500
add a help element to the server plugin descriptor schema. we can show this in the plugin UI page
diff --git a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
index b88d338..215e044 100644
--- a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -10,6 +10,11 @@
xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
xmlns:c="urn:xmlns:rhq-configuration">
+ <serverplugin:help><![CDATA[
+ This is a sample plugin that has a plugin component which simply outputs messages during lifecycle changes.
+ It also demonstrates several jobs using different types of schedules.
+ ]]></serverplugin:help>
+
<serverplugin:plugin-component class="MyLifecycleListener" />
<serverplugin:scheduled-jobs>
diff --git a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
index 6445aab..9b79376 100644
--- a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
+++ b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
@@ -39,6 +39,15 @@
<xs:complexType name="ServerPluginDescriptorType">
<xs:sequence minOccurs="0" maxOccurs="1">
+ <xs:element name="help" minOccurs="0" maxOccurs="1" type="serverplugin:HelpType">
+ <xs:annotation>
+ <xs:documentation>
+ Help documentation that can provide useful information to a user.
+ This information typically assists users on how to integrate the
+ plugin with third party servers and systems.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
<xs:element name="plugin-component" minOccurs="0" maxOccurs="1" type="serverplugin:ServerPluginComponentType">
<xs:annotation>
<xs:documentation>
@@ -174,4 +183,11 @@
<xs:pattern value="[a-zA-Z_][a-zA-Z_0-9]*(.[a-zA-Z_][a-zA-Z_0-9]*)*" />
</xs:restriction>
</xs:simpleType>
+
+ <xs:complexType name="HelpType" mixed="true">
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+
</xs:schema>
diff --git a/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java b/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
index f38a541..c3b70ea 100644
--- a/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
+++ b/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
@@ -39,6 +39,7 @@ import org.testng.annotations.Test;
import org.rhq.core.clientapi.descriptor.configuration.ConfigurationDescriptor;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.HelpType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginComponentType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.alert.AlertPluginDescriptorType;
@@ -70,6 +71,13 @@ public class ServerPluginDescriptorUtilTest {
assert descriptor.getDescription().equals("generic description");
assert descriptor.getPackage().equals("generic.package");
+ HelpType help = descriptor.getHelp();
+ assert help != null;
+ List<Object> content = help.getContent();
+ assert content != null;
+ String helpStr = content.get(0).toString();
+ assert helpStr.equals("help text with <em>XML</em>");
+
ServerPluginComponentType pluginComponent = descriptor.getPluginComponent();
assert pluginComponent.getClazz().equals("generic.plugin.component");
diff --git a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
index e4b37a9..ae1f5af 100644
--- a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
+++ b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
@@ -11,6 +11,8 @@
xmlns:c="urn:xmlns:rhq-configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <serverplugin:help><![CDATA[help text with <em>XML</em>]]></serverplugin:help>
+
<serverplugin:plugin-component class="generic.plugin.component" />
<serverplugin:scheduled-jobs>
commit 831b27efed3353801c085d490083517e9d872200
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 18 00:49:41 2009 -0500
eclipse tool to hide dev-container files when searching for resources
diff --git a/etc/eclipse-tools/RHQ_Ignore_Target.js b/etc/eclipse-tools/RHQ_Ignore_Target.js
index 0329bde..498fe8c 100644
--- a/etc/eclipse-tools/RHQ_Ignore_Target.js
+++ b/etc/eclipse-tools/RHQ_Ignore_Target.js
@@ -8,11 +8,14 @@ function main() {
var targetFolder;
for each( file in files ) {
- if (targetFolder = file.eclipseObject.parent.findMember("target")) {
- targetFolder.setDerived(true);
- }
- else if (targetFolder = file.eclipseObject.parent.findMember("dev-container")) {
- targetFolder.setDerived(true);
- }
+ if (targetFolder = file.eclipseObject.parent.findMember("target")) {
+ targetFolder.setDerived(true);
+ }
}
-}
\ No newline at end of file
+
+ /* if it looks like dev-container is built, mark it derived also */
+ files = resources.filesMatching(".*/dev-container/jbossas/bin/run.sh");
+ for each( file in files ) {
+ file.eclipseObject.parent.parent.parent.setDerived(true);
+ }
+}
commit 4b618e36d53ef97c8710243ba0868312e4da71c0
Author: John Matthews <jmatthew(a)redhat.com>
Date: Tue Nov 17 21:11:17 2009 -0500
Allows RHN plugin to save 'metadata' needed by RHQ Yum operations
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
index 03fea76..f33e3e7 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
@@ -21,9 +21,11 @@ package org.rhq.enterprise.server.plugins.rhnhosted;
import java.io.IOException;
import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.zip.GZIPOutputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -133,7 +135,7 @@ public class RHNHelper {
*
* @return ContentProviderPackageDetails pkg object
*/
- private ContentProviderPackageDetails getDetails(RhnPackageType p, String channelName) {
+ private ContentProviderPackageDetails getDetails(RhnPackageType p, String channelName) throws IOException {
String name = p.getName();
String version = p.getVersion();
@@ -144,6 +146,7 @@ public class RHNHelper {
"Linux", "Platforms");
ContentProviderPackageDetails pkg = new ContentProviderPackageDetails(key);
+
pkg.setDisplayName(name);
pkg.setShortDescription(p.getRhnPackageSummary());
pkg.setLongDescription(p.getRhnPackageDescription());
@@ -153,7 +156,11 @@ public class RHNHelper {
pkg.setLicenseName("license");
pkg.setMD5(p.getMd5Sum());
pkg.setLocation(constructPackageUrl(channelName, rpmname));
- //pkg.setMetadata();
+
+ String metadata = PrimaryXML.createPackageXML(p);
+ byte[] gzippedMetadata = gzip(metadata.getBytes());
+ pkg.setMetadata(gzippedMetadata);
+
return pkg;
}
@@ -322,6 +329,16 @@ public class RHNHelper {
return name + "-" + version + "-" + releaseepoch + "." + arch + ".rpm";
}
+ private byte[] gzip(byte[] input ) throws IOException {
+
+ ByteArrayOutputStream zipped = new ByteArrayOutputStream();
+ GZIPOutputStream gzip = new GZIPOutputStream(zipped);
+ gzip.write(input);
+ gzip.flush();
+ gzip.close();
+ return zipped.toByteArray();
+ }
+
/*
* (non-Javadoc) @see java.lang.Object#toString()
*/
commit 4051ded4547cf520f08f8866c085cfce6b186b1d
Author: John Matthews <jmatthew(a)redhat.com>
Date: Tue Nov 17 20:51:59 2009 -0500
Adding 'metadata' to package store in RHQ.
RHQ requires us to form a Package element from a primary.xml for each package
We then need to ensure this xml string is gzipped and passed into the DTO
so it will be preserved and later used to reconstruct a primary.xml to give to yum
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/PrimaryXML.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/PrimaryXML.java
new file mode 100644
index 0000000..c40a338
--- /dev/null
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/PrimaryXML.java
@@ -0,0 +1,300 @@
+/*
+ * 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.plugins.rhnhosted;
+
+import java.util.List;
+import java.io.Serializable;
+
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageProvidesType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageProvidesEntryType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageRequiresType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageRequiresEntryType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageObsoletesType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageObsoletesEntryType;
+import org.jdom.Element;
+import org.jdom.output.XMLOutputter;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.Log;
+
+/**
+ * @author John Matthews
+ */
+public class PrimaryXML
+{
+ /** Example package element from primary.xml used by yum
+ *
+
+ <package type="rpm">
+ <name>gnome-user-docs</name>
+ <arch>noarch</arch>
+ <version ver="2.16.0" rel="2.fc6" epoch="0"/>
+ <checksum type="md5" pkgid="YES">4e7d379301407b4c79f211596b802a13</checksum>
+ <summary>GNOME User Documentation</summary>
+ <description>This package contains end user documentation for the GNOME desktop environment.</description>
+ <packager/>
+ <url/>
+ <time file="1157750823" build="1157750823"/>
+ <size package="6549456" archive="11858600" installed=""/>
+ <location href="getPackage/gnome-user-docs-2.16.0-2.fc6.noarch.rpm"/>
+ <format>
+ <rpm:license>FDL</rpm:license>
+ <rpm:vendor>Red Hat, Inc.</rpm:vendor>
+ <rpm:group>Documentation</rpm:group>
+ <rpm:buildhost>altix2.build.redhat.com</rpm:buildhost>
+ <rpm:sourcerpm>gnome-user-docs-2.16.0-2.fc6.src.rpm</rpm:sourcerpm>
+ <rpm:header-range start="440" end="97656"/>
+ <rpm:provides>
+ <rpm:entry name="gnome-user-docs" flags="EQ" epoch="0" ver="2.16.0" rel="2.fc6"/>
+ </rpm:provides>
+ <rpm:requires>
+ <rpm:entry name="/bin/sh"/>
+ <rpm:entry name="/bin/sh"/>
+ <rpm:entry name="rpmlib(CompressedFileNames)" flags="LE" epoch="0" ver="3.0.4" rel="1"/>
+ <rpm:entry name="rpmlib(PayloadFilesHavePrefix)" flags="LE" epoch="0" ver="4.0" rel="1"/>
+ <rpm:entry name="rpmlib(VersionedDependencies)" flags="LE" epoch="0" ver="3.0.3" rel="1"/>
+ <rpm:entry name="scrollkeeper" flags="GE" epoch="0" ver="0.3.11"/>
+ </rpm:requires>
+ <rpm:conflicts/>
+ <rpm:obsoletes>
+ <rpm:entry name="gnome-users-guide"/>
+ </rpm:obsoletes>
+ </format>
+</package>
+
+ **/
+
+
+ /** RPM uses bit flags to determine if a package relationships is "Greater, LessThan, Equals";
+ * These values can be found from running the python console and executing
+ * "import rpm" "print rpm.RPMSENSE_LESS", "print rpm.RPMSENSE_GREATER", "print rpm.RPMSENSE_EQUAL"
+ */
+ final static int RPM_SENSE_LESS = 2;
+ final static int RPM_SENSE_GREATER = 4;
+ final static int RPM_SENSE_EQUAL = 8;
+
+ static private final Log log = LogFactory.getLog(PrimaryXML.class);
+
+ static public String getFlags(String sense) {
+ int tmp = Integer.parseInt(sense);
+ int flags = tmp & (RPM_SENSE_LESS | RPM_SENSE_GREATER | RPM_SENSE_EQUAL);
+ if (flags == (RPM_SENSE_LESS | RPM_SENSE_EQUAL)) {
+ return "LE";
+ }
+ else if (flags == RPM_SENSE_LESS) {
+ return "LT";
+ }
+ else if (flags == (RPM_SENSE_GREATER | RPM_SENSE_EQUAL)) {
+ return "GE";
+ }
+ else if (flags == (RPM_SENSE_GREATER)) {
+ return "GT";
+ } else if (flags == (RPM_SENSE_EQUAL)) {
+ return "EQ";
+ }
+
+ log.error("Unknown rpm sense value of " + sense + " which parsed to an integer of " + tmp);
+ return "";
+ }
+
+ static public String getEpoch(String version) {
+ int end = version.indexOf("-");
+ if (end < 0) {
+ return "";
+ }
+ String tmp = version.substring(0, end);
+ int index = tmp.indexOf(":");
+ if (index < 0) {
+ return "";
+ }
+ String epoch = tmp.substring(0, index);
+ return epoch;
+ }
+
+ static public String getVersion(String version) {
+ int end = version.indexOf("-");
+ if (end < 0) {
+ return version; //unsure how to parse, return passed in string
+ }
+ String tmp = version.substring(0, end);
+ int start = tmp.indexOf(":");
+ if (start < 0) {
+ start = 0;
+ } else {
+ start = start + 1;
+ }
+ return tmp.substring(start, end);
+ }
+
+ static public String getRelease(String version) {
+ int start = version.indexOf("-");
+ if (start < 0) {
+ return ""; //unsure how to parse, return ""
+ }
+ start = start + 1; // go past the "-" character
+ return version.substring(start);
+ }
+
+ /**
+ * Will create a xml string snippet conforming to the <package> entry in a primary.xml file used by yum
+ *
+ * @param pkg JAXB Object to transform
+ * @return string snippet of xml data
+ */
+ static public String createPackageXML(RhnPackageType pkg) {
+ Element top = new Element("package");
+ top.setAttribute("type", "rpm");
+
+ Element name = new Element("name");
+ name.setText(pkg.getName());
+ top.addContent(name);
+
+ Element arch = new Element("arch");
+ arch.setText(pkg.getPackageArch());
+ top.addContent(arch);
+
+ Element version = new Element("version");
+ version.setText(pkg.getVersion());
+ version.setAttribute("ver", pkg.getVersion());
+ version.setAttribute("rel", pkg.getRelease());
+ version.setAttribute("epoch", pkg.getEpoch());
+ top.addContent(version);
+
+ Element checksum = new Element("checksum");
+ checksum.setAttribute("type", "md5");
+ checksum.setAttribute("pkgid", "YES");
+ checksum.setText(pkg.getMd5Sum());
+ top.addContent(checksum);
+
+ Element summary = new Element("summary");
+ summary.setText(pkg.getRhnPackageSummary());
+ top.addContent(summary);
+
+ Element description = new Element("description");
+ description.setText(pkg.getRhnPackageDescription());
+ top.addContent(description);
+
+ Element packager = new Element("packager");
+ //TODO: Not sure if we get 'packager' info from RHN.
+ packager.setText("");
+ top.addContent(packager);
+
+ Element url = new Element("url");
+ //TODO: Not sure what to put for url value, don't think it applies to RHN
+ url.setText("");
+ top.addContent(url);
+
+ Element time = new Element("time");
+ //TODO: Verify below, guessing for file/build times.
+ time.setAttribute("file", pkg.getLastModified());
+ time.setAttribute("build", pkg.getBuildTime());
+ top.addContent(time);
+
+ Element size = new Element("size");
+ size.setAttribute("package", pkg.getPackageSize());
+ size.setAttribute("archive", pkg.getPayloadSize());
+ //TODO: Unsure about installed, does this need to change on server side when package is installed on a client?
+ size.setAttribute("installed", "");
+ top.addContent(size);
+
+ Element location = new Element("location");
+ //TODO: Unsure about href
+ location.setAttribute("href", "");
+ top.addContent(location);
+
+ Element format = new Element("format");
+
+ Element rpmLicense = new Element("license", "rpm");
+ rpmLicense.setText(pkg.getRhnPackageCopyright());
+ format.addContent(rpmLicense);
+
+ Element rpmVendor = new Element("vendor", "rpm");
+ rpmVendor.setText(pkg.getRhnPackageVendor());
+ format.addContent(rpmVendor);
+
+ Element rpmGroup = new Element("group", "rpm");
+ rpmGroup.setText(pkg.getPackageGroup());
+ format.addContent(rpmGroup);
+
+ Element rpmBuildHost = new Element("buildhost", "rpm");
+ rpmBuildHost.setText(pkg.getBuildHost());
+ format.addContent(rpmBuildHost);
+
+ Element rpmSourceRPM = new Element("sourcerpm", "rpm");
+ rpmSourceRPM.setText(pkg.getSourceRpm());
+ format.addContent(rpmSourceRPM);
+
+ Element rpmHeaderRange = new Element("header-range", "rpm");
+ rpmHeaderRange.setAttribute("start", pkg.getRhnPackageHeaderStart());
+ rpmHeaderRange.setAttribute("end", pkg.getRhnPackageHeaderEnd());
+ format.addContent(rpmHeaderRange);
+
+ Element rpmProvides = new Element("provides", "rpm");
+ RhnPackageProvidesType provides_type = pkg.getRhnPackageProvides();
+ if (provides_type != null) {
+ List<RhnPackageProvidesEntryType> provides = provides_type.getRhnPackageProvidesEntry();
+ for (RhnPackageProvidesEntryType provEntry: provides) {
+ Element entry = new Element("entry", "rpm");
+ entry.setAttribute("name", provEntry.getName());
+ entry.setAttribute("flags", getFlags(provEntry.getSense()));
+ entry.setAttribute("epoch", getEpoch(provEntry.getVersion()));
+ entry.setAttribute("ver", getVersion(provEntry.getVersion()));
+ entry.setAttribute("rel", getRelease(provEntry.getVersion()));
+ rpmProvides.addContent(entry);
+ }
+ }
+ format.addContent(rpmProvides);
+
+ Element rpmRequires = new Element("requires", "rpm");
+ RhnPackageRequiresType requires_type = pkg.getRhnPackageRequires();
+ if (requires_type != null) {
+ List<RhnPackageRequiresEntryType> requires = requires_type.getRhnPackageRequiresEntry();
+ for (RhnPackageRequiresEntryType reqEntry: requires) {
+ Element entry = new Element("entry", "rpm");
+ entry.setAttribute("name", reqEntry.getName());
+ entry.setAttribute("flags", getFlags(reqEntry.getSense()));
+ entry.setAttribute("epoch", getEpoch(reqEntry.getVersion()));
+ entry.setAttribute("ver", getVersion(reqEntry.getVersion()));
+ entry.setAttribute("rel", getRelease(reqEntry.getVersion()));
+ rpmRequires.addContent(entry);
+ }
+ }
+ format.addContent(rpmRequires);
+
+ Element rpmConflicts = new Element("conflicts", "rpm");
+ rpmConflicts.setText(pkg.getRhnPackageConflicts());
+ format.addContent(rpmConflicts);
+
+ Element rpmObsoletes = new Element("obsoletes", "rpm");
+ RhnPackageObsoletesType obs_type = pkg.getRhnPackageObsoletes();
+ if (obs_type != null) {
+ List<Serializable> obsoletes = obs_type.getContent();
+ for (Serializable obsEntry: obsoletes) {
+ Element entry = new Element("entry", "rpm");
+ entry.setAttribute("name", obsEntry.toString());
+ rpmObsoletes.addContent(entry);
+ }
+ }
+ format.addContent(rpmObsoletes);
+
+ top.addContent(format);
+ XMLOutputter xmlOut = new XMLOutputter();
+ return xmlOut.outputString(top);
+ }
+}
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/PrimaryXMLTest.java b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/PrimaryXMLTest.java
new file mode 100644
index 0000000..dd6acab
--- /dev/null
+++ b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/PrimaryXMLTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.plugins.rhnhosted;
+
+import java.util.List;
+import java.io.ByteArrayInputStream;
+
+import junit.framework.TestCase;
+
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageProvidesEntryType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageProvidesType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageRequiresType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageRequiresEntryType;
+import org.apache.commons.lang.StringUtils;
+import org.jdom.input.SAXBuilder;
+import org.jdom.Document;
+import org.jdom.Element;
+
+/**
+ * @author John Matthews
+ */
+public class PrimaryXMLTest extends TestCase
+{
+ protected RhnPackageType getTestRhnPackage() {
+ RhnPackageType pkg = new RhnPackageType();
+ pkg.setName("gnome-user-docs");
+ pkg.setPackageArch("noarch");
+ pkg.setVersion("2.16.0");
+ pkg.setRelease("2.6fc6");
+ pkg.setEpoch("0");
+ pkg.setMd5Sum("4e7d379301407b4c79f211596b802a13");
+ pkg.setRhnPackageSummary("GNOME User Documentation");
+ pkg.setRhnPackageDescription("This package contains end user documentation for the GNOME desktop environment.");
+ pkg.setLastModified("1157750823");
+ pkg.setBuildTime("1157750823");
+ pkg.setPackageSize("6549456");
+ pkg.setPayloadSize("11858600");
+ pkg.setRhnPackageCopyright("FDL");
+ pkg.setRhnPackageVendor("Red Hat, Inc.");
+ pkg.setPackageGroup("Documentation");
+ pkg.setBuildHost("altix2.build.redhat.com");
+ pkg.setSourceRpm("gnome-user-docs-2.16.0-2.fc6.src.rpm");
+ pkg.setRhnPackageHeaderStart("440");
+ pkg.setRhnPackageHeaderEnd("97656");
+
+
+ RhnPackageProvidesType provides_type = new RhnPackageProvidesType();
+ List<RhnPackageProvidesEntryType> provides = provides_type.getRhnPackageProvidesEntry();
+ RhnPackageProvidesEntryType prov = new RhnPackageProvidesEntryType();
+ prov.setName("gnome-user-docs");
+ prov.setSense("8");
+ prov.setVersion("2.16.0-2.fc6");
+ provides.add(prov);
+ pkg.setRhnPackageProvides(provides_type);
+
+ RhnPackageRequiresType requires_type = new RhnPackageRequiresType();
+ List<RhnPackageRequiresEntryType> requires = requires_type.getRhnPackageRequiresEntry();
+ RhnPackageRequiresEntryType req = new RhnPackageRequiresEntryType();
+ req.setName("rpmlib(CompressedFileNames)");
+ req.setSense("10");
+ req.setVersion("2:3.0.4-1");
+ requires.add(req);
+ pkg.setRhnPackageRequires(requires_type);
+
+ pkg.setRhnPackageConflicts("entry1, entry2");
+ return pkg;
+ }
+
+ public void testGetFlags()
+ {
+ String value = PrimaryXML.getFlags("8");
+ assert StringUtils.equals(value, "EQ");
+
+ value = PrimaryXML.getFlags("2");
+ assert StringUtils.equals(value, "LT");
+
+ value = PrimaryXML.getFlags("4");
+ assert StringUtils.equals(value, "GT");
+
+ value = PrimaryXML.getFlags("10");
+ assert StringUtils.equals(value, "LE");
+
+ value = PrimaryXML.getFlags("12");
+ assert StringUtils.equals(value, "GE");
+
+ }
+
+ public void testGetEpoch()
+ {
+ String value = PrimaryXML.getEpoch("4:98.9-4");
+ assert StringUtils.equals(value, "4");
+
+ value = PrimaryXML.getEpoch("98.9-4");
+ assert StringUtils.equals(value, "");
+
+ value = PrimaryXML.getEpoch("");
+ assert StringUtils.equals(value, "");
+
+ value = PrimaryXML.getEpoch("98.9-45:3.f");
+ assert StringUtils.equals(value, "");
+ }
+
+
+ public void testGetVersion()
+ {
+ String value = PrimaryXML.getVersion("4:98.9-4");
+ assert StringUtils.equals(value, "98.9");
+
+ value = PrimaryXML.getVersion("98.9-4");
+ assert StringUtils.equals(value, "98.9");
+
+ value = PrimaryXML.getVersion("");
+ assert StringUtils.equals(value, "");
+
+ }
+
+ public void testGetRelease()
+ {
+ String value = PrimaryXML.getRelease("4:98.9-4");
+ assert StringUtils.equals(value, "4");
+
+ value = PrimaryXML.getRelease("98.9-4");
+ assert StringUtils.equals(value, "4");
+
+ value = PrimaryXML.getRelease("");
+ assert StringUtils.equals(value, "");
+
+ value = PrimaryXML.getRelease("98.9");
+ assert StringUtils.equals(value, "");
+ }
+
+ public void testCreatePackageXML() throws Exception
+ {
+ RhnPackageType pkg = getTestRhnPackage();
+ String xml = PrimaryXML.createPackageXML(pkg);
+ System.out.println(xml);
+
+ ByteArrayInputStream inStream = new ByteArrayInputStream(xml.getBytes());
+ SAXBuilder builder = new SAXBuilder();
+ Document doc = builder.build(inStream);
+ Element root = doc.getRootElement();
+ assert StringUtils.equals(root.getName(), "package");
+ }
+}
commit 8100fe5ddac0d87c71ba7761c3245679c9c54249
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 17 17:31:57 2009 -0500
refactor the plugin scanner to make it easier to add server-side plugin scanning
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
new file mode 100644
index 0000000..e0600e6
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginScanner.java
@@ -0,0 +1,594 @@
+/*
+ * 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.core.plugin;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.InputStream;
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.sql.DataSource;
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
+import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
+import org.rhq.core.db.DatabaseType;
+import org.rhq.core.db.DatabaseTypeFactory;
+import org.rhq.core.db.H2DatabaseType;
+import org.rhq.core.db.OracleDatabaseType;
+import org.rhq.core.db.PostgresqlDatabaseType;
+import org.rhq.core.db.SQLServerDatabaseType;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.core.util.jdbc.JDBCUtil;
+import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.core.plugin.ProductPluginDeployer.DeploymentInfo;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * This looks at both the file system and the database for new agent plugins.
+ *
+ * If an agent plugin is different in the database than on the filesystem,
+ * this scanner will stream the plugin's content to the filesystem. This
+ * allows for the normal file system scanning to occur (the normal file
+ * system scanning processor will see the new plugin from the database
+ * now in the file system and will process it normally, as if someone
+ * hand-copied that plugin to the file system). So the job of this scanner
+ * is merely to look at the database and reconcile the file system so
+ * the file system has the most up-to-date plugins. Any old plugins
+ * will be deleted from the file system. This will delegate to
+ * {@link ProductPluginDeployer} to do the actual deployment of agent plugins.
+ *
+ * @author John Mazzitelli
+ */
+public class AgentPluginScanner {
+ private Log log = LogFactory.getLog(PluginDeploymentScanner.class);
+
+ private DatabaseType dbType = null;
+
+ /** Maintains a cache of what we had on the filesystem during the last scan */
+ private Map<File, Plugin> agentPluginsOnFilesystem = new HashMap<File, Plugin>();
+
+ /** the object that we delegate to in order to do the heavy lifting of agent plugin deployment */
+ private final ProductPluginDeployer agentPluginDeployer = new ProductPluginDeployer();
+
+ /** a list of agent plugins found on previous scans that have not yet been added to the agent plugin deployer yet */
+ private List<DeploymentInfo> scanned = new ArrayList<DeploymentInfo>();
+
+ ProductPluginDeployer getAgentPluginDeployer() {
+ return this.agentPluginDeployer;
+ }
+
+ void registerAgentPlugins() throws Exception {
+ for (DeploymentInfo di : this.scanned) {
+ log.debug("Hot deploying plugin [" + di.url + "]...");
+ this.agentPluginDeployer.pluginDetected(di);
+ }
+ this.scanned.clear();
+
+ // Register all the new plugins.
+ // Call this even if we don't have any update files this time, in case an error occurred last time
+ // and we need to finish what we started before.
+ this.agentPluginDeployer.registerPlugins();
+
+ return;
+ }
+
+ 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.
+ // this is for two reasons: a) allow a caller just to make sure the filesystem
+ // is up-to-date with the latest agent plugins and b) to assign unit tests that only
+ // want to make sure the scanning works, but not worry about deploying to the DB
+ log.debug("Scanning for agent plugins");
+
+ // ensure that the filesystem and database are in a consistent state
+ List<File> updatedFiles1 = agentPluginScanFilesystem();
+ List<File> updatedFiles2 = agentPluginScanDatabase();
+
+ // process any newly detected plugins
+ List<File> allUpdatedFiles = new ArrayList<File>();
+ allUpdatedFiles.addAll(updatedFiles1);
+ allUpdatedFiles.addAll(updatedFiles2);
+
+ for (File updatedFile : allUpdatedFiles) {
+ DeploymentInfo di = new DeploymentInfo(updatedFile.toURI().toURL());
+ log.debug("Scan detected plugin [" + di.url + "]...");
+ this.scanned.add(di);
+ }
+ return;
+ }
+
+ /**
+ * 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() {
+ List<File> updated = new ArrayList<File>();
+
+ // 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");
+ }
+ });
+
+ // refresh our cache so it reflects what is currently on the filesystem
+ // first we remove any jar files in our cache that we no longer have on the filesystem
+ ArrayList<File> doomedPluginFiles = new ArrayList<File>();
+ for (File cachedPluginFile : this.agentPluginsOnFilesystem.keySet()) {
+ boolean existsOnFileSystem = false;
+ for (File filesystemPluginFile : pluginJars) {
+ if (cachedPluginFile.equals(filesystemPluginFile)) {
+ existsOnFileSystem = true;
+ continue; // our cached jar still exists on the file system
+ }
+ }
+ if (!existsOnFileSystem) {
+ doomedPluginFiles.add(cachedPluginFile); // this plugin file has been deleted from the filesystem, remove it from the cache
+ }
+ }
+ for (File deletedPluginFile : doomedPluginFiles) {
+ this.agentPluginsOnFilesystem.remove(deletedPluginFile);
+ }
+
+ // now insert new cache items representing new jar files and update existing ones as appropriate
+ for (File pluginJar : pluginJars) {
+ String md5 = null;
+
+ Plugin plugin = this.agentPluginsOnFilesystem.get(pluginJar);
+ try {
+ if (plugin != null) {
+ if (pluginJar.lastModified() == 0L) {
+ // for some reason the operating system can't give us the last mod time, we need to do MD5 check
+ md5 = MessageDigestGenerator.getDigestString(pluginJar);
+ if (!md5.equals(plugin.getMd5())) {
+ plugin = null; // this plugin jar has changed - force it to refresh the cache.
+ }
+ } else if (pluginJar.lastModified() != plugin.getMtime()) {
+ plugin = null; // this plugin jar has changed - force it to refresh the cache.
+ }
+ }
+
+ if (plugin == null) {
+ cacheFilesystemAgentPluginJar(pluginJar, md5);
+ updated.add(pluginJar);
+ }
+ } catch (Exception e) {
+ log.warn("Failed to scan plugin [" + pluginJar + "] found on filesystem. Skipping it. Cause: " + e);
+ this.agentPluginsOnFilesystem.remove(pluginJar); // act like we never saw it
+ updated.remove(pluginJar);
+ }
+ }
+
+ // Let's check to see if there are any obsolete plugins that need to be deleted.
+ // This is needed if plugin-A-1.0.jar exists and someone deployed plugin-A-1.1.jar but fails to delete plugin-A-1.0.jar.
+ doomedPluginFiles.clear();
+ HashMap<String, Plugin> pluginsByName = new HashMap<String, Plugin>();
+ for (Map.Entry<File, Plugin> currentPluginFileEntry : this.agentPluginsOnFilesystem.entrySet()) {
+ Plugin currentPlugin = currentPluginFileEntry.getValue();
+ Plugin existingPlugin = pluginsByName.get(currentPlugin.getName());
+ if (existingPlugin == null) {
+ // this is the usual case - this is the only plugin with the given name we've seen
+ pluginsByName.put(currentPlugin.getName(), currentPlugin);
+ } else {
+ Plugin obsolete = AgentPluginDescriptorUtil.determineObsoletePlugin(currentPlugin, existingPlugin);
+ if (obsolete == null) {
+ obsolete = currentPlugin; // both were identical, but we only want one file so pick one to get rid of
+ }
+ doomedPluginFiles.add(new File(this.agentPluginDeployer.getPluginDir(), obsolete.getPath()));
+ if (obsolete == existingPlugin) { // yes use == for reference equality!
+ pluginsByName.put(currentPlugin.getName(), currentPlugin); // override the original one we saw with this latest one
+ }
+ }
+ }
+
+ // now we need to actually delete any obsolete plugin files from the file system
+ for (File doomedPluginFile : doomedPluginFiles) {
+ if (doomedPluginFile.delete()) {
+ log.info("Deleted an obsolete plugin file: " + doomedPluginFile);
+ this.agentPluginsOnFilesystem.remove(doomedPluginFile);
+ updated.remove(doomedPluginFile);
+ } else {
+ log.warn("Failed to delete what was deemed an obsolete plugin file: " + doomedPluginFile);
+ }
+ }
+
+ return updated;
+ }
+
+ /**
+ * Creates a {@link Plugin} object for the given plugin jar and caches it.
+ * @param pluginJar information about this plugin jar will be cached
+ * @param md5 if known, this is the plugin jar's MD5, <code>null</code> if not known
+ * @return the plugin jar files's information that has been cached
+ * @throws Exception if failed to get information about the plugin
+ */
+ private Plugin cacheFilesystemAgentPluginJar(File pluginJar, String md5) throws Exception {
+ if (md5 == null) { // don't calculate the MD5 is we've already done it before
+ md5 = MessageDigestGenerator.getDigestString(pluginJar);
+ }
+ URL pluginUrl = pluginJar.toURI().toURL();
+ PluginDescriptor descriptor = AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginUrl);
+ String version = AgentPluginDescriptorUtil.getPluginVersion(pluginJar, descriptor).toString();
+ String name = descriptor.getName();
+ Plugin plugin = new Plugin(name, pluginJar.getName());
+ plugin.setMd5(md5);
+ plugin.setVersion(version);
+ plugin.setMtime(pluginJar.lastModified());
+ this.agentPluginsOnFilesystem.put(pluginJar, plugin);
+ return plugin;
+ }
+
+ /**
+ * This method scans the database for any new or updated agent plugins and make sure this server
+ * has a plugin file on the filesystem for each of those new/updated agent plugins.
+ *
+ * @return a list of files that appear to be new or updated and should be deployed
+ */
+ List<File> agentPluginScanDatabase() throws Exception {
+ Connection conn = null;
+ PreparedStatement ps = null;
+ ResultSet rs = null;
+
+ // these are plugins (name/path/md5/mtime) that have changed in the DB but are missing from the file system
+ List<Plugin> updatedPlugins = new ArrayList<Plugin>();
+
+ // the same list as above, only they are the files that are written to the filesystem and no longer missing
+ List<File> updatedFiles = new ArrayList<File>();
+
+ try {
+ DataSource ds = LookupUtil.getDataSource();
+ conn = ds.getConnection();
+
+ // get all the plugins
+ ps = conn.prepareStatement("SELECT NAME, PATH, MD5, MTIME, VERSION FROM " + Plugin.TABLE_NAME
+ + " WHERE ENABLED=?");
+ setEnabledFlag(conn, ps, 1, true);
+ rs = ps.executeQuery();
+ while (rs.next()) {
+ String name = rs.getString(1);
+ String path = rs.getString(2);
+ String md5 = rs.getString(3);
+ long mtime = rs.getLong(4);
+ String version = rs.getString(5);
+
+ // let's see if we have this logical plugin on the filesystem (it may or may not be under the same filename)
+ File expectedFile = new File(this.agentPluginDeployer.getPluginDir(), path);
+ File currentFile = null; // will be non-null if we find that we have this plugin on the filesystem already
+ Plugin cachedPluginOnFilesystem = this.agentPluginsOnFilesystem.get(expectedFile);
+
+ if (cachedPluginOnFilesystem != null) {
+ currentFile = expectedFile; // we have it where we are expected to have it
+ if (!cachedPluginOnFilesystem.getName().equals(name)) {
+ // I have no idea when or if this would ever happen, but at least log it so we'll see it if it does happen
+ log.warn("For some reason, the plugin file [" + expectedFile + "] is plugin ["
+ + cachedPluginOnFilesystem.getName() + "] but the database says it should be [" + name
+ + "]");
+ } else {
+ log.debug("File system and database agree on a plugin location for [" + expectedFile + "]");
+ }
+ } else {
+ // the plugin might still be on the file system but under a different filename, see if we can find it
+ for (Map.Entry<File, Plugin> cachePluginEntry : this.agentPluginsOnFilesystem.entrySet()) {
+ if (cachePluginEntry.getValue().getName().equals(name)) {
+ currentFile = cachePluginEntry.getKey();
+ cachedPluginOnFilesystem = cachePluginEntry.getValue();
+ log.info("Filesystem has a plugin [" + name + "] at the file [" + currentFile
+ + "] which is different than where the DB thinks it should be [" + expectedFile + "]");
+ break; // we found it, no need to continue the loop
+ }
+ }
+ }
+
+ if (cachedPluginOnFilesystem != null && currentFile != null && currentFile.exists()) {
+ Plugin dbPlugin = new Plugin(name, path);
+ dbPlugin.setMd5(md5);
+ dbPlugin.setVersion(version);
+ dbPlugin.setMtime(mtime);
+
+ Plugin obsoletePlugin = AgentPluginDescriptorUtil.determineObsoletePlugin(dbPlugin,
+ cachedPluginOnFilesystem);
+
+ if (obsoletePlugin == cachedPluginOnFilesystem) { // yes use == for reference equality!
+ StringBuilder logMsg = new StringBuilder();
+ logMsg.append("Found agent plugin [").append(name);
+ logMsg.append("] in the DB that is newer than the one on the filesystem: ");
+ logMsg.append("DB path=[").append(path);
+ logMsg.append("]; file path=[").append(currentFile.getName());
+ logMsg.append("]; DB MD5=[").append(md5);
+ logMsg.append("]; file MD5=[").append(cachedPluginOnFilesystem.getMd5());
+ logMsg.append("]; DB version=[").append(version);
+ logMsg.append("]; file version=[").append(cachedPluginOnFilesystem.getVersion());
+ logMsg.append("]; DB timestamp=[").append(new Date(mtime));
+ logMsg.append("]; file timestamp=[").append(new Date(cachedPluginOnFilesystem.getMtime()));
+ logMsg.append("]");
+ log.info(logMsg.toString());
+
+ updatedPlugins.add(dbPlugin);
+
+ if (currentFile.delete()) {
+ log.info("Deleted the obsolete plugin file to be updated: " + currentFile);
+ this.agentPluginsOnFilesystem.remove(currentFile);
+ } else {
+ log.warn("Failed to delete the obsolete (to-be-updated) plugin file: " + currentFile);
+ }
+ currentFile = null;
+ } else if (obsoletePlugin == null) {
+ // the db is up-to-date, but update the cache so we don't check MD5 or parse the descriptor again
+ currentFile.setLastModified(mtime);
+ cachedPluginOnFilesystem.setMtime(mtime);
+ cachedPluginOnFilesystem.setVersion(version);
+ cachedPluginOnFilesystem.setMd5(md5);
+ } else {
+ log.info("It appears that the plugin [" + dbPlugin
+ + "] in the database may be obsolete. If so, it will be updated by the plugin deployer.");
+ }
+ } else {
+ log.info("Found agent plugin in the DB that we do not yet have: " + name);
+ Plugin plugin = new Plugin(name, path, md5);
+ plugin.setMtime(mtime);
+ plugin.setVersion(version);
+ updatedPlugins.add(plugin);
+ this.agentPluginsOnFilesystem.remove(expectedFile); // paranoia, make sure the cache doesn't have this
+ }
+ }
+ JDBCUtil.safeClose(ps, rs);
+
+ // write all our updated plugins to the file system
+ ps = conn.prepareStatement("SELECT CONTENT FROM " + Plugin.TABLE_NAME + " WHERE NAME = ? AND ENABLED = ?");
+ for (Plugin plugin : updatedPlugins) {
+ File file = new File(this.agentPluginDeployer.getPluginDir(), plugin.getPath());
+
+ ps.setString(1, plugin.getName());
+ setEnabledFlag(conn, ps, 2, true);
+ rs = ps.executeQuery();
+ rs.next();
+ InputStream content = rs.getBinaryStream(1);
+ StreamUtil.copy(content, new FileOutputStream(file));
+ rs.close();
+ file.setLastModified(plugin.getMtime()); // so our file matches the database mtime
+ updatedFiles.add(file);
+ }
+ } finally {
+ JDBCUtil.safeClose(conn, ps, rs);
+ }
+
+ return updatedFiles;
+ }
+
+ private void setEnabledFlag(Connection conn, PreparedStatement ps, int index, boolean enabled) throws Exception {
+ if (null == this.dbType) {
+ this.dbType = DatabaseTypeFactory.getDatabaseType(conn);
+ }
+ if (dbType instanceof PostgresqlDatabaseType || dbType instanceof H2DatabaseType) {
+ ps.setBoolean(index, enabled);
+ } else if (dbType instanceof OracleDatabaseType || dbType instanceof SQLServerDatabaseType) {
+ ps.setInt(index, (enabled ? 1 : 0));
+ } else {
+ throw new RuntimeException("Unknown database type : " + dbType);
+ }
+ }
+
+ /**
+ * This method will stream up plugin content if the server has a plugin file
+ * but there is null content in the database (only occurs when upgrading an old server to the new
+ * schema that supports database-storage for plugins). This method will be a no-op for
+ * recent versions of the server because the database will no longer have null content from now on.
+ */
+ void fixMissingAgentPluginContent() throws Exception {
+ Connection conn = null;
+ PreparedStatement ps = null;
+ ResultSet rs = null;
+
+ // This map contains the names/paths of plugins that are missing their content in the database.
+ // This map will only have entries if this server was recently upgraded from an older version
+ // that did not support database-stored plugin content.
+ Map<String, String> pluginsMissingContentInDb = new HashMap<String, String>();
+
+ // This map contains the names/MD5s of plugins that are missing their content in the database.
+ // This map will only have entries if this server was recently upgraded from an older version
+ // that did not support database-stored plugin content.
+ Map<String, String> pluginsMissingContentInDbMD5 = new HashMap<String, String>();
+
+ try {
+ DataSource ds = LookupUtil.getDataSource();
+ conn = ds.getConnection();
+ ps = conn.prepareStatement("SELECT NAME, PATH, MD5 FROM " + Plugin.TABLE_NAME
+ + " WHERE CONTENT IS NULL AND ENABLED = ?");
+ setEnabledFlag(conn, ps, 1, true);
+ rs = ps.executeQuery();
+ while (rs.next()) {
+ String name = rs.getString(1);
+ String path = rs.getString(2);
+ String md5 = rs.getString(3);
+ pluginsMissingContentInDb.put(name, path);
+ pluginsMissingContentInDbMD5.put(name, md5);
+ }
+ } finally {
+ JDBCUtil.safeClose(conn, ps, rs);
+ }
+
+ if (!pluginsMissingContentInDb.isEmpty()) {
+ // if a plugin used to exist but now doesn't, it should be deleted - we should not fail when this occurs
+ List<String> pluginsToDelete = new ArrayList<String>();
+
+ // in all likelihood, the new plugins have different filenames; but since the descriptors
+ // will have the same plugin names, we'll be able to key off of plugin name
+ PluginDescriptor descriptor;
+ Map<String, File> existingPluginFiles = new HashMap<String, File>(); // keyed on plugin name
+ for (File file : this.agentPluginDeployer.getPluginDir().listFiles()) {
+ if (file.getName().endsWith(".jar")) {
+ try {
+ descriptor = AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(file.toURI().toURL());
+ existingPluginFiles.put(descriptor.getName(), file);
+ } catch (Exception e) {
+ log.warn("File [" + file + "] is not a valid plugin and will be ignored: " + e);
+ }
+ }
+ }
+
+ // now let's take the new content and stream it into the DB
+ for (Map.Entry<String, String> entry : pluginsMissingContentInDb.entrySet()) {
+ String name = entry.getKey();
+ String path = entry.getValue();
+ String expectedMD5 = pluginsMissingContentInDbMD5.get(name);
+ File pluginFile = existingPluginFiles.get(name);
+ if (pluginFile != null) {
+ String newMD5 = MessageDigestGenerator.getDigestString(pluginFile);
+ boolean different = !expectedMD5.equals(newMD5);
+ streamPluginFileContentToDatabase(name, pluginFile, different);
+ log.info("Missing content for plugin [" + name + "] will be uploaded from [" + pluginFile
+ + "]. different=" + different);
+ } else {
+ pluginsToDelete.add(name);
+ log.warn("The database knows of a plugin named [" + name + "] with path [" + path
+ + "] but the content is missing. This server does not have this plugin in ["
+ + this.agentPluginDeployer.getPluginDir()
+ + "] so the database cannot be updated with the content."
+ + " This plugin must be installed to manage existing inventory for its resource types.");
+ }
+ }
+
+ if (!pluginsToDelete.isEmpty()) {
+ TransactionManager tm = LookupUtil.getTransactionManager();
+ for (String pluginName : pluginsToDelete) {
+ try {
+ tm.begin();
+ DataSource ds = LookupUtil.getDataSource();
+ conn = ds.getConnection();
+ ps = conn.prepareStatement("UPDATE " + Plugin.TABLE_NAME + " SET ENABLED = ? WHERE NAME = ?");
+ setEnabledFlag(conn, ps, 1, false);
+ ps.setString(2, pluginName);
+ int updateResults = ps.executeUpdate();
+ if (updateResults == 1) {
+ log.warn("Disabled unavailable plugin [" + pluginName
+ + "] - This plugin must be provided to manage committed resources for its types."
+ + " Uninventory obsolete resources to avoid getting warnings in the server and agent.");
+ } else {
+ // TODO: should we throw an exception or is continuing the right thing to do?
+ log.error("Failed to disable unavailable plugin [" + pluginName + "].");
+ }
+ } catch (Exception e) {
+ tm.rollback();
+ tm = null;
+ throw e;
+ } finally {
+ JDBCUtil.safeClose(conn, ps, null);
+ if (tm != null) {
+ tm.commit();
+ }
+ }
+ }
+ }
+ }
+
+ return;
+ }
+
+ /**
+ * This will write the contents of the given plugin file to the database.
+ * This will store both the contents and the MD5 in an atomic transaction
+ * so they remain insync.
+ *
+ * When <code>different</code> is <code>false</code>, it means the original
+ * plugin and the one currently found on the file system are the same.
+ *
+ * When <code>different</code> is <code>true</code>, it means the plugin
+ * is most likely a different one than the one that originally existed.
+ * When this happens, it is assumed that the {@link ProductPluginDeployer} needs
+ * to see the plugin on the file system as new and needing to be processed, therefore
+ * the MD5, CONTENT and MTIME columns will be updated to ensure the deployer
+ * will process this plugin and thus update all the metadata for this plugin.
+ *
+ * @param name the name of the plugin whose content is being updated
+ * @param file the plugin file whose content will be streamed to the database
+ * @param different this will be <code>true</code> if the given file has a different filename
+ * that the plugin's "path" as found in the database.
+ *
+ *
+ * @throws Exception
+ */
+ private void streamPluginFileContentToDatabase(String name, File file, boolean different) throws Exception {
+ Connection conn = null;
+ PreparedStatement ps = null;
+ ResultSet rs = null;
+ TransactionManager tm = null;
+
+ String sql = "UPDATE " + Plugin.TABLE_NAME + " SET CONTENT = ?, MD5 = ?, MTIME = ?, PATH = ? WHERE NAME = ?";
+
+ // if 'different' is true, give bogus data so the plugin deployer will think the plugin on the file system is new
+ String md5 = (!different) ? MessageDigestGenerator.getDigestString(file) : "TO BE UPDATED";
+ long mtime = (!different) ? file.lastModified() : 0L;
+ InputStream fis = (!different) ? new FileInputStream(file) : new ByteArrayInputStream(new byte[0]);
+ int contentSize = (int) ((!different) ? file.length() : 0);
+
+ try {
+ tm = LookupUtil.getTransactionManager();
+ tm.begin();
+ DataSource ds = LookupUtil.getDataSource();
+ conn = ds.getConnection();
+ ps = conn.prepareStatement(sql);
+ ps.setBinaryStream(1, new BufferedInputStream(fis), contentSize);
+ ps.setString(2, md5);
+ ps.setLong(3, mtime);
+ ps.setString(4, file.getName());
+ ps.setString(5, name);
+ int updateResults = ps.executeUpdate();
+ if (updateResults == 1) {
+ log.info("Stored content for plugin [" + name + "] in the db. file=" + file);
+ } else {
+ throw new Exception("Failed to update content for plugin [" + name + "] from [" + file + "]");
+ }
+ } catch (Exception e) {
+ tm.rollback();
+ tm = null;
+ throw e;
+ } finally {
+ JDBCUtil.safeClose(conn, ps, rs);
+
+ try {
+ fis.close();
+ } catch (Throwable t) {
+ }
+
+ if (tm != null) {
+ tm.commit();
+ }
+ }
+ return;
+ }
+}
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 ceffd05..91bb8bd 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
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2009 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -18,93 +18,44 @@
*/
package org.rhq.enterprise.server.core.plugin;
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FilenameFilter;
-import java.io.InputStream;
-import java.net.URL;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
-import javax.sql.DataSource;
-import javax.transaction.TransactionManager;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
-import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
-import org.rhq.core.db.DatabaseType;
-import org.rhq.core.db.DatabaseTypeFactory;
-import org.rhq.core.db.H2DatabaseType;
-import org.rhq.core.db.OracleDatabaseType;
-import org.rhq.core.db.PostgresqlDatabaseType;
-import org.rhq.core.db.SQLServerDatabaseType;
-import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.core.util.file.FileUtil;
-import org.rhq.core.util.jdbc.JDBCUtil;
-import org.rhq.core.util.stream.StreamUtil;
-import org.rhq.enterprise.server.core.plugin.ProductPluginDeployer.DeploymentInfo;
import org.rhq.enterprise.server.util.LoggingThreadFactory;
-import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
/**
* This looks at both the file system and the database for new agent and server plugins.
*
- * If an agent plugin is different in the database than on the filesystem,
- * this scanner will stream the plugin's content to the filesystem. This
- * allows for the normal file system scanning to occur (the normal file
- * system scanning processor will see the new plugin from the database
- * now in the file system and will process it normally, as if someone
- * hand-copied that plugin to the file system). So the job of this scanner
- * is merely to look at the database and reconcile the file system so
- * the file system has the most up-to-date plugins. Any old plugins
- * will be deleted from the file system. This will delegate to
- * {@link ProductPluginDeployer} to do the actual deployment of agent plugins.
- *
* @author John Mazzitelli
*/
public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
private Log log = LogFactory.getLog(PluginDeploymentScanner.class);
- private DatabaseType dbType = null;
-
- /** Maintains a cache of what we had on the filesystem during the last scan */
- private Map<File, Plugin> pluginsOnFilesystem = new HashMap<File, Plugin>();
-
/** time, in millis, between each scans */
private long scanPeriod = 300000L;
+ /** handles the scheduled scanning */
+ private ScheduledExecutorService poller;
+
/** where the server-side plugins live */
private File serverPluginDir = null;
/** where the user can copy agent or server plugins */
private File userPluginDir = null;
- /** the object that we delegate to in order to do the heavy lifting of agent plugin deployment */
- private ProductPluginDeployer pluginDeployer = new ProductPluginDeployer();
-
- /** handles the scheduled scanning */
- private ScheduledExecutorService poller;
-
- /** a list of plugins found on previous scans that have not yet been added to the plugin deployer yet */
- private List<DeploymentInfo> scanned = new ArrayList<DeploymentInfo>();
+ /** what looks for new or changed agent plugins */
+ private AgentPluginScanner agentPluginScanner = new AgentPluginScanner();
public Long getScanPeriod() {
return Long.valueOf(this.scanPeriod);
@@ -135,90 +86,38 @@ public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
}
public File getAgentPluginDir() {
- return this.pluginDeployer.getPluginDir();
+ return this.agentPluginScanner.getAgentPluginDeployer().getPluginDir();
}
public void setAgentPluginDir(File dir) {
- this.pluginDeployer.setPluginDir(dir);
+ this.agentPluginScanner.getAgentPluginDeployer().setPluginDir(dir);
}
public File getLicenseFile() {
- return this.pluginDeployer.getLicenseFile();
+ return this.agentPluginScanner.getAgentPluginDeployer().getLicenseFile();
}
public void setLicenseFile(File file) {
- this.pluginDeployer.setLicenseFile(file);
- }
-
- public synchronized void scan() throws Exception {
- // The user directory is a simple location for the user to put all plugins in.
- // It makes it easy for the user to know where to put the plugins without
- // having to know the internal location for the real plugins under the ear.
- // Now we move the user's plugins to their real location in the ear.
- scanUserDirectory();
-
- // this method just scans the filesystem and database for changes but makes
- // no attempt to register them or do anything with the plugin deployer.
- // this is for two reasons: a) allow a caller just to make sure the filesystem
- // is up-to-date with the latest plugins and b) to assign unit tests that only
- // want to make sure the scanning works, but not worry about deploying to the DB
-
- log.debug("Scanning for agent plugins");
-
- // ensure that the filesystem and database are in a consistent state
- List<File> updatedFiles1 = scanFilesystem();
- List<File> updatedFiles2 = scanDatabase();
-
- // process any newly detected plugins
- List<File> allUpdatedFiles = new ArrayList<File>();
- allUpdatedFiles.addAll(updatedFiles1);
- allUpdatedFiles.addAll(updatedFiles2);
-
- for (File updatedFile : allUpdatedFiles) {
- DeploymentInfo di = new DeploymentInfo(updatedFile.toURI().toURL());
- log.debug("Scan detected plugin [" + di.url + "]...");
- this.scanned.add(di);
- }
-
- return;
- }
-
- public synchronized void scanAndRegister() throws Exception {
- // do the scan first to find any new/updated plugins
- // this will place new deployment info on updated plugins in this.scanned
- scan();
-
- for (DeploymentInfo di : this.scanned) {
- log.debug("Hot deploying plugin [" + di.url + "]...");
- this.pluginDeployer.pluginDetected(di);
- }
- this.scanned.clear();
-
- // Register all the new plugins.
- // Call this even if we don't have any update files this time, in case an error occurred last time
- // and we need to finish what we started before.
- this.pluginDeployer.registerPlugins();
-
- return;
+ this.agentPluginScanner.getAgentPluginDeployer().setLicenseFile(file);
}
public void start() throws Exception {
- // This will check to see if there are any plugin records in the database
+ // This will check to see if there are any agent plugin records in the database
// that do not have content associated with them and if so, will stream
// the content from the file system to the database. This is needed only
// in the case when this server has recently been upgraded from an old
// version of the software that did not originally have content stored in the DB.
- fixMissingPluginContent();
-
- this.pluginDeployer.start();
+ // Once we do that, we can start the agent plugin deployer.
+ this.agentPluginScanner.fixMissingAgentPluginContent();
+ this.agentPluginScanner.getAgentPluginDeployer().start();
shutdownPoller(); // paranoia - just in case somehow one is still running
- this.poller = Executors.newSingleThreadScheduledExecutor(new LoggingThreadFactory("AgentPluginScanner", true));
+ this.poller = Executors.newSingleThreadScheduledExecutor(new LoggingThreadFactory("PluginScanner", true));
return;
}
public void stop() {
- this.pluginDeployer.stop();
+ this.agentPluginScanner.getAgentPluginDeployer().stop();
shutdownPoller();
return;
}
@@ -233,10 +132,10 @@ public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
public void startDeployment() {
// We are being called by the server's startup servlet which essentially informs us that
- // the server's internal EJB/SLSBs are ready and can be called. This means we are
- // allowed to begin registering types from deployed plugins.
- this.pluginDeployer.startDeployment();
+ // the server's internal EJB/SLSBs are ready and can be called. This means we are allowed to start.
+ this.agentPluginScanner.getAgentPluginDeployer().startDeployment();
+ // this is the runnable task that executes each scan period - it runs in our thread pool
Runnable runnable = new Runnable() {
public void run() {
try {
@@ -258,6 +157,27 @@ public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
return;
}
+ public synchronized void scan() throws Exception {
+ // The user directory is a simple location for the user to put all plugins in.
+ // It makes it easy for the user to know where to put the plugins without
+ // having to know the internal location for the real plugins under the ear.
+ // Now we move the user's plugins to their real location in the ear.
+ scanUserDirectory();
+
+ // scan for agent plugins
+ this.agentPluginScanner.agentPluginScan();
+
+ return;
+ }
+
+ public synchronized void scanAndRegister() throws Exception {
+ // do the scan first to find any new/updated plugins
+ scan();
+
+ // now tell the agent plugin scanner to register plugins that it determined needs to be registered
+ this.agentPluginScanner.registerAgentPlugins();
+ }
+
/**
* Take the plugins placed in the user directory, and copy them to their apprpriate places
* in the server.
@@ -319,465 +239,4 @@ public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
return;
}
-
- /**
- * 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
- */
- private List<File> scanFilesystem() {
- List<File> updated = new ArrayList<File>();
-
- // get the current list of plugins deployed on the filesystem
- File[] pluginJars = this.pluginDeployer.getPluginDir().listFiles(new FilenameFilter() {
- public boolean accept(File dir, String name) {
- return name.endsWith(".jar");
- }
- });
-
- // refresh our cache so it reflects what is currently on the filesystem
- // first we remove any jar files in our cache that we no longer have on the filesystem
- ArrayList<File> doomedPluginFiles = new ArrayList<File>();
- for (File cachedPluginFile : this.pluginsOnFilesystem.keySet()) {
- boolean existsOnFileSystem = false;
- for (File filesystemPluginFile : pluginJars) {
- if (cachedPluginFile.equals(filesystemPluginFile)) {
- existsOnFileSystem = true;
- continue; // our cached jar still exists on the file system
- }
- }
- if (!existsOnFileSystem) {
- doomedPluginFiles.add(cachedPluginFile); // this plugin file has been deleted from the filesystem, remove it from the cache
- }
- }
- for (File deletedPluginFile : doomedPluginFiles) {
- this.pluginsOnFilesystem.remove(deletedPluginFile);
- }
-
- // now insert new cache items representing new jar files and update existing ones as appropriate
- for (File pluginJar : pluginJars) {
- String md5 = null;
-
- Plugin plugin = this.pluginsOnFilesystem.get(pluginJar);
- try {
- if (plugin != null) {
- if (pluginJar.lastModified() == 0L) {
- // for some reason the operating system can't give us the last mod time, we need to do MD5 check
- md5 = MessageDigestGenerator.getDigestString(pluginJar);
- if (!md5.equals(plugin.getMd5())) {
- plugin = null; // this plugin jar has changed - force it to refresh the cache.
- }
- } else if (pluginJar.lastModified() != plugin.getMtime()) {
- plugin = null; // this plugin jar has changed - force it to refresh the cache.
- }
- }
-
- if (plugin == null) {
- cacheFilesystemPluginJar(pluginJar, md5);
- updated.add(pluginJar);
- }
- } catch (Exception e) {
- log.warn("Failed to scan plugin [" + pluginJar + "] found on filesystem. Skipping it. Cause: " + e);
- this.pluginsOnFilesystem.remove(pluginJar); // act like we never saw it
- updated.remove(pluginJar);
- }
- }
-
- // Let's check to see if there are any obsolete plugins that need to be deleted.
- // This is needed if plugin-A-1.0.jar exists and someone deployed plugin-A-1.1.jar but fails to delete plugin-A-1.0.jar.
- doomedPluginFiles.clear();
- HashMap<String, Plugin> pluginsByName = new HashMap<String, Plugin>();
- for (Map.Entry<File, Plugin> currentPluginFileEntry : this.pluginsOnFilesystem.entrySet()) {
- Plugin currentPlugin = currentPluginFileEntry.getValue();
- Plugin existingPlugin = pluginsByName.get(currentPlugin.getName());
- if (existingPlugin == null) {
- // this is the usual case - this is the only plugin with the given name we've seen
- pluginsByName.put(currentPlugin.getName(), currentPlugin);
- } else {
- Plugin obsolete = AgentPluginDescriptorUtil.determineObsoletePlugin(currentPlugin, existingPlugin);
- if (obsolete == null) {
- obsolete = currentPlugin; // both were identical, but we only want one file so pick one to get rid of
- }
- doomedPluginFiles.add(new File(this.pluginDeployer.getPluginDir(), obsolete.getPath()));
- if (obsolete == existingPlugin) { // yes use == for reference equality!
- pluginsByName.put(currentPlugin.getName(), currentPlugin); // override the original one we saw with this latest one
- }
- }
- }
-
- // now we need to actually delete any obsolete plugin files from the file system
- for (File doomedPluginFile : doomedPluginFiles) {
- if (doomedPluginFile.delete()) {
- log.info("Deleted an obsolete plugin file: " + doomedPluginFile);
- this.pluginsOnFilesystem.remove(doomedPluginFile);
- updated.remove(doomedPluginFile);
- } else {
- log.warn("Failed to delete what was deemed an obsolete plugin file: " + doomedPluginFile);
- }
- }
-
- return updated;
- }
-
- /**
- * Creates a {@link Plugin} object for the given plugin jar and caches it.
- * @param pluginJar information about this plugin jar will be cached
- * @param md5 if known, this is the plugin jar's MD5, <code>null</code> if not known
- * @return the plugin jar files's information that has been cached
- * @throws Exception if failed to get information about the plugin
- */
- private Plugin cacheFilesystemPluginJar(File pluginJar, String md5) throws Exception {
- if (md5 == null) { // don't calculate the MD5 is we've already done it before
- md5 = MessageDigestGenerator.getDigestString(pluginJar);
- }
- URL pluginUrl = pluginJar.toURI().toURL();
- PluginDescriptor descriptor = AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginUrl);
- String version = AgentPluginDescriptorUtil.getPluginVersion(pluginJar, descriptor).toString();
- String name = descriptor.getName();
- Plugin plugin = new Plugin(name, pluginJar.getName());
- plugin.setMd5(md5);
- plugin.setVersion(version);
- plugin.setMtime(pluginJar.lastModified());
- this.pluginsOnFilesystem.put(pluginJar, plugin);
- return plugin;
- }
-
- /**
- * This method scans the database for any new or updated agent plugins and make sure this server
- * has a plugin file on the filesystem for each of those new/updated agent plugins.
- *
- * @return a list of files that appear to be new or updated and should be deployed
- */
- private List<File> scanDatabase() throws Exception {
- Connection conn = null;
- PreparedStatement ps = null;
- ResultSet rs = null;
-
- // these are plugins (name/path/md5/mtime) that have changed in the DB but are missing from the file system
- List<Plugin> updatedPlugins = new ArrayList<Plugin>();
-
- // the same list as above, only they are the files that are written to the filesystem and no longer missing
- List<File> updatedFiles = new ArrayList<File>();
-
- try {
- DataSource ds = LookupUtil.getDataSource();
- conn = ds.getConnection();
-
- // get all the plugins
- ps = conn.prepareStatement("SELECT NAME, PATH, MD5, MTIME, VERSION FROM " + Plugin.TABLE_NAME
- + " WHERE ENABLED=?");
- setEnabledFlag(conn, ps, 1, true);
- rs = ps.executeQuery();
- while (rs.next()) {
- String name = rs.getString(1);
- String path = rs.getString(2);
- String md5 = rs.getString(3);
- long mtime = rs.getLong(4);
- String version = rs.getString(5);
-
- // let's see if we have this logical plugin on the filesystem (it may or may not be under the same filename)
- File expectedFile = new File(this.pluginDeployer.getPluginDir(), path);
- File currentFile = null; // will be non-null if we find that we have this plugin on the filesystem already
- Plugin cachedPluginOnFilesystem = this.pluginsOnFilesystem.get(expectedFile);
-
- if (cachedPluginOnFilesystem != null) {
- currentFile = expectedFile; // we have it where we are expected to have it
- if (!cachedPluginOnFilesystem.getName().equals(name)) {
- // I have no idea when or if this would ever happen, but at least log it so we'll see it if it does happen
- log.warn("For some reason, the plugin file [" + expectedFile + "] is plugin ["
- + cachedPluginOnFilesystem.getName() + "] but the database says it should be [" + name
- + "]");
- } else {
- log.debug("File system and database agree on a plugin location for [" + expectedFile + "]");
- }
- } else {
- // the plugin might still be on the file system but under a different filename, see if we can find it
- for (Map.Entry<File, Plugin> cachePluginEntry : this.pluginsOnFilesystem.entrySet()) {
- if (cachePluginEntry.getValue().getName().equals(name)) {
- currentFile = cachePluginEntry.getKey();
- cachedPluginOnFilesystem = cachePluginEntry.getValue();
- log.info("Filesystem has a plugin [" + name + "] at the file [" + currentFile
- + "] which is different than where the DB thinks it should be [" + expectedFile + "]");
- break; // we found it, no need to continue the loop
- }
- }
- }
-
- if (cachedPluginOnFilesystem != null && currentFile != null && currentFile.exists()) {
- Plugin dbPlugin = new Plugin(name, path);
- dbPlugin.setMd5(md5);
- dbPlugin.setVersion(version);
- dbPlugin.setMtime(mtime);
-
- Plugin obsoletePlugin = AgentPluginDescriptorUtil.determineObsoletePlugin(dbPlugin,
- cachedPluginOnFilesystem);
-
- if (obsoletePlugin == cachedPluginOnFilesystem) { // yes use == for reference equality!
- StringBuilder logMsg = new StringBuilder();
- logMsg.append("Found agent plugin [").append(name);
- logMsg.append("] in the DB that is newer than the one on the filesystem: ");
- logMsg.append("DB path=[").append(path);
- logMsg.append("]; file path=[").append(currentFile.getName());
- logMsg.append("]; DB MD5=[").append(md5);
- logMsg.append("]; file MD5=[").append(cachedPluginOnFilesystem.getMd5());
- logMsg.append("]; DB version=[").append(version);
- logMsg.append("]; file version=[").append(cachedPluginOnFilesystem.getVersion());
- logMsg.append("]; DB timestamp=[").append(new Date(mtime));
- logMsg.append("]; file timestamp=[").append(new Date(cachedPluginOnFilesystem.getMtime()));
- logMsg.append("]");
- log.info(logMsg.toString());
-
- updatedPlugins.add(dbPlugin);
-
- if (currentFile.delete()) {
- log.info("Deleted the obsolete plugin file to be updated: " + currentFile);
- this.pluginsOnFilesystem.remove(currentFile);
- } else {
- log.warn("Failed to delete the obsolete (to-be-updated) plugin file: " + currentFile);
- }
- currentFile = null;
- } else if (obsoletePlugin == null) {
- // the db is up-to-date, but update the cache so we don't check MD5 or parse the descriptor again
- currentFile.setLastModified(mtime);
- cachedPluginOnFilesystem.setMtime(mtime);
- cachedPluginOnFilesystem.setVersion(version);
- cachedPluginOnFilesystem.setMd5(md5);
- } else {
- log.info("It appears that the plugin [" + dbPlugin
- + "] in the database may be obsolete. If so, it will be updated by the plugin deployer.");
- }
- } else {
- log.info("Found agent plugin in the DB that we do not yet have: " + name);
- Plugin plugin = new Plugin(name, path, md5);
- plugin.setMtime(mtime);
- plugin.setVersion(version);
- updatedPlugins.add(plugin);
- this.pluginsOnFilesystem.remove(expectedFile); // paranoia, make sure the cache doesn't have this
- }
- }
- JDBCUtil.safeClose(ps, rs);
-
- // write all our updated plugins to the file system
- ps = conn.prepareStatement("SELECT CONTENT FROM " + Plugin.TABLE_NAME + " WHERE NAME = ? AND ENABLED = ?");
- for (Plugin plugin : updatedPlugins) {
- File file = new File(this.pluginDeployer.getPluginDir(), plugin.getPath());
-
- ps.setString(1, plugin.getName());
- setEnabledFlag(conn, ps, 2, true);
- rs = ps.executeQuery();
- rs.next();
- InputStream content = rs.getBinaryStream(1);
- StreamUtil.copy(content, new FileOutputStream(file));
- rs.close();
- file.setLastModified(plugin.getMtime()); // so our file matches the database mtime
- updatedFiles.add(file);
- }
- } finally {
- JDBCUtil.safeClose(conn, ps, rs);
- }
-
- return updatedFiles;
- }
-
- /**
- * This method will stream up plugin content if the server has a plugin file
- * but there is null content in the database (only occurs when upgrading an old server to the new
- * schema that supports database-storage for plugins). This method will be a no-op for
- * recent versions of the server because the database will no longer have null content from now on.
- */
- private void fixMissingPluginContent() throws Exception {
- Connection conn = null;
- PreparedStatement ps = null;
- ResultSet rs = null;
-
- // This map contains the names/paths of plugins that are missing their content in the database.
- // This map will only have entries if this server was recently upgraded from an older version
- // that did not support database-stored plugin content.
- Map<String, String> pluginsMissingContentInDb = new HashMap<String, String>();
-
- // This map contains the names/MD5s of plugins that are missing their content in the database.
- // This map will only have entries if this server was recently upgraded from an older version
- // that did not support database-stored plugin content.
- Map<String, String> pluginsMissingContentInDbMD5 = new HashMap<String, String>();
-
- try {
- DataSource ds = LookupUtil.getDataSource();
- conn = ds.getConnection();
- ps = conn.prepareStatement("SELECT NAME, PATH, MD5 FROM " + Plugin.TABLE_NAME
- + " WHERE CONTENT IS NULL AND ENABLED = ?");
- setEnabledFlag(conn, ps, 1, true);
- rs = ps.executeQuery();
- while (rs.next()) {
- String name = rs.getString(1);
- String path = rs.getString(2);
- String md5 = rs.getString(3);
- pluginsMissingContentInDb.put(name, path);
- pluginsMissingContentInDbMD5.put(name, md5);
- }
- } finally {
- JDBCUtil.safeClose(conn, ps, rs);
- }
-
- if (!pluginsMissingContentInDb.isEmpty()) {
- // if a plugin used to exist but now doesn't, it should be deleted - we should not fail when this occurs
- List<String> pluginsToDelete = new ArrayList<String>();
-
- // in all likelihood, the new plugins have different filenames; but since the descriptors
- // will have the same plugin names, we'll be able to key off of plugin name
- PluginDescriptor descriptor;
- Map<String, File> existingPluginFiles = new HashMap<String, File>(); // keyed on plugin name
- for (File file : this.pluginDeployer.getPluginDir().listFiles()) {
- if (file.getName().endsWith(".jar")) {
- try {
- descriptor = AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(file.toURI().toURL());
- existingPluginFiles.put(descriptor.getName(), file);
- } catch (Exception e) {
- log.warn("File [" + file + "] is not a valid plugin and will be ignored: " + e);
- }
- }
- }
-
- // now let's take the new content and stream it into the DB
- for (Map.Entry<String, String> entry : pluginsMissingContentInDb.entrySet()) {
- String name = entry.getKey();
- String path = entry.getValue();
- String expectedMD5 = pluginsMissingContentInDbMD5.get(name);
- File pluginFile = existingPluginFiles.get(name);
- if (pluginFile != null) {
- String newMD5 = MessageDigestGenerator.getDigestString(pluginFile);
- boolean different = !expectedMD5.equals(newMD5);
- streamPluginFileContentToDatabase(name, pluginFile, different);
- log.info("Missing content for plugin [" + name + "] will be uploaded from [" + pluginFile
- + "]. different=" + different);
- } else {
- pluginsToDelete.add(name);
- log.warn("The database knows of a plugin named [" + name + "] with path [" + path
- + "] but the content is missing. This server does not have this plugin in ["
- + this.pluginDeployer.getPluginDir() + "] so the database cannot be updated with the content."
- + " This plugin must be installed to manage existing inventory for its resource types.");
- }
- }
-
- if (!pluginsToDelete.isEmpty()) {
- TransactionManager tm = LookupUtil.getTransactionManager();
- for (String pluginName : pluginsToDelete) {
- try {
- tm.begin();
- DataSource ds = LookupUtil.getDataSource();
- conn = ds.getConnection();
- ps = conn.prepareStatement("UPDATE " + Plugin.TABLE_NAME + " SET ENABLED = ? WHERE NAME = ?");
- setEnabledFlag(conn, ps, 1, false);
- ps.setString(2, pluginName);
- int updateResults = ps.executeUpdate();
- if (updateResults == 1) {
- log.warn("Disabled unavailable plugin [" + pluginName
- + "] - This plugin must be provided to manage committed resources for its types."
- + " Uninventory obsolete resources to avoid getting warnings in the server and agent.");
- } else {
- // TODO: should we throw an exception or is continuing the right thing to do?
- log.error("Failed to disable unavailable plugin [" + pluginName + "].");
- }
- } catch (Exception e) {
- tm.rollback();
- tm = null;
- throw e;
- } finally {
- JDBCUtil.safeClose(conn, ps, null);
- if (tm != null) {
- tm.commit();
- }
- }
- }
- }
- }
-
- return;
- }
-
- private void setEnabledFlag(Connection conn, PreparedStatement ps, int index, boolean enabled) throws Exception {
- if (null == this.dbType) {
- this.dbType = DatabaseTypeFactory.getDatabaseType(conn);
- }
- if (dbType instanceof PostgresqlDatabaseType || dbType instanceof H2DatabaseType) {
- ps.setBoolean(index, enabled);
- } else if (dbType instanceof OracleDatabaseType || dbType instanceof SQLServerDatabaseType) {
- ps.setInt(index, (enabled ? 1 : 0));
- } else {
- throw new RuntimeException("Unknown database type : " + dbType);
- }
- }
-
- /**
- * This will write the contents of the given plugin file to the database.
- * This will store both the contents and the MD5 in an atomic transaction
- * so they remain insync.
- *
- * When <code>different</code> is <code>false</code>, it means the original
- * plugin and the one currently found on the file system are the same.
- *
- * When <code>different</code> is <code>true</code>, it means the plugin
- * is most likely a different one than the one that originally existed.
- * When this happens, it is assumed that the {@link ProductPluginDeployer} needs
- * to see the plugin on the file system as new and needing to be processed, therefore
- * the MD5, CONTENT and MTIME columns will be updated to ensure the deployer
- * will process this plugin and thus update all the metadata for this plugin.
- *
- * @param name the name of the plugin whose content is being updated
- * @param file the plugin file whose content will be streamed to the database
- * @param different this will be <code>true</code> if the given file has a different filename
- * that the plugin's "path" as found in the database.
- *
- *
- * @throws Exception
- */
- private void streamPluginFileContentToDatabase(String name, File file, boolean different) throws Exception {
- Connection conn = null;
- PreparedStatement ps = null;
- ResultSet rs = null;
- TransactionManager tm = null;
-
- String sql = "UPDATE " + Plugin.TABLE_NAME + " SET CONTENT = ?, MD5 = ?, MTIME = ?, PATH = ? WHERE NAME = ?";
-
- // if 'different' is true, give bogus data so the plugin deployer will think the plugin on the file system is new
- String md5 = (!different) ? MessageDigestGenerator.getDigestString(file) : "TO BE UPDATED";
- long mtime = (!different) ? file.lastModified() : 0L;
- InputStream fis = (!different) ? new FileInputStream(file) : new ByteArrayInputStream(new byte[0]);
- int contentSize = (int) ((!different) ? file.length() : 0);
-
- try {
- tm = LookupUtil.getTransactionManager();
- tm.begin();
- DataSource ds = LookupUtil.getDataSource();
- conn = ds.getConnection();
- ps = conn.prepareStatement(sql);
- ps.setBinaryStream(1, new BufferedInputStream(fis), contentSize);
- ps.setString(2, md5);
- ps.setLong(3, mtime);
- ps.setString(4, file.getName());
- ps.setString(5, name);
- int updateResults = ps.executeUpdate();
- if (updateResults == 1) {
- log.info("Stored content for plugin [" + name + "] in the db. file=" + file);
- } else {
- throw new Exception("Failed to update content for plugin [" + name + "] from [" + file + "]");
- }
- } catch (Exception e) {
- tm.rollback();
- tm = null;
- throw e;
- } finally {
- JDBCUtil.safeClose(conn, ps, rs);
-
- try {
- fis.close();
- } catch (Throwable t) {
- }
-
- if (tm != null) {
- tm.commit();
- }
- }
- return;
- }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ProductPluginDeployer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ProductPluginDeployer.java
index bec6ebb..5842f42 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ProductPluginDeployer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ProductPluginDeployer.java
@@ -55,8 +55,6 @@ import org.rhq.enterprise.server.util.LookupUtil;
*/
public class ProductPluginDeployer {
- public static final String AMPS_VERSION = "2.0";
-
private Log log = LogFactory.getLog(ProductPluginDeployer.class.getName());
private File pluginDir = null;
private File licenseFile = null;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
index 5b614fa..67ebfc3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
@@ -90,7 +90,7 @@ import org.rhq.enterprise.server.core.AgentManagerLocal;
import org.rhq.enterprise.server.core.CoreServerMBean;
import org.rhq.enterprise.server.core.EmailManagerBean;
import org.rhq.enterprise.server.core.EmailManagerLocal;
-import org.rhq.enterprise.server.core.plugin.PluginDeploymentScanner;
+import org.rhq.enterprise.server.core.plugin.PluginDeploymentScannerMBean;
import org.rhq.enterprise.server.discovery.DiscoveryBossBean;
import org.rhq.enterprise.server.discovery.DiscoveryBossLocal;
import org.rhq.enterprise.server.event.EventManagerBean;
@@ -535,10 +535,10 @@ public final class LookupUtil {
return jonServer;
}
- public static PluginDeploymentScanner getPluginDeploymentScanner() {
+ public static PluginDeploymentScannerMBean getPluginDeploymentScanner() {
MBeanServer jBossMBeanServer = MBeanServerLocator.locateJBoss();
- PluginDeploymentScanner scanner = (PluginDeploymentScanner) MBeanProxyExt.create(PluginDeploymentScanner.class,
- PluginDeploymentScanner.OBJECT_NAME, jBossMBeanServer);
+ PluginDeploymentScannerMBean scanner = (PluginDeploymentScannerMBean) MBeanProxyExt.create(
+ PluginDeploymentScannerMBean.class, PluginDeploymentScannerMBean.OBJECT_NAME, jBossMBeanServer);
return scanner;
}
commit b94c5c88b19054c502b4094578554c4d31585186
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 17 14:30:49 2009 -0500
log when we detect a user plugin and copy it to the internal location
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 064b1c1..ceffd05 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
@@ -301,6 +301,8 @@ public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
if (file.lastModified() > realPluginFile.lastModified()) {
FileUtil.copyFile(file, realPluginFile);
realPluginFile.setLastModified(file.lastModified());
+ log.info("Found plugin jar at [" + file.getAbsolutePath() + "] and placed it at ["
+ + realPluginFile.getAbsolutePath() + "]");
}
}
boolean deleted = file.delete();
commit 4a49cfb8be89a4162906169231646e86b50276a2
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 17 14:26:30 2009 -0500
fix possible NPE
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 1a777e4..064b1c1 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
@@ -268,7 +268,12 @@ public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
return; // not configured for a user directory, just return immediately and do nothing
}
- for (File file : userDir.listFiles()) {
+ File[] listFiles = userDir.listFiles();
+ if (listFiles == null || listFiles.length == 0) {
+ return; // nothing to do
+ }
+
+ for (File file : listFiles) {
File destinationDirectory;
if (file.getName().endsWith(".jar")) {
try {
commit b5538448b4f6d1fe875ff94761e636ccf9517344
Author: Jeff Ortel <jortel(a)redhat.com>
Date: Tue Nov 17 13:01:39 2009 -0600
800 - Add message detail and rerender repo panel on provider selection instead of table.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
index d93466a..99661b1 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
@@ -55,7 +55,15 @@ public class RepoImportUIBean extends PagedDataTableUIBean {
private List<OptionItem<Integer>> providers = null;
public RepoImportUIBean() {
- getProviderOptions();
+ }
+
+ public String getProviderName() {
+ for (OptionItem<Integer> item : providers) {
+ if (item.getId() == selectedProvider) {
+ return item.getDisplayName();
+ }
+ }
+ return "";
}
/**
@@ -99,9 +107,6 @@ public class RepoImportUIBean extends PagedDataTableUIBean {
for (ContentSource p : results) {
OptionItem<Integer> item = new OptionItem<Integer>(p.getId(), p.getName());
providers.add(item);
- if (selectedProvider == 0) {
- selectedProvider = p.getId();
- }
}
}
return SelectItemUtils.convertFromListOptionItem(providers, false);
@@ -132,11 +137,11 @@ public class RepoImportUIBean extends PagedDataTableUIBean {
repoManager.importCandidateRepo(subject, repoIds);
} catch (RepoException e) {
FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR,
- "Failed to import one or more Repositories from Content Provider", e);
+ "Failed to import one or more Repositories from " + getProviderName(), e);
return "failed";
}
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, selected.length
- + " Repositories imported from Content Provider");
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "[" + selected.length
+ + "] Repositories imported from " + getProviderName());
return "success";
}
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml
index a62bdc9..a4e0e66 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml
@@ -20,7 +20,7 @@
</h:outputLink>
>
<h:outputLink value="importRepos.xhtml">
- Import From Content Provider
+ Import
</h:outputLink>
</ui:define>
<ui:define name="body">
@@ -46,76 +46,79 @@
value="#{RepoImportUIBean.selectedProvider}"
layout="pageDirection">
<f:selectItems value="#{RepoImportUIBean.providerOptions}"/>
- <a4j:support ajaxSingle="true" event="onchange" reRender="repoTable"/>
+ <a4j:support ajaxSingle="true" event="onchange" reRender="repoPanel"/>
</h:selectOneRadio>
</h:panelGrid>
</rich:panel>
<!-- REPOS -->
- <rich:panel>
- <f:facet name="header">
- <h:outputText value="Available Repositories"/>
- </f:facet>
- <h:panelGrid columns="1" width="100%">
- <ui:param name="repoModel" value="#{RepoImportUIBean.dataModel}"/>
- <rich:dataTable id="repoTable"
- rows="#{PageControl.ReposToImportList.pageSize}"
- value="#{repoModel}"
- var="item"
- width="100%"
- columnsWidth="1%, 99%"
- headerClass="tableRowHeader"
- footerClass="on-pager-footer"
- onRowMouseOver="this.style.backgroundColor='#E7E7E7'"
- onRowMouseOut="this.style.backgroundColor='#{a4jSkin.tableBackgroundColor}'">
- <a4j:keepAlive beanName="RepoImportUIBean" />
- <f:facet name="PageControlView">
- <onc:paginationControl id="ReposToImportList" />
+ <rich:panel id="repoPanel">
+ <c:if test="#{RepoImportUIBean.selectedProvider != '0'}">
+ <f:facet name="header">
+ <h:outputText value="Available repositories provided by #{RepoImportUIBean.providerName}"/>
</f:facet>
- <rich:column>
- <f:facet name="header">
- <onc:allSelect target="selectedRepos" />
+ <h:panelGrid columns="1" width="100%">
+ <ui:param name="repoModel" value="#{RepoImportUIBean.dataModel}"/>
+ <rich:dataTable id="repoTable"
+ rows="#{PageControl.ReposToImportList.pageSize}"
+ value="#{repoModel}"
+ var="item"
+ width="100%"
+ columnsWidth="1%, 99%"
+ headerClass="tableRowHeader"
+ footerClass="on-pager-footer"
+ onRowMouseOver="this.style.backgroundColor='#E7E7E7'"
+ onRowMouseOut="this.style.backgroundColor='#{a4jSkin.tableBackgroundColor}'">
+ <a4j:keepAlive beanName="RepoImportUIBean" />
+ <f:facet name="PageControlView">
+ <onc:paginationControl id="ReposToImportList" />
</f:facet>
- <onc:select rendered="#{RepoImportUIBean.selectedRepos[item.id] eq null}"
- name="selectedRepos"
- value="#{item.id}" />
- </rich:column>
- <rich:column rendered="#{param.debug}">
- <f:facet name="header">
- <onc:sortableColumnHeader sort="c.id">
- <h:outputText styleClass="headerText" value="ID" />
- </onc:sortableColumnHeader>
+ <rich:column>
+ <f:facet name="header">
+ <onc:allSelect target="selectedRepos" />
+ </f:facet>
+ <onc:select rendered="#{RepoImportUIBean.selectedRepos[item.id] eq null}"
+ name="selectedRepos"
+ value="#{item.id}" />
+ </rich:column>
+ <rich:column rendered="#{param.debug}">
+ <f:facet name="header">
+ <onc:sortableColumnHeader sort="c.id">
+ <h:outputText styleClass="headerText" value="ID" />
+ </onc:sortableColumnHeader>
+ </f:facet>
+ <h:outputText value="#{item.id}"/>
+ </rich:column>
+ <rich:column>
+ <f:facet name="header">
+ <onc:sortableColumnHeader sort="c.name">
+ <h:outputText styleClass="headerText" value="Name" />
+ </onc:sortableColumnHeader>
+ </f:facet>
+ <h:outputLink value="repo.xhtml">
+ <f:param name="mode" value="view"/>
+ <f:param name="id" value="#{item.id}"/>
+ <h:outputText value="#{item.name}" />
+ </h:outputLink>
+ </rich:column>
+ <f:facet name="footer">
+ <rich:columnGroup>
+ <!-- colspan 6:5 for the debug 'id' column -->
+ <rich:column colspan="#{param.debug ? 6 : 5}" width="100%">
+ <onc:selectCommandButton
+ action="#{RepoImportUIBean.importSelected}"
+ value="IMPORT SELECTED"
+ target="selectedRepos"
+ styleClass="on-pager-button buttonsmall"/>
+ <ui:param name="paginationDataTableName" value="repoTable"/>
+ <ui:param name="paginationDataModel" value="#{repoModel}"/>
+ <ui:param name="paginationPageControl" value="#{PageControl.ReposToImportList}"/>
+ <ui:include src="../resource/include/pagination.xhtml"/>
+ </rich:column>
+ </rich:columnGroup>
</f:facet>
- <h:outputText value="#{item.id}"/>
- </rich:column>
- <rich:column>
- <f:facet name="header">
- <onc:sortableColumnHeader sort="c.name">
- <h:outputText styleClass="headerText" value="Name" />
- </onc:sortableColumnHeader>
- </f:facet>
- <h:outputLink value="repo.xhtml">
- <f:param name="mode" value="view"/>
- <f:param name="id" value="#{item.id}"/>
- <h:outputText value="#{item.name}" />
- </h:outputLink>
- </rich:column>
- <f:facet name="footer">
- <rich:columnGroup>
- <!-- colspan 6:5 for the debug 'id' column -->
- <rich:column colspan="#{param.debug ? 6 : 5}" width="100%">
- <onc:selectCommandButton action="#{RepoImportUIBean.importSelected}"
- value="IMPORT SELECTED"
- target="selectedRepos"
- styleClass="on-pager-button buttonsmall"/>
- <ui:param name="paginationDataTableName" value="repoTable"/>
- <ui:param name="paginationDataModel" value="#{repoModel}"/>
- <ui:param name="paginationPageControl" value="#{PageControl.ReposToImportList}"/>
- <ui:include src="../resource/include/pagination.xhtml"/>
- </rich:column>
- </rich:columnGroup>
- </f:facet>
- </rich:dataTable>
- </h:panelGrid>
+ </rich:dataTable>
+ </h:panelGrid>
+ </c:if>
</rich:panel>
</h:form>
</ui:define>
commit f1d7169360a886d42722015e541eeb707f47e4c0
Merge: a584f35... 65c4924...
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Tue Nov 17 10:50:06 2009 -0800
Merge branch 'master' into content
commit 65c4924bf459d67ae95787da6cd43861c04e33d5
Merge: 44ff607... 8d44815...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 17 11:59:22 2009 -0500
Merge branch 'pc' - this is the last of the squishes. I will never squish again, I'm all squooshed out.
this provides new scheduling metadata.
Conflicts:
etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java
etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
commit a584f355a80f3edb124afa9962122d4d6e89d561
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Tue Nov 17 10:17:55 2009 -0500
Added hook to delete candidate repos when a content provider is deleted.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
index 9eb3a35..2d1d0aa 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
@@ -86,7 +86,15 @@ import org.rhq.core.domain.resource.Resource;
@NamedQuery(name = Repo.QUERY_FIND_AVAILABLE_REPO_COMPOSITES_BY_RESOURCE_ID_COUNT, query = "SELECT COUNT( c ) "
+ "FROM Repo AS c "
+ "WHERE c.id NOT IN ( SELECT rc.repo.id FROM ResourceRepo rc WHERE rc.resource.id = :resourceId ) "
- + "AND c.candidate = false ") })
+ + "AND c.candidate = false "),
+ @NamedQuery(name = Repo.QUERY_FIND_CANDIDATES_WITH_ONLY_CONTENT_SOURCE, query = "SELECT r FROM Repo r " //
+ + "WHERE r.candidate = true " //
+ + "AND (SELECT COUNT(rcs.repo) FROM RepoContentSource rcs " //
+ + " WHERE rcs.repo.id = r.id " //
+ + " AND rcs.contentSource.id = :contentSourceId) = 1 " //
+ + "AND (SELECT COUNT(rcs) FROM RepoContentSource rcs" //
+ + " WHERE rcs.repo.id = r.id) = 1 ")
+ })
@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_REPO_ID_SEQ")
@Table(name = "RHQ_REPO")
public class Repo implements Serializable, Taggable {
@@ -105,6 +113,7 @@ public class Repo implements Serializable, Taggable {
public static final String QUERY_FIND_REPO_COMPOSITES_BY_RESOURCE_ID_COUNT = "Repo.findRepoCompositesByResourceId_count";
public static final String QUERY_FIND_AVAILABLE_REPO_COMPOSITES_BY_RESOURCE_ID = "Repo.findAvailableRepoCompositesByResourceId";
public static final String QUERY_FIND_AVAILABLE_REPO_COMPOSITES_BY_RESOURCE_ID_COUNT = "Repo.findAvailableRepoCompositesByResourceId_count";
+ public static final String QUERY_FIND_CANDIDATES_WITH_ONLY_CONTENT_SOURCE = "Repo.findCandidatesWithOnlyContentSource";
private static final long serialVersionUID = 1L;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
index bc6d543..15e4b08 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
@@ -219,6 +219,8 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
entityManager.remove(cs);
log.debug("User [" + subject + "] deleted content source [" + cs + "]");
+ repoManager.deleteCandidatesWithOnlyContentSource(subject, contentSourceId);
+
// make sure we stop its adapter and unschedule any sync job associated with it
try {
ContentServerPluginContainer pc = ContentManagerHelper.getPluginContainer();
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 13995a7..0688ddd 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
@@ -332,6 +332,20 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
return repo;
}
+ @SuppressWarnings("unchecked")
+ @RequiredPermission(Permission.MANAGE_INVENTORY)
+ public void deleteCandidatesWithOnlyContentSource(Subject subject, int contentSourceId) {
+ Query query = entityManager.createNamedQuery(Repo.QUERY_FIND_CANDIDATES_WITH_ONLY_CONTENT_SOURCE);
+
+ query.setParameter("contentSourceId", contentSourceId);
+
+ List<Repo> repoList = query.getResultList();
+
+ for (Repo deleteMe : repoList) {
+ deleteRepo(subject, deleteMe.getId());
+ }
+ }
+
@RequiredPermission(Permission.MANAGE_INVENTORY)
public void processRepoImportReport(Subject subject, RepoImportReport report, int contentSourceId,
StringBuilder result) {
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 7ed6c66..fe2090b 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
@@ -157,6 +157,14 @@ public interface RepoManagerLocal {
Repo createCandidateRepo(Subject subject, Repo repo) throws RepoException;
/**
+ * Removes candidate repos whose only content source is the indicated content source.
+ *
+ * @param subject user performing the delete
+ * @param contentSourceId identifies the content source
+ */
+ void deleteCandidatesWithOnlyContentSource(Subject subject, int contentSourceId);
+
+ /**
* Handles a repo report from a content provider, adding and removing candidate repos as necessary into the
* database.
*
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
index 5c9db6a..a1537c3 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
@@ -442,4 +442,49 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
}
}
+
+ @Test(enabled = ENABLED)
+ public void deleteCandidatesForContentSource() throws Exception {
+ // Setup
+ ContentSourceType contentSourceType = new ContentSourceType("testSourceType");
+ Set<ContentSourceType> types = new HashSet<ContentSourceType>(1);
+ types.add(contentSourceType);
+ contentSourceMetadataManager.registerTypes(types);
+
+ ContentSource source1 = new ContentSource("testSource1", contentSourceType);
+ source1 = contentSourceManager.simpleCreateContentSource(overlord, source1);
+
+ ContentSource source2 = new ContentSource("testSource2", contentSourceType);
+ source2 = contentSourceManager.simpleCreateContentSource(overlord, source2);
+
+ // -> Only has source to delete, should be deleted
+ Repo repo1 = new Repo("repo1");
+ repo1.addContentSource(source1);
+
+ // -> Has different source, should not be deleted
+ Repo repo2 = new Repo("repo2");
+ repo2.addContentSource(source2);
+
+ // -> Has source to delete and another source, should not be deleted
+ Repo repo3 = new Repo("repo3");
+ repo3.addContentSource(source1);
+ repo3.addContentSource(source2);
+
+ // -> No sources, should not be deleted
+ Repo repo4 = new Repo("repo4");
+
+ repo1 = repoManager.createCandidateRepo(overlord, repo1);
+ repo2 = repoManager.createCandidateRepo(overlord, repo2);
+ repo3 = repoManager.createCandidateRepo(overlord, repo3);
+ repo4 = repoManager.createCandidateRepo(overlord, repo4);
+
+ // Test
+ repoManager.deleteCandidatesWithOnlyContentSource(overlord, source1.getId());
+
+ // Verify
+ assert repoManager.getRepo(overlord, repo1.getId()) == null;
+ assert repoManager.getRepo(overlord, repo2.getId()) != null;
+ assert repoManager.getRepo(overlord, repo3.getId()) != null;
+ assert repoManager.getRepo(overlord, repo4.getId()) != null;
+ }
}
\ No newline at end of file
commit 6c56ac3960e4995a65668598a2202e7bb61bf433
Author: Sayli Karmarkar <skarmark(a)redhat.com>
Date: Tue Nov 17 03:52:25 2009 -0500
800 - Filtering out expired channels from repos that can be imported
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
index ebf7d23..03fea76 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
@@ -29,18 +29,17 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xmlrpc.XmlRpcException;
+import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails;
+import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetailsKey;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionDetails;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionFileDetails;
import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnChannelFamilyType;
import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnChannelType;
-import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageType;
-import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartableTreeType;
import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartFileType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartableTreeType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageType;
import org.rhq.enterprise.server.plugins.rhnhosted.xmlrpc.RhnComm;
import org.rhq.enterprise.server.plugins.rhnhosted.xmlrpc.RhnDownloader;
-import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails;
-import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetailsKey;
-import org.rhq.enterprise.server.plugin.pc.content.DistributionDetails;
-import org.rhq.enterprise.server.plugin.pc.content.DistributionFileDetails;
-
/**
* @author pkilambi
@@ -54,7 +53,6 @@ public class RHNHelper {
private final String systemid;
private final String distributionType;
-
private final Log log = LogFactory.getLog(RHNHelper.class);
/**
@@ -73,28 +71,28 @@ public class RHNHelper {
}
- public List<DistributionDetails> getDistributionMetaData(List<String> labels)
- throws IOException, XmlRpcException {
+ public List<DistributionDetails> getDistributionMetaData(List<String> labels) throws IOException, XmlRpcException {
log.debug("getDistributionMetaData(" + labels + " invoked");
List<DistributionDetails> distros = new ArrayList<DistributionDetails>();
List<RhnKickstartableTreeType> ksTreeTypes = rhndata.getKickstartTreeMetadata(this.systemid, labels);
- for (RhnKickstartableTreeType ksTree: ksTreeTypes) {
- log.debug("Forming DistributionDetails(" + ksTree.getLabel() + ", " + ksTree.getBasePath() +
- " , " + distributionType);
- DistributionDetails details =
- new DistributionDetails(ksTree.getLabel(), ksTree.getBasePath(), distributionType);
+ for (RhnKickstartableTreeType ksTree : ksTreeTypes) {
+ log.debug("Forming DistributionDetails(" + ksTree.getLabel() + ", " + ksTree.getBasePath() + " , "
+ + distributionType);
+ DistributionDetails details = new DistributionDetails(ksTree.getLabel(), ksTree.getBasePath(),
+ distributionType);
distros.add(details);
List<RhnKickstartFileType> ksFiles = ksTree.getRhnKickstartFiles().getRhnKickstartFile();
- for (RhnKickstartFileType ksFile: ksFiles) {
+ for (RhnKickstartFileType ksFile : ksFiles) {
if (log.isDebugEnabled()) {
- log.debug("RHNHelper::getDistributionMetaData<ksLabel=" + ksTree.getLabel() +
- "> current file = " + ksFile.getRelativePath() + ", md5sum = " + ksFile.getMd5Sum() +
- ", lastModified = " + ksFile.getLastModified() + ", fileSize = " + ksFile.getFileSize());
+ log.debug("RHNHelper::getDistributionMetaData<ksLabel=" + ksTree.getLabel() + "> current file = "
+ + ksFile.getRelativePath() + ", md5sum = " + ksFile.getMd5Sum() + ", lastModified = "
+ + ksFile.getLastModified() + ", fileSize = " + ksFile.getFileSize());
}
Long lastMod = Long.parseLong(ksFile.getLastModified());
- DistributionFileDetails dFile = new DistributionFileDetails(ksFile.getRelativePath(), lastMod, ksFile.getMd5Sum());
+ DistributionFileDetails dFile = new DistributionFileDetails(ksFile.getRelativePath(), lastMod, ksFile
+ .getMd5Sum());
Long fileSize = Long.parseLong(ksFile.getFileSize());
dFile.setFileSize(fileSize);
details.addFile(dFile);
@@ -136,7 +134,7 @@ public class RHNHelper {
* @return ContentProviderPackageDetails pkg object
*/
private ContentProviderPackageDetails getDetails(RhnPackageType p, String channelName) {
-
+
String name = p.getName();
String version = p.getVersion();
String arch = p.getPackageArch();
@@ -159,7 +157,7 @@ public class RHNHelper {
return pkg;
}
-
+
/**
* Get List of packagesIds for Given Channels
* @param channelName channel name
@@ -191,9 +189,17 @@ public class RHNHelper {
*/
public List<String> getSyncableChannels() throws IOException, XmlRpcException {
log.debug("getSyncableChannels()");
- ArrayList<String> allchannels = new ArrayList();
+ ArrayList<String> allchannels = new ArrayList<String>();
+ String[] ignoredChannelFamiliesArray = { "education", "k12ltsp", "rh-public", "rhel-devsuite", "rhel-gfs" };
+ List<String> ignoredChannelFamilies = Arrays.asList(ignoredChannelFamiliesArray);
+ log.debug("Ignoring expired channel families :");
+ log.debug(ignoredChannelFamilies.toString());
+
List<RhnChannelFamilyType> cfts = rhndata.getChannelFamilies(this.systemid);
for (RhnChannelFamilyType cf : cfts) {
+ if (ignoredChannelFamilies.contains(cf.getLabel())) {
+ continue;
+ }
String channeldata = cf.getChannelLabels();
String[] clabels = channeldata.split(" ");
if (clabels.length > 1) {
@@ -241,7 +247,7 @@ public class RHNHelper {
log.debug("getSyncableKickstartLabels(" + channelLabels + ")");
List<String> ksLabels = new ArrayList<String>();
List<RhnChannelType> rct = rhndata.getChannels(this.systemid, channelLabels);
- for (RhnChannelType ct: rct) {
+ for (RhnChannelType ct : rct) {
String ksTrees = ct.getKickstartableTrees();
String[] trees = ksTrees.split(" ");
ksLabels.addAll(Arrays.asList(trees));
@@ -249,7 +255,6 @@ public class RHNHelper {
return ksLabels;
}
-
/**
* Open an input stream to specifed relative url. Prepends the baseurl to the <i>url</i> and opens and opens and
* input stream. Files with a .gz suffix will be unziped (inline).
@@ -284,20 +289,20 @@ public class RHNHelper {
return baseurl + appendurl;
}
- /**
- * Constructs a downloadable url for package downloads.
- * @param channelName channel label to be synced.
- * @param ksTreeLabel kickstart tree label name
- * @param ksFilePath path to kickstart file
- * @return a valid url location to fetch the rpm from.
- */
+ /**
+ * Constructs a downloadable url for package downloads.
+ * @param channelName channel label to be synced.
+ * @param ksTreeLabel kickstart tree label name
+ * @param ksFilePath path to kickstart file
+ * @return a valid url location to fetch the rpm from.
+ */
public String constructKickstartFileUrl(String channelName, String ksTreeLabel, String ksFilePath) {
return constructKickstartFileUrl(baseurl, channelName, ksTreeLabel, ksFilePath);
}
static public String constructKickstartFileUrl(String baseurl, String channelName, String ksTreeLabel,
- String ksFilePath) {
+ String ksFilePath) {
String appendurl = "/SAT/$RHN/" + channelName + "/getKickstartFile/" + ksTreeLabel + "/" + ksFilePath;
return baseurl + appendurl;
}
commit 8d44815664708f2971cfafc34a2cb5f4afe19283
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 17 00:32:19 2009 -0500
rename the agent plugin scanner to indicate it scans for both kinds of plugins, not just agent
start the coding of the scanning of the top level plugins directory
diff --git a/etc/eclipse-tools/RHQ_Ignore_Target.js b/etc/eclipse-tools/RHQ_Ignore_Target.js
new file mode 100644
index 0000000..0329bde
--- /dev/null
+++ b/etc/eclipse-tools/RHQ_Ignore_Target.js
@@ -0,0 +1,18 @@
+/*
+ * Menu: RHQ > Make Maven Targets Derived
+ * DOM: http://download.eclipse.org/technology/dash/update/org.eclipse.eclipsemon...
+ */
+
+function main() {
+ var files = resources.filesMatching(".*/pom\\.xml");
+ var targetFolder;
+
+ for each( file in files ) {
+ if (targetFolder = file.eclipseObject.parent.findMember("target")) {
+ targetFolder.setDerived(true);
+ }
+ else if (targetFolder = file.eclipseObject.parent.findMember("dev-container")) {
+ targetFolder.setDerived(true);
+ }
+ }
+}
\ No newline at end of file
diff --git a/etc/samples/skeleton-plugin/pom.xml b/etc/samples/skeleton-plugin/pom.xml
index 26110ed..517ccf4 100644
--- a/etc/samples/skeleton-plugin/pom.xml
+++ b/etc/samples/skeleton-plugin/pom.xml
@@ -15,7 +15,7 @@
<description>A template for building a custom RHQ agent plugin</description>
<properties>
- <rhq.version>1.2.0.GA</rhq.version>
+ <rhq.version>1.4.0-SNAPSHOT</rhq.version>
</properties>
<dependencies>
@@ -252,4 +252,4 @@
</snapshots>
</pluginRepository>
</pluginRepositories>
-</project>
\ No newline at end of file
+</project>
diff --git a/modules/core/util/src/main/java/org/rhq/core/util/file/FileUtil.java b/modules/core/util/src/main/java/org/rhq/core/util/file/FileUtil.java
index 0d69c5d..c1f6fad 100644
--- a/modules/core/util/src/main/java/org/rhq/core/util/file/FileUtil.java
+++ b/modules/core/util/src/main/java/org/rhq/core/util/file/FileUtil.java
@@ -1,25 +1,25 @@
- /*
- * 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.
- */
+/*
+ * 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.util.file;
import java.io.BufferedInputStream;
@@ -33,7 +33,9 @@ import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+
import org.rhq.core.util.collection.IntHashMap;
+import org.rhq.core.util.stream.StreamUtil;
public class FileUtil {
private static IntHashMap invalidChars = null;
@@ -44,23 +46,21 @@ public class FileUtil {
public static void copyFile(File inFile, File outFile) throws FileNotFoundException, IOException {
BufferedInputStream is = new BufferedInputStream(new FileInputStream(inFile));
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(outFile));
- copyStream(is, os);
- is.close();
- os.close();
+ StreamUtil.copy(is, os);
}
/**
- * Default buffer size for copyStream method
- */
- public static final int BUFSIZ = 2048;
-
- /**
- * Copy a stream, using a buffer
+ * Copy a stream, using a buffer.
+ * @deprecated use {@link StreamUtil} for more methods like this - those are unit tested and used more
*/
public static void copyStream(InputStream is, OutputStream os) throws IOException {
- copyStream(is, os, new byte[BUFSIZ]);
+ StreamUtil.copy(is, os, false);
}
+ /**
+ * Copy a stream, using a buffer.
+ * @deprecated use {@link StreamUtil} for more methods like this - those are unit tested and used more
+ */
public static void copyStream(InputStream is, OutputStream os, byte[] buf) throws IOException {
int bytesRead = 0;
while (true) {
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
index b28866d..67404ae 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
@@ -39,7 +39,7 @@ import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
import org.rhq.enterprise.server.authz.PermissionException;
import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceMBean;
import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceUtil;
-import org.rhq.enterprise.server.core.plugin.AgentPluginDeploymentScannerMBean;
+import org.rhq.enterprise.server.core.plugin.PluginDeploymentScannerMBean;
import org.rhq.enterprise.server.resource.metadata.ResourceMetadataManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -65,7 +65,7 @@ public class InstalledPluginsUIBean {
hasPermission();
try {
- AgentPluginDeploymentScannerMBean scanner = LookupUtil.getAgentPluginDeploymentScanner();
+ PluginDeploymentScannerMBean scanner = LookupUtil.getPluginDeploymentScanner();
scanner.scanAndRegister();
FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Done scanning for updated agent plugins.");
} catch (Exception e) {
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
index b87c576..5bb81d3 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
@@ -51,7 +51,7 @@ import org.rhq.enterprise.server.cloud.instance.ServerManagerLocal;
import org.rhq.enterprise.server.core.AgentManagerLocal;
import org.rhq.enterprise.server.core.CustomJaasDeploymentServiceMBean;
import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceUtil;
-import org.rhq.enterprise.server.core.plugin.AgentPluginDeploymentScannerMBean;
+import org.rhq.enterprise.server.core.plugin.PluginDeploymentScannerMBean;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
@@ -212,12 +212,12 @@ public class StartupServlet extends HttpServlet {
log("Starting the agent-plugin deployer");
try {
- AgentPluginDeploymentScannerMBean deployer_mbean;
+ PluginDeploymentScannerMBean deployer_mbean;
MBeanServer mbs = MBeanServerLocator.locateJBoss();
- ObjectName name = AgentPluginDeploymentScannerMBean.OBJECT_NAME;
- Class<?> iface = AgentPluginDeploymentScannerMBean.class;
- deployer_mbean = (AgentPluginDeploymentScannerMBean) MBeanServerInvocationHandler.newProxyInstance(mbs,
- name, iface, false);
+ ObjectName name = PluginDeploymentScannerMBean.OBJECT_NAME;
+ Class<?> iface = PluginDeploymentScannerMBean.class;
+ deployer_mbean = (PluginDeploymentScannerMBean) MBeanServerInvocationHandler.newProxyInstance(mbs, name,
+ iface, false);
deployer_mbean.startDeployment();
} catch (Exception e) {
throw new ServletException("Cannot start the agent-plugin deployer", e);
diff --git a/modules/enterprise/server/container/src/main/resources/plugins/README.txt b/modules/enterprise/server/container/src/main/resources/plugins/README.txt
new file mode 100644
index 0000000..8189194
--- /dev/null
+++ b/modules/enterprise/server/container/src/main/resources/plugins/README.txt
@@ -0,0 +1,7 @@
+You can copy agent plugins or server plugins to this directory.
+
+When the server is running, it will periodically scan this
+directory and hot-deploy the plugins it finds.
+
+The jar files will be removed from this directory after they have
+been detected.
\ No newline at end of file
diff --git a/modules/enterprise/server/ear/src/main/resources/product-plugin-service.xml b/modules/enterprise/server/ear/src/main/resources/product-plugin-service.xml
index 76d1f62..1344ec8 100644
--- a/modules/enterprise/server/ear/src/main/resources/product-plugin-service.xml
+++ b/modules/enterprise/server/ear/src/main/resources/product-plugin-service.xml
@@ -3,10 +3,12 @@
<!DOCTYPE server>
<server>
- <mbean code="org.rhq.enterprise.server.core.plugin.AgentPluginDeploymentScanner"
- name="rhq:service=AgentPluginDeploymentScanner">
+ <mbean code="org.rhq.enterprise.server.core.plugin.PluginDeploymentScanner"
+ name="rhq:service=PluginDeploymentScanner">
<attribute name="ScanPeriod">${rhq.server.agent-plugin-scan-period-ms:300000}</attribute>
- <attribute name="PluginDir">${jboss.server.home.dir}/deploy/${rhq.earName}/rhq-downloads/rhq-plugins</attribute>
+ <attribute name="AgentPluginDir">${jboss.server.home.dir}/deploy/${rhq.earName}/rhq-downloads/rhq-plugins</attribute>
+ <attribute name="ServerPluginDir">${jboss.server.home.dir}/deploy/${rhq.earName}/rhq-serverplugins</attribute>
+ <attribute name="UserPluginDir">${jboss.home.dir}/../plugins</attribute>
<attribute name="LicenseFile">${jboss.server.home.dir}/deploy/${rhq.earName}/license/license.xml</attribute>
</mbean>
</server>
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 ac3bc09..2ef7f49 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
@@ -323,7 +323,7 @@ public class CoreServerServiceImpl implements CoreServerService {
if (!file_to_stream.exists()) {
log.debug("Agent is asking for a plugin that isn't on file system [" + file_to_stream
+ "] - performing plugin scan");
- LookupUtil.getAgentPluginDeploymentScanner().scan();
+ LookupUtil.getPluginDeploymentScanner().scan();
}
FileInputStream fis = new FileInputStream(file_to_stream);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginDeploymentScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginDeploymentScanner.java
deleted file mode 100644
index 4bdd40b..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginDeploymentScanner.java
+++ /dev/null
@@ -1,694 +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.core.plugin;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.FilenameFilter;
-import java.io.InputStream;
-import java.net.URL;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
-import javax.sql.DataSource;
-import javax.transaction.TransactionManager;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
-import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
-import org.rhq.core.db.DatabaseType;
-import org.rhq.core.db.DatabaseTypeFactory;
-import org.rhq.core.db.H2DatabaseType;
-import org.rhq.core.db.OracleDatabaseType;
-import org.rhq.core.db.PostgresqlDatabaseType;
-import org.rhq.core.db.SQLServerDatabaseType;
-import org.rhq.core.domain.plugin.Plugin;
-import org.rhq.core.util.MessageDigestGenerator;
-import org.rhq.core.util.exception.ThrowableUtil;
-import org.rhq.core.util.jdbc.JDBCUtil;
-import org.rhq.core.util.stream.StreamUtil;
-import org.rhq.enterprise.server.core.plugin.ProductPluginDeployer.DeploymentInfo;
-import org.rhq.enterprise.server.util.LoggingThreadFactory;
-import org.rhq.enterprise.server.util.LookupUtil;
-
-/**
- * This looks at both the file system and the database for new agent plugins.
- *
- * If an agent plugin is different in the database than on the filesystem,
- * this scanner will stream the plugin's content to the filesystem. This
- * allows for the normal file system scanning to occur (the normal file
- * system scanning processor will see the new plugin from the database
- * now in the file system and will process it normally, as if someone
- * hand-copied that plugin to the file system).
- *
- * So the job of this scanner is merely to look at the database and
- * reconcile the file system so the file system has the most up-to-date
- * plugins. Any old plugins will be deleted from the file system.
- *
- * This will delegate to {@link ProductPluginDeployer} to do the actual
- * deployment of agent plugins.
- *
- * @author John Mazzitelli
- */
-public class AgentPluginDeploymentScanner implements AgentPluginDeploymentScannerMBean {
-
- private Log log = LogFactory.getLog(AgentPluginDeploymentScanner.class);
-
- private DatabaseType dbType = null;
-
- /** Maintains a cache of what we had on the filesystem during the last scan */
- private Map<File, Plugin> pluginsOnFilesystem = new HashMap<File, Plugin>();
-
- /** time, in millis, between each scans */
- private long scanPeriod = 300000L;
-
- /** the object that we delegate to in order to do the heavy lifting of agent plugin deployment */
- private ProductPluginDeployer pluginDeployer = new ProductPluginDeployer();
-
- /** handles the scheduled scanning */
- private ScheduledExecutorService poller;
-
- /** a list of plugins found on previous scans that have not yet been added to the plugin deployer yet */
- private List<DeploymentInfo> scanned = new ArrayList<DeploymentInfo>();
-
- public Long getScanPeriod() {
- return Long.valueOf(this.scanPeriod);
- }
-
- public void setScanPeriod(Long ms) {
- if (ms != null) {
- this.scanPeriod = ms.longValue();
- } else {
- this.scanPeriod = 300000L;
- }
- }
-
- public File getPluginDir() {
- return this.pluginDeployer.getPluginDir();
- }
-
- public void setPluginDir(File pluginDirectory) {
- this.pluginDeployer.setPluginDir(pluginDirectory);
- }
-
- public File getLicenseFile() {
- return this.pluginDeployer.getLicenseFile();
- }
-
- public void setLicenseFile(File file) {
- this.pluginDeployer.setLicenseFile(file);
- }
-
- public synchronized void scan() throws Exception {
- // this method just scans the filesystem and database for changes but makes
- // no attempt to register them or do anything with the plugin deployer.
- // this is for two reasons: a) allow a caller just to make sure the filesystem
- // is up-to-date with the latest plugins and b) to assign unit tests that only
- // want to make sure the scanning works, but not worry about deploying to the DB
-
- log.debug("Scanning for agent plugins");
-
- // ensure that the filesystem and database are in a consistent state
- List<File> updatedFiles1 = scanFilesystem();
- List<File> updatedFiles2 = scanDatabase();
-
- // process any newly detected plugins
- List<File> allUpdatedFiles = new ArrayList<File>();
- allUpdatedFiles.addAll(updatedFiles1);
- allUpdatedFiles.addAll(updatedFiles2);
-
- for (File updatedFile : allUpdatedFiles) {
- DeploymentInfo di = new DeploymentInfo(updatedFile.toURI().toURL());
- log.debug("Scan detected plugin [" + di.url + "]...");
- this.scanned.add(di);
- }
-
- return;
- }
-
- public synchronized void scanAndRegister() throws Exception {
- // do the scan first to find any new/updated plugins
- // this will place new deployment info on updated plugins in this.scanned
- scan();
-
- for (DeploymentInfo di : this.scanned) {
- log.debug("Hot deploying plugin [" + di.url + "]...");
- this.pluginDeployer.pluginDetected(di);
- }
- this.scanned.clear();
-
- // Register all the new plugins.
- // Call this even if we don't have any update files this time, in case an error occurred last time
- // and we need to finish what we started before.
- this.pluginDeployer.registerPlugins();
-
- return;
- }
-
- public void start() throws Exception {
- // This will check to see if there are any plugin records in the database
- // that do not have content associated with them and if so, will stream
- // the content from the file system to the database. This is needed only
- // in the case when this server has recently been upgraded from an old
- // version of the software that did not originally have content stored in the DB.
- fixMissingPluginContent();
-
- this.pluginDeployer.start();
-
- shutdownPoller(); // paranoia - just in case somehow one is still running
- this.poller = Executors.newSingleThreadScheduledExecutor(new LoggingThreadFactory("AgentPluginScanner", true));
- return;
- }
-
- public void stop() {
- this.pluginDeployer.stop();
- shutdownPoller();
- return;
- }
-
- private void shutdownPoller() {
- if (this.poller != null) {
- this.poller.shutdownNow();
- this.poller = null;
- }
- return;
- }
-
- public void startDeployment() {
- // We are being called by the server's startup servlet which essentially informs us that
- // the server's internal EJB/SLSBs are ready and can be called. This means we are
- // allowed to begin registering types from deployed plugins.
- this.pluginDeployer.startDeployment();
-
- Runnable runnable = new Runnable() {
- public void run() {
- try {
- scanAndRegister();
- } catch (Throwable t) {
- log.error("Scan failed. Cause: " + ThrowableUtil.getAllMessages(t));
- if (log.isDebugEnabled()) {
- log.debug("Scan failure stack trace follows:", t);
- }
- }
- }
- };
-
- // do the initial scan now
- runnable.run();
-
- // schedule it to run periodically from here on out
- this.poller.scheduleWithFixedDelay(runnable, this.scanPeriod, this.scanPeriod, TimeUnit.MILLISECONDS);
- return;
- }
-
- /**
- * 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
- */
- private List<File> scanFilesystem() {
- List<File> updated = new ArrayList<File>();
-
- // get the current list of plugins deployed on the filesystem
- File[] pluginJars = this.pluginDeployer.getPluginDir().listFiles(new FilenameFilter() {
- public boolean accept(File dir, String name) {
- return name.endsWith(".jar");
- }
- });
-
- // refresh our cache so it reflects what is currently on the filesystem
- // first we remove any jar files in our cache that we no longer have on the filesystem
- ArrayList<File> doomedPluginFiles = new ArrayList<File>();
- for (File cachedPluginFile : this.pluginsOnFilesystem.keySet()) {
- boolean existsOnFileSystem = false;
- for (File filesystemPluginFile : pluginJars) {
- if (cachedPluginFile.equals(filesystemPluginFile)) {
- existsOnFileSystem = true;
- continue; // our cached jar still exists on the file system
- }
- }
- if (!existsOnFileSystem) {
- doomedPluginFiles.add(cachedPluginFile); // this plugin file has been deleted from the filesystem, remove it from the cache
- }
- }
- for (File deletedPluginFile : doomedPluginFiles) {
- this.pluginsOnFilesystem.remove(deletedPluginFile);
- }
-
- // now insert new cache items representing new jar files and update existing ones as appropriate
- for (File pluginJar : pluginJars) {
- String md5 = null;
-
- Plugin plugin = this.pluginsOnFilesystem.get(pluginJar);
- try {
- if (plugin != null) {
- if (pluginJar.lastModified() == 0L) {
- // for some reason the operating system can't give us the last mod time, we need to do MD5 check
- md5 = MessageDigestGenerator.getDigestString(pluginJar);
- if (!md5.equals(plugin.getMd5())) {
- plugin = null; // this plugin jar has changed - force it to refresh the cache.
- }
- } else if (pluginJar.lastModified() != plugin.getMtime()) {
- plugin = null; // this plugin jar has changed - force it to refresh the cache.
- }
- }
-
- if (plugin == null) {
- cacheFilesystemPluginJar(pluginJar, md5);
- updated.add(pluginJar);
- }
- } catch (Exception e) {
- log.warn("Failed to scan plugin [" + pluginJar + "] found on filesystem. Skipping it. Cause: " + e);
- this.pluginsOnFilesystem.remove(pluginJar); // act like we never saw it
- updated.remove(pluginJar);
- }
- }
-
- // Let's check to see if there are any obsolete plugins that need to be deleted.
- // This is needed if plugin-A-1.0.jar exists and someone deployed plugin-A-1.1.jar but fails to delete plugin-A-1.0.jar.
- doomedPluginFiles.clear();
- HashMap<String, Plugin> pluginsByName = new HashMap<String, Plugin>();
- for (Map.Entry<File, Plugin> currentPluginFileEntry : this.pluginsOnFilesystem.entrySet()) {
- Plugin currentPlugin = currentPluginFileEntry.getValue();
- Plugin existingPlugin = pluginsByName.get(currentPlugin.getName());
- if (existingPlugin == null) {
- // this is the usual case - this is the only plugin with the given name we've seen
- pluginsByName.put(currentPlugin.getName(), currentPlugin);
- } else {
- Plugin obsolete = AgentPluginDescriptorUtil.determineObsoletePlugin(currentPlugin, existingPlugin);
- if (obsolete == null) {
- obsolete = currentPlugin; // both were identical, but we only want one file so pick one to get rid of
- }
- doomedPluginFiles.add(new File(this.pluginDeployer.getPluginDir(), obsolete.getPath()));
- if (obsolete == existingPlugin) { // yes use == for reference equality!
- pluginsByName.put(currentPlugin.getName(), currentPlugin); // override the original one we saw with this latest one
- }
- }
- }
-
- // now we need to actually delete any obsolete plugin files from the file system
- for (File doomedPluginFile : doomedPluginFiles) {
- if (doomedPluginFile.delete()) {
- log.info("Deleted an obsolete plugin file: " + doomedPluginFile);
- this.pluginsOnFilesystem.remove(doomedPluginFile);
- updated.remove(doomedPluginFile);
- } else {
- log.warn("Failed to delete what was deemed an obsolete plugin file: " + doomedPluginFile);
- }
- }
-
- return updated;
- }
-
- /**
- * Creates a {@link Plugin} object for the given plugin jar and caches it.
- * @param pluginJar information about this plugin jar will be cached
- * @param md5 if known, this is the plugin jar's MD5, <code>null</code> if not known
- * @return the plugin jar files's information that has been cached
- * @throws Exception if failed to get information about the plugin
- */
- private Plugin cacheFilesystemPluginJar(File pluginJar, String md5) throws Exception {
- if (md5 == null) { // don't calculate the MD5 is we've already done it before
- md5 = MessageDigestGenerator.getDigestString(pluginJar);
- }
- URL pluginUrl = pluginJar.toURI().toURL();
- PluginDescriptor descriptor = AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginUrl);
- String version = AgentPluginDescriptorUtil.getPluginVersion(pluginJar, descriptor).toString();
- String name = descriptor.getName();
- Plugin plugin = new Plugin(name, pluginJar.getName());
- plugin.setMd5(md5);
- plugin.setVersion(version);
- plugin.setMtime(pluginJar.lastModified());
- this.pluginsOnFilesystem.put(pluginJar, plugin);
- return plugin;
- }
-
- /**
- * This method scans the database for any new or updated agent plugins and make sure this server
- * has a plugin file on the filesystem for each of those new/updated agent plugins.
- *
- * @return a list of files that appear to be new or updated and should be deployed
- */
- private List<File> scanDatabase() throws Exception {
- Connection conn = null;
- PreparedStatement ps = null;
- ResultSet rs = null;
-
- // these are plugins (name/path/md5/mtime) that have changed in the DB but are missing from the file system
- List<Plugin> updatedPlugins = new ArrayList<Plugin>();
-
- // the same list as above, only they are the files that are written to the filesystem and no longer missing
- List<File> updatedFiles = new ArrayList<File>();
-
- try {
- DataSource ds = LookupUtil.getDataSource();
- conn = ds.getConnection();
-
- // get all the plugins
- ps = conn.prepareStatement("SELECT NAME, PATH, MD5, MTIME, VERSION FROM " + Plugin.TABLE_NAME
- + " WHERE ENABLED=?");
- setEnabledFlag(conn, ps, 1, true);
- rs = ps.executeQuery();
- while (rs.next()) {
- String name = rs.getString(1);
- String path = rs.getString(2);
- String md5 = rs.getString(3);
- long mtime = rs.getLong(4);
- String version = rs.getString(5);
-
- // let's see if we have this logical plugin on the filesystem (it may or may not be under the same filename)
- File expectedFile = new File(this.pluginDeployer.getPluginDir(), path);
- File currentFile = null; // will be non-null if we find that we have this plugin on the filesystem already
- Plugin cachedPluginOnFilesystem = this.pluginsOnFilesystem.get(expectedFile);
-
- if (cachedPluginOnFilesystem != null) {
- currentFile = expectedFile; // we have it where we are expected to have it
- if (!cachedPluginOnFilesystem.getName().equals(name)) {
- // I have no idea when or if this would ever happen, but at least log it so we'll see it if it does happen
- log.warn("For some reason, the plugin file [" + expectedFile + "] is plugin ["
- + cachedPluginOnFilesystem.getName() + "] but the database says it should be [" + name
- + "]");
- } else {
- log.debug("File system and database agree on a plugin location for [" + expectedFile + "]");
- }
- } else {
- // the plugin might still be on the file system but under a different filename, see if we can find it
- for (Map.Entry<File, Plugin> cachePluginEntry : this.pluginsOnFilesystem.entrySet()) {
- if (cachePluginEntry.getValue().getName().equals(name)) {
- currentFile = cachePluginEntry.getKey();
- cachedPluginOnFilesystem = cachePluginEntry.getValue();
- log.info("Filesystem has a plugin [" + name + "] at the file [" + currentFile
- + "] which is different than where the DB thinks it should be [" + expectedFile + "]");
- break; // we found it, no need to continue the loop
- }
- }
- }
-
- if (cachedPluginOnFilesystem != null && currentFile != null && currentFile.exists()) {
- Plugin dbPlugin = new Plugin(name, path);
- dbPlugin.setMd5(md5);
- dbPlugin.setVersion(version);
- dbPlugin.setMtime(mtime);
-
- Plugin obsoletePlugin = AgentPluginDescriptorUtil.determineObsoletePlugin(dbPlugin,
- cachedPluginOnFilesystem);
-
- if (obsoletePlugin == cachedPluginOnFilesystem) { // yes use == for reference equality!
- StringBuilder logMsg = new StringBuilder();
- logMsg.append("Found agent plugin [").append(name);
- logMsg.append("] in the DB that is newer than the one on the filesystem: ");
- logMsg.append("DB path=[").append(path);
- logMsg.append("]; file path=[").append(currentFile.getName());
- logMsg.append("]; DB MD5=[").append(md5);
- logMsg.append("]; file MD5=[").append(cachedPluginOnFilesystem.getMd5());
- logMsg.append("]; DB version=[").append(version);
- logMsg.append("]; file version=[").append(cachedPluginOnFilesystem.getVersion());
- logMsg.append("]; DB timestamp=[").append(new Date(mtime));
- logMsg.append("]; file timestamp=[").append(new Date(cachedPluginOnFilesystem.getMtime()));
- logMsg.append("]");
- log.info(logMsg.toString());
-
- updatedPlugins.add(dbPlugin);
-
- if (currentFile.delete()) {
- log.info("Deleted the obsolete plugin file to be updated: " + currentFile);
- this.pluginsOnFilesystem.remove(currentFile);
- } else {
- log.warn("Failed to delete the obsolete (to-be-updated) plugin file: " + currentFile);
- }
- currentFile = null;
- } else if (obsoletePlugin == null) {
- // the db is up-to-date, but update the cache so we don't check MD5 or parse the descriptor again
- currentFile.setLastModified(mtime);
- cachedPluginOnFilesystem.setMtime(mtime);
- cachedPluginOnFilesystem.setVersion(version);
- cachedPluginOnFilesystem.setMd5(md5);
- } else {
- log.info("It appears that the plugin [" + dbPlugin
- + "] in the database may be obsolete. If so, it will be updated by the plugin deployer.");
- }
- } else {
- log.info("Found agent plugin in the DB that we do not yet have: " + name);
- Plugin plugin = new Plugin(name, path, md5);
- plugin.setMtime(mtime);
- plugin.setVersion(version);
- updatedPlugins.add(plugin);
- this.pluginsOnFilesystem.remove(expectedFile); // paranoia, make sure the cache doesn't have this
- }
- }
- JDBCUtil.safeClose(ps, rs);
-
- // write all our updated plugins to the file system
- ps = conn.prepareStatement("SELECT CONTENT FROM " + Plugin.TABLE_NAME + " WHERE NAME = ? AND ENABLED = ?");
- for (Plugin plugin : updatedPlugins) {
- File file = new File(this.pluginDeployer.getPluginDir(), plugin.getPath());
-
- ps.setString(1, plugin.getName());
- setEnabledFlag(conn, ps, 2, true);
- rs = ps.executeQuery();
- rs.next();
- InputStream content = rs.getBinaryStream(1);
- StreamUtil.copy(content, new FileOutputStream(file));
- rs.close();
- file.setLastModified(plugin.getMtime()); // so our file matches the database mtime
- updatedFiles.add(file);
- }
- } finally {
- JDBCUtil.safeClose(conn, ps, rs);
- }
-
- return updatedFiles;
- }
-
- /**
- * This method will stream up plugin content if the server has a plugin file
- * but there is null content in the database (only occurs when upgrading an old server to the new
- * schema that supports database-storage for plugins). This method will be a no-op for
- * recent versions of the server because the database will no longer have null content from now on.
- */
- private void fixMissingPluginContent() throws Exception {
- Connection conn = null;
- PreparedStatement ps = null;
- ResultSet rs = null;
-
- // This map contains the names/paths of plugins that are missing their content in the database.
- // This map will only have entries if this server was recently upgraded from an older version
- // that did not support database-stored plugin content.
- Map<String, String> pluginsMissingContentInDb = new HashMap<String, String>();
-
- // This map contains the names/MD5s of plugins that are missing their content in the database.
- // This map will only have entries if this server was recently upgraded from an older version
- // that did not support database-stored plugin content.
- Map<String, String> pluginsMissingContentInDbMD5 = new HashMap<String, String>();
-
- try {
- DataSource ds = LookupUtil.getDataSource();
- conn = ds.getConnection();
- ps = conn.prepareStatement("SELECT NAME, PATH, MD5 FROM " + Plugin.TABLE_NAME
- + " WHERE CONTENT IS NULL AND ENABLED = ?");
- setEnabledFlag(conn, ps, 1, true);
- rs = ps.executeQuery();
- while (rs.next()) {
- String name = rs.getString(1);
- String path = rs.getString(2);
- String md5 = rs.getString(3);
- pluginsMissingContentInDb.put(name, path);
- pluginsMissingContentInDbMD5.put(name, md5);
- }
- } finally {
- JDBCUtil.safeClose(conn, ps, rs);
- }
-
- if (!pluginsMissingContentInDb.isEmpty()) {
- // if a plugin used to exist but now doesn't, it should be deleted - we should not fail when this occurs
- List<String> pluginsToDelete = new ArrayList<String>();
-
- // in all likelihood, the new plugins have different filenames; but since the descriptors
- // will have the same plugin names, we'll be able to key off of plugin name
- PluginDescriptor descriptor;
- Map<String, File> existingPluginFiles = new HashMap<String, File>(); // keyed on plugin name
- for (File file : this.pluginDeployer.getPluginDir().listFiles()) {
- if (file.getName().endsWith(".jar")) {
- try {
- descriptor = AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(file.toURI().toURL());
- existingPluginFiles.put(descriptor.getName(), file);
- } catch (Exception e) {
- log.warn("File [" + file + "] is not a valid plugin and will be ignored: " + e);
- }
- }
- }
-
- // now let's take the new content and stream it into the DB
- for (Map.Entry<String, String> entry : pluginsMissingContentInDb.entrySet()) {
- String name = entry.getKey();
- String path = entry.getValue();
- String expectedMD5 = pluginsMissingContentInDbMD5.get(name);
- File pluginFile = existingPluginFiles.get(name);
- if (pluginFile != null) {
- String newMD5 = MessageDigestGenerator.getDigestString(pluginFile);
- boolean different = !expectedMD5.equals(newMD5);
- streamPluginFileContentToDatabase(name, pluginFile, different);
- log.info("Missing content for plugin [" + name + "] will be uploaded from [" + pluginFile
- + "]. different=" + different);
- } else {
- pluginsToDelete.add(name);
- log.warn("The database knows of a plugin named [" + name + "] with path [" + path
- + "] but the content is missing. This server does not have this plugin in ["
- + this.pluginDeployer.getPluginDir() + "] so the database cannot be updated with the content."
- + " This plugin must be installed to manage existing inventory for its resource types.");
- }
- }
-
- if (!pluginsToDelete.isEmpty()) {
- TransactionManager tm = LookupUtil.getTransactionManager();
- for (String pluginName : pluginsToDelete) {
- try {
- tm.begin();
- DataSource ds = LookupUtil.getDataSource();
- conn = ds.getConnection();
- ps = conn.prepareStatement("UPDATE " + Plugin.TABLE_NAME + " SET ENABLED = ? WHERE NAME = ?");
- setEnabledFlag(conn, ps, 1, false);
- ps.setString(2, pluginName);
- int updateResults = ps.executeUpdate();
- if (updateResults == 1) {
- log.warn("Disabled unavailable plugin [" + pluginName
- + "] - This plugin must be provided to manage committed resources for its types."
- + " Uninventory obsolete resources to avoid getting warnings in the server and agent.");
- } else {
- // TODO: should we throw an exception or is continuing the right thing to do?
- log.error("Failed to disable unavailable plugin [" + pluginName + "].");
- }
- } catch (Exception e) {
- tm.rollback();
- tm = null;
- throw e;
- } finally {
- JDBCUtil.safeClose(conn, ps, null);
- if (tm != null) {
- tm.commit();
- }
- }
- }
- }
- }
-
- return;
- }
-
- private void setEnabledFlag(Connection conn, PreparedStatement ps, int index, boolean enabled) throws Exception {
- if (null == this.dbType) {
- this.dbType = DatabaseTypeFactory.getDatabaseType(conn);
- }
- if (dbType instanceof PostgresqlDatabaseType || dbType instanceof H2DatabaseType) {
- ps.setBoolean(index, enabled);
- } else if (dbType instanceof OracleDatabaseType || dbType instanceof SQLServerDatabaseType) {
- ps.setInt(index, (enabled ? 1 : 0));
- } else {
- throw new RuntimeException("Unknown database type : " + dbType);
- }
- }
-
- /**
- * This will write the contents of the given plugin file to the database.
- * This will store both the contents and the MD5 in an atomic transaction
- * so they remain insync.
- *
- * When <code>different</code> is <code>false</code>, it means the original
- * plugin and the one currently found on the file system are the same.
- *
- * When <code>different</code> is <code>true</code>, it means the plugin
- * is most likely a different one than the one that originally existed.
- * When this happens, it is assumed that the {@link ProductPluginDeployer} needs
- * to see the plugin on the file system as new and needing to be processed, therefore
- * the MD5, CONTENT and MTIME columns will be updated to ensure the deployer
- * will process this plugin and thus update all the metadata for this plugin.
- *
- * @param name the name of the plugin whose content is being updated
- * @param file the plugin file whose content will be streamed to the database
- * @param different this will be <code>true</code> if the given file has a different filename
- * that the plugin's "path" as found in the database.
- *
- *
- * @throws Exception
- */
- private void streamPluginFileContentToDatabase(String name, File file, boolean different) throws Exception {
- Connection conn = null;
- PreparedStatement ps = null;
- ResultSet rs = null;
- TransactionManager tm = null;
-
- String sql = "UPDATE " + Plugin.TABLE_NAME + " SET CONTENT = ?, MD5 = ?, MTIME = ?, PATH = ? WHERE NAME = ?";
-
- // if 'different' is true, give bogus data so the plugin deployer will think the plugin on the file system is new
- String md5 = (!different) ? MessageDigestGenerator.getDigestString(file) : "TO BE UPDATED";
- long mtime = (!different) ? file.lastModified() : 0L;
- InputStream fis = (!different) ? new FileInputStream(file) : new ByteArrayInputStream(new byte[0]);
- int contentSize = (int) ((!different) ? file.length() : 0);
-
- try {
- tm = LookupUtil.getTransactionManager();
- tm.begin();
- DataSource ds = LookupUtil.getDataSource();
- conn = ds.getConnection();
- ps = conn.prepareStatement(sql);
- ps.setBinaryStream(1, new BufferedInputStream(fis), contentSize);
- ps.setString(2, md5);
- ps.setLong(3, mtime);
- ps.setString(4, file.getName());
- ps.setString(5, name);
- int updateResults = ps.executeUpdate();
- if (updateResults == 1) {
- log.info("Stored content for plugin [" + name + "] in the db. file=" + file);
- } else {
- throw new Exception("Failed to update content for plugin [" + name + "] from [" + file + "]");
- }
- } catch (Exception e) {
- tm.rollback();
- tm = null;
- throw e;
- } finally {
- JDBCUtil.safeClose(conn, ps, rs);
-
- try {
- fis.close();
- } catch (Throwable t) {
- }
-
- if (tm != null) {
- tm.commit();
- }
- }
- return;
- }
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginDeploymentScannerMBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginDeploymentScannerMBean.java
deleted file mode 100644
index 0d762b9..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/AgentPluginDeploymentScannerMBean.java
+++ /dev/null
@@ -1,91 +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.core.plugin;
-
-import java.io.File;
-
-import javax.management.ObjectName;
-
-import org.rhq.core.util.ObjectNameFactory;
-
-public interface AgentPluginDeploymentScannerMBean {
- /**
- * The name this service will be registered as.
- */
- ObjectName OBJECT_NAME = ObjectNameFactory.create("rhq:service=AgentPluginDeploymentScanner");
-
- void start() throws Exception;
-
- void stop();
-
- /**
- * This is called separately from the start/stop lifecycle methods. It should only be called
- * when we know the EJB/SLSB layer is fully initialized and ready to accept requests.
- */
- void startDeployment();
-
- /**
- * This will scan the database for new/updated plugins and if it finds
- * any, will write the content as plugin files in the file system. This
- * will also delete old, obsolete plugins.
- *
- * @see #scanAndRegister()
- */
- void scan() throws Exception;
-
- /**
- * This will scan the database for new/updated plugins and if it finds
- * any, will write the content as plugin files in the file system. This
- * will also delete old, obsolete plugins. Once finished, this will register
- * agent plugins and update the database as appropriate.
- */
- void scanAndRegister() throws Exception;
-
- /**
- * Sets the amount of time (in milliseconds) between scans.
- *
- * @param ms time in millis between each scans
- */
- void setScanPeriod(Long ms);
-
- /**
- * Gets the amount of time (in milliseconds) between scans.
- *
- * @return the time in millis between each scans
- */
- Long getScanPeriod();
-
- /**
- * Sets the directory where the plugin jars are located.
- *
- * @param name the name of the plugins dir
- */
- void setPluginDir(File name);
-
- /**
- * Gets the directory name where the plugin jars are located.
- *
- * @return plugin directory name
- */
- File getPluginDir();
-
- void setLicenseFile(File name);
-
- File getLicenseFile();
-}
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
new file mode 100644
index 0000000..1a777e4
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScanner.java
@@ -0,0 +1,776 @@
+/*
+ * 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.core.plugin;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.InputStream;
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import javax.sql.DataSource;
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
+import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
+import org.rhq.core.db.DatabaseType;
+import org.rhq.core.db.DatabaseTypeFactory;
+import org.rhq.core.db.H2DatabaseType;
+import org.rhq.core.db.OracleDatabaseType;
+import org.rhq.core.db.PostgresqlDatabaseType;
+import org.rhq.core.db.SQLServerDatabaseType;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.util.MessageDigestGenerator;
+import org.rhq.core.util.exception.ThrowableUtil;
+import org.rhq.core.util.file.FileUtil;
+import org.rhq.core.util.jdbc.JDBCUtil;
+import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.core.plugin.ProductPluginDeployer.DeploymentInfo;
+import org.rhq.enterprise.server.util.LoggingThreadFactory;
+import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
+
+/**
+ * This looks at both the file system and the database for new agent and server plugins.
+ *
+ * If an agent plugin is different in the database than on the filesystem,
+ * this scanner will stream the plugin's content to the filesystem. This
+ * allows for the normal file system scanning to occur (the normal file
+ * system scanning processor will see the new plugin from the database
+ * now in the file system and will process it normally, as if someone
+ * hand-copied that plugin to the file system). So the job of this scanner
+ * is merely to look at the database and reconcile the file system so
+ * the file system has the most up-to-date plugins. Any old plugins
+ * will be deleted from the file system. This will delegate to
+ * {@link ProductPluginDeployer} to do the actual deployment of agent plugins.
+ *
+ * @author John Mazzitelli
+ */
+public class PluginDeploymentScanner implements PluginDeploymentScannerMBean {
+
+ private Log log = LogFactory.getLog(PluginDeploymentScanner.class);
+
+ private DatabaseType dbType = null;
+
+ /** Maintains a cache of what we had on the filesystem during the last scan */
+ private Map<File, Plugin> pluginsOnFilesystem = new HashMap<File, Plugin>();
+
+ /** time, in millis, between each scans */
+ private long scanPeriod = 300000L;
+
+ /** where the server-side plugins live */
+ private File serverPluginDir = null;
+
+ /** where the user can copy agent or server plugins */
+ private File userPluginDir = null;
+
+ /** the object that we delegate to in order to do the heavy lifting of agent plugin deployment */
+ private ProductPluginDeployer pluginDeployer = new ProductPluginDeployer();
+
+ /** handles the scheduled scanning */
+ private ScheduledExecutorService poller;
+
+ /** a list of plugins found on previous scans that have not yet been added to the plugin deployer yet */
+ private List<DeploymentInfo> scanned = new ArrayList<DeploymentInfo>();
+
+ public Long getScanPeriod() {
+ return Long.valueOf(this.scanPeriod);
+ }
+
+ public void setScanPeriod(Long ms) {
+ if (ms != null) {
+ this.scanPeriod = ms.longValue();
+ } else {
+ this.scanPeriod = 300000L;
+ }
+ }
+
+ public File getUserPluginDir() {
+ return this.userPluginDir;
+ }
+
+ public void setUserPluginDir(File dir) {
+ this.userPluginDir = dir;
+ }
+
+ public File getServerPluginDir() {
+ return this.serverPluginDir;
+ }
+
+ public void setServerPluginDir(File dir) {
+ this.serverPluginDir = dir;
+ }
+
+ public File getAgentPluginDir() {
+ return this.pluginDeployer.getPluginDir();
+ }
+
+ public void setAgentPluginDir(File dir) {
+ this.pluginDeployer.setPluginDir(dir);
+ }
+
+ public File getLicenseFile() {
+ return this.pluginDeployer.getLicenseFile();
+ }
+
+ public void setLicenseFile(File file) {
+ this.pluginDeployer.setLicenseFile(file);
+ }
+
+ public synchronized void scan() throws Exception {
+ // The user directory is a simple location for the user to put all plugins in.
+ // It makes it easy for the user to know where to put the plugins without
+ // having to know the internal location for the real plugins under the ear.
+ // Now we move the user's plugins to their real location in the ear.
+ scanUserDirectory();
+
+ // this method just scans the filesystem and database for changes but makes
+ // no attempt to register them or do anything with the plugin deployer.
+ // this is for two reasons: a) allow a caller just to make sure the filesystem
+ // is up-to-date with the latest plugins and b) to assign unit tests that only
+ // want to make sure the scanning works, but not worry about deploying to the DB
+
+ log.debug("Scanning for agent plugins");
+
+ // ensure that the filesystem and database are in a consistent state
+ List<File> updatedFiles1 = scanFilesystem();
+ List<File> updatedFiles2 = scanDatabase();
+
+ // process any newly detected plugins
+ List<File> allUpdatedFiles = new ArrayList<File>();
+ allUpdatedFiles.addAll(updatedFiles1);
+ allUpdatedFiles.addAll(updatedFiles2);
+
+ for (File updatedFile : allUpdatedFiles) {
+ DeploymentInfo di = new DeploymentInfo(updatedFile.toURI().toURL());
+ log.debug("Scan detected plugin [" + di.url + "]...");
+ this.scanned.add(di);
+ }
+
+ return;
+ }
+
+ public synchronized void scanAndRegister() throws Exception {
+ // do the scan first to find any new/updated plugins
+ // this will place new deployment info on updated plugins in this.scanned
+ scan();
+
+ for (DeploymentInfo di : this.scanned) {
+ log.debug("Hot deploying plugin [" + di.url + "]...");
+ this.pluginDeployer.pluginDetected(di);
+ }
+ this.scanned.clear();
+
+ // Register all the new plugins.
+ // Call this even if we don't have any update files this time, in case an error occurred last time
+ // and we need to finish what we started before.
+ this.pluginDeployer.registerPlugins();
+
+ return;
+ }
+
+ public void start() throws Exception {
+ // This will check to see if there are any plugin records in the database
+ // that do not have content associated with them and if so, will stream
+ // the content from the file system to the database. This is needed only
+ // in the case when this server has recently been upgraded from an old
+ // version of the software that did not originally have content stored in the DB.
+ fixMissingPluginContent();
+
+ this.pluginDeployer.start();
+
+ shutdownPoller(); // paranoia - just in case somehow one is still running
+ this.poller = Executors.newSingleThreadScheduledExecutor(new LoggingThreadFactory("AgentPluginScanner", true));
+ return;
+ }
+
+ public void stop() {
+ this.pluginDeployer.stop();
+ shutdownPoller();
+ return;
+ }
+
+ private void shutdownPoller() {
+ if (this.poller != null) {
+ this.poller.shutdownNow();
+ this.poller = null;
+ }
+ return;
+ }
+
+ public void startDeployment() {
+ // We are being called by the server's startup servlet which essentially informs us that
+ // the server's internal EJB/SLSBs are ready and can be called. This means we are
+ // allowed to begin registering types from deployed plugins.
+ this.pluginDeployer.startDeployment();
+
+ Runnable runnable = new Runnable() {
+ public void run() {
+ try {
+ scanAndRegister();
+ } catch (Throwable t) {
+ log.error("Scan failed. Cause: " + ThrowableUtil.getAllMessages(t));
+ if (log.isDebugEnabled()) {
+ log.debug("Scan failure stack trace follows:", t);
+ }
+ }
+ }
+ };
+
+ // do the initial scan now
+ runnable.run();
+
+ // schedule it to run periodically from here on out
+ this.poller.scheduleWithFixedDelay(runnable, this.scanPeriod, this.scanPeriod, TimeUnit.MILLISECONDS);
+ return;
+ }
+
+ /**
+ * Take the plugins placed in the user directory, and copy them to their apprpriate places
+ * in the server.
+ */
+ private void scanUserDirectory() {
+ File userDir = getUserPluginDir();
+ if (userDir == null || !userDir.isDirectory()) {
+ return; // not configured for a user directory, just return immediately and do nothing
+ }
+
+ for (File file : userDir.listFiles()) {
+ File destinationDirectory;
+ if (file.getName().endsWith(".jar")) {
+ try {
+ AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(file.toURI().toURL());
+ destinationDirectory = getAgentPluginDir();
+ } catch (Exception e) {
+ try {
+ ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(file.toURI().toURL());
+ destinationDirectory = getServerPluginDir();
+ } catch (Exception e1) {
+ // skip it, doesn't look like a valid plugin jar
+ log.warn("Does not look like [" + file.getAbsolutePath() + "] is a plugin jar - ignoring");
+ continue;
+ }
+ }
+
+ try {
+ String fileMd5 = MessageDigestGenerator.getDigestString(file);
+ File realPluginFile = new File(destinationDirectory, file.getName());
+ String realPluginFileMd5 = null;
+ if (realPluginFile.exists()) {
+ realPluginFileMd5 = MessageDigestGenerator.getDigestString(realPluginFile);
+ }
+ if (!fileMd5.equals(realPluginFileMd5)) {
+ if (file.lastModified() > realPluginFile.lastModified()) {
+ FileUtil.copyFile(file, realPluginFile);
+ realPluginFile.setLastModified(file.lastModified());
+ }
+ }
+ boolean deleted = file.delete();
+ if (!deleted) {
+ log.info("The plugin jar found at[" + file.getAbsolutePath()
+ + "] has been processed and can be deleted. It failed to get deleted, "
+ + "so it may get processed again. You should delete it manually now.");
+ }
+ } catch (Exception e) {
+ log.error("Failed to process plugin [" + file.getAbsolutePath() + "], ignoring it", e);
+ }
+ }
+ }
+
+ return;
+ }
+
+ /**
+ * 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
+ */
+ private List<File> scanFilesystem() {
+ List<File> updated = new ArrayList<File>();
+
+ // get the current list of plugins deployed on the filesystem
+ File[] pluginJars = this.pluginDeployer.getPluginDir().listFiles(new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return name.endsWith(".jar");
+ }
+ });
+
+ // refresh our cache so it reflects what is currently on the filesystem
+ // first we remove any jar files in our cache that we no longer have on the filesystem
+ ArrayList<File> doomedPluginFiles = new ArrayList<File>();
+ for (File cachedPluginFile : this.pluginsOnFilesystem.keySet()) {
+ boolean existsOnFileSystem = false;
+ for (File filesystemPluginFile : pluginJars) {
+ if (cachedPluginFile.equals(filesystemPluginFile)) {
+ existsOnFileSystem = true;
+ continue; // our cached jar still exists on the file system
+ }
+ }
+ if (!existsOnFileSystem) {
+ doomedPluginFiles.add(cachedPluginFile); // this plugin file has been deleted from the filesystem, remove it from the cache
+ }
+ }
+ for (File deletedPluginFile : doomedPluginFiles) {
+ this.pluginsOnFilesystem.remove(deletedPluginFile);
+ }
+
+ // now insert new cache items representing new jar files and update existing ones as appropriate
+ for (File pluginJar : pluginJars) {
+ String md5 = null;
+
+ Plugin plugin = this.pluginsOnFilesystem.get(pluginJar);
+ try {
+ if (plugin != null) {
+ if (pluginJar.lastModified() == 0L) {
+ // for some reason the operating system can't give us the last mod time, we need to do MD5 check
+ md5 = MessageDigestGenerator.getDigestString(pluginJar);
+ if (!md5.equals(plugin.getMd5())) {
+ plugin = null; // this plugin jar has changed - force it to refresh the cache.
+ }
+ } else if (pluginJar.lastModified() != plugin.getMtime()) {
+ plugin = null; // this plugin jar has changed - force it to refresh the cache.
+ }
+ }
+
+ if (plugin == null) {
+ cacheFilesystemPluginJar(pluginJar, md5);
+ updated.add(pluginJar);
+ }
+ } catch (Exception e) {
+ log.warn("Failed to scan plugin [" + pluginJar + "] found on filesystem. Skipping it. Cause: " + e);
+ this.pluginsOnFilesystem.remove(pluginJar); // act like we never saw it
+ updated.remove(pluginJar);
+ }
+ }
+
+ // Let's check to see if there are any obsolete plugins that need to be deleted.
+ // This is needed if plugin-A-1.0.jar exists and someone deployed plugin-A-1.1.jar but fails to delete plugin-A-1.0.jar.
+ doomedPluginFiles.clear();
+ HashMap<String, Plugin> pluginsByName = new HashMap<String, Plugin>();
+ for (Map.Entry<File, Plugin> currentPluginFileEntry : this.pluginsOnFilesystem.entrySet()) {
+ Plugin currentPlugin = currentPluginFileEntry.getValue();
+ Plugin existingPlugin = pluginsByName.get(currentPlugin.getName());
+ if (existingPlugin == null) {
+ // this is the usual case - this is the only plugin with the given name we've seen
+ pluginsByName.put(currentPlugin.getName(), currentPlugin);
+ } else {
+ Plugin obsolete = AgentPluginDescriptorUtil.determineObsoletePlugin(currentPlugin, existingPlugin);
+ if (obsolete == null) {
+ obsolete = currentPlugin; // both were identical, but we only want one file so pick one to get rid of
+ }
+ doomedPluginFiles.add(new File(this.pluginDeployer.getPluginDir(), obsolete.getPath()));
+ if (obsolete == existingPlugin) { // yes use == for reference equality!
+ pluginsByName.put(currentPlugin.getName(), currentPlugin); // override the original one we saw with this latest one
+ }
+ }
+ }
+
+ // now we need to actually delete any obsolete plugin files from the file system
+ for (File doomedPluginFile : doomedPluginFiles) {
+ if (doomedPluginFile.delete()) {
+ log.info("Deleted an obsolete plugin file: " + doomedPluginFile);
+ this.pluginsOnFilesystem.remove(doomedPluginFile);
+ updated.remove(doomedPluginFile);
+ } else {
+ log.warn("Failed to delete what was deemed an obsolete plugin file: " + doomedPluginFile);
+ }
+ }
+
+ return updated;
+ }
+
+ /**
+ * Creates a {@link Plugin} object for the given plugin jar and caches it.
+ * @param pluginJar information about this plugin jar will be cached
+ * @param md5 if known, this is the plugin jar's MD5, <code>null</code> if not known
+ * @return the plugin jar files's information that has been cached
+ * @throws Exception if failed to get information about the plugin
+ */
+ private Plugin cacheFilesystemPluginJar(File pluginJar, String md5) throws Exception {
+ if (md5 == null) { // don't calculate the MD5 is we've already done it before
+ md5 = MessageDigestGenerator.getDigestString(pluginJar);
+ }
+ URL pluginUrl = pluginJar.toURI().toURL();
+ PluginDescriptor descriptor = AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginUrl);
+ String version = AgentPluginDescriptorUtil.getPluginVersion(pluginJar, descriptor).toString();
+ String name = descriptor.getName();
+ Plugin plugin = new Plugin(name, pluginJar.getName());
+ plugin.setMd5(md5);
+ plugin.setVersion(version);
+ plugin.setMtime(pluginJar.lastModified());
+ this.pluginsOnFilesystem.put(pluginJar, plugin);
+ return plugin;
+ }
+
+ /**
+ * This method scans the database for any new or updated agent plugins and make sure this server
+ * has a plugin file on the filesystem for each of those new/updated agent plugins.
+ *
+ * @return a list of files that appear to be new or updated and should be deployed
+ */
+ private List<File> scanDatabase() throws Exception {
+ Connection conn = null;
+ PreparedStatement ps = null;
+ ResultSet rs = null;
+
+ // these are plugins (name/path/md5/mtime) that have changed in the DB but are missing from the file system
+ List<Plugin> updatedPlugins = new ArrayList<Plugin>();
+
+ // the same list as above, only they are the files that are written to the filesystem and no longer missing
+ List<File> updatedFiles = new ArrayList<File>();
+
+ try {
+ DataSource ds = LookupUtil.getDataSource();
+ conn = ds.getConnection();
+
+ // get all the plugins
+ ps = conn.prepareStatement("SELECT NAME, PATH, MD5, MTIME, VERSION FROM " + Plugin.TABLE_NAME
+ + " WHERE ENABLED=?");
+ setEnabledFlag(conn, ps, 1, true);
+ rs = ps.executeQuery();
+ while (rs.next()) {
+ String name = rs.getString(1);
+ String path = rs.getString(2);
+ String md5 = rs.getString(3);
+ long mtime = rs.getLong(4);
+ String version = rs.getString(5);
+
+ // let's see if we have this logical plugin on the filesystem (it may or may not be under the same filename)
+ File expectedFile = new File(this.pluginDeployer.getPluginDir(), path);
+ File currentFile = null; // will be non-null if we find that we have this plugin on the filesystem already
+ Plugin cachedPluginOnFilesystem = this.pluginsOnFilesystem.get(expectedFile);
+
+ if (cachedPluginOnFilesystem != null) {
+ currentFile = expectedFile; // we have it where we are expected to have it
+ if (!cachedPluginOnFilesystem.getName().equals(name)) {
+ // I have no idea when or if this would ever happen, but at least log it so we'll see it if it does happen
+ log.warn("For some reason, the plugin file [" + expectedFile + "] is plugin ["
+ + cachedPluginOnFilesystem.getName() + "] but the database says it should be [" + name
+ + "]");
+ } else {
+ log.debug("File system and database agree on a plugin location for [" + expectedFile + "]");
+ }
+ } else {
+ // the plugin might still be on the file system but under a different filename, see if we can find it
+ for (Map.Entry<File, Plugin> cachePluginEntry : this.pluginsOnFilesystem.entrySet()) {
+ if (cachePluginEntry.getValue().getName().equals(name)) {
+ currentFile = cachePluginEntry.getKey();
+ cachedPluginOnFilesystem = cachePluginEntry.getValue();
+ log.info("Filesystem has a plugin [" + name + "] at the file [" + currentFile
+ + "] which is different than where the DB thinks it should be [" + expectedFile + "]");
+ break; // we found it, no need to continue the loop
+ }
+ }
+ }
+
+ if (cachedPluginOnFilesystem != null && currentFile != null && currentFile.exists()) {
+ Plugin dbPlugin = new Plugin(name, path);
+ dbPlugin.setMd5(md5);
+ dbPlugin.setVersion(version);
+ dbPlugin.setMtime(mtime);
+
+ Plugin obsoletePlugin = AgentPluginDescriptorUtil.determineObsoletePlugin(dbPlugin,
+ cachedPluginOnFilesystem);
+
+ if (obsoletePlugin == cachedPluginOnFilesystem) { // yes use == for reference equality!
+ StringBuilder logMsg = new StringBuilder();
+ logMsg.append("Found agent plugin [").append(name);
+ logMsg.append("] in the DB that is newer than the one on the filesystem: ");
+ logMsg.append("DB path=[").append(path);
+ logMsg.append("]; file path=[").append(currentFile.getName());
+ logMsg.append("]; DB MD5=[").append(md5);
+ logMsg.append("]; file MD5=[").append(cachedPluginOnFilesystem.getMd5());
+ logMsg.append("]; DB version=[").append(version);
+ logMsg.append("]; file version=[").append(cachedPluginOnFilesystem.getVersion());
+ logMsg.append("]; DB timestamp=[").append(new Date(mtime));
+ logMsg.append("]; file timestamp=[").append(new Date(cachedPluginOnFilesystem.getMtime()));
+ logMsg.append("]");
+ log.info(logMsg.toString());
+
+ updatedPlugins.add(dbPlugin);
+
+ if (currentFile.delete()) {
+ log.info("Deleted the obsolete plugin file to be updated: " + currentFile);
+ this.pluginsOnFilesystem.remove(currentFile);
+ } else {
+ log.warn("Failed to delete the obsolete (to-be-updated) plugin file: " + currentFile);
+ }
+ currentFile = null;
+ } else if (obsoletePlugin == null) {
+ // the db is up-to-date, but update the cache so we don't check MD5 or parse the descriptor again
+ currentFile.setLastModified(mtime);
+ cachedPluginOnFilesystem.setMtime(mtime);
+ cachedPluginOnFilesystem.setVersion(version);
+ cachedPluginOnFilesystem.setMd5(md5);
+ } else {
+ log.info("It appears that the plugin [" + dbPlugin
+ + "] in the database may be obsolete. If so, it will be updated by the plugin deployer.");
+ }
+ } else {
+ log.info("Found agent plugin in the DB that we do not yet have: " + name);
+ Plugin plugin = new Plugin(name, path, md5);
+ plugin.setMtime(mtime);
+ plugin.setVersion(version);
+ updatedPlugins.add(plugin);
+ this.pluginsOnFilesystem.remove(expectedFile); // paranoia, make sure the cache doesn't have this
+ }
+ }
+ JDBCUtil.safeClose(ps, rs);
+
+ // write all our updated plugins to the file system
+ ps = conn.prepareStatement("SELECT CONTENT FROM " + Plugin.TABLE_NAME + " WHERE NAME = ? AND ENABLED = ?");
+ for (Plugin plugin : updatedPlugins) {
+ File file = new File(this.pluginDeployer.getPluginDir(), plugin.getPath());
+
+ ps.setString(1, plugin.getName());
+ setEnabledFlag(conn, ps, 2, true);
+ rs = ps.executeQuery();
+ rs.next();
+ InputStream content = rs.getBinaryStream(1);
+ StreamUtil.copy(content, new FileOutputStream(file));
+ rs.close();
+ file.setLastModified(plugin.getMtime()); // so our file matches the database mtime
+ updatedFiles.add(file);
+ }
+ } finally {
+ JDBCUtil.safeClose(conn, ps, rs);
+ }
+
+ return updatedFiles;
+ }
+
+ /**
+ * This method will stream up plugin content if the server has a plugin file
+ * but there is null content in the database (only occurs when upgrading an old server to the new
+ * schema that supports database-storage for plugins). This method will be a no-op for
+ * recent versions of the server because the database will no longer have null content from now on.
+ */
+ private void fixMissingPluginContent() throws Exception {
+ Connection conn = null;
+ PreparedStatement ps = null;
+ ResultSet rs = null;
+
+ // This map contains the names/paths of plugins that are missing their content in the database.
+ // This map will only have entries if this server was recently upgraded from an older version
+ // that did not support database-stored plugin content.
+ Map<String, String> pluginsMissingContentInDb = new HashMap<String, String>();
+
+ // This map contains the names/MD5s of plugins that are missing their content in the database.
+ // This map will only have entries if this server was recently upgraded from an older version
+ // that did not support database-stored plugin content.
+ Map<String, String> pluginsMissingContentInDbMD5 = new HashMap<String, String>();
+
+ try {
+ DataSource ds = LookupUtil.getDataSource();
+ conn = ds.getConnection();
+ ps = conn.prepareStatement("SELECT NAME, PATH, MD5 FROM " + Plugin.TABLE_NAME
+ + " WHERE CONTENT IS NULL AND ENABLED = ?");
+ setEnabledFlag(conn, ps, 1, true);
+ rs = ps.executeQuery();
+ while (rs.next()) {
+ String name = rs.getString(1);
+ String path = rs.getString(2);
+ String md5 = rs.getString(3);
+ pluginsMissingContentInDb.put(name, path);
+ pluginsMissingContentInDbMD5.put(name, md5);
+ }
+ } finally {
+ JDBCUtil.safeClose(conn, ps, rs);
+ }
+
+ if (!pluginsMissingContentInDb.isEmpty()) {
+ // if a plugin used to exist but now doesn't, it should be deleted - we should not fail when this occurs
+ List<String> pluginsToDelete = new ArrayList<String>();
+
+ // in all likelihood, the new plugins have different filenames; but since the descriptors
+ // will have the same plugin names, we'll be able to key off of plugin name
+ PluginDescriptor descriptor;
+ Map<String, File> existingPluginFiles = new HashMap<String, File>(); // keyed on plugin name
+ for (File file : this.pluginDeployer.getPluginDir().listFiles()) {
+ if (file.getName().endsWith(".jar")) {
+ try {
+ descriptor = AgentPluginDescriptorUtil.loadPluginDescriptorFromUrl(file.toURI().toURL());
+ existingPluginFiles.put(descriptor.getName(), file);
+ } catch (Exception e) {
+ log.warn("File [" + file + "] is not a valid plugin and will be ignored: " + e);
+ }
+ }
+ }
+
+ // now let's take the new content and stream it into the DB
+ for (Map.Entry<String, String> entry : pluginsMissingContentInDb.entrySet()) {
+ String name = entry.getKey();
+ String path = entry.getValue();
+ String expectedMD5 = pluginsMissingContentInDbMD5.get(name);
+ File pluginFile = existingPluginFiles.get(name);
+ if (pluginFile != null) {
+ String newMD5 = MessageDigestGenerator.getDigestString(pluginFile);
+ boolean different = !expectedMD5.equals(newMD5);
+ streamPluginFileContentToDatabase(name, pluginFile, different);
+ log.info("Missing content for plugin [" + name + "] will be uploaded from [" + pluginFile
+ + "]. different=" + different);
+ } else {
+ pluginsToDelete.add(name);
+ log.warn("The database knows of a plugin named [" + name + "] with path [" + path
+ + "] but the content is missing. This server does not have this plugin in ["
+ + this.pluginDeployer.getPluginDir() + "] so the database cannot be updated with the content."
+ + " This plugin must be installed to manage existing inventory for its resource types.");
+ }
+ }
+
+ if (!pluginsToDelete.isEmpty()) {
+ TransactionManager tm = LookupUtil.getTransactionManager();
+ for (String pluginName : pluginsToDelete) {
+ try {
+ tm.begin();
+ DataSource ds = LookupUtil.getDataSource();
+ conn = ds.getConnection();
+ ps = conn.prepareStatement("UPDATE " + Plugin.TABLE_NAME + " SET ENABLED = ? WHERE NAME = ?");
+ setEnabledFlag(conn, ps, 1, false);
+ ps.setString(2, pluginName);
+ int updateResults = ps.executeUpdate();
+ if (updateResults == 1) {
+ log.warn("Disabled unavailable plugin [" + pluginName
+ + "] - This plugin must be provided to manage committed resources for its types."
+ + " Uninventory obsolete resources to avoid getting warnings in the server and agent.");
+ } else {
+ // TODO: should we throw an exception or is continuing the right thing to do?
+ log.error("Failed to disable unavailable plugin [" + pluginName + "].");
+ }
+ } catch (Exception e) {
+ tm.rollback();
+ tm = null;
+ throw e;
+ } finally {
+ JDBCUtil.safeClose(conn, ps, null);
+ if (tm != null) {
+ tm.commit();
+ }
+ }
+ }
+ }
+ }
+
+ return;
+ }
+
+ private void setEnabledFlag(Connection conn, PreparedStatement ps, int index, boolean enabled) throws Exception {
+ if (null == this.dbType) {
+ this.dbType = DatabaseTypeFactory.getDatabaseType(conn);
+ }
+ if (dbType instanceof PostgresqlDatabaseType || dbType instanceof H2DatabaseType) {
+ ps.setBoolean(index, enabled);
+ } else if (dbType instanceof OracleDatabaseType || dbType instanceof SQLServerDatabaseType) {
+ ps.setInt(index, (enabled ? 1 : 0));
+ } else {
+ throw new RuntimeException("Unknown database type : " + dbType);
+ }
+ }
+
+ /**
+ * This will write the contents of the given plugin file to the database.
+ * This will store both the contents and the MD5 in an atomic transaction
+ * so they remain insync.
+ *
+ * When <code>different</code> is <code>false</code>, it means the original
+ * plugin and the one currently found on the file system are the same.
+ *
+ * When <code>different</code> is <code>true</code>, it means the plugin
+ * is most likely a different one than the one that originally existed.
+ * When this happens, it is assumed that the {@link ProductPluginDeployer} needs
+ * to see the plugin on the file system as new and needing to be processed, therefore
+ * the MD5, CONTENT and MTIME columns will be updated to ensure the deployer
+ * will process this plugin and thus update all the metadata for this plugin.
+ *
+ * @param name the name of the plugin whose content is being updated
+ * @param file the plugin file whose content will be streamed to the database
+ * @param different this will be <code>true</code> if the given file has a different filename
+ * that the plugin's "path" as found in the database.
+ *
+ *
+ * @throws Exception
+ */
+ private void streamPluginFileContentToDatabase(String name, File file, boolean different) throws Exception {
+ Connection conn = null;
+ PreparedStatement ps = null;
+ ResultSet rs = null;
+ TransactionManager tm = null;
+
+ String sql = "UPDATE " + Plugin.TABLE_NAME + " SET CONTENT = ?, MD5 = ?, MTIME = ?, PATH = ? WHERE NAME = ?";
+
+ // if 'different' is true, give bogus data so the plugin deployer will think the plugin on the file system is new
+ String md5 = (!different) ? MessageDigestGenerator.getDigestString(file) : "TO BE UPDATED";
+ long mtime = (!different) ? file.lastModified() : 0L;
+ InputStream fis = (!different) ? new FileInputStream(file) : new ByteArrayInputStream(new byte[0]);
+ int contentSize = (int) ((!different) ? file.length() : 0);
+
+ try {
+ tm = LookupUtil.getTransactionManager();
+ tm.begin();
+ DataSource ds = LookupUtil.getDataSource();
+ conn = ds.getConnection();
+ ps = conn.prepareStatement(sql);
+ ps.setBinaryStream(1, new BufferedInputStream(fis), contentSize);
+ ps.setString(2, md5);
+ ps.setLong(3, mtime);
+ ps.setString(4, file.getName());
+ ps.setString(5, name);
+ int updateResults = ps.executeUpdate();
+ if (updateResults == 1) {
+ log.info("Stored content for plugin [" + name + "] in the db. file=" + file);
+ } else {
+ throw new Exception("Failed to update content for plugin [" + name + "] from [" + file + "]");
+ }
+ } catch (Exception e) {
+ tm.rollback();
+ tm = null;
+ throw e;
+ } finally {
+ JDBCUtil.safeClose(conn, ps, rs);
+
+ try {
+ fis.close();
+ } catch (Throwable t) {
+ }
+
+ if (tm != null) {
+ tm.commit();
+ }
+ }
+ return;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScannerMBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScannerMBean.java
new file mode 100644
index 0000000..cb5c795
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/PluginDeploymentScannerMBean.java
@@ -0,0 +1,122 @@
+/*
+ * 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.core.plugin;
+
+import java.io.File;
+
+import javax.management.ObjectName;
+
+import org.rhq.core.util.ObjectNameFactory;
+
+public interface PluginDeploymentScannerMBean {
+ /**
+ * The name this service will be registered as.
+ */
+ ObjectName OBJECT_NAME = ObjectNameFactory.create("rhq:service=PluginDeploymentScanner");
+
+ void start() throws Exception;
+
+ void stop();
+
+ /**
+ * This is called separately from the start/stop lifecycle methods. It should only be called
+ * when we know the EJB/SLSB layer is fully initialized and ready to accept requests.
+ */
+ void startDeployment();
+
+ /**
+ * This will scan the database for new/updated plugins and if it finds
+ * any, will write the content as plugin files in the file system. This
+ * will also delete old, obsolete plugins.
+ *
+ * @see #scanAndRegister()
+ */
+ void scan() throws Exception;
+
+ /**
+ * This will scan the database for new/updated plugins and if it finds
+ * any, will write the content as plugin files in the file system. This
+ * will also delete old, obsolete plugins. Once finished, this will register
+ * agent plugins and update the database as appropriate.
+ */
+ void scanAndRegister() throws Exception;
+
+ /**
+ * Sets the amount of time (in milliseconds) between scans.
+ *
+ * @param ms time in millis between each scans
+ */
+ void setScanPeriod(Long ms);
+
+ /**
+ * Gets the amount of time (in milliseconds) between scans.
+ *
+ * @return the time in millis between each scans
+ */
+ Long getScanPeriod();
+
+ /**
+ * Sets the directory where the user can place agent or server plugin jars.
+ * The scanner will move plugins found here to their appropriate internal
+ * locations based on the kind of plugins it finds.
+ *
+ * @param name the name of the plugins dir where the user can copy plugins
+ */
+ void setUserPluginDir(File name);
+
+ /**
+ * Gets the directory name where the user can place agent or server plugin jars.
+ * If <code>null</code>, do not look for any user plugins.
+ *
+ * @return plugin directory name where the user puts plugins
+ */
+ File getUserPluginDir();
+
+ /**
+ * Sets the directory where the server plugin jars are located.
+ *
+ * @param name the name of the server plugins dir
+ */
+ void setServerPluginDir(File name);
+
+ /**
+ * Gets the directory name where the server plugin jars are located.
+ *
+ * @return server plugin directory name
+ */
+ File getServerPluginDir();
+
+ /**
+ * Sets the directory where the agent plugin jars are located.
+ *
+ * @param name the name of the agent plugins dir
+ */
+ void setAgentPluginDir(File name);
+
+ /**
+ * Gets the directory name where the agent plugin jars are located.
+ *
+ * @return agent plugin directory name
+ */
+ File getAgentPluginDir();
+
+ void setLicenseFile(File name);
+
+ File getLicenseFile();
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
index 4503776..5b614fa 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
@@ -90,7 +90,7 @@ import org.rhq.enterprise.server.core.AgentManagerLocal;
import org.rhq.enterprise.server.core.CoreServerMBean;
import org.rhq.enterprise.server.core.EmailManagerBean;
import org.rhq.enterprise.server.core.EmailManagerLocal;
-import org.rhq.enterprise.server.core.plugin.AgentPluginDeploymentScannerMBean;
+import org.rhq.enterprise.server.core.plugin.PluginDeploymentScanner;
import org.rhq.enterprise.server.discovery.DiscoveryBossBean;
import org.rhq.enterprise.server.discovery.DiscoveryBossLocal;
import org.rhq.enterprise.server.event.EventManagerBean;
@@ -535,10 +535,10 @@ public final class LookupUtil {
return jonServer;
}
- public static AgentPluginDeploymentScannerMBean getAgentPluginDeploymentScanner() {
+ public static PluginDeploymentScanner getPluginDeploymentScanner() {
MBeanServer jBossMBeanServer = MBeanServerLocator.locateJBoss();
- AgentPluginDeploymentScannerMBean scanner = (AgentPluginDeploymentScannerMBean) MBeanProxyExt.create(
- AgentPluginDeploymentScannerMBean.class, AgentPluginDeploymentScannerMBean.OBJECT_NAME, jBossMBeanServer);
+ PluginDeploymentScanner scanner = (PluginDeploymentScanner) MBeanProxyExt.create(PluginDeploymentScanner.class,
+ PluginDeploymentScanner.OBJECT_NAME, jBossMBeanServer);
return scanner;
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/core/plugin/DatabaseAndFilePluginDeploymentTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/core/plugin/DatabaseAndFilePluginDeploymentTest.java
index aa90dc8..d57506a 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/core/plugin/DatabaseAndFilePluginDeploymentTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/core/plugin/DatabaseAndFilePluginDeploymentTest.java
@@ -130,7 +130,7 @@ public class DatabaseAndFilePluginDeploymentTest extends AbstractEJB3Test {
public void test2() throws Exception {
Plugin plugin10feb = deployPluginJarToDatabase(TESTPLUGIN_1_0_FEB);
- AgentPluginDeploymentScanner scanner = createScanner();
+ PluginDeploymentScanner scanner = createScanner();
scan(scanner, null);
assertPluginInDb(plugin10feb);
assertPluginOnFilesystem(plugin10feb);
@@ -467,16 +467,16 @@ public class DatabaseAndFilePluginDeploymentTest extends AbstractEJB3Test {
return !file.exists();
}
- private AgentPluginDeploymentScanner createScannerAndScan(String pluginId) throws Exception {
- AgentPluginDeploymentScanner scanner = createScanner();
+ private PluginDeploymentScanner createScannerAndScan(String pluginId) throws Exception {
+ PluginDeploymentScanner scanner = createScanner();
scan(scanner, pluginId); // see comments in scan() for what pluginId is
return scanner;
}
- private AgentPluginDeploymentScanner createScanner() throws Exception {
- AgentPluginDeploymentScanner scanner = new AgentPluginDeploymentScanner();
+ private PluginDeploymentScanner createScanner() throws Exception {
+ PluginDeploymentScanner scanner = new PluginDeploymentScanner();
File pluginDirectoryFile = new File(DEPLOY_LOCATION);
- scanner.setPluginDir(pluginDirectoryFile);
+ scanner.setAgentPluginDir(pluginDirectoryFile);
return scanner;
}
@@ -489,7 +489,7 @@ public class DatabaseAndFilePluginDeploymentTest extends AbstractEJB3Test {
* @param pluginId if not-null, this is registered (i.e. a file scan registering this plugin)
* @throws Exception
*/
- private void scan(AgentPluginDeploymentScanner scanner, String pluginId) throws Exception {
+ private void scan(PluginDeploymentScanner scanner, String pluginId) throws Exception {
if (scanner != null) {
scanner.scan();
}
commit 08abb1f7a094aa0842fd797b13e3ed5767c28fcb
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Mon Nov 16 17:24:13 2009 -0800
fixing NPE for unfinished syncs
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
index 761e7cd..80cedf7 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
@@ -301,10 +301,22 @@ public class ContentSource implements Serializable {
Comparator dc = new Comparator() {
public int compare(Object arg0, Object arg1) {
+ long currTime = System.currentTimeMillis();
ContentSourceSyncResults c1 = (ContentSourceSyncResults) arg0;
ContentSourceSyncResults c2 = (ContentSourceSyncResults) arg1;
- Date d1 = new Date(c1.getEndTime());
- Date d2 = new Date(c2.getEndTime());
+ Date d1 = null;
+ Date d2 = null;
+
+ if (c1.getEndTime() == null) {
+ d1 = new Date(currTime);
+ } else {
+ d1 = new Date(c1.getEndTime());
+ }
+ if (c2.getEndTime() == null) {
+ d2 = new Date(currTime);
+ } else {
+ d2 = new Date(c2.getEndTime());
+ }
return d1.compareTo(d2);
}
};
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
index 0a8c80f..5c9db6a 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
@@ -146,6 +146,13 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
em.persist(results);
cs.addSyncResult(results);
}
+
+ // Add one with no end time. This is to test NPE during sorting
+ ContentSourceSyncResults results = new ContentSourceSyncResults(cs);
+ results.setStartTime(cal.getTimeInMillis());
+ em.persist(results);
+ cs.addSyncResult(results);
+
repo.addContentSource(cs);
em.flush();
@@ -153,9 +160,6 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
// Check sync status
cs.getSyncResults();
- for (ContentSourceSyncResults r : cs.getSyncResults()) {
- System.out.println("R: " + new Date(r.getEndTime().longValue()) + " s: " + r.getStatus());
- }
String status = repoManager.calculateSyncStatus(overlord, repo.getId());
assert status.equals(ContentSourceSyncStatus.SUCCESS.toString());
}
commit 22ca0dafe589e3e100a3e344a8f84520cfcb8380
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Mon Nov 16 15:16:38 2009 -0800
810 - switching out package list with repo list on provider page
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PageControlView.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PageControlView.java
index d993d0e..c6f06a4 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PageControlView.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PageControlView.java
@@ -30,7 +30,7 @@ import org.rhq.enterprise.gui.configuration.group.GroupResourceConfigurationHist
import org.rhq.enterprise.gui.configuration.history.ListConfigurationUpdateUIBean;
import org.rhq.enterprise.gui.content.AuditTrailUIBean;
import org.rhq.enterprise.gui.content.AvailableResourceReposUIBean;
-import org.rhq.enterprise.gui.content.ContentSourcePackageVersionsUIBean;
+import org.rhq.enterprise.gui.content.ContentSourceCandidateReposUIBean;
import org.rhq.enterprise.gui.content.ContentSourceReposUIBean;
import org.rhq.enterprise.gui.content.ContentSourceSyncResultsUIBean;
import org.rhq.enterprise.gui.content.DeployPackagesUIBean;
@@ -44,8 +44,8 @@ import org.rhq.enterprise.gui.content.ListReposUIBean;
import org.rhq.enterprise.gui.content.RepoAssociationsUIBean;
import org.rhq.enterprise.gui.content.RepoContentSourcesUIBean;
import org.rhq.enterprise.gui.content.RepoDisassociationsUIBean;
-import org.rhq.enterprise.gui.content.RepoImportUIBean;
import org.rhq.enterprise.gui.content.RepoDistributionUIBean;
+import org.rhq.enterprise.gui.content.RepoImportUIBean;
import org.rhq.enterprise.gui.content.RepoPackageVersionsUIBean;
import org.rhq.enterprise.gui.content.RepoResourcesUIBean;
import org.rhq.enterprise.gui.content.RepoSubscriptionsUIBean;
@@ -137,7 +137,7 @@ public enum PageControlView {
/** */
RepoResourcesList(RepoResourcesUIBean.class),
/** */
- ContentSourcePackageVersionsList(ContentSourcePackageVersionsUIBean.class),
+ ContentSourceCandidateReposList(ContentSourceCandidateReposUIBean.class),
/** */
RepoPackageVersionsList(RepoPackageVersionsUIBean.class),
/** */
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ContentSourceCandidateReposUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ContentSourceCandidateReposUIBean.java
new file mode 100644
index 0000000..5f3ea5a
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ContentSourceCandidateReposUIBean.java
@@ -0,0 +1,69 @@
+/*
+ * 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.content;
+
+import javax.faces.model.DataModel;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.core.gui.util.FacesContextUtility;
+import org.rhq.enterprise.gui.common.framework.PagedDataTableUIBean;
+import org.rhq.enterprise.gui.common.paging.PageControlView;
+import org.rhq.enterprise.gui.common.paging.PagedListDataModel;
+import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
+import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+public class ContentSourceCandidateReposUIBean extends PagedDataTableUIBean {
+
+ public static final String MANAGED_BEAN_NAME = ContentSourceCandidateReposUIBean.class.getSimpleName();
+
+ public ContentSourceCandidateReposUIBean() {
+ }
+
+ @Override
+ public DataModel getDataModel() {
+ if (dataModel == null) {
+ dataModel = new ContentSourceCandidateReposDataModel(PageControlView.ContentSourceCandidateReposList,
+ MANAGED_BEAN_NAME);
+ }
+
+ return dataModel;
+ }
+
+ private class ContentSourceCandidateReposDataModel extends PagedListDataModel<Repo> {
+ public ContentSourceCandidateReposDataModel(PageControlView view, String beanName) {
+ super(view, beanName);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public PageList<Repo> fetchPage(PageControl pc) {
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
+ int id = Integer.valueOf(FacesContextUtility.getRequiredRequestParameter("id"));
+
+ ContentSourceManagerLocal manager = LookupUtil.getContentSourceManager();
+
+ PageList<Repo> results = manager.getCandidateRepos(subject, id, pc);
+ return results;
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ContentSourcePackageVersionsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ContentSourcePackageVersionsUIBean.java
deleted file mode 100644
index cd27d3b..0000000
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ContentSourcePackageVersionsUIBean.java
+++ /dev/null
@@ -1,67 +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.gui.content;
-
-import javax.faces.model.DataModel;
-import org.rhq.core.domain.auth.Subject;
-import org.rhq.core.domain.content.PackageVersionContentSource;
-import org.rhq.core.domain.util.PageControl;
-import org.rhq.core.domain.util.PageList;
-import org.rhq.core.gui.util.FacesContextUtility;
-import org.rhq.enterprise.gui.common.framework.PagedDataTableUIBean;
-import org.rhq.enterprise.gui.common.paging.PageControlView;
-import org.rhq.enterprise.gui.common.paging.PagedListDataModel;
-import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
-import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
-import org.rhq.enterprise.server.util.LookupUtil;
-
-public class ContentSourcePackageVersionsUIBean extends PagedDataTableUIBean {
- public static final String MANAGED_BEAN_NAME = "ContentSourcePackageVersionsUIBean";
-
- public ContentSourcePackageVersionsUIBean() {
- }
-
- @Override
- public DataModel getDataModel() {
- if (dataModel == null) {
- dataModel = new ContentSourcePackageVersionsDataModel(PageControlView.ContentSourcePackageVersionsList,
- MANAGED_BEAN_NAME);
- }
-
- return dataModel;
- }
-
- private class ContentSourcePackageVersionsDataModel extends PagedListDataModel<PackageVersionContentSource> {
- public ContentSourcePackageVersionsDataModel(PageControlView view, String beanName) {
- super(view, beanName);
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public PageList<PackageVersionContentSource> fetchPage(PageControl pc) {
- Subject subject = EnterpriseFacesContextUtility.getSubject();
- int id = Integer.valueOf(FacesContextUtility.getRequiredRequestParameter("id"));
- ContentSourceManagerLocal manager = LookupUtil.getContentSourceManager();
-
- PageList<PackageVersionContentSource> results;
- results = manager.getPackageVersionsFromContentSource(subject, id, pc);
- return results;
- }
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/content-beans.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/content-beans.xml
index 6bce7d7..b27abee 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/content-beans.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/content-beans.xml
@@ -121,8 +121,8 @@
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
- <managed-bean-name>ContentSourcePackageVersionsUIBean</managed-bean-name>
- <managed-bean-class>org.rhq.enterprise.gui.content.ContentSourcePackageVersionsUIBean</managed-bean-class>
+ <managed-bean-name>ContentSourceCandidateReposUIBean</managed-bean-name>
+ <managed-bean-class>org.rhq.enterprise.gui.content.ContentSourceCandidateReposUIBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/contentProvider.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/contentProvider.xhtml
index 9f5f533..373507b 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/contentProvider.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/contentProvider.xhtml
@@ -424,26 +424,26 @@
</h:form>
- <!-- PACKAGE VERSION LIST -->
+ <!-- REPO LIST -->
- <h:form id="contentSourcePackageVersionsListForm">
+ <h:form id="contentSourceRepoListForm">
<input type="hidden" name="id" value="${param.id}"/>
<input type="hidden" name="mode" value="${param.mode}"/>
<rich:panel>
<f:facet name="header">
- <h:outputText value="Package Versions Originating From This Content Provider"/>
+ <h:outputText value="Repositories you can synchronize from this Content Provider"/>
</f:facet>
- <h:panelGrid columns="1" width="100%">
+ <h:panelGrid columns="2" width="100%">
- <ui:param name="contentSourcePackageVersionsDataModel" value="#{ContentSourcePackageVersionsUIBean.dataModel}"/>
- <rich:dataTable id="contentSourcePackageVersionsDataTable"
- rows="#{PageControl.ContentSourcePackageVersionsList.pageSize}"
- value="#{contentSourcePackageVersionsDataModel}"
- var="pvitem"
+ <ui:param name="contentSourceReposDataModel" value="#{ContentSourceCandidateReposUIBean.dataModel}"/>
+ <rich:dataTable id="contentSourceReposDataTable"
+ rows="#{PageControl.ContentSourceCandidateReposList.pageSize}"
+ value="#{contentSourceReposDataModel}"
+ var="repoitem"
width="100%"
- columnsWidth="20%, 10%, 10%, 40%, 20%"
+ columnsWidth="100%"
headerClass="tableRowHeader"
footerClass="on-pager-footer"
onRowMouseOver="this.style.backgroundColor='#E7E7E7'"
@@ -451,81 +451,35 @@
<f:facet name="PageControlView">
- <onc:paginationControl id="ContentSourcePackageVersionsList" />
+ <onc:paginationControl id="ContentSourceCandidateReposList" />
</f:facet>
-
<rich:column rendered="#{param.debug}">
<f:facet name="header">
- <onc:sortableColumnHeader sort="pvcs.packageVersion.id">
+ <onc:sortableColumnHeader sort="c.id">
<h:outputText styleClass="headerText" value="ID" />
</onc:sortableColumnHeader>
</f:facet>
-
- <h:outputText value="#{pvitem.packageVersionContentSourcePK.packageVersion.id}"/>
+ <h:outputText value="#{repoitem.id}"/>
</rich:column>
-
<rich:column>
<f:facet name="header">
- <onc:sortableColumnHeader sort="pvcs.packageVersion.displayName">
+ <onc:sortableColumnHeader sort="c.name">
<h:outputText styleClass="headerText" value="Name" />
</onc:sortableColumnHeader>
</f:facet>
-
- <h:outputLink value="packageVersion.xhtml">
- <f:param name="id" value="#{pvitem.packageVersionContentSourcePK.packageVersion.id}"/>
- <f:param name="content_source_id" value="#{param.id}"/>
- <f:param name="content_source_name" value="#{ContentProviderDetailsUIBean.contentSource.name}"/>
- <h:outputText value="#{pvitem.packageVersionContentSourcePK.packageVersion.displayName}" />
+ <h:outputLink value="repo.xhtml">
+ <f:param name="mode" value="view"/>
+ <f:param name="id" value="#{repoitem.id}"/>
+ <h:outputText value="#{repoitem.name}" />
</h:outputLink>
</rich:column>
-
- <rich:column>
- <f:facet name="header">
- <onc:sortableColumnHeader sort="pvcs.packageVersion.version">
- <h:outputText styleClass="headerText" value="Version" />
- </onc:sortableColumnHeader>
- </f:facet>
-
- <h:outputText value="#{pvitem.packageVersionContentSourcePK.packageVersion.displayVersion}"/>
- </rich:column>
-
- <rich:column>
- <f:facet name="header">
- <onc:sortableColumnHeader sort="pvcs.packageVersion.architecture.name">
- <h:outputText styleClass="headerText" value="Arch" />
- </onc:sortableColumnHeader>
- </f:facet>
-
- <h:outputText value="#{pvitem.packageVersionContentSourcePK.packageVersion.architecture.name}"/>
- </rich:column>
-
- <rich:column>
- <f:facet name="header">
- <onc:sortableColumnHeader sort="pvcs.packageVersion.shortDescription">
- <h:outputText styleClass="headerText" value="Description" />
- </onc:sortableColumnHeader>
- </f:facet>
-
- <h:outputText value="#{pvitem.packageVersionContentSourcePK.packageVersion.shortDescription}" escape="false"/>
- </rich:column>
-
- <rich:column>
- <f:facet name="header">
- <onc:sortableColumnHeader sort="pvcs.location">
- <h:outputText styleClass="headerText" value="Location" />
- </onc:sortableColumnHeader>
- </f:facet>
-
- <h:outputText value="#{pvitem.location}"/>
- </rich:column>
-
<f:facet name="footer">
<rich:columnGroup>
<!-- colspan 6:5 for the debug 'id' column -->
<rich:column colspan="#{param.debug ? 6 : 5}" width="100%">
- <ui:param name="paginationDataTableName" value="contentSourcePackageVersionsDataTable"/>
- <ui:param name="paginationDataModel" value="#{contentSourcePackageVersionsDataModel}"/>
- <ui:param name="paginationPageControl" value="#{PageControl.ContentSourcePackageVersionsList}"/>
+ <ui:param name="paginationDataTableName" value="contentSourceReposDataTable"/>
+ <ui:param name="paginationDataModel" value="#{contentSourceReposDataModel}"/>
+ <ui:param name="paginationPageControl" value="#{PageControl.ContentSourceCandidateReposList}"/>
<ui:include src="../resource/include/pagination.xhtml"/>
</rich:column>
</rich:columnGroup>
commit 74e78cb5e68849648a8c6f37392b0d6c062b9086
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Mon Nov 16 13:17:16 2009 -0800
800 - now we sync immediately upon creation
Now we sync when we create a CP. This will help the GUI show the
content that is available without waiting for hours until the 1st
scheduled sync.
Please enter the commit message for your changes. Lines starting
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
index b47b50f..bc6d543 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
@@ -61,6 +61,9 @@ import org.rhq.core.domain.content.ContentSource;
import org.rhq.core.domain.content.ContentSourceSyncResults;
import org.rhq.core.domain.content.ContentSourceSyncStatus;
import org.rhq.core.domain.content.ContentSourceType;
+import org.rhq.core.domain.content.Distribution;
+import org.rhq.core.domain.content.DistributionFile;
+import org.rhq.core.domain.content.DistributionType;
import org.rhq.core.domain.content.DownloadMode;
import org.rhq.core.domain.content.Package;
import org.rhq.core.domain.content.PackageBits;
@@ -72,14 +75,12 @@ import org.rhq.core.domain.content.PackageVersionContentSourcePK;
import org.rhq.core.domain.content.ProductVersionPackageVersion;
import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.content.RepoContentSource;
-import org.rhq.core.domain.content.RepoPackageVersion;
-import org.rhq.core.domain.content.Distribution;
-import org.rhq.core.domain.content.DistributionFile;
-import org.rhq.core.domain.content.DistributionType;
import org.rhq.core.domain.content.RepoDistribution;
+import org.rhq.core.domain.content.RepoPackageVersion;
import org.rhq.core.domain.content.composite.LoadedPackageBitsComposite;
import org.rhq.core.domain.content.composite.PackageVersionFile;
import org.rhq.core.domain.content.composite.PackageVersionMetadataComposite;
+import org.rhq.core.domain.criteria.RepoCriteria;
import org.rhq.core.domain.resource.ProductVersion;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
@@ -87,27 +88,26 @@ import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.PageOrdering;
import org.rhq.core.domain.util.PersistenceUtility;
-import org.rhq.core.domain.criteria.RepoCriteria;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.enterprise.server.RHQConstants;
-import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
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.ContentProviderPackageDetails;
import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetailsKey;
import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.content.InitializationException;
-import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
-import org.rhq.enterprise.server.plugin.pc.content.RepoDetails;
-import org.rhq.enterprise.server.plugin.pc.content.DistributionSyncReport;
import org.rhq.enterprise.server.plugin.pc.content.DistributionDetails;
import org.rhq.enterprise.server.plugin.pc.content.DistributionFileDetails;
-import org.rhq.enterprise.server.plugin.pc.content.ContentProvider;
import org.rhq.enterprise.server.plugin.pc.content.DistributionSource;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionSyncReport;
+import org.rhq.enterprise.server.plugin.pc.content.InitializationException;
+import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
+import org.rhq.enterprise.server.plugin.pc.content.RepoDetails;
import org.rhq.enterprise.server.resource.ProductVersionManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
/**
* A SLSB wrapper around our server-side content source plugin container. This bean provides access to the
@@ -321,9 +321,10 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
public PageList<Repo> getAssociatedRepos(Subject subject, int contentSourceId, PageControl pc) {
pc.initDefaultOrderingField("c.id");
- Query query = PersistenceUtility
- .createQueryWithOrderBy(entityManager, Repo.QUERY_FIND_IMPORTED_BY_CONTENT_SOURCE_ID, pc);
- Query countQuery = PersistenceUtility.createCountQuery(entityManager, Repo.QUERY_FIND_IMPORTED_BY_CONTENT_SOURCE_ID);
+ Query query = PersistenceUtility.createQueryWithOrderBy(entityManager,
+ Repo.QUERY_FIND_IMPORTED_BY_CONTENT_SOURCE_ID, pc);
+ Query countQuery = PersistenceUtility.createCountQuery(entityManager,
+ Repo.QUERY_FIND_IMPORTED_BY_CONTENT_SOURCE_ID);
query.setParameter("id", contentSourceId);
countQuery.setParameter("id", contentSourceId);
@@ -337,9 +338,10 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
public PageList<Repo> getCandidateRepos(Subject subject, int contentSourceId, PageControl pc) {
pc.initDefaultOrderingField("c.name");
- Query query = PersistenceUtility
- .createQueryWithOrderBy(entityManager, Repo.QUERY_FIND_CANDIDATE_BY_CONTENT_SOURCE_ID, pc);
- Query countQuery = PersistenceUtility.createCountQuery(entityManager, Repo.QUERY_FIND_CANDIDATE_BY_CONTENT_SOURCE_ID);
+ Query query = PersistenceUtility.createQueryWithOrderBy(entityManager,
+ Repo.QUERY_FIND_CANDIDATE_BY_CONTENT_SOURCE_ID, pc);
+ Query countQuery = PersistenceUtility.createCountQuery(entityManager,
+ Repo.QUERY_FIND_CANDIDATE_BY_CONTENT_SOURCE_ID);
query.setParameter("id", contentSourceId);
countQuery.setParameter("id", contentSourceId);
@@ -421,7 +423,10 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
try {
ContentServerPluginContainer pc = ContentManagerHelper.getPluginContainer();
pc.getAdapterManager().startAdapter(contentSource);
+ // Schedule a job for the future
pc.scheduleSyncJob(contentSource);
+ // Also sync immediately so we have the metadata
+ pc.syncNow(contentSource);
} catch (InitializationException ie) {
log.warn("Failed to start adapter for [" + contentSource + "]", ie);
@@ -568,11 +573,10 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
@SuppressWarnings("unchecked")
@RequiredPermission(Permission.MANAGE_INVENTORY)
public List<PackageVersionContentSource> getPackageVersionsFromContentSourceForRepo(Subject subject,
- int contentSourceId,
- int repoId) {
+ int contentSourceId, int repoId) {
- Query query =
- entityManager.createNamedQuery(PackageVersionContentSource.QUERY_FIND_BY_CONTENT_SOURCE_ID_AND_REPO_ID);
+ Query query = entityManager
+ .createNamedQuery(PackageVersionContentSource.QUERY_FIND_BY_CONTENT_SOURCE_ID_AND_REPO_ID);
query.setParameter("content_source_id", contentSourceId);
query.setParameter("repo_id", repoId);
@@ -684,7 +688,7 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
ContentProviderManager cpMgr = pc.getAdapterManager();
ContentProvider provider = cpMgr.getIsolatedContentProvider(contentSource.getId());
assert (provider instanceof DistributionSource);
- DistributionSource distSource = (DistributionSource)provider;
+ DistributionSource distSource = (DistributionSource) provider;
//
// Following same sort of workaround done in ContentProviderManager for synchronizeContentSource
@@ -696,8 +700,8 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
Subject overlord = LookupUtil.getSubjectManager().getOverlord();
List<Repo> repos = repoManager.findReposByCriteria(overlord, reposForContentSource);
log.debug("downloadDistributionBits found " + repos.size() + " repos associated with this contentSourceId "
- + contentSourceId);
- for (Repo repo: repos) {
+ + contentSourceId);
+ for (Repo repo : repos) {
log.debug("downloadDistributionBits operating on repo: " + repo.getName() + " id = " + repo.getId());
// Look up Distributions associated with this ContentSource.
PageControl pageControl = PageControl.getUnlimitedInstance();
@@ -705,51 +709,47 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
List<Distribution> dists = repoManager.findAssociatedDistributions(overlord, repo.getId(), pageControl);
log.debug("Found " + dists.size() + " Distributions for repoId " + repo.getId());
- for (Distribution dist: dists) {
+ for (Distribution dist : dists) {
log.debug("Looking up DistributionFiles for dist: " + dist);
List<DistributionFile> distFiles = distManager.getDistributionFilesByDistId(dist.getId());
log.debug("Found " + distFiles.size() + " DistributionFiles");
- for (DistributionFile dFile: distFiles) {
+ for (DistributionFile dFile : distFiles) {
String relPath = dist.getBasePath() + "/" + dFile.getRelativeFilename();
- File outputFile =
- getDistLocalFileAndCreateParentDir(dist.getLabel(), relPath);
+ File outputFile = getDistLocalFileAndCreateParentDir(dist.getLabel(), relPath);
log.debug("Checking if file exists at: " + outputFile.getAbsolutePath());
if (outputFile.exists()) {
log.debug("File " + outputFile.getAbsolutePath() + " exists, checking md5sum");
String expectedMD5 = (dFile.getMd5sum() != null) ? dFile.getMd5sum() : "<unspecified MD5>";
String actualMD5 = MessageDigestGenerator.getDigestString(outputFile);
if (!expectedMD5.trim().toLowerCase().equals(actualMD5.toLowerCase())) {
- log.error("Expected [" + expectedMD5 + "] versus actual [" +
- actualMD5 + "] md5sums for file " + outputFile.getAbsolutePath() +
- " do not match.");
- log.error("Need to re-fetch file. Will download from DistributionSource" +
- " and overwrite local file.");
+ log.error("Expected [" + expectedMD5 + "] versus actual [" + actualMD5
+ + "] md5sums for file " + outputFile.getAbsolutePath() + " do not match.");
+ log.error("Need to re-fetch file. Will download from DistributionSource"
+ + " and overwrite local file.");
} else {
- log.info(outputFile + " exists and md5sum matches [" + actualMD5 +
- "] no need to re-download");
+ log.info(outputFile + " exists and md5sum matches [" + actualMD5
+ + "] no need to re-download");
continue; // skip the download from bitsStream
}
}
- log.debug("Attempting download of " + dFile.getRelativeFilename() +
- " from contentSourceId " + contentSourceId);
+ log.debug("Attempting download of " + dFile.getRelativeFilename() + " from contentSourceId "
+ + contentSourceId);
String remoteFetchLoc = distSource.getDistFileRemoteLocation(repo.getName(), dist.getLabel(),
- dFile.getRelativeFilename());
+ dFile.getRelativeFilename());
InputStream bitsStream = pc.getAdapterManager().loadDistributionFileBits(contentSourceId,
- remoteFetchLoc);
+ remoteFetchLoc);
StreamUtil.copy(bitsStream, new FileOutputStream(outputFile), true);
bitsStream = null;
log.debug("DistributionFile has been downloaded to: " + outputFile.getAbsolutePath());
}
}
}
- }
- catch (Exception e) {
+ } catch (Exception e) {
log.error(e);
e.printStackTrace();
}
}
-
@RequiredPermission(Permission.MANAGE_INVENTORY)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@TransactionTimeout(45 * 60)
@@ -928,8 +928,8 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
// we really want NEVER, but support tests that might be in a tx
- public ContentSourceSyncResults mergeContentSourceSyncReport(ContentSource contentSource, DistributionSyncReport report,
- ContentSourceSyncResults syncResults) {
+ public ContentSourceSyncResults mergeContentSourceSyncReport(ContentSource contentSource,
+ DistributionSyncReport report, ContentSourceSyncResults syncResults) {
try {
StringBuilder progress = new StringBuilder();
if (syncResults.getResults() != null) {
@@ -938,11 +938,13 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
//////////////////
// REMOVE
- syncResults = contentSourceManager._mergeContentSourceSyncReportREMOVE(contentSource, report, syncResults, progress);
+ syncResults = contentSourceManager._mergeContentSourceSyncReportREMOVE(contentSource, report, syncResults,
+ progress);
//////////////////
// ADD
- syncResults = contentSourceManager._mergeContentSourceSyncReportADD(contentSource, report, syncResults, progress);
+ syncResults = contentSourceManager._mergeContentSourceSyncReportADD(contentSource, report, syncResults,
+ progress);
// if we added/updated/deleted anything, change the last modified time of all repos
// that get content from this content source
@@ -966,9 +968,6 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
return syncResults;
}
-
-
-
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
// we really want NEVER, but support tests that might be in a tx
public ContentSourceSyncResults mergeContentSourceSyncReport(ContentSource contentSource, PackageSyncReport report,
@@ -1136,7 +1135,7 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
Subject overlord = LookupUtil.getSubjectManager().getOverlord();
// remove all distributions that are no longer available on the remote repository
- for (DistributionDetails doomedDetails: report.getDeletedDistributions()) {
+ for (DistributionDetails doomedDetails : report.getDeletedDistributions()) {
Distribution doomedDist = distManager.getDistributionByLabel(doomedDetails.getLabel());
distManager.deleteDistributionByDistId(overlord, doomedDist.getId());
distManager.deleteDistributionFilesByDistId(overlord, doomedDist.getId());
@@ -1161,29 +1160,28 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
Subject overlord = LookupUtil.getSubjectManager().getOverlord();
List<DistributionDetails> newDetails = report.getDistributions();
- for (DistributionDetails detail: newDetails) {
+ for (DistributionDetails detail : newDetails) {
try {
log.debug("Attempting to create new distribution based off of: " + detail);
DistributionType distType = distManager.getDistributionTypeByName(detail.getDistributionType());
- Distribution newDist = distManager.createDistribution(overlord, detail.getLabel(),
- detail.getDistributionPath(), distType);
+ Distribution newDist = distManager.createDistribution(overlord, detail.getLabel(), detail
+ .getDistributionPath(), distType);
log.debug("Created new distribution: " + newDist);
Repo repo = repoManager.getRepo(overlord, report.getRepoId());
RepoDistribution repoDist = new RepoDistribution(repo, newDist);
- log.debug("Created new mapping of RepoDistribution repoId = " + repo.getId() +
- ", distId = " + newDist.getId());
+ log.debug("Created new mapping of RepoDistribution repoId = " + repo.getId() + ", distId = "
+ + newDist.getId());
entityManager.persist(repoDist);
List<DistributionFileDetails> files = detail.getFiles();
- for (DistributionFileDetails f: files) {
+ for (DistributionFileDetails f : files) {
log.debug("Creating DistributionFile for: " + f);
DistributionFile df = new DistributionFile(newDist, f.getRelativeFilename(), f.getMd5sum());
df.setLastModified(f.getLastModified());
entityManager.persist(df);
entityManager.flush();
}
- }
- catch (DistributionException e) {
+ } catch (DistributionException e) {
progress.append("Caught exception when trying to add: " + detail.getLabel() + "\n");
progress.append("Error is: " + e.getMessage());
syncResults.setResults(progress.toString());
@@ -1194,8 +1192,6 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
return syncResults;
}
-
-
@SuppressWarnings("unchecked")
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public ContentSourceSyncResults _mergeContentSourceSyncReportADD(ContentSource contentSource,
@@ -1412,7 +1408,6 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
return syncResults;
}
-
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public ContentSourceSyncResults _mergeContentSourceSyncReportUPDATE(ContentSource contentSource,
PackageSyncReport report, Map<ContentProviderPackageDetailsKey, PackageVersionContentSource> previous,
@@ -1864,7 +1859,6 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
return packageBitsFile;
}
-
private File getDistLocalFileAndCreateParentDir(String distLabel, String fileName) throws Exception {
File distBitsFile = getDistributionFileBitsLocalFilesystemFile(distLabel, fileName);
commit f8453124311f18e8d573f15200e0521e7c3534fc
Author: Jeff Ortel <jortel(a)redhat.com>
Date: Mon Nov 16 16:42:37 2009 -0600
800 - Fix paging and add inital selection on repo import page
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
index dc9e056..d93466a 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
@@ -52,8 +52,10 @@ public class RepoImportUIBean extends PagedDataTableUIBean {
public static final String MANAGED_BEAN_NAME = "RepoImportUIBean";
private int selectedProvider = 0;
+ private List<OptionItem<Integer>> providers = null;
public RepoImportUIBean() {
+ getProviderOptions();
}
/**
@@ -67,6 +69,7 @@ public class RepoImportUIBean extends PagedDataTableUIBean {
* @param selectedProvider the selectedProvider to set
*/
public void setSelectedProvider(String selectedProvider) {
+ dataModel = null;
this.selectedProvider = Integer.valueOf(selectedProvider);
}
@@ -87,16 +90,21 @@ public class RepoImportUIBean extends PagedDataTableUIBean {
* @return An array of options.
*/
public SelectItem[] getProviderOptions() {
- List<OptionItem<Integer>> list = new ArrayList<OptionItem<Integer>>();
- Subject subject = EnterpriseFacesContextUtility.getSubject();
- ContentSourceManagerLocal manager = LookupUtil.getContentSourceManager();
- PageControl pc = new PageControl();
- PageList<ContentSource> results = manager.getAllContentSources(subject, pc);
- for (ContentSource p : results) {
- OptionItem<Integer> item = new OptionItem<Integer>(p.getId(), p.getName());
- list.add(item);
+ if (providers == null) {
+ providers = new ArrayList<OptionItem<Integer>>();
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
+ ContentSourceManagerLocal manager = LookupUtil.getContentSourceManager();
+ PageControl pc = new PageControl();
+ PageList<ContentSource> results = manager.getAllContentSources(subject, pc);
+ for (ContentSource p : results) {
+ OptionItem<Integer> item = new OptionItem<Integer>(p.getId(), p.getName());
+ providers.add(item);
+ if (selectedProvider == 0) {
+ selectedProvider = p.getId();
+ }
+ }
}
- return SelectItemUtils.convertFromListOptionItem(list, false);
+ return SelectItemUtils.convertFromListOptionItem(providers, false);
}
/**
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml
index d44036d..a62bdc9 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml
@@ -67,6 +67,7 @@
footerClass="on-pager-footer"
onRowMouseOver="this.style.backgroundColor='#E7E7E7'"
onRowMouseOut="this.style.backgroundColor='#{a4jSkin.tableBackgroundColor}'">
+ <a4j:keepAlive beanName="RepoImportUIBean" />
<f:facet name="PageControlView">
<onc:paginationControl id="ReposToImportList" />
</f:facet>
commit 44ff6077508f3764c10a5f557f519fdd32b5e2ad
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Nov 16 17:33:38 2009 -0500
fix relative path
diff --git a/modules/enterprise/gui/perspectives/sample-perspective-war/pom.xml b/modules/enterprise/gui/perspectives/sample-perspective-war/pom.xml
index c653fef..2d59114 100644
--- a/modules/enterprise/gui/perspectives/sample-perspective-war/pom.xml
+++ b/modules/enterprise/gui/perspectives/sample-perspective-war/pom.xml
@@ -67,7 +67,7 @@
<id>dev</id>
<properties>
- <rhq.rootDir>../../../..</rhq.rootDir>
+ <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.deploymentName}</rhq.deploymentDir>
@@ -140,4 +140,4 @@
</profiles>
-</project>
\ No newline at end of file
+</project>
commit a922daee3ba5c25a44fc6c46f7703c308725a3f3
Author: Jeff Ortel <jortel(a)redhat.com>
Date: Mon Nov 16 15:05:00 2009 -0600
800 - Add repo import success/failure messages on import page.
Also, fix index out of range exception for cases when ContentSource.getSyncResults() returns an empty list.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
index 11b4fdb..dc9e056 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
@@ -22,6 +22,7 @@ package org.rhq.enterprise.gui.content;
import java.util.ArrayList;
import java.util.List;
+import javax.faces.application.FacesMessage;
import javax.faces.model.DataModel;
import javax.faces.model.SelectItem;
@@ -122,8 +123,12 @@ public class RepoImportUIBean extends PagedDataTableUIBean {
try {
repoManager.importCandidateRepo(subject, repoIds);
} catch (RepoException e) {
- // TODO: Handle
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR,
+ "Failed to import one or more Repositories from Content Provider", e);
+ return "failed";
}
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, selected.length
+ + " Repositories imported from Content Provider");
return "success";
}
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/content-navigation.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/content-navigation.xml
index 3e9e4f4..80b38f8 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/content-navigation.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/content-navigation.xml
@@ -218,21 +218,24 @@
<navigation-rule>
<from-view-id>/rhq/content/importRepos.xhtml</from-view-id>
-
<navigation-case>
<!-- catch all navigation-case: if any actions return 'success', go here -->
<from-outcome>success</from-outcome>
<to-view-id>/rhq/content/listRepos.xhtml</to-view-id>
<redirect/>
</navigation-case>
-
+ <navigation-case>
+ <!-- import failed -->
+ <from-outcome>failed</from-outcome>
+ <to-view-id>/rhq/content/importRepos.xhtml</to-view-id>
+ <redirect/>
+ </navigation-case>
<navigation-case>
<!-- sorting rule -->
<from-outcome>sort</from-outcome>
<to-view-id>/rhq/content/importRepos.xhtml</to-view-id>
<redirect/>
</navigation-case>
-
</navigation-rule>
<!-- Repo View -->
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 81fae3e..13995a7 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
@@ -40,6 +40,7 @@ import org.jboss.annotation.IgnoreDependency;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.content.ContentSource;
+import org.rhq.core.domain.content.ContentSourceSyncResults;
import org.rhq.core.domain.content.ContentSourceSyncStatus;
import org.rhq.core.domain.content.Distribution;
import org.rhq.core.domain.content.PackageVersion;
@@ -881,9 +882,10 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
Iterator<ContentSource> i = contentSources.iterator();
while (i.hasNext()) {
ContentSource cs = i.next();
+ List<ContentSourceSyncResults> syncResults = cs.getSyncResults();
// Add the most recent sync results status
- if (cs.getSyncResults() != null && cs.getSyncResults().get(0) != null) {
- stati.add(cs.getSyncResults().get(0).getStatus());
+ if (syncResults != null && (!syncResults.isEmpty()) && syncResults.get(0) != null) {
+ stati.add(syncResults.get(0).getStatus());
} else {
stati.add(ContentSourceSyncStatus.NONE);
}
commit ce1863541efa2a8a932e32d72c44bd587f74039b
Author: Jeff Ortel <jortel(a)redhat.com>
Date: Mon Nov 16 14:25:08 2009 -0600
800 - Fix ajax part of import page.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
index 14b931f..11b4fdb 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
@@ -38,8 +38,8 @@ import org.rhq.enterprise.gui.common.paging.PageControlView;
import org.rhq.enterprise.gui.common.paging.PagedListDataModel;
import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
-import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.content.RepoException;
+import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
/**
@@ -50,7 +50,7 @@ public class RepoImportUIBean extends PagedDataTableUIBean {
public static final String MANAGED_BEAN_NAME = "RepoImportUIBean";
- private int selectedProvider = 10001;
+ private int selectedProvider = 0;
public RepoImportUIBean() {
}
@@ -80,6 +80,11 @@ public class RepoImportUIBean extends PagedDataTableUIBean {
return dataModel;
}
+ /**
+ * Creates the list of content providers to be displayed in
+ * the radio buttons.
+ * @return An array of options.
+ */
public SelectItem[] getProviderOptions() {
List<OptionItem<Integer>> list = new ArrayList<OptionItem<Integer>>();
Subject subject = EnterpriseFacesContextUtility.getSubject();
@@ -93,28 +98,32 @@ public class RepoImportUIBean extends PagedDataTableUIBean {
return SelectItemUtils.convertFromListOptionItem(list, false);
}
+ /**
+ * Get the list of the selected repos.
+ * @return An array of repo IDs.
+ */
public String[] getSelectedRepos() {
return FacesContextUtility.getRequest().getParameterValues("selectedRepos");
}
+ /**
+ * Import the selected repos.
+ * To import a repo, is to change it from is_candidate=true to is_candidate=false.
+ * @return The next page defined in the navigation.
+ */
public String importSelected() {
Subject subject = EnterpriseFacesContextUtility.getSubject();
String[] selected = getSelectedRepos();
-
List<Integer> repoIds = new ArrayList<Integer>(selected.length);
-
for (String sRepoId : selected) {
repoIds.add(Integer.valueOf(sRepoId));
}
-
RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
try {
repoManager.importCandidateRepo(subject, repoIds);
- }
- catch (RepoException e) {
+ } catch (RepoException e) {
// TODO: Handle
}
-
return "success";
}
@@ -128,7 +137,7 @@ public class RepoImportUIBean extends PagedDataTableUIBean {
Subject subject = EnterpriseFacesContextUtility.getSubject();
ContentSourceManagerLocal manager = LookupUtil.getContentSourceManager();
PageList<Repo> results = manager.getCandidateRepos(subject, selectedProvider, pc);
-
+
return results;
}
}
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml
index a29ca9f..d44036d 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml
@@ -46,7 +46,7 @@
value="#{RepoImportUIBean.selectedProvider}"
layout="pageDirection">
<f:selectItems value="#{RepoImportUIBean.providerOptions}"/>
- <a4j:support event="onchange" reRender="repoTable"/>
+ <a4j:support ajaxSingle="true" event="onchange" reRender="repoTable"/>
</h:selectOneRadio>
</h:panelGrid>
</rich:panel>
commit 72f13d7bf21f7e545f56eb37c652a0419ef1676b
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Mon Nov 16 15:59:17 2009 -0500
Updated to be consistent with eclipse
diff --git a/etc/intellij-tools/rhq-style.xml b/etc/intellij-tools/rhq-style.xml
index ab57fb9..d28fa1b 100644
--- a/etc/intellij-tools/rhq-style.xml
+++ b/etc/intellij-tools/rhq-style.xml
@@ -15,6 +15,24 @@
<option name="INDENT_CASE_FROM_SWITCH" value="false" />
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999999" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999999" />
+ <option name="IMPORT_LAYOUT_TABLE">
+ <value>
+ <package name="java" withSubpackages="true" />
+ <emptyLine />
+ <package name="javax" withSubpackages="true" />
+ <emptyLine />
+ <package name="com" withSubpackages="true" />
+ <emptyLine />
+ <package name="org" withSubpackages="true" />
+ <emptyLine />
+ <package name="org.jboss" withSubpackages="true" />
+ <emptyLine />
+ <package name="org.rhq" withSubpackages="true" />
+ <emptyLine />
+ <package name="" withSubpackages="true" />
+ <emptyLine />
+ </value>
+ </option>
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="EXTENDS_LIST_WRAP" value="1" />
@@ -28,7 +46,43 @@
<option name="WRAP_COMMENTS" value="true" />
<option name="JD_P_AT_EMPTY_LINES" value="false" />
<option name="HTML_DO_NOT_ALIGN_CHILDREN_OF_MIN_LINES" value="500" />
- <ADDITIONAL_INDENT_OPTIONS fileType="js">
+ <ADDITIONAL_INDENT_OPTIONS fileType="">
+ <option name="INDENT_SIZE" value="4" />
+ <option name="CONTINUATION_INDENT_SIZE" value="8" />
+ <option name="TAB_SIZE" value="4" />
+ <option name="USE_TAB_CHARACTER" value="false" />
+ <option name="SMART_TABS" value="false" />
+ <option name="LABEL_INDENT_SIZE" value="0" />
+ <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+ </ADDITIONAL_INDENT_OPTIONS>
+ <ADDITIONAL_INDENT_OPTIONS fileType="java">
+ <option name="INDENT_SIZE" value="4" />
+ <option name="CONTINUATION_INDENT_SIZE" value="4" />
+ <option name="TAB_SIZE" value="8" />
+ <option name="USE_TAB_CHARACTER" value="false" />
+ <option name="SMART_TABS" value="false" />
+ <option name="LABEL_INDENT_SIZE" value="0" />
+ <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+ </ADDITIONAL_INDENT_OPTIONS>
+ <ADDITIONAL_INDENT_OPTIONS fileType="jsp">
+ <option name="INDENT_SIZE" value="4" />
+ <option name="CONTINUATION_INDENT_SIZE" value="8" />
+ <option name="TAB_SIZE" value="4" />
+ <option name="USE_TAB_CHARACTER" value="false" />
+ <option name="SMART_TABS" value="false" />
+ <option name="LABEL_INDENT_SIZE" value="0" />
+ <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+ </ADDITIONAL_INDENT_OPTIONS>
+ <ADDITIONAL_INDENT_OPTIONS fileType="sql">
+ <option name="INDENT_SIZE" value="2" />
+ <option name="CONTINUATION_INDENT_SIZE" value="8" />
+ <option name="TAB_SIZE" value="4" />
+ <option name="USE_TAB_CHARACTER" value="false" />
+ <option name="SMART_TABS" value="false" />
+ <option name="LABEL_INDENT_SIZE" value="0" />
+ <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+ </ADDITIONAL_INDENT_OPTIONS>
+ <ADDITIONAL_INDENT_OPTIONS fileType="xml">
<option name="INDENT_SIZE" value="4" />
<option name="CONTINUATION_INDENT_SIZE" value="8" />
<option name="TAB_SIZE" value="4" />
commit fd8568d25c5594e312e9871ee5d6759d7eac3407
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Mon Nov 16 15:59:17 2009 -0500
Updated to be consistent with eclipse
diff --git a/etc/intellij-tools/rhq-style.xml b/etc/intellij-tools/rhq-style.xml
index ab57fb9..d28fa1b 100644
--- a/etc/intellij-tools/rhq-style.xml
+++ b/etc/intellij-tools/rhq-style.xml
@@ -15,6 +15,24 @@
<option name="INDENT_CASE_FROM_SWITCH" value="false" />
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999999" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="999999" />
+ <option name="IMPORT_LAYOUT_TABLE">
+ <value>
+ <package name="java" withSubpackages="true" />
+ <emptyLine />
+ <package name="javax" withSubpackages="true" />
+ <emptyLine />
+ <package name="com" withSubpackages="true" />
+ <emptyLine />
+ <package name="org" withSubpackages="true" />
+ <emptyLine />
+ <package name="org.jboss" withSubpackages="true" />
+ <emptyLine />
+ <package name="org.rhq" withSubpackages="true" />
+ <emptyLine />
+ <package name="" withSubpackages="true" />
+ <emptyLine />
+ </value>
+ </option>
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="EXTENDS_LIST_WRAP" value="1" />
@@ -28,7 +46,43 @@
<option name="WRAP_COMMENTS" value="true" />
<option name="JD_P_AT_EMPTY_LINES" value="false" />
<option name="HTML_DO_NOT_ALIGN_CHILDREN_OF_MIN_LINES" value="500" />
- <ADDITIONAL_INDENT_OPTIONS fileType="js">
+ <ADDITIONAL_INDENT_OPTIONS fileType="">
+ <option name="INDENT_SIZE" value="4" />
+ <option name="CONTINUATION_INDENT_SIZE" value="8" />
+ <option name="TAB_SIZE" value="4" />
+ <option name="USE_TAB_CHARACTER" value="false" />
+ <option name="SMART_TABS" value="false" />
+ <option name="LABEL_INDENT_SIZE" value="0" />
+ <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+ </ADDITIONAL_INDENT_OPTIONS>
+ <ADDITIONAL_INDENT_OPTIONS fileType="java">
+ <option name="INDENT_SIZE" value="4" />
+ <option name="CONTINUATION_INDENT_SIZE" value="4" />
+ <option name="TAB_SIZE" value="8" />
+ <option name="USE_TAB_CHARACTER" value="false" />
+ <option name="SMART_TABS" value="false" />
+ <option name="LABEL_INDENT_SIZE" value="0" />
+ <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+ </ADDITIONAL_INDENT_OPTIONS>
+ <ADDITIONAL_INDENT_OPTIONS fileType="jsp">
+ <option name="INDENT_SIZE" value="4" />
+ <option name="CONTINUATION_INDENT_SIZE" value="8" />
+ <option name="TAB_SIZE" value="4" />
+ <option name="USE_TAB_CHARACTER" value="false" />
+ <option name="SMART_TABS" value="false" />
+ <option name="LABEL_INDENT_SIZE" value="0" />
+ <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+ </ADDITIONAL_INDENT_OPTIONS>
+ <ADDITIONAL_INDENT_OPTIONS fileType="sql">
+ <option name="INDENT_SIZE" value="2" />
+ <option name="CONTINUATION_INDENT_SIZE" value="8" />
+ <option name="TAB_SIZE" value="4" />
+ <option name="USE_TAB_CHARACTER" value="false" />
+ <option name="SMART_TABS" value="false" />
+ <option name="LABEL_INDENT_SIZE" value="0" />
+ <option name="LABEL_INDENT_ABSOLUTE" value="false" />
+ </ADDITIONAL_INDENT_OPTIONS>
+ <ADDITIONAL_INDENT_OPTIONS fileType="xml">
<option name="INDENT_SIZE" value="4" />
<option name="CONTINUATION_INDENT_SIZE" value="8" />
<option name="TAB_SIZE" value="4" />
commit 4639868d5b2685130993f456e7f415b2bd0d82cd
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Mon Nov 16 15:42:42 2009 -0500
Random cleanup
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
index a513a60..761e7cd 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
@@ -300,7 +300,6 @@ public class ContentSource implements Serializable {
public List<ContentSourceSyncResults> getSyncResults() {
Comparator dc = new Comparator() {
- @Override
public int compare(Object arg0, Object arg1) {
ContentSourceSyncResults c1 = (ContentSourceSyncResults) arg0;
ContentSourceSyncResults c2 = (ContentSourceSyncResults) arg1;
@@ -333,7 +332,7 @@ public class ContentSource implements Serializable {
*
* @return the mapping entities
*
- * @see #getContentSources()
+ * @see #getRepoContentSources()
*/
public Set<RepoContentSource> getRepoContentSources() {
return repoContentSources;
commit 61fa4206f5acc4db146179e528d54a1f15043e46
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Mon Nov 16 15:16:28 2009 -0500
Removed incorrect @Overrides declaration
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 58ec4de..81fae3e 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
@@ -900,7 +900,6 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
return null;
}
- @Override
public int synchronizeRepos(Subject subject, Integer[] repoIds) {
int syncCount = 0;
commit fd970870762eca8feaa78a2b882a8e34c33b2e8b
Author: John Matthews <jmatthew(a)redhat.com>
Date: Mon Nov 16 15:08:47 2009 -0500
Fixed package syncs
Two main problems
1) Assumption changed for RHNProvider, now it's 1 RHNProvider for ALL Channels,
therefore for each call out to RHN we need to supply the channel name.
2) XML processing was running out of memory (OutOfMemory java heap) for reading rsponse
Syncing full channels, such as rhel5 i386 contains a large amount of metadata (1.1gb).
Fix was:
i) Cache the response to a file
ii) Chunk the work, so we operate on a smaller sublist for get package metadata.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
index adc4b5a..b47b50f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
@@ -732,7 +732,7 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
}
log.debug("Attempting download of " + dFile.getRelativeFilename() +
" from contentSourceId " + contentSourceId);
- String remoteFetchLoc = distSource.getRemoteLocation(repo.getName(), dist.getLabel(),
+ String remoteFetchLoc = distSource.getDistFileRemoteLocation(repo.getName(), dist.getLabel(),
dFile.getRelativeFilename());
InputStream bitsStream = pc.getAdapterManager().loadDistributionFileBits(contentSourceId,
remoteFetchLoc);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java
index feb0dce..9efd9c7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java
@@ -61,7 +61,7 @@ public interface DistributionSource {
* @param relativeFilename relative path of file to fetch
* @return a remote location that can be passed into getInputStream to fetch a file from this source.
*/
- String getRemoteLocation(String repoName, String label, String relativeFilename);
+ String getDistFileRemoteLocation(String repoName, String label, String relativeFilename);
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
index 74842dc..5c2565f 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
@@ -463,7 +463,7 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
*/
private class TestContentProviderManager extends ContentProviderManager {
- protected ContentProvider getIsolatedContentProvider(int contentProviderId) throws RuntimeException {
+ public ContentProvider getIsolatedContentProvider(int contentProviderId) throws RuntimeException {
return testProvider;
}
}
diff --git a/modules/enterprise/server/plugins/rhnhosted/pom.xml b/modules/enterprise/server/plugins/rhnhosted/pom.xml
index 73d6596..a0d25da 100644
--- a/modules/enterprise/server/plugins/rhnhosted/pom.xml
+++ b/modules/enterprise/server/plugins/rhnhosted/pom.xml
@@ -126,6 +126,16 @@
<build>
+
+ <testResources>
+ <testResource>
+ <directory>src/test/resources</directory>
+ <includes>
+ <include>test-log4j.xml</include>
+ </includes>
+ </testResource>
+ </testResources>
+
<plugins>
<plugin>
@@ -145,6 +155,18 @@
<name>RunRHNProviderTest</name>
<value>false</value>
</property>
+ <property>
+ <!--
+ set this to true if you want the temp xmlrpc data read to be saved.
+ by default the files are stored in /tmp and will be deleted after use.
+ -->
+ <name>RhnJaxbSaveTempFiles</name>
+ <value>false</value>
+ </property>
+ <property>
+ <name>log4j.configuration</name>
+ <value>test-log4j.xml</value>
+ </property>
</systemProperties>
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
index 271397f..ebf7d23 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
@@ -49,14 +49,11 @@ import org.rhq.enterprise.server.plugin.pc.content.DistributionFileDetails;
public class RHNHelper {
private final String baseurl;
- private final String repolabel;
private final RhnComm rhndata;
private final RhnDownloader rhndownload;
private final String systemid;
private final String distributionType;
-
- //TODO: Need to determine what the ksTreeType should be for RHN Kickstarts
- private final String ksTreeType = "CHANGE_ME";
+
private final Log log = LogFactory.getLog(RHNHelper.class);
@@ -64,13 +61,11 @@ public class RHNHelper {
* Constructor.
*
* @param baseurl The base url to connect to hosted
- * @param repolabelIn channel label
* @param systemIdIn systemId to use for auth
*/
- public RHNHelper(String baseurl, String repolabelIn, String systemIdIn) {
+ public RHNHelper(String baseurl, String systemIdIn) {
this.baseurl = baseurl;
- this.repolabel = repolabelIn;
this.rhndata = new RhnComm(baseurl);
this.rhndownload = new RhnDownloader(baseurl);
this.systemid = systemIdIn;
@@ -80,10 +75,13 @@ public class RHNHelper {
public List<DistributionDetails> getDistributionMetaData(List<String> labels)
throws IOException, XmlRpcException {
+ log.debug("getDistributionMetaData(" + labels + " invoked");
List<DistributionDetails> distros = new ArrayList<DistributionDetails>();
List<RhnKickstartableTreeType> ksTreeTypes = rhndata.getKickstartTreeMetadata(this.systemid, labels);
for (RhnKickstartableTreeType ksTree: ksTreeTypes) {
+ log.debug("Forming DistributionDetails(" + ksTree.getLabel() + ", " + ksTree.getBasePath() +
+ " , " + distributionType);
DistributionDetails details =
new DistributionDetails(ksTree.getLabel(), ksTree.getBasePath(), distributionType);
distros.add(details);
@@ -108,15 +106,18 @@ public class RHNHelper {
/**
* Extract the package metadata for all available packages to sync
* @param packageIds Valid package ids for getPackageMatadata call to fetch from hosted
+ * @param channelName channel name of passed in package ids
* @return A list of package detail objects
* @throws Exception On all errors
*/
- public List<ContentProviderPackageDetails> getPackageDetails(List packageIds) throws Exception {
+ public List<ContentProviderPackageDetails> getPackageDetails(List packageIds, String channelName) throws Exception {
+ log.debug("getPackageDetails() for " + packageIds.size() + " packageIds on channel " + channelName);
List<ContentProviderPackageDetails> pdlist = new ArrayList<ContentProviderPackageDetails>();
List<RhnPackageType> pkgs = rhndata.getPackageMetadata(this.systemid, packageIds);
+ log.debug(pkgs.size() + " packages were returned from getPackageMetadata().");
for (RhnPackageType pkg : pkgs) {
try {
- pdlist.add(getDetails(pkg));
+ pdlist.add(getDetails(pkg, channelName));
} catch (Exception e) {
// something went wrong while constructing the pkg object.
// Proceed to next and get as many packages as we can.
@@ -130,11 +131,12 @@ public class RHNHelper {
* Extract the package details for each rpm metadata fetched
*
* @param p an rpm package metadata object
+ * @param channelName channel name
*
* @return ContentProviderPackageDetails pkg object
*/
- private ContentProviderPackageDetails getDetails(RhnPackageType p) {
-
+ private ContentProviderPackageDetails getDetails(RhnPackageType p, String channelName) {
+
String name = p.getName();
String version = p.getVersion();
String arch = p.getPackageArch();
@@ -152,42 +154,11 @@ public class RHNHelper {
pkg.setFileCreatedDate(new Long(p.getLastModified()));
pkg.setLicenseName("license");
pkg.setMD5(p.getMd5Sum());
- pkg.setLocation(constructPackageUrl(repolabel, rpmname));
+ pkg.setLocation(constructPackageUrl(channelName, rpmname));
//pkg.setMetadata();
return pkg;
}
-
- /**
- * Get List of kickstart labels for the channel associated to this instance.
- * @return List of all kickstart labels associate to the channel
- * @throws IOException on io errors on systemid reads
- * @throws XmlRpcException on xmlrpc faults
- */
- public List<String> getChannelKickstartLabels() throws IOException, XmlRpcException {
- return getChannelKickstartLabels(this.repolabel);
- }
-
- /**
- * Get List of kickstart labels for the channel associated to this instance.
- * @param channelName channel name
- * @return List of all kickstart labels associate to the channel
- * @throws IOException on io errors on systemid reads
- * @throws XmlRpcException on xmlrpc faults
- */
- public List<String> getChannelKickstartLabels(String channelName) throws IOException, XmlRpcException {
- return getSyncableKickstartLabels(Arrays.asList(channelName));
- }
-
- /**
- * Get List of packagesIds for Given Channels
- * @return List of all package ids associated to the channel
- * @throws IOException on io errors on systemid reads
- * @throws XmlRpcException on xmlrpc faults
- */
- public List<String> getChannelPackages() throws IOException, XmlRpcException {
- return getChannelPackages(this.repolabel);
- }
/**
* Get List of packagesIds for Given Channels
@@ -197,10 +168,8 @@ public class RHNHelper {
* @throws XmlRpcException on xmlrpc faults
*/
public List<String> getChannelPackages(String channelName) throws IOException, XmlRpcException {
+ log.debug("getChannelPackages(" + channelName + ")");
ArrayList<String> allPackages = new ArrayList();
-
- log.info("Systemid: " + this.systemid);
- log.info("repolist: " + this.repolabel);
List<RhnChannelType> channels = rhndata.getChannels(this.systemid, Arrays.asList(channelName));
for (RhnChannelType channel : channels) {
@@ -221,6 +190,7 @@ public class RHNHelper {
* @throws XmlRpcException on xmlrpc faults
*/
public List<String> getSyncableChannels() throws IOException, XmlRpcException {
+ log.debug("getSyncableChannels()");
ArrayList<String> allchannels = new ArrayList();
List<RhnChannelFamilyType> cfts = rhndata.getChannelFamilies(this.systemid);
for (RhnChannelFamilyType cf : cfts) {
@@ -234,13 +204,41 @@ public class RHNHelper {
return allchannels;
}
-
+ /**
+ *
+ * @return returns list of all possible kickstart labels from all possible channels
+ * @throws IOException
+ * @throws XmlRpcException
+ */
public List<String> getSyncableKickstartLabels() throws IOException, XmlRpcException {
+ log.debug("getSyncableKickstartLabels() - no channels passed, will use all available channels");
List<String> allChannels = getSyncableChannels();
return getSyncableKickstartLabels(allChannels);
}
+ /**
+ *
+ * @param channelName channel name
+ * @return kickstart labels part of the passed in channel name
+ * @throws IOException
+ * @throws XmlRpcException
+ */
+ public List<String> getSyncableKickstartLabels(String channelName) throws IOException, XmlRpcException {
+ log.debug("getSyncableKickstartLabels(" + channelName + ")");
+ List<String> names = new ArrayList<String>();
+ names.add(channelName);
+ return getSyncableKickstartLabels(names);
+ }
+
+ /**
+ *
+ * @param channelLabels list of channel names to restrict return data to
+ * @return kickstart labels from the passed in list of channel names
+ * @throws IOException
+ * @throws XmlRpcException
+ */
public List<String> getSyncableKickstartLabels(List<String> channelLabels) throws IOException, XmlRpcException {
+ log.debug("getSyncableKickstartLabels(" + channelLabels + ")");
List<String> ksLabels = new ArrayList<String>();
List<RhnChannelType> rct = rhndata.getChannels(this.systemid, channelLabels);
for (RhnChannelType ct: rct) {
@@ -265,8 +263,7 @@ public class RHNHelper {
* @throws XmlRpcException On all errors.
*/
public InputStream openStream(String location) throws IOException, XmlRpcException {
-
- log.info("Package Fetched from: " + location);
+ log.info("File being fetched from: " + location);
return rhndownload.getFileStream(this.systemid, location);
}
@@ -276,7 +273,12 @@ public class RHNHelper {
* @param rpmName rpm file name
* @return a valid url location to fetch the rpm from.
*/
- private String constructPackageUrl(String channelName, String rpmName) {
+ public String constructPackageUrl(String channelName, String rpmName) {
+
+ return constructPackageUrl(baseurl, channelName, rpmName);
+ }
+
+ static public String constructPackageUrl(String baseurl, String channelName, String rpmName) {
String appendurl = "/SAT/$RHN/" + channelName + "/getPackage/" + rpmName;
return baseurl + appendurl;
@@ -291,6 +293,11 @@ public class RHNHelper {
*/
public String constructKickstartFileUrl(String channelName, String ksTreeLabel, String ksFilePath) {
+ return constructKickstartFileUrl(baseurl, channelName, ksTreeLabel, ksFilePath);
+ }
+
+ static public String constructKickstartFileUrl(String baseurl, String channelName, String ksTreeLabel,
+ String ksFilePath) {
String appendurl = "/SAT/$RHN/" + channelName + "/getKickstartFile/" + ksTreeLabel + "/" + ksFilePath;
return baseurl + appendurl;
}
@@ -304,7 +311,7 @@ public class RHNHelper {
* @param arch rpm package arch
* @return an rpm package name string
*/
- private String constructRpmName(String name, String version, String release, String epoch, String arch) {
+ static public String constructRpmName(String name, String version, String release, String epoch, String arch) {
String releaseepoch = release + ":" + epoch;
return name + "-" + version + "-" + releaseepoch + "." + arch + ".rpm";
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
index 1b1a0b0..4ed7352 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
@@ -64,13 +64,6 @@ public class RHNProvider implements ContentProvider, PackageSource, RepoSource,
private final Log log = LogFactory.getLog(RHNProvider.class);
private RHNActivator rhnObject;
private RHNHelper helper;
- private boolean testMode = false;
-
- public void initializeForTest(Configuration configuration) throws Exception {
- log.info("**TEST MODE RHNProvider is running in a test configuration**");
- testMode = true;
- initialize(configuration);
- }
/**
* Initializes the adapter with the specified configuration.
@@ -133,12 +126,10 @@ public class RHNProvider implements ContentProvider, PackageSource, RepoSource,
throw new InitializationException("Server Activation Failed.", e);
}
- String repos = configuration.getSimpleValue("SyncableChannels", null);
- log.info("Syncable Channel list :" + repos);
-
// RHQ Server is now active, initialize the handler for the bits.
- helper = new RHNHelper(locationIn, repos, rhnObject.getSystemid());
- log.info("RHNProvider initialized RHNHelper with repos: " + repos);
+ helper = new RHNHelper(locationIn, rhnObject.getSystemid());
+ log.info("RHNProvider initialized RHNHelper with ( location = " + locationIn + "\n " +
+ "systemid = " + rhnObject.getSystemid());
}
/**
@@ -162,6 +153,8 @@ public class RHNProvider implements ContentProvider, PackageSource, RepoSource,
public void synchronizePackages(String repoName, PackageSyncReport report,
Collection<ContentProviderPackageDetails> existingPackages)
throws Exception {
+ log.info("synchronizePackages(repoName = " + repoName + ", report = " + report +
+ ", existingPackages.size() = " + existingPackages.size());
RHNSummary summary = new RHNSummary(helper);
List<ContentProviderPackageDetails> deletedPackages = new ArrayList<ContentProviderPackageDetails>();
deletedPackages.addAll(existingPackages);
@@ -171,7 +164,33 @@ public class RHNProvider implements ContentProvider, PackageSource, RepoSource,
summary.markStarted();
List<String> pkgIds = helper.getChannelPackages(repoName);
log.info("RHNProvider:: helper.getChannelPackages returned " + pkgIds.size() + " packages");
- for (ContentProviderPackageDetails p : helper.getPackageDetails(pkgIds)) {
+ List<ContentProviderPackageDetails> pkgDetails = new ArrayList<ContentProviderPackageDetails>();
+
+ //
+ // We ran into problems when syncing large package lists, example 6000 packages.
+ // We are going to chunk the list to processing a smaller amount at a time.
+ //
+ long startTime = System.currentTimeMillis();
+ int sliceSize = 100;
+ for (int index = 0; index < pkgIds.size(); index += sliceSize) {
+ int end = index + sliceSize;
+ if (end >= pkgIds.size()) {
+ end = pkgIds.size() - 1;
+ }
+ long startTimeSlice = System.currentTimeMillis();
+ log.debug("Getting package details for slice [" + index + " -> " + end + "]");
+ List<String> pkgSliceList = pkgIds.subList(index, end);
+ pkgDetails.addAll(helper.getPackageDetails(pkgSliceList, repoName));
+ long endTimeSlice = System.currentTimeMillis();
+ log.debug("Slice processed in " + (endTimeSlice - startTimeSlice) +
+ "ms current size of pkgDetails is " + pkgDetails.size());
+ }
+ long endTime = System.currentTimeMillis();
+ log.info("It took " + (endTime - startTime) + "ms too get PackageDetails for " + pkgIds.size() + " packages");
+
+
+
+ for (ContentProviderPackageDetails p : pkgDetails) {
log.debug("Processing package at (" + p.getLocation());
deletedPackages.remove(p);
if (!existingPackages.contains(p)) {
@@ -215,7 +234,7 @@ public class RHNProvider implements ContentProvider, PackageSource, RepoSource,
List<String> deletedDistros = new ArrayList<String>(); //Existing distros we want to remove.
deletedDistros.addAll(existingLabels);
- List<String> availableLabels = helper.getChannelKickstartLabels(repoName);
+ List<String> availableLabels = helper.getSyncableKickstartLabels(repoName);
log.debug("Found " + availableLabels.size() + " available kickstart trees");
for (String label: availableLabels) {
log.debug("Processing kickstart: " + label);
@@ -294,7 +313,7 @@ public class RHNProvider implements ContentProvider, PackageSource, RepoSource,
/**
* @inheritDoc
*/
- public String getRemoteLocation(String repoName, String label, String relativeFilename) {
+ public String getDistFileRemoteLocation(String repoName, String label, String relativeFilename) {
return helper.constructKickstartFileUrl(repoName, label, relativeFilename);
}
}
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnComm.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnComm.java
index 7674bf6..155096a 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnComm.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnComm.java
@@ -6,6 +6,8 @@ import java.util.List;
import javax.xml.bind.JAXBElement;
import org.apache.xmlrpc.XmlRpcException;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.Log;
import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnChannelFamilyType;
import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnChannelType;
@@ -16,7 +18,7 @@ import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnProductNameType;
import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnSatelliteType;
public class RhnComm {
-
+ private final Log log = LogFactory.getLog(RhnComm.class);
protected XmlRpcExecutor dumpHandler;
protected String serverUrl;
protected String SATDUMP_HANDLER = "/SAT-DUMP";
@@ -28,6 +30,8 @@ public class RhnComm {
public List<RhnProductNameType> getProductNames(String systemId) throws IOException, XmlRpcException {
Object[] params = new Object[] { systemId };
+
+ log.debug("getProductNames()");
JAXBElement<RhnSatelliteType> result = (JAXBElement) dumpHandler.execute("dump.product_names", params);
RhnSatelliteType sat = result.getValue();
List<RhnProductNameType> names = sat.getRhnProductNames().getRhnProductName();
@@ -36,6 +40,8 @@ public class RhnComm {
public List<RhnChannelFamilyType> getChannelFamilies(String systemId) throws IOException, XmlRpcException {
Object[] params = new Object[] { systemId };
+
+ log.debug("getChannelFamilies()");
JAXBElement<RhnSatelliteType> result = (JAXBElement) dumpHandler.execute("dump.channel_families", params);
RhnSatelliteType sat = result.getValue();
List<RhnChannelFamilyType> families = sat.getRhnChannelFamilies().getRhnChannelFamily();
@@ -45,6 +51,7 @@ public class RhnComm {
public List<RhnChannelType> getChannels(String systemId, List<String> channelLabels) throws IOException,
XmlRpcException {
+ log.debug("getChannels(" + channelLabels + ")");
Object[] params = new Object[] { systemId, channelLabels };
JAXBElement<RhnSatelliteType> result = (JAXBElement) dumpHandler.execute("dump.channels", params);
RhnSatelliteType sat = result.getValue();
@@ -55,6 +62,7 @@ public class RhnComm {
public List<RhnPackageShortType> getPackageShortInfo(String systemId, List<String> pkgIds) throws IOException,
XmlRpcException {
+ log.debug("getPackageShortInfo() passed in package id list has " + pkgIds.size() + " entries");
Object[] params = new Object[] { systemId, pkgIds };
JAXBElement<RhnSatelliteType> result = (JAXBElement) dumpHandler.execute("dump.packages_short", params);
RhnSatelliteType sat = result.getValue();
@@ -65,6 +73,7 @@ public class RhnComm {
public List<RhnPackageType> getPackageMetadata(String systemId, List<String> pkgIds) throws IOException,
XmlRpcException {
+ log.debug("getPackageMetadata() passed in package id list has " + pkgIds.size() + " entries");
Object[] params = new Object[] { systemId, pkgIds };
JAXBElement<RhnSatelliteType> result = (JAXBElement) dumpHandler.execute("dump.packages", params);
RhnSatelliteType sat = result.getValue();
@@ -75,6 +84,7 @@ public class RhnComm {
public List<RhnKickstartableTreeType> getKickstartTreeMetadata(String systemId, List<String> ksLabels)
throws IOException, XmlRpcException {
+ log.debug("getKickstartTreeMetadata(" + ksLabels + ")");
Object[] params = new Object[] { systemId, ksLabels };
JAXBElement<RhnSatelliteType> result = (JAXBElement) dumpHandler.execute("dump.kickstartable_trees", params);
RhnSatelliteType sat = result.getValue();
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnJaxbTransport.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnJaxbTransport.java
index ebbf8c3..48458c3 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnJaxbTransport.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnJaxbTransport.java
@@ -12,12 +12,23 @@ import javax.xml.bind.Unmarshaller;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;
+import java.io.StringWriter;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Reader;
+import java.io.FileInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.BufferedOutputStream;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.common.XmlRpcStreamRequestConfig;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
import org.jdom.input.SAXBuilder;
import org.jdom.Document;
@@ -25,9 +36,10 @@ import org.jdom.JDOMException;
public class RhnJaxbTransport extends CustomReqPropTransport {
+ protected String PROP_NAME_TO_SAVE_TEMP_FILES = "RhnJaxbSaveTempFiles";
protected String jaxbDomain;
- protected boolean dumpMessageToFile;
- protected String dumpPath;
+ protected boolean dumpMessageToFile; // used during debug to save a copy of the data received
+ protected String dumpPath; // location to save
private final Log log = LogFactory.getLog(RhnJaxbTransport.class);
public RhnJaxbTransport(XmlRpcClient pClient) {
@@ -58,9 +70,10 @@ public class RhnJaxbTransport extends CustomReqPropTransport {
return jaxbDomain;
}
- protected boolean isJaxbMessage(String message) {
+ protected boolean isJaxbMessage(File message) {
try {
- Document doc = new SAXBuilder().build(new ByteArrayInputStream(message.getBytes()));
+ FileInputStream in = new FileInputStream(message);
+ Document doc = new SAXBuilder().build(in);
String name = doc.getRootElement().getName();
log.info("Root element name is " + name);
if (name.equalsIgnoreCase("rhn-satellite")) {
@@ -77,35 +90,128 @@ public class RhnJaxbTransport extends CustomReqPropTransport {
return false;
}
- protected Object readResponse(XmlRpcStreamRequestConfig pConfig, InputStream pStream) throws XmlRpcException {
- InputStream stream;
- String data = "";
+ protected File cacheResponseToFile_v2(InputStream inStream) throws XmlRpcException {
+
+ //
+ // We will read the response and write it to a file. Prior approach read all data in memory and parsed it.
+ // This created a problem when retrieving package details for large package lists of 6000+ packages.
+ // We were seeing out of memory exceptions,
+ // estimate on "rhel-i386-server-5" are 6200+ packages, metadata size written to disk in xml is 1.1GB
+ //
+ File tempFile = null;
+ Reader in = null;
+ BufferedWriter fileOut = null;
try {
- BufferedReader reader = new BufferedReader(new InputStreamReader(pStream));
- String line;
- StringBuffer sb = new StringBuffer();
- while ((line = reader.readLine()) != null) {
- sb.append(line + "\n");
- }
- data = sb.toString();
- log.debug("Message received is: " + data);
- stream = new ByteArrayInputStream(data.getBytes());
if (dumpMessageToFile) {
- FileWriter fstream = new FileWriter(getDumpFilePath());
- BufferedWriter out = new BufferedWriter(fstream);
- try {
- out.write(data);
+ tempFile = new File(getDumpFilePath());
+ }
+ else {
+ tempFile = File.createTempFile("rhn-jaxb-xmlrpc-output", ".tmp");
+ }
+ final char[] buffer = new char[0x100000];
+
+ in = new BufferedReader(new InputStreamReader(inStream, "UTF-8"));
+ fileOut = new BufferedWriter(new FileWriter(tempFile, false));
+
+ int read;
+ do {
+ //long startRead = System.currentTimeMillis();
+ read = in.read(buffer, 0, buffer.length);
+ if (read>0) {
+ //long endRead = System.currentTimeMillis();
+ //log.debug("Read " + read + " bytes took " + (endRead - startRead) + "ms");
+ //long startWrite = System.currentTimeMillis();
+ fileOut.write(buffer, 0, read);
+ //long endWrite = System.currentTimeMillis();
+ //log.debug("Wrote " + read + " bytes in " + (endWrite - startWrite) + "ms");
}
- finally {
- out.close();
+ } while (read>=0);
+ }
+ catch (Exception e) {
+ log.warn("RhnJaxbTransport readResponse exception", e);
+ throw new XmlRpcException(e.getMessage());
+ } finally {
+ try {
+ if (fileOut != null) {
+ fileOut.close();
+ fileOut = null;
+ }
+ if (in != null) {
+ in.close();
+ in = null;
}
}
+ catch (Exception e) {
+ ; //ignore exceptions from close
+ }
+ }
+ return tempFile;
+ }
+
+ protected File cacheResponseToFile(InputStream inStream) throws XmlRpcException {
+
+ //
+ // We will read the response and write it to a file. Prior approach read all data in memory and parsed it.
+ // This created a problem when retrieving package details for large package lists of 6000+ packages.
+ // We were seeing out of memory exceptions,
+ // estimate on "rhel-i386-server-5" are 6200+ packages, metadata size written to disk in xml is 1.1GB
+ //
+ File tempFile = null;
+ BufferedOutputStream outStream = null;
+ try {
+ if (dumpMessageToFile) {
+ tempFile = new File(getDumpFilePath());
+ }
+ else {
+ tempFile = File.createTempFile("rhn-jaxb-xmlrpc-output", ".tmp");
+ }
+ outStream = new BufferedOutputStream(new FileOutputStream(tempFile, false));
+ final byte[] buffer = new byte[0x100000];
+
+ BufferedInputStream buffInStream = new BufferedInputStream(inStream);
+
+ int read;
+ do {
+ //long startRead = System.currentTimeMillis();
+ read = buffInStream.read(buffer, 0, buffer.length);
+ //read = inStream.read(buffer, 0, buffer.length);
+ if (read>0) {
+ //long endRead = System.currentTimeMillis();
+ //log.debug("Read " + read + " bytes took " + (endRead - startRead) + "ms");
+ //long startWrite = System.currentTimeMillis();
+ outStream.write(buffer, 0, read);
+ //long endWrite = System.currentTimeMillis();
+ //log.debug("Wrote " + read + " bytes in " + (endWrite - startWrite) + "ms");
+ }
+ } while (read>=0);
}
catch (Exception e) {
log.warn("RhnJaxbTransport readResponse exception", e);
throw new XmlRpcException(e.getMessage());
+ } finally {
+ try {
+ if (outStream != null) {
+ outStream.close();
+ outStream = null;
+ }
+ }
+ catch (Exception e) {
+ ; //ignore exceptions from close
+ }
}
+ return tempFile;
+ }
+ protected Object readResponse(XmlRpcStreamRequestConfig pConfig, InputStream pStream) throws XmlRpcException {
+
+ log.debug("readResponse invoked");
+ long start = System.currentTimeMillis();
+ File tempFile = cacheResponseToFile(pStream);
+ long end = System.currentTimeMillis();
+ float bandwidth = (float)tempFile.length() / (1024);
+ bandwidth = (bandwidth / (end-start))*1000;
+ log.info("response cached " + ((float)tempFile.length()/1024) + " KB in " + (end - start) +
+ "ms. Estimated Bandwidth: " + bandwidth + " KB/sec");
/**
* Point of this method is to not require the traditional "methodResponse" xml wrapping
@@ -116,21 +222,63 @@ public class RhnJaxbTransport extends CustomReqPropTransport {
* if it's "methodResponse" do traditional XMLRPC parsing.
*
* */
- if (isJaxbMessage(data) == false) {
- log.info("Message is not a JAXB element");
- //Remember to use 'stream' and not 'pStream', as 'pStream' was consumed earlier
- return super.readResponse(pConfig, stream);
- }
-
-
+ FileInputStream dataStream = null;
try {
+ dataStream = new FileInputStream(tempFile);
+ if (isJaxbMessage(tempFile) == false) {
+ log.info("Message is not a JAXB element");
+ return super.readResponse(pConfig, dataStream);
+ }
+
JAXBContext jc = JAXBContext.newInstance(jaxbDomain);
Unmarshaller u = jc.createUnmarshaller();
- return u.unmarshal(stream);
+ return u.unmarshal(dataStream);
}
catch (JAXBException e) {
+ log.error(e);
+ e.printStackTrace();
+ throw new XmlRpcException(e.getMessage());
+ }
+ catch (IOException e) {
+ log.error(e);
e.printStackTrace();
throw new XmlRpcException(e.getMessage());
}
+ finally {
+ if (doWeDeleteTempFile(tempFile)) {
+ log.info("Deleting temp file: " + tempFile.getAbsolutePath());
+ tempFile.delete();
+ }
+ else {
+ log.info("Temporary file of xmlrpc data is available at: " + tempFile.getAbsolutePath());
+ }
+ try {
+ if (dataStream != null) {
+ dataStream.close();
+ }
+ }
+ catch (Exception e) {
+ ; //ignore exception from close
+ }
+ }
+ }
+
+ protected boolean doWeDeleteTempFile(File f) {
+ // Check basic file access to ensure we could delete the file
+ if ( !f.exists() || f.isDirectory() || !f.canWrite()) {
+ return false;
+ }
+ // If we set dumpMessageToFile, then we obviously don't want to delete it
+ if (dumpMessageToFile) {
+ return false;
+ }
+ // Check our System Prop to see if maybe we are debugging and want to keep temp files.
+ String value = System.getProperty(PROP_NAME_TO_SAVE_TEMP_FILES);
+ if (!StringUtils.isBlank(value)) {
+ if (Boolean.parseBoolean(value)) {
+ return false;
+ }
+ }
+ return true;
}
}
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelperTest.java b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelperTest.java
index b07f2e8..a12aa0b 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelperTest.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelperTest.java
@@ -27,15 +27,15 @@ public class RHNHelperTest extends BaseRHNTest {
System.setProperty(ApacheXmlRpcExecutor.class.getName(), MockRhnXmlRpcExecutor.class.getName());
System.setProperty(RhnHttpURLConnectionFactory.RHN_MOCK_HTTP_URL_CONNECTION, MockRhnHttpURLConnection.class
.getName());
- helper = new RHNHelper(TEST_SERVER_URL, REPO_LABEL, SYSTEM_ID);
+ helper = new RHNHelper(TEST_SERVER_URL, SYSTEM_ID);
}
public void testGetPackageDetails() throws Exception {
boolean success;
try {
- List pids = helper.getChannelPackages();
- List<ContentProviderPackageDetails> pkgdetails = helper.getPackageDetails(pids);
+ List pids = helper.getChannelPackages(REPO_LABEL);
+ List<ContentProviderPackageDetails> pkgdetails = helper.getPackageDetails(pids, REPO_LABEL);
for (ContentProviderPackageDetails pkg : pkgdetails) {
assertFalse(StringUtils.isBlank(pkg.getDisplayName()));
assertFalse(StringUtils.isBlank(pkg.getArchitectureName()));
@@ -58,7 +58,7 @@ public class RHNHelperTest extends BaseRHNTest {
public void testGetChannelPackages() throws Exception {
boolean success = true;
try {
- List<String> pkgIds = helper.getChannelPackages();
+ List<String> pkgIds = helper.getChannelPackages(REPO_LABEL);
assertTrue(pkgIds.size() > 0);
} catch (Exception e) {
e.printStackTrace();
@@ -71,7 +71,7 @@ public class RHNHelperTest extends BaseRHNTest {
public void testGetSyncableKickstartTrees() throws Exception {
boolean success = true;
try {
- List<String> ksLabels = helper.getSyncableKickstartLabels();
+ List<String> ksLabels = helper.getSyncableKickstartLabels(REPO_LABEL);
assertTrue(ksLabels.size() > 0);
} catch (Exception e) {
e.printStackTrace();
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java
index 3a2f1e3..e37c38b 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java
@@ -23,9 +23,12 @@ import java.util.List;
import java.util.ArrayList;
import java.io.InputStream;
import java.io.File;
+import java.io.FileOutputStream;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails;
import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
import org.rhq.enterprise.server.plugin.pc.content.DistributionSyncReport;
@@ -72,7 +75,7 @@ public class RHNProviderTest
{
}
- public Configuration getConfiguration(String channelName) {
+ public Configuration getConfiguration() {
String certData = "";
try {
certData = FileUtils.readFileToString(new File(certLoc));
@@ -81,10 +84,10 @@ public class RHNProviderTest
e.printStackTrace();
assert false;
}
- return getConfiguration(channelName, rhnURL, certData);
+ return getConfiguration(rhnURL, certData);
}
- public Configuration getConfiguration(String channelName, String location, String certData) {
+ public Configuration getConfiguration(String location, String certData) {
Configuration config = new Configuration();
PropertySimple locProp = new PropertySimple();
locProp.setName("location");
@@ -94,10 +97,6 @@ public class RHNProviderTest
certProp.setName("certificate");
certProp.setStringValue(certData);
config.put(certProp);
- PropertySimple channelsProp = new PropertySimple();
- channelsProp.setName("SyncableChannels");
- channelsProp.setStringValue(channelName);
- config.put(channelsProp);
return config;
}
@@ -116,10 +115,11 @@ public class RHNProviderTest
String cName = "rhel-x86_64-server-5";
String rName = "openhpi-2.4.1-6.el5.1.x86_64.rpm";
RHNProvider provider = new RHNProvider();
- Configuration config = getConfiguration(cName);
+ Configuration config = getConfiguration();
try {
- provider.initializeForTest(config);
- String loc = rhnURL + "/SAT/$RHN/" + cName + "/getPackage/" + rName;
+ provider.initialize(config);
+ String loc = RHNHelper.constructPackageUrl(rhnURL, cName, rName);
+ //String loc = rhnURL + "/SAT/$RHN/" + cName + "/getPackage/" + rName;
InputStream in = provider.getInputStream(loc);
assert (in != null);
}
@@ -139,15 +139,16 @@ public class RHNProviderTest
return;
}
- String channelName = "rhn-tools-rhel-i386-server-5";
- Configuration config = getConfiguration(channelName);
+ //String channelName = "rhn-tools-rhel-i386-server-5";
+ String channelName = "rhel-i386-server-5";
+ Configuration config = getConfiguration();
RHNProvider provider = new RHNProvider();
System.out.println("testSynchronizePackages invoked");
PackageSyncReport report = new PackageSyncReport();
List<ContentProviderPackageDetails> existingPackages = new ArrayList<ContentProviderPackageDetails>();
try {
- provider.initializeForTest(config);
+ provider.initialize(config);
provider.synchronizePackages(channelName, report, existingPackages);
}
catch (Exception e) {
@@ -160,18 +161,20 @@ public class RHNProviderTest
@Test
public void testSynchronizeDistribution()
{
+
if (!isTesting) {
System.out.println("Intentionally skipping test, since property is missing: -D" + PROP_NAME_TO_TRIGGER_TEST);
return;
}
System.out.println("testSynchronizeDistribution invoked");
String channelName = "rhel-x86_64-server-5";
- DistributionSyncReport report = new DistributionSyncReport();
+ int dummyValueContentSourceId = -1;
+ DistributionSyncReport report = new DistributionSyncReport(dummyValueContentSourceId);
List<DistributionDetails> existingDistro = new ArrayList<DistributionDetails>();
RHNProvider provider = new RHNProvider();
- Configuration config = getConfiguration(channelName);
+ Configuration config = getConfiguration();
try {
- provider.initializeForTest(config);
+ provider.initialize(config);
provider.synchronizeDistribution(channelName, report, existingDistro);
}
catch (Exception e) {
@@ -189,11 +192,13 @@ public class RHNProviderTest
f.getRelativeFilename() + " , " + f.getMd5sum() + ", lastModified = " + f.getLastModified() +
", fileSize = " + f.getFileSize());
try {
- String url = rhnURL +
- RhnDownloader.getURLForKickstartFile(channelName, d.getLabel(), f.getRelativeFilename());
+ String url = RHNHelper.constructKickstartFileUrl(rhnURL, channelName, d.getLabel(),
+ f.getRelativeFilename());
InputStream in = provider.getInputStream(url);
- assert(in != null);
- //TODO: Consider mplementing read from inputStream, compare against fileSize & md5sum
+
+ String actualMd5sum = MessageDigestGenerator.getDigestString(in);
+ String expectedMd5sum = f.getMd5sum();
+ assert(StringUtils.equalsIgnoreCase(actualMd5sum, expectedMd5sum));
}
catch (Exception e) {
e.printStackTrace();
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/test/resources/test-log4j.xml b/modules/enterprise/server/plugins/rhnhosted/src/test/resources/test-log4j.xml
new file mode 100644
index 0000000..c25ccf4
--- /dev/null
+++ b/modules/enterprise/server/plugins/rhnhosted/src/test/resources/test-log4j.xml
@@ -0,0 +1,464 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE log4j:configuration PUBLIC
+ "-//log4j/log4j configuration//EN"
+ "http://logging.apache.org/log4j/docs/api/org/apache/log4j/xml/log4j.dtd">
+
+<!-- ===================================================================== -->
+<!-- RHQ Server Log4j Configuration -->
+<!-- ===================================================================== -->
+
+<!--
+ | For details on configuring Log4J, see: http://logging.apache.org/log4j/docs/
+ -->
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
+
+ <!-- ========= -->
+ <!-- Appenders -->
+ <!-- ========= -->
+
+ <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out"/>
+ <!-- Appender will not log any messages with priority lower than INFO even if the category's priority is set lower.
+ So essentially, this means DEBUG and TRACE messages will never be output to the console -->
+ <param name="Threshold" value="DEBUG"/>
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
+ </layout>
+ </appender>
+
+ <!-- a size-based rolling file appender -->
+ <appender name="FILE" class="org.jboss.logging.appender.RollingFileAppender">
+ <param name="File" value="./test-log4j.log"/>
+ <param name="Append" value="true"/>
+ <param name="MaxFileSize" value="5MB"/>
+ <param name="MaxBackupIndex" value="5"/>
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
+ </layout>
+ </appender>
+
+ <!-- ========================================= -->
+ <!-- Categories for the various RHQ subsystems -->
+ <!-- ========================================= -->
+
+ <!-- unless otherwise overridden, all org, com and net categories will be at INFO level -->
+ <category name="org">
+ <priority value="INFO"/>
+ </category>
+ <category name="com">
+ <priority value="INFO"/>
+ </category>
+ <category name="net">
+ <priority value="INFO"/>
+ </category>
+
+ <!-- this will control RHQ categories - set to DEBUG if you want full RHQ debug messages -->
+ <!--
+ <category name="org.rhq">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- details on dbsetup and dbupgrade ant tasks and their internals -->
+ <category name="org.rhq.core.db.ant">
+ <priority value="DEBUG"/>
+ </category>
+
+ <!-- details on the db setup classes used to build the database schema -->
+ <category name="org.rhq.core.db.setup">
+ <priority value="DEBUG"/>
+ </category>
+
+ <!-- details for hourly data compression job -->
+ <!--
+ <category name="org.rhq.enterprise.server.measurement.MeasurementCompressionManagerBean">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- trace commands coming in from agents -->
+ <!--
+ <category name="org.rhq.enterprise.communications.command.server.CommandProcessor">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- details on baseline calculations -->
+ <!--
+ <category name="org.rhq.enterprise.server.measurement.MeasurementBaselineManagerBean">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- details on incoming remote pojo invocations; emits concurrency limit debug messages -->
+ <!--
+ <category name="org.rhq.enterprise.communications.command.impl.remotepojo.server.RemotePojoInvocationCommandService">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- emits global concurrency limit debug messages -->
+ <!--
+ <category name="org.rhq.enterprise.communications.GlobalConcurrencyLimitCommandListener">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- details on outgoing messages; emits concurrency limit debug messages -->
+ <!--
+ <category name="org.rhq.enterprise.communications.command.client.ClientCommandSenderTask">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- details on incoming inventory reports -->
+ <!--
+ <category name="org.rhq.enterprise.server.discovery.DiscoveryBossBean">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- Logs Hibernate statistics used to help trace Hibernate queries -->
+ <!--
+ <category name="org.rhq.enterprise.server.util.HibernatePerformanceMonitor">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- Top category for the entire comm module -->
+ <!--
+ <category name="org.rhq.enterprise.communications">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- Agent plugin deployer -->
+ <!--
+ <category name="org.rhq.enterprise.server.core.plugin">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- Top category for the enterprise GUI module -->
+ <!--
+ <category name="org.rhq.enterprise.gui">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- Top category for the serializers to log synchronized access to certain subsystems -->
+ <!--
+ <category name="org.rhq.enterprise.server.util.concurrent">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- INFO level gives full stacks to all threads active in aborted transactions -->
+ <!-- Set to WARN to only log these events with single-line messages -->
+ <category name="org.rhq.enterprise.server.common.TransactionInterruptInterceptor">
+ <priority value="INFO"/>
+ </category>
+
+ <!-- Setting the status manager bean to DEBUG would allow you to see specific status bits -->
+ <!-- DEBUG also has a negative impact on database performance -->
+ <category name="org.rhq.enterprise.server.cloud.StatusManagerBean">
+ <priority value="INFO" />
+ </category>
+
+ <!-- Top category for the server-side code, including SLSBs -->
+ <!--
+ <category name="org.rhq.enterprise.server">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!--
+ <category name="org.rhq.enterprise.server.alert">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!--
+ <category name="org.rhq.enterprise.server.authz">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!--
+ <category name="org.rhq.enterprise.server.cloud">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!--
+ <category name="org.rhq.enterprise.server.configuration">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <category name="org.rhq.enterprise.server.content">
+ <priority value="DEBUG"/>
+ </category>
+
+ <category name="org.rhq.enterprise.server.plugin.pc.content">
+ <priority value="DEBUG"/>
+ </category>
+
+ <category name="org.rhq.enterprise.server.plugins.rhnhosted">
+ <priority value="DEBUG"/>
+ </category>
+
+ <!--
+ <category name="org.rhq.enterprise.server.core">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!--
+ <category name="org.rhq.enterprise.server.discovery">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!--
+ <category name="org.rhq.enterprise.server.event">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!--
+ <category name="org.rhq.enterprise.server.measurement">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!--
+ <category name="org.rhq.enterprise.server.operation">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!--
+ <category name="org.rhq.enterprise.server.plugin">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!--
+ <category name="org.rhq.enterprise.server.resource">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!--
+ <category name="org.rhq.enterprise.server.scheduler">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!--
+ <category name="org.rhq.enterprise.server.system">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!--
+ <category name="org.rhq.enterprise.server.util">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- ============================================= -->
+ <!-- Categories for the various JBossAS subsystems -->
+ <!-- ============================================= -->
+
+ <category name="org.jboss.ejb.EJBDeployer.verifier">
+ <priority value="OFF"/>
+ </category>
+
+ <category name="org.hibernate.ejb.Ejb3Configuration">
+ <priority value="WARN"/>
+ </category>
+
+ <category name="org.jboss.ejb3.JmxKernelAbstraction">
+ <priority value="WARN"/>
+ </category>
+
+ <category name="org.jboss.ejb3.EJBContainer">
+ <priority value="WARN"/>
+ </category>
+
+ <category name="org.jboss.resource.deployment.RARDeployment">
+ <priority value="WARN"/>
+ </category>
+
+ <category name="org.jgroups">
+ <priority value="WARN"/>
+ </category>
+
+ <category name="jacorb">
+ <priority value="WARN"/>
+ </category>
+
+ <category name="org.hibernate.cfg">
+ <priority value="WARN"/>
+ </category>
+
+ <!-- JBNADM-2090: suppress warnings -->
+ <category name="org.hibernate.engine.loading.LoadContexts">
+ <priority value="OFF"/>
+ </category>
+
+ <!-- Suppress heavy ERROR level logging generated due to EJB3SafeEndpointInvoker, which unavoidably
+ forces this exception, Hibernate has no workaround. -->
+ <category name="org.hibernate.LazyInitializationException">
+ <priority value="OFF"/>
+ </category>
+
+ <!-- log SQL statements -->
+ <!--
+ <category name="org.hibernate.SQL">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!-- log JDBC bind parameters -->
+ <!--
+ <category name="org.hibernate.type">
+ <priority value="INFO"/>
+ </category>
+ -->
+
+ <!-- Show the evolution of the DataSource pool in the logs [inUse/Available/Max]
+ <category name="org.jboss.resource.connectionmanager.JBossManagedConnectionPool">
+ <priority value="TRACE" class="org.jboss.logging.XLevel"/>
+ </category>
+ -->
+
+ <!-- Increase the priority threshold for the RHQ Datasource category
+ Useful for debugging connection leaks
+ -->
+ <!--
+ <category name="RHQDS">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+ <!--
+ <category name="NoTxRHQDS">
+ <priority value="DEBUG"/>
+ </category>
+ -->
+
+ <!--
+ | An example of enabling the custom TRACE level priority that is used
+ | by the JBoss internals to diagnose low level details. This example
+ | turns on TRACE level msgs for the org.jboss.ejb.plugins package and its
+ | subpackages. This will produce A LOT of logging output.
+ <category name="org.jboss.system">
+ <priority value="TRACE" class="org.jboss.logging.XLevel"/>
+ </category>
+ <category name="org.jboss.ejb.plugins">
+ <priority value="TRACE" class="org.jboss.logging.XLevel"/>
+ </category>
+ -->
+
+ <!-- Clustering logging -->
+ <!-- Uncomment the following to redirect the org.jgroups and
+ org.jboss.ha categories to a cluster.log file.
+
+ <appender name="CLUSTER" class="org.jboss.logging.appender.RollingFileAppender">
+ <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
+ <param name="File" value="${jboss.server.log.dir}/cluster.log"/>
+ <param name="Append" value="false"/>
+ <param name="MaxFileSize" value="500KB"/>
+ <param name="MaxBackupIndex" value="1"/>
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%d %-5p [%c] %m%n"/>
+ </layout>
+ </appender>
+ <category name="org.jgroups">
+ <priority value="DEBUG" />
+ <appender-ref ref="CLUSTER"/>
+ </category>
+ <category name="org.jboss.ha">
+ <priority value="DEBUG" />
+ <appender-ref ref="CLUSTER"/>
+ </category>
+ -->
+
+ <!-- JSF RI (i.e. com.sun.faces.*) -->
+ <category name="javax.enterprise.resource.webcontainer.jsf.application">
+ <priority value="WARN" />
+ </category>
+ <category name="javax.enterprise.resource.webcontainer.jsf.config">
+ <priority value="WARN" />
+ </category>
+ <category name="javax.enterprise.resource.webcontainer.jsf.context">
+ <priority value="WARN" />
+ </category>
+ <category name="javax.enterprise.resource.webcontainer.jsf.lifecycle">
+ <priority value="WARN" />
+ </category>
+ <category name="javax.enterprise.resource.webcontainer.jsf.managedbean">
+ <priority value="WARN" />
+ </category>
+ <category name="javax.enterprise.resource.webcontainer.jsf.renderkit">
+ <priority value="WARN" />
+ </category>
+ <category name="javax.enterprise.resource.webcontainer.jsf.taglib">
+ <priority value="WARN" />
+ </category>
+ <category name="javax.enterprise.resource.webcontainer.jsf.timing">
+ <priority value="WARN" />
+ </category>
+
+ <!-- ===================================================== -->
+ <!-- Categories for the various 3rd-party libs used by RHQ -->
+ <!-- ===================================================== -->
+
+ <category name="org.quartz.impl.jdbcjobstore.JobStoreCMT">
+ <priority value="WARN"/>
+ </category>
+
+ <category name="org.quartz.impl.jdbcjobstore.StdRowLockSemaphore">
+ <priority value="ERROR"/>
+ </category>
+
+ <category name="org.apache.commons.validator.ValidatorResources">
+ <priority value="OFF"/>
+ </category>
+
+ <category name="org.apache.struts">
+ <priority value="ERROR"/>
+ </category>
+
+ <category name="org.apache.commons.httpclient">
+ <priority value="ERROR"/>
+ </category>
+
+ <category name="org.ajax4jsf">
+ <priority value="WARN"/>
+ </category>
+
+ <category name="org.jboss.seam">
+ <priority value="WARN"/>
+ </category>
+
+ <!-- ================= -->
+ <!-- The root category -->
+ <!-- ================= -->
+
+ <root>
+ <!-- default log priority -->
+ <priority value="INFO"/>
+
+ <appender-ref ref="CONSOLE"/>
+ <appender-ref ref="FILE"/>
+ </root>
+
+</log4j:configuration>
commit 54be28c6e9a2cea64b3896b4d571ba9a5ef84a92
Author: John Matthews <jmatthew(a)redhat.com>
Date: Sun Nov 15 12:59:52 2009 -0500
dos2unix on pom.xml for rhnhosted plugin
diff --git a/modules/enterprise/server/plugins/rhnhosted/pom.xml b/modules/enterprise/server/plugins/rhnhosted/pom.xml
index 8ff4be6..73d6596 100644
--- a/modules/enterprise/server/plugins/rhnhosted/pom.xml
+++ b/modules/enterprise/server/plugins/rhnhosted/pom.xml
@@ -1,140 +1,140 @@
-<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-enterprise-server-plugins-parent</artifactId>
- <version>1.4.0-SNAPSHOT</version>
- </parent>
-
- <groupId>org.rhq</groupId>
- <artifactId>rhq-serverplugin-rhnhosted</artifactId>
- <packaging>jar</packaging>
-
- <name>RHQ Enterprise Server RHN Hosted Plugin</name>
- <description>Provides ability to communicate with RHN Hosted</description>
-
- <scm>
- <connection>scm:svn:http://svn.rhq-project.org/repos/rhq/trunk/modules/enterprise/ser...</connection>
- <developerConnection>scm:svn:http://svn.rhq-project.org/repos/rhq/trunk/modules/enterprise/ser...</developerConnection>
- </scm>
-
- <properties>
- <scm.module.path>modules/enterprise/server/plugins/rhnhosted/</scm.module.path>
- </properties>
-
- <dependencies>
-
- <!-- Internal Deps -->
-
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-core-domain</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
-
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-core-client-api</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
-
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-enterprise-server</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
-
- <!-- 3rd Party Deps -->
-
- <!-- 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>javax.persistence</groupId>
- <artifactId>persistence-api</artifactId>
- <version>1.0</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>
- <!-- needed for referenced domain entities that use Hibernate annotations -->
- </dependency>
-
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>1.4</version>
- </dependency>
-
- <dependency>
- <groupId>commons-beanutils</groupId>
- <artifactId>commons-beanutils</artifactId>
- <version>1.8.0</version>
- </dependency>
- <dependency>
- <groupId>commons-lang</groupId>
- <artifactId>commons-lang</artifactId>
- <version>2.4</version>
- </dependency>
-
- <!-- Bouncy Castle -->
- <dependency>
- <groupId>bouncycastle</groupId>
- <artifactId>bcprov-jdk15</artifactId>
- <version>140</version>
- </dependency>
-
- <dependency>
- <groupId>bouncycastle</groupId>
- <artifactId>bcpg-jdk15</artifactId>
- <version>140</version>
- </dependency>
-
- <!-- Apache WS XMLRPC -->
- <dependency>
- <groupId>org.apache.xmlrpc</groupId>
- <artifactId>xmlrpc-client</artifactId>
- <version>3.1.2</version>
- </dependency>
- <dependency>
- <groupId>org.apache.xmlrpc</groupId>
- <artifactId>xmlrpc-common</artifactId>
- <version>3.1.2</version>
- </dependency>
-
- <!-- JAXB -->
- <dependency>
- <groupId>javax.xml.bind</groupId>
- <artifactId>jaxb-api</artifactId>
- <version>2.1</version>
- </dependency>
-
- <dependency>
- <groupId>com.sun.xml.bind</groupId>
- <artifactId>jaxb-impl</artifactId>
- <version>2.1.3</version>
- </dependency>
- </dependencies>
-
-
- <build>
- <plugins>
-
- <plugin>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
- <!--
- <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
- -->
+<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-enterprise-server-plugins-parent</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-serverplugin-rhnhosted</artifactId>
+ <packaging>jar</packaging>
+
+ <name>RHQ Enterprise Server RHN Hosted Plugin</name>
+ <description>Provides ability to communicate with RHN Hosted</description>
+
+ <scm>
+ <connection>scm:svn:http://svn.rhq-project.org/repos/rhq/trunk/modules/enterprise/ser...</connection>
+ <developerConnection>scm:svn:http://svn.rhq-project.org/repos/rhq/trunk/modules/enterprise/ser...</developerConnection>
+ </scm>
+
+ <properties>
+ <scm.module.path>modules/enterprise/server/plugins/rhnhosted/</scm.module.path>
+ </properties>
+
+ <dependencies>
+
+ <!-- Internal Deps -->
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-domain</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-core-client-api</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-server</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- 3rd Party Deps -->
+
+ <!-- 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>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ <version>1.0</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>
+ <!-- needed for referenced domain entities that use Hibernate annotations -->
+ </dependency>
+
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>1.4</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-beanutils</groupId>
+ <artifactId>commons-beanutils</artifactId>
+ <version>1.8.0</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.4</version>
+ </dependency>
+
+ <!-- Bouncy Castle -->
+ <dependency>
+ <groupId>bouncycastle</groupId>
+ <artifactId>bcprov-jdk15</artifactId>
+ <version>140</version>
+ </dependency>
+
+ <dependency>
+ <groupId>bouncycastle</groupId>
+ <artifactId>bcpg-jdk15</artifactId>
+ <version>140</version>
+ </dependency>
+
+ <!-- Apache WS XMLRPC -->
+ <dependency>
+ <groupId>org.apache.xmlrpc</groupId>
+ <artifactId>xmlrpc-client</artifactId>
+ <version>3.1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.xmlrpc</groupId>
+ <artifactId>xmlrpc-common</artifactId>
+ <version>3.1.2</version>
+ </dependency>
+
+ <!-- JAXB -->
+ <dependency>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ <version>2.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-impl</artifactId>
+ <version>2.1.3</version>
+ </dependency>
+ </dependencies>
+
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+ <!--
+ <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ -->
<systemProperties>
<property>
<!--
@@ -146,103 +146,103 @@
<value>false</value>
</property>
</systemProperties>
- </configuration>
- </plugin>
-
- <plugin>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>copy-dependencies</id>
- <phase>package</phase>
- <goals>
- <goal>copy-dependencies</goal>
- </goals>
- <configuration>
- <includeScope>runtime</includeScope>
- <excludeTransitive>false</excludeTransitive>
- <outputDirectory>${project.build.outputDirectory}/lib</outputDirectory>
- </configuration>
- </execution>
- </executions>
- </plugin>
-
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>jaxb2-maven-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>xjc</goal>
- </goals>
- </execution>
- </executions>
- <configuration>
- <packageName>org.rhq.enterprise.server.plugins.rhnhosted.xml</packageName>
- <outputDirectory>${project.build.outputDirectory}/generated-source</outputDirectory>
- </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}/rhq-serverplugins</rhq.deploymentDir>
- </properties>
-
- <build>
- <plugins>
-
- <plugin>
- <artifactId>maven-antrun-plugin</artifactId>
- <version>1.1</version>
- <executions>
-
- <execution>
- <id>deploy</id>
- <phase>package</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>
-
- </profiles>
-
-</project>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <includeScope>runtime</includeScope>
+ <excludeTransitive>false</excludeTransitive>
+ <outputDirectory>${project.build.outputDirectory}/lib</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>jaxb2-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>xjc</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <packageName>org.rhq.enterprise.server.plugins.rhnhosted.xml</packageName>
+ <outputDirectory>${project.build.outputDirectory}/generated-source</outputDirectory>
+ </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}/rhq-serverplugins</rhq.deploymentDir>
+ </properties>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.1</version>
+ <executions>
+
+ <execution>
+ <id>deploy</id>
+ <phase>package</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>
+
+ </profiles>
+
+</project>
commit 02788c9602e3edc24ec0f443a37b95e3c6216c61
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 16 00:09:40 2009 -0500
put boolean in quartz data map as string
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index 057f7c8..f6ed889 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -275,7 +275,7 @@ public abstract class AbstractTypeServerPluginContainer {
jobData.put(AbstractJobWrapper.DATAMAP_JOB_ID, schedule.getJobId());
jobData.put(AbstractJobWrapper.DATAMAP_SCHEDULE_TYPE, schedule.getScheduleType().getTypeName());
jobData.put(AbstractJobWrapper.DATAMAP_SCHEDULE_TRIGGER, schedule.getScheduleType().getScheduleTrigger());
- jobData.put(AbstractJobWrapper.DATAMAP_IS_CONCURRENT, schedule.getScheduleType().isConcurrent());
+ jobData.putAsString(AbstractJobWrapper.DATAMAP_IS_CONCURRENT, schedule.getScheduleType().isConcurrent());
jobData.put(AbstractJobWrapper.DATAMAP_JOB_METHOD_NAME, schedule.getMethodName());
if (schedule.getClassName() != null) {
jobData.put(AbstractJobWrapper.DATAMAP_JOB_CLASS, schedule.getClassName());
commit e339f4cf55d5dc497f857587a346c84b6dc9bcde
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 15 23:53:55 2009 -0500
get test to pass
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
index a9c0ee4..1dace0b 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
@@ -65,7 +65,7 @@ public class GenericServerPluginTest extends AbstractEJB3Test {
TestGenericServerPluginContainer pc = this.pluginService.genericPC;
assert pc.state == State.STARTED;
TestGenericPluginManager pm = (TestGenericPluginManager) pc.getPluginManager();
- TestLifecycleListener component = (TestLifecycleListener) pm.listeners.values().iterator().next();
+ TestLifecycleListener component = (TestLifecycleListener) pm.components.values().iterator().next();
assert component.state == LifecycleState.STARTED;
// make sure the context is correct
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
index fcdf743..b1888f4 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
@@ -28,8 +28,8 @@ import java.util.Map;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
-import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
import org.rhq.enterprise.server.plugin.pc.ServerPluginManager;
import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
@@ -154,19 +154,19 @@ public class TestGenericServerPluginService extends ServerPluginService implemen
* The test plugin manager.
*/
class TestGenericPluginManager extends ServerPluginManager {
- public final Map<String, ServerPluginComponent> listeners;
+ public final Map<String, ServerPluginComponent> components;
public TestGenericPluginManager(TestGenericServerPluginContainer pc) {
super(pc);
- listeners = new HashMap<String, ServerPluginComponent>();
+ components = new HashMap<String, ServerPluginComponent>();
}
@Override
protected ServerPluginComponent createServerPluginComponent(ServerPluginEnvironment environment)
throws Exception {
- ServerPluginComponent listener = super.createServerPluginComponent(environment);
- listeners.put(environment.getPluginName(), listener);
- return listener;
+ ServerPluginComponent component = super.createServerPluginComponent(environment);
+ components.put(environment.getPluginName(), component);
+ return component;
}
}
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml b/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml
index 26a2646..5044d16 100644
--- a/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml
+++ b/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml
@@ -9,8 +9,7 @@
xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
xmlns:c="urn:xmlns:rhq-configuration">
- <serverplugin:plugin-component class="org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener">
- </serverplugin:plugin-component>
+ <serverplugin:plugin-component class="org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener"></serverplugin:plugin-component>
<serverplugin:plugin-configuration>
<c:simple-property name="plugin-simple-prop-1" defaultValue="prop1value" required="true" />
diff --git a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
index a378f2b..6445aab 100644
--- a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
+++ b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
@@ -64,11 +64,11 @@
Whether the method name is defined by the map name itself or the optional
"methodName" simple property, the method signature must be either
a no-arg signature or one that has a single argument of type
- ScheduledJobInvocationContext.
+ ScheduledJobInvocationContext.
2) has simple properties called "scheduleType" and "scheduleTrigger" where
"scheduleType" is either "cron" or "periodic" and "scheduleTrigger" is either
the cron expression or a time period in milliseconds.
- 3) has a simple property called "concurrent" of type boolean to indicate if
+ 3) has a simple property called "concurrent" of type boolean to indicate if
multiple invocations of the scheduled job are allowed to
occur at the same time. If false, only one invocation will ever run at any
one time. This means that if a schedule triggers again while the previous
@@ -81,7 +81,7 @@
name of class to be instantiated as the target of the job invocation.
If not defined, the target of the job invocation is the stateful plugin component
itself. Whatever class is used as the target, it must have a method as defined
- in the method name simple property as explained above.
+ in the method name simple property as explained above.
Typically, plugin developers don't use this class property because you normally
want to target the stateful plugin component; however, this class property provides
the plugin developer a way to declare stateless jobs if that is needed.
@@ -155,6 +155,7 @@
</xs:complexType>
<xs:complexType name="ServerPluginComponentType">
+ <xs:sequence></xs:sequence>
<xs:attribute name="class" type="serverplugin:classNameType" use="required">
<xs:annotation>
<xs:documentation>
@@ -162,7 +163,7 @@
instance will be notified when the plugin is started, stopped or when schedules are triggered.
</xs:documentation>
</xs:annotation>
- </xs:attribute>
+ </xs:attribute>
</xs:complexType>
<xs:simpleType name="classNameType">
commit 552d1df3772b50f7637cf270ebd431aaffba0b4e
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Sun Nov 15 16:46:32 2009 -0800
582 - fixing bug in status reporting where we showed failed
we showed FAILED if any CS failed in the past. Now we only
care about the most recent.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
index 9a57ba8..a513a60 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
@@ -24,6 +24,9 @@ package org.rhq.core.domain.content;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -291,10 +294,24 @@ public class ContentSource implements Serializable {
}
/**
- * The list of sync results; should be ordered with the latest results first in the list, but this is not
+ * The list of sync results; ordered with the latest results first in the list guaranteed.
* guaranteed.
*/
public List<ContentSourceSyncResults> getSyncResults() {
+
+ Comparator dc = new Comparator() {
+ @Override
+ public int compare(Object arg0, Object arg1) {
+ ContentSourceSyncResults c1 = (ContentSourceSyncResults) arg0;
+ ContentSourceSyncResults c2 = (ContentSourceSyncResults) arg1;
+ Date d1 = new Date(c1.getEndTime());
+ Date d2 = new Date(c2.getEndTime());
+ return d1.compareTo(d2);
+ }
+ };
+
+ Collections.sort(syncResults, dc);
+
return syncResults;
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSourceSyncStatus.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSourceSyncStatus.java
index ef249c1..e304a41 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSourceSyncStatus.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSourceSyncStatus.java
@@ -1,27 +1,27 @@
- /*
- * 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.
- */
+/*
+ * 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.content;
public enum ContentSourceSyncStatus {
- INPROGRESS, SUCCESS, FAILURE
+ INPROGRESS, SUCCESS, FAILURE, NONE
}
\ 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 bb83c94..58ec4de 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
@@ -40,7 +40,6 @@ import org.jboss.annotation.IgnoreDependency;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.content.ContentSource;
-import org.rhq.core.domain.content.ContentSourceSyncResults;
import org.rhq.core.domain.content.ContentSourceSyncStatus;
import org.rhq.core.domain.content.Distribution;
import org.rhq.core.domain.content.PackageVersion;
@@ -882,9 +881,11 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
Iterator<ContentSource> i = contentSources.iterator();
while (i.hasNext()) {
ContentSource cs = i.next();
- List<ContentSourceSyncResults> results = cs.getSyncResults();
- for (ContentSourceSyncResults result : results) {
- stati.add(result.getStatus());
+ // Add the most recent sync results status
+ if (cs.getSyncResults() != null && cs.getSyncResults().get(0) != null) {
+ stati.add(cs.getSyncResults().get(0).getStatus());
+ } else {
+ stati.add(ContentSourceSyncStatus.NONE);
}
}
if (stati.contains(ContentSourceSyncStatus.FAILURE)) {
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
index 36e0943..0a8c80f 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
@@ -19,6 +19,8 @@
package org.rhq.enterprise.server.content.test;
import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
@@ -101,25 +103,19 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
@Test(enabled = ENABLED)
public void testSyncRepos() throws Exception {
- try {
- Repo repo = new Repo("testSyncStatus");
- repoManager.createRepo(overlord, repo);
- Integer[] ids = { repo.getId() };
- int syncCount = repoManager.synchronizeRepos(overlord, ids);
-
- assert syncCount == 0;
-
- ContentSourceType cst = new ContentSourceType("testSyncStatus");
- ContentSource cs = new ContentSource("testSyncStatus", cst);
- repo.addContentSource(cs);
- syncCount = repoManager.synchronizeRepos(overlord, ids);
-
- assert syncCount == 1;
- } catch (Throwable t) {
- System.out.println("ERROR: " + t);
- t.printStackTrace();
- }
+ Repo repo = new Repo("testSyncStatus");
+ repoManager.createRepo(overlord, repo);
+ Integer[] ids = { repo.getId() };
+ int syncCount = repoManager.synchronizeRepos(overlord, ids);
+ assert syncCount == 0;
+
+ ContentSourceType cst = new ContentSourceType("testSyncStatus");
+ ContentSource cs = new ContentSource("testSyncStatus", cst);
+ repo.addContentSource(cs);
+ syncCount = repoManager.synchronizeRepos(overlord, ids);
+
+ assert syncCount == 1;
}
@Test(enabled = ENABLED)
@@ -127,23 +123,41 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
Repo repo = new Repo("testSyncStatus");
repoManager.createRepo(overlord, repo).getId();
+ Calendar cal = Calendar.getInstance();
+
ContentSourceType cst = new ContentSourceType("testSyncStatus");
ContentSource cs = new ContentSource("testSyncStatus", cst);
- ContentSourceSyncResults results = new ContentSourceSyncResults(cs);
- repo.addContentSource(cs);
-
EntityManager em = getEntityManager();
em.persist(cst);
em.persist(cs);
- em.persist(results);
- cs.addSyncResult(results);
+
+ for (int i = 0; i < 10; i++) {
+ cal.roll(Calendar.DATE, false);
+ ContentSourceSyncResults results = new ContentSourceSyncResults(cs);
+ if (i % 2 == 0 && i != 0) {
+ System.out.println("Setting failed: i: [" + i + "]");
+ results.setStatus(ContentSourceSyncStatus.FAILURE);
+ } else {
+ results.setStatus(ContentSourceSyncStatus.SUCCESS);
+ }
+
+ results.setEndTime(cal.getTimeInMillis());
+ System.out.println("EndTime: " + new Date(results.getEndTime().longValue()));
+ em.persist(results);
+ cs.addSyncResult(results);
+ }
+ repo.addContentSource(cs);
+
em.flush();
em.close();
// Check sync status
+ cs.getSyncResults();
+ for (ContentSourceSyncResults r : cs.getSyncResults()) {
+ System.out.println("R: " + new Date(r.getEndTime().longValue()) + " s: " + r.getStatus());
+ }
String status = repoManager.calculateSyncStatus(overlord, repo.getId());
- assert status.equals(ContentSourceSyncStatus.INPROGRESS.toString());
-
+ assert status.equals(ContentSourceSyncStatus.SUCCESS.toString());
}
@Test(enabled = ENABLED)
commit 7d8a77e61b12bd1c776ac2514e688e852e0ec309
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 15 19:40:07 2009 -0500
remove erroneous usage of seam class in javadoc
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
index 7ab8444..9b3d64d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -29,8 +29,6 @@ import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
-import org.jboss.seam.async.Schedule;
-
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.AbstractScheduleType;
@@ -64,7 +62,7 @@ abstract class AbstractJobWrapper implements Job {
/**
* Key to the job data map that indicates the ID of the job.
* This ID is passed to the plugin container when the job was scheduled, see:
- * {@link AbstractTypeServerPluginContainer#scheduleJob(Schedule, String, String, ScheduledJob, java.util.Properties)}
+ * {@link AbstractTypeServerPluginContainer#scheduleJob(ScheduledJobDefinition, String)}
*/
public static final String DATAMAP_JOB_ID = DATAMAP_LEADER + "jobId";
commit 2ce459fdee6b6a3f60b4eb4e12d717b2d81afd06
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 15 19:16:04 2009 -0500
finalize the coding to the new way we declare schedules
diff --git a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
index 7141a89..b88d338 100644
--- a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -38,6 +38,16 @@
<c:simple-property name="anothercustom2" type="long" required="true" default="12345" summary="true" description="A custom long for callback data"/>
</c:map-property>
+ <c:map-property name="statelessJob1" description="invokes a stateless job class but given a job context">
+ <c:simple-property name="class" type="string" required="true" readOnly="true" default="MyScheduledJob" summary="true" />
+ <c:simple-property name="methodName" type="string" required="true" readOnly="true" default="executeWithContext" summary="true" />
+ </c:map-property>
+
+ <c:map-property name="statelessJob2" description="invokes a stateless job class no-arg method">
+ <c:simple-property name="class" type="string" required="true" readOnly="true" default="MyScheduledJob" summary="true" />
+ <c:simple-property name="methodName" type="string" required="true" readOnly="true" default="executeNoArg" summary="true" />
+ </c:map-property>
+
<c:list-property name="myUserDefinedJobs" description="A list of user-defined scheduled jobs">
<c:map-property name="myUserDefinedJob" description="A user-defined scheduled job">
<c:simple-property name="methodName" type="string" required="true" default="" summary="true" description="The method to call on the plugin component when the schedule triggers" />
@@ -56,7 +66,7 @@
<!-- custom global config - unrelated to schedules -->
<serverplugin:plugin-configuration>
- <c:simple-property name="myCustomProperty" type="string" required="true"
+ <c:simple-property name="myCustomProperty" type="string" required="true" default="custom-prop-value"
description="A property my plugin needs to be properly configured" />
</serverplugin:plugin-configuration>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
index d18ffed..7ab8444 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -33,6 +33,8 @@ import org.jboss.seam.async.Schedule;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.xmlschema.AbstractScheduleType;
+import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
/**
* The superclass to the concurrent and stateful job wrappers.
@@ -79,6 +81,26 @@ abstract class AbstractJobWrapper implements Job {
public static final String DATAMAP_JOB_METHOD_NAME = DATAMAP_LEADER + "jobMethodName";
/**
+ * Key to the job data map that indicates what kind of schedule triggered the job
+ */
+ public static final String DATAMAP_SCHEDULE_TYPE = DATAMAP_LEADER + "scheduleType";
+
+ /**
+ * Key to the job data map that indicates how the schedule is triggered.
+ * The value of the trigger datamap entry depends on the {@link #DATAMAP_SCHEDULE_TYPE type of schedule}.
+ * For example, a cron schedule type has a schedule trigger that is a cron expression.
+ * A periodic schedule type has a schedule trigger that is a time period, in milliseconds.
+ */
+ public static final String DATAMAP_SCHEDULE_TRIGGER = DATAMAP_LEADER + "scheduleTrigger";
+
+ /**
+ * Key to the job data map that indicates if the job is concurrent or not. The
+ * value does not necessarily mean any currently executing job is concurrently running
+ * with another; this just indicates if the job is allowed to run concurrently with another.
+ */
+ public static final String DATAMAP_IS_CONCURRENT = DATAMAP_LEADER + "isConcurrent";
+
+ /**
* This is the method that quartz calls when the schedule has triggered. This method will
* delegate to the plugin component that is responsible to do work for the plugin.
*
@@ -95,6 +117,23 @@ abstract class AbstractJobWrapper implements Job {
String jobId = dataMap.getString(DATAMAP_JOB_ID);
String jobClass = dataMap.getString(DATAMAP_JOB_CLASS);
String jobMethodName = dataMap.getString(DATAMAP_JOB_METHOD_NAME);
+ boolean isConcurrent = Boolean.parseBoolean(dataMap.getString(DATAMAP_IS_CONCURRENT));
+ String scheduleTypeStr = dataMap.getString(DATAMAP_SCHEDULE_TYPE);
+ String scheduleTrigger = dataMap.getString(DATAMAP_SCHEDULE_TRIGGER);
+
+ // verify the datamap has all the things we require
+ if (pluginName == null) {
+ throwJobExecutionException(pluginName, pluginTypeString, jobId, "Datamap missing plugin name", null);
+ }
+ if (pluginTypeString == null) {
+ throwJobExecutionException(pluginName, pluginTypeString, jobId, "Datamap missing plugin type", null);
+ }
+ if (jobId == null) {
+ throwJobExecutionException(pluginName, pluginTypeString, jobId, "Datamap missing job ID", null);
+ }
+ if (jobMethodName == null) {
+ throwJobExecutionException(pluginName, pluginTypeString, jobId, "Datamap missing method name", null);
+ }
// obtain the plugin's own callback data from the datamap
Properties callbackData = new Properties();
@@ -105,65 +144,72 @@ abstract class AbstractJobWrapper implements Job {
}
// determine what type of plugin is being triggered
- ServerPluginType pluginType;
+ ServerPluginType pluginType = null;
try {
pluginType = new ServerPluginType(pluginTypeString);
} catch (Throwable t) {
// datamap has an invalid plugin type string - we need to unschedule this, do not refire
- log.error(logMsg(pluginName, pluginTypeString, jobId, "Datamap had invalid plugin type string", t));
- JobExecutionException jobException = new JobExecutionException(t, false);
- jobException.setUnscheduleFiringTrigger(true);
- throw jobException;
+ throwJobExecutionException(pluginName, pluginTypeString, jobId, "Datamap had invalid plugin type string", t);
}
// determine which plugin component class will be invoked to perform the work of the job
MasterServerPluginContainer mpc = LookupUtil.getServerPluginService().getMasterPluginContainer();
AbstractTypeServerPluginContainer pc = mpc.getPluginContainerByPluginType(pluginType);
- Object pluginJobObject;
+ Object pluginJobObject = null;
ServerPluginManager pluginManager = pc.getPluginManager();
ServerPluginEnvironment pluginEnv = pluginManager.getPluginEnvironment(pluginName);
- ServerPluginComponent pluginComponent = pluginManager.getServerPluginComponent(pluginName);
+
+ if (pluginEnv == null) {
+ throwJobExecutionException(pluginName, pluginType, jobId, "missing environment for plugin [" + pluginName
+ + "]", null);
+ }
if (jobClass == null) {
- pluginJobObject = pluginComponent;
+ // null classname means use the stateful plugin component as the target object
+ pluginJobObject = pluginManager.getServerPluginComponent(pluginName);
if (pluginJobObject == null) {
- JobExecutionException jobException = new JobExecutionException(logMsg(pluginName, pluginType, jobId,
- "no plugin component to process job", null), false);
- jobException.setUnscheduleAllTriggers(true);
- throw jobException;
+ throwJobExecutionException(pluginName, pluginType, jobId, "no plugin component to process job", null);
}
} else {
try {
pluginJobObject = pluginManager.instantiatePluginClass(pluginEnv, jobClass);
} catch (Throwable t) {
// invalid class - we need to unschedule this, do not refire since it will never work
- log.error(logMsg(pluginName, pluginType, jobId, "bad schedule job class [" + jobClass + "]", t));
- JobExecutionException jobException = new JobExecutionException(t, false);
- jobException.setUnscheduleAllTriggers(true);
- throw jobException;
+ throwJobExecutionException(pluginName, pluginType, jobId, "bad job class [" + jobClass + "]", t);
}
}
// try to find the method to invoke - first, see if the method exists with a parameter
// that is the type of our job invocation context. Otherwise, rely on a no-arg method.
- Method jobMethod;
- Object[] params;
+ Method jobMethod = null;
+ Object[] params = null;
try {
jobMethod = pluginJobObject.getClass().getMethod(jobMethodName, ScheduledJobInvocationContext.class);
params = new Object[1];
- // params[0] = new ScheduledJobInvocationContext(jobDefinition, pluginContext);
+
+ AbstractScheduleType scheduleType = AbstractScheduleType.create(isConcurrent, scheduleTypeStr,
+ scheduleTrigger);
+ if (scheduleType == null) {
+ // how is this possible that we got bad schedule data in the datamap? this isn't fatal, just log it and leave it null
+ log.warn(logMsg(pluginName, pluginType, jobId, "ignoring bad schedule type found in data map ["
+ + scheduleTypeStr + "]", null));
+ }
+
+ ScheduledJobDefinition jobDefinition = new ScheduledJobDefinition(jobId, true, jobClass, jobMethodName,
+ scheduleType, callbackData);
+ ServerPluginContext pluginContext = pluginManager.getServerPluginContext(pluginEnv);
+ params[0] = new ScheduledJobInvocationContext(jobDefinition, pluginContext);
} catch (NoSuchMethodException e) {
try {
+ // see if there is a no-arg method of the given name
jobMethod = pluginJobObject.getClass().getMethod(jobMethodName);
params = null;
} catch (Throwable t) {
// invalid method - we need to unschedule this, do not refire since it will never work
- log.error(logMsg(pluginName, pluginType, jobId, "bad schedule job method [" + jobMethodName + "]", t));
- JobExecutionException jobException = new JobExecutionException(t, false);
- jobException.setUnscheduleAllTriggers(true);
- throw jobException;
+ throwJobExecutionException(pluginName, pluginType, jobId, "bad schedule job method [" + jobMethodName
+ + "]", t);
}
}
@@ -179,15 +225,27 @@ abstract class AbstractJobWrapper implements Job {
log.info(logMsg(pluginName, pluginType, jobId, "scheduled job executed", null));
} catch (Throwable t) {
// any exception thrown out of the job will mean the job is to be unscheduled
- log.error(logMsg(pluginName, pluginType, jobId, "job threw exception, unscheduling it", t));
- JobExecutionException jobException = new JobExecutionException(t, false);
- jobException.setUnscheduleFiringTrigger(true);
- throw jobException;
+ throwJobExecutionException(pluginName, pluginType, jobId, "job threw exception, unscheduling it", t);
}
return;
}
+ protected void throwJobExecutionException(String pluginName, Object pluginType, String jobId, String errorMsg,
+ Throwable t) throws JobExecutionException {
+
+ log.error(logMsg(pluginName, pluginType, jobId, errorMsg, t));
+
+ JobExecutionException jobException;
+ if (t != null) {
+ jobException = new JobExecutionException(t, false);
+ } else {
+ jobException = new JobExecutionException(false);
+ }
+ jobException.setUnscheduleFiringTrigger(true);
+ throw jobException;
+ }
+
protected String logMsg(String pluginName, Object pluginType, String jobId, String msg, Throwable t) {
String s = "Plugin [" + pluginName + "], type=[" + pluginType + "], jobId=[" + jobId + "]: " + msg;
if (t != null) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index 19910d8..057f7c8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -273,6 +273,9 @@ public abstract class AbstractTypeServerPluginContainer {
jobData.put(AbstractJobWrapper.DATAMAP_PLUGIN_NAME, pluginName);
jobData.put(AbstractJobWrapper.DATAMAP_PLUGIN_TYPE, getSupportedServerPluginType().stringify());
jobData.put(AbstractJobWrapper.DATAMAP_JOB_ID, schedule.getJobId());
+ jobData.put(AbstractJobWrapper.DATAMAP_SCHEDULE_TYPE, schedule.getScheduleType().getTypeName());
+ jobData.put(AbstractJobWrapper.DATAMAP_SCHEDULE_TRIGGER, schedule.getScheduleType().getScheduleTrigger());
+ jobData.put(AbstractJobWrapper.DATAMAP_IS_CONCURRENT, schedule.getScheduleType().isConcurrent());
jobData.put(AbstractJobWrapper.DATAMAP_JOB_METHOD_NAME, schedule.getMethodName());
if (schedule.getClassName() != null) {
jobData.put(AbstractJobWrapper.DATAMAP_JOB_CLASS, schedule.getClassName());
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java
index e363018..e204b31 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java
@@ -30,18 +30,18 @@ import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
*/
public class ScheduledJobInvocationContext {
private final ScheduledJobDefinition jobDefinition;
- private final ServerPluginContext pluginContext;
+ private final ServerPluginContext serverPluginContext;
public ScheduledJobInvocationContext(ScheduledJobDefinition jobDefinition, ServerPluginContext pluginContext) {
this.jobDefinition = jobDefinition;
- this.pluginContext = pluginContext;
+ this.serverPluginContext = pluginContext;
}
public ScheduledJobDefinition getJobDefinition() {
- return jobDefinition;
+ return this.jobDefinition;
}
- public ServerPluginContext getPluginContext() {
- return pluginContext;
+ public ServerPluginContext getServerPluginContext() {
+ return this.serverPluginContext;
}
}
diff --git a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/AbstractScheduleType.java b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/AbstractScheduleType.java
index cb30ded..7fdecfa 100644
--- a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/AbstractScheduleType.java
+++ b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/AbstractScheduleType.java
@@ -22,6 +22,9 @@ package org.rhq.enterprise.server.xmlschema;
/**
* Defines a type of schedule for a server plugin job.
*
+ * This also has a static factory that allows you to build concrete forms
+ * of schedule types.
+ *
* @author John Mazzitelli
*/
@@ -30,6 +33,25 @@ public abstract class AbstractScheduleType {
private final boolean concurrent;
/**
+ * Factory method that creates a concrete schedule type object based on the given parameters.
+ *
+ * @param concurrent if true, multiple jobs can run concurrently.
+ * @param scheduleType the name of the concrete schedule type
+ * @param scheduleTrigger the string form of the schedule's trigger
+ *
+ * @return a new instance of the desired schedule type
+ */
+ public static final AbstractScheduleType create(boolean concurrent, String scheduleType, String scheduleTrigger) {
+ AbstractScheduleType scheduleTypeObj = null;
+ if (PeriodicScheduleType.TYPE_NAME.equalsIgnoreCase(scheduleType)) {
+ scheduleTypeObj = new PeriodicScheduleType(concurrent, Long.parseLong(scheduleTrigger));
+ } else if (CronScheduleType.TYPE_NAME.equalsIgnoreCase(scheduleType)) {
+ scheduleTypeObj = new CronScheduleType(concurrent, scheduleTrigger);
+ }
+ return scheduleTypeObj;
+ }
+
+ /**
* Builds the schedule type.
*
* @param concurrent if true, multiple jobs can run concurrently. If false, only one
@@ -61,4 +83,11 @@ public abstract class AbstractScheduleType {
public boolean isConcurrent() {
return this.concurrent;
}
+
+ /**
+ * Returns the string form of the trigger that causes the job to be invoked.
+ *
+ * @return a string that describes the trigger of the schedule
+ */
+ public abstract String getScheduleTrigger();
}
diff --git a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/CronScheduleType.java b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/CronScheduleType.java
index ab72af1..6802609 100644
--- a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/CronScheduleType.java
+++ b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/CronScheduleType.java
@@ -37,4 +37,9 @@ public class CronScheduleType extends AbstractScheduleType {
public String getCronExpression() {
return this.cronExpression;
}
+
+ @Override
+ public String getScheduleTrigger() {
+ return getCronExpression();
+ }
}
diff --git a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/PeriodicScheduleType.java b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/PeriodicScheduleType.java
index 321ceda..e6bf4d9 100644
--- a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/PeriodicScheduleType.java
+++ b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/PeriodicScheduleType.java
@@ -37,4 +37,9 @@ public class PeriodicScheduleType extends AbstractScheduleType {
public long getPeriod() {
return this.period;
}
+
+ @Override
+ public String getScheduleTrigger() {
+ return String.valueOf(getPeriod());
+ }
}
diff --git a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ScheduledJobDefinition.java b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ScheduledJobDefinition.java
index a12f7f1..e80921d 100644
--- a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ScheduledJobDefinition.java
+++ b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ScheduledJobDefinition.java
@@ -33,12 +33,12 @@ public class ScheduledJobDefinition {
private final AbstractScheduleType scheduleType;
private final Properties callbackData;
- public ScheduledJobDefinition(String jobId, boolean enabled, String methodName, AbstractScheduleType scheduleType,
- Properties callbackData) {
+ public ScheduledJobDefinition(String jobId, boolean enabled, String className, String methodName,
+ AbstractScheduleType scheduleType, Properties callbackData) {
this.jobId = jobId;
this.enabled = enabled;
- this.className = null; // TODO: for future.. add class to schedule xml schema to support stateless job classes
+ this.className = className;
this.methodName = methodName;
this.scheduleType = scheduleType;
this.callbackData = callbackData;
diff --git a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorMetadataParser.java b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorMetadataParser.java
index 0c81095..cfaa1a8 100644
--- a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorMetadataParser.java
+++ b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorMetadataParser.java
@@ -48,6 +48,7 @@ public class ServerPluginDescriptorMetadataParser {
// pre-defined property names for schedule definitions
private static final String SCHEDULED_JOB_PROP_NAME_ENABLED = "enabled";
+ private static final String SCHEDULED_JOB_PROP_NAME_CLASS = "class";
private static final String SCHEDULED_JOB_PROP_NAME_METHOD_NAME = "methodName";
private static final String SCHEDULED_JOB_PROP_NAME_CONCURRENT = "concurrent";
private static final String SCHEDULED_JOB_PROP_NAME_SCHEDULE_TYPE = "scheduleType";
@@ -113,11 +114,13 @@ public class ServerPluginDescriptorMetadataParser {
// prepare some defaults if the schedule didn't define some of these
// we assume:
// the map name is the methodName that will be invoked
+ // the class name is null, which means its the stateful plugin component to be invoked
// the schedule is always enabled
// the schedule is never concurrent
// the schedule is a periodic schedule that triggers every 10 minutes
// the schedule has no callback data
String methodName = defaults.getSimpleValue(SCHEDULED_JOB_PROP_NAME_METHOD_NAME, mapDef.getName());
+ String className = defaults.getSimpleValue(SCHEDULED_JOB_PROP_NAME_CLASS, null);
String enabledStr = defaults.getSimpleValue(SCHEDULED_JOB_PROP_NAME_ENABLED, "true");
String concurrentStr = defaults.getSimpleValue(SCHEDULED_JOB_PROP_NAME_CONCURRENT, "false");
String scheduleTypeStr = defaults.getSimpleValue(SCHEDULED_JOB_PROP_NAME_SCHEDULE_TYPE,
@@ -129,11 +132,8 @@ public class ServerPluginDescriptorMetadataParser {
boolean concurrent = Boolean.parseBoolean(concurrentStr);
AbstractScheduleType scheduleType;
- if (PeriodicScheduleType.TYPE_NAME.equalsIgnoreCase(scheduleTypeStr)) {
- scheduleType = new PeriodicScheduleType(concurrent, Long.parseLong(scheduleTriggerStr));
- } else if (CronScheduleType.TYPE_NAME.equalsIgnoreCase(scheduleTypeStr)) {
- scheduleType = new CronScheduleType(concurrent, scheduleTriggerStr);
- } else {
+ scheduleType = AbstractScheduleType.create(concurrent, scheduleTypeStr, scheduleTriggerStr);
+ if (scheduleType == null) {
throw new InvalidPluginDescriptorException("Invalid schedule type: " + scheduleTypeStr);
}
@@ -147,7 +147,7 @@ public class ServerPluginDescriptorMetadataParser {
}
}
- job = new ScheduledJobDefinition(jobId, enabled, methodName, scheduleType, callbackData);
+ job = new ScheduledJobDefinition(jobId, enabled, className, methodName, scheduleType, callbackData);
}
return job;
@@ -200,11 +200,13 @@ public class ServerPluginDescriptorMetadataParser {
// prepare some defaults if the schedule didn't define some of these
// we assume:
// the map name is the methodName that will be invoked
+ // the class name is null, which means its the stateful plugin component to be invoked
// the schedule is always enabled
// the schedule is never concurrent
// the schedule is a periodic schedule that triggers every 10 minutes
// the schedule has no callback data
- String methodName = jobMap.getSimpleValue(SCHEDULED_JOB_PROP_NAME_METHOD_NAME, map.getName());
+ String methodName = jobMap.getSimpleValue(SCHEDULED_JOB_PROP_NAME_METHOD_NAME, jobMap.getName());
+ String className = jobMap.getSimpleValue(SCHEDULED_JOB_PROP_NAME_CLASS, null);
String enabledStr = jobMap.getSimpleValue(SCHEDULED_JOB_PROP_NAME_ENABLED, "true");
String concurrentStr = jobMap.getSimpleValue(SCHEDULED_JOB_PROP_NAME_CONCURRENT, "false");
String scheduleTypeStr = jobMap.getSimpleValue(SCHEDULED_JOB_PROP_NAME_SCHEDULE_TYPE,
@@ -216,11 +218,8 @@ public class ServerPluginDescriptorMetadataParser {
boolean concurrent = Boolean.parseBoolean(concurrentStr);
AbstractScheduleType scheduleType;
- if (PeriodicScheduleType.TYPE_NAME.equalsIgnoreCase(scheduleTypeStr)) {
- scheduleType = new PeriodicScheduleType(concurrent, Long.parseLong(scheduleTriggerStr));
- } else if (CronScheduleType.TYPE_NAME.equalsIgnoreCase(scheduleTypeStr)) {
- scheduleType = new CronScheduleType(concurrent, scheduleTriggerStr);
- } else {
+ scheduleType = AbstractScheduleType.create(concurrent, scheduleTypeStr, scheduleTriggerStr);
+ if (scheduleType == null) {
throw new InvalidPluginDescriptorException("Invalid schedule type: " + scheduleTypeStr);
}
@@ -234,7 +233,7 @@ public class ServerPluginDescriptorMetadataParser {
}
}
- job = new ScheduledJobDefinition(jobId, enabled, methodName, scheduleType, callbackData);
+ job = new ScheduledJobDefinition(jobId, enabled, className, methodName, scheduleType, callbackData);
}
return job;
diff --git a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
index 81e2e01..a378f2b 100644
--- a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
+++ b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
@@ -58,8 +58,13 @@
has special semantics that require special properties to be defined.
If you use this element, it must contain map properties where each map:
1) has a name that is a method name of the plugin component. This method
- name identifies what is called on the plugin component when the schedule triggers.
+ name identifies what is called on the plugin component (or the target
+ class, see below) when the schedule triggers.
You may override this by defining a simple property called "methodName".
+ Whether the method name is defined by the map name itself or the optional
+ "methodName" simple property, the method signature must be either
+ a no-arg signature or one that has a single argument of type
+ ScheduledJobInvocationContext.
2) has simple properties called "scheduleType" and "scheduleTrigger" where
"scheduleType" is either "cron" or "periodic" and "scheduleTrigger" is either
the cron expression or a time period in milliseconds.
@@ -72,7 +77,15 @@
RHQ Server in the system, and this is false, you can be assured that only
a single server will handle the invocation at any one time (i.e. multiple servers
will not run invocations at the same time).
- 4) has any other simple properties that will be used as custom callback data properties.
+ 4) has an optional simple property called "class" of type string that is the
+ name of class to be instantiated as the target of the job invocation.
+ If not defined, the target of the job invocation is the stateful plugin component
+ itself. Whatever class is used as the target, it must have a method as defined
+ in the method name simple property as explained above.
+ Typically, plugin developers don't use this class property because you normally
+ want to target the stateful plugin component; however, this class property provides
+ the plugin developer a way to declare stateless jobs if that is needed.
+ 5) has any other simple properties that will be used as custom callback data properties.
You may additionally define one list-of-maps property which can be used to allow a user
to define their own custom jobs. The list-of-maps must contain a map property definition
that follows the same rules as described above.
commit f5ca90e2f45e7062404fedf409c5ae9dde3dc19a
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 15 01:14:48 2009 -0500
rename lifecycle listener to component
diff --git a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
index 0275e01..e174c0e 100644
--- a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
+++ b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
@@ -20,13 +20,13 @@
package org.custom;
import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
-import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
/**
* A sample lifecycle listener for the sample generic plugin. This listener will be
* the main plugin component the server uses to start and stop the plugin.
*/
-public class MyLifecycleListener implements ServerPluginLifecycleListener {
+public class MyLifecycleListener implements ServerPluginComponent {
private ServerPluginContext context;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
index 79e5a89..d18ffed 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -123,7 +123,7 @@ abstract class AbstractJobWrapper implements Job {
Object pluginJobObject;
ServerPluginManager pluginManager = pc.getPluginManager();
ServerPluginEnvironment pluginEnv = pluginManager.getPluginEnvironment(pluginName);
- ServerPluginLifecycleListener pluginComponent = pluginManager.getServerPluginComponent(pluginName);
+ ServerPluginComponent pluginComponent = pluginManager.getServerPluginComponent(pluginName);
if (jobClass == null) {
pluginJobObject = pluginComponent;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginComponent.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginComponent.java
new file mode 100644
index 0000000..e7ac3ce
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginComponent.java
@@ -0,0 +1,73 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.rhq.enterprise.server.plugin.pc;
+
+/**
+ * Performs global initialization and shutdown of a server side plugin. This provides a place
+ * for plugin developers to allocate global resources needed by all plugin components and
+ * a place to clean up those resources.
+ *
+ * Plugin components are required of generic server plugins because they provide
+ * the only mechanism to start and stop.
+ *
+ * @author John Mazzitelli
+ */
+public interface ServerPluginComponent {
+ /**
+ * When a plugin's container loads a plugin, this method will be called.
+ * When this is called, no other plugin components have been instantiated
+ * or invoked yet. This is merely called to notify the plugin that it is about to be
+ * placed into service and its components will soon be asked to perform work.
+ *
+ * If this method returns normally, the plugin is saying it is ready and able to {@link #start()}.
+ *
+ * @param context a context with information about the runtime plugin environment
+ *
+ * @throws Exception if the plugin finds that it should not be loaded, an exception should be thrown.
+ * If thrown, this plugin will not be started and will be considered disabled. If
+ * other plugins are dependent on this failed plugin, those other plugins will
+ * fail to operate correctly.
+ */
+ void initialize(ServerPluginContext context) throws Exception;
+
+ /**
+ * When a plugin container has been started (which occurs after all plugins are loaded), this
+ * method is called to inform the plugin is can begin performing work.
+ */
+ void start();
+
+ /**
+ * When a plugin container has been stopped (but before it unloads plugins), this
+ * method is called to inform the plugin it should stop performing work and prepare
+ * to shutdown.
+ */
+ void stop();
+
+ /**
+ * When the plugin container shuts down and it unloads the plugin, this method will be called.
+ * This provides an opportunity for the plugin to clean up any global resources it has previously
+ * allocated. After this method is called, invocations of this plugin's discovery or
+ * resource components will no longer occur.
+ */
+ void shutdown();
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginLifecycleListener.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginLifecycleListener.java
deleted file mode 100644
index f427d73..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginLifecycleListener.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2009 Red Hat, Inc.
- * All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2, as
- * published by the Free Software Foundation, and/or the GNU Lesser
- * General Public License, version 2.1, also as published by the Free
- * Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License and the GNU Lesser General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * and the GNU Lesser General Public License along with this program;
- * if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.rhq.enterprise.server.plugin.pc;
-
-/**
- * Performs global initialization and shutdown of a server side plugin. This provides a place
- * for plugin developers to allocate global resources needed by all plugin components and
- * a place to clean up those resources.
- *
- * Plugin components are required of generic server plugins because they provide
- * the only mechanism to start and stop.
- *
- * @author John Mazzitelli
- */
-public interface ServerPluginLifecycleListener {
- /**
- * When a plugin's container loads a plugin, this method will be called.
- * When this is called, no other plugin components have been instantiated
- * or invoked yet. This is merely called to notify the plugin that it is about to be
- * placed into service and its components will soon be asked to perform work.
- *
- * If this method returns normally, the plugin is saying it is ready and able to {@link #start()}.
- *
- * @param context a context with information about the runtime plugin environment
- *
- * @throws Exception if the plugin finds that it should not be loaded, an exception should be thrown.
- * If thrown, this plugin will not be started and will be considered disabled. If
- * other plugins are dependent on this failed plugin, those other plugins will
- * fail to operate correctly.
- */
- void initialize(ServerPluginContext context) throws Exception;
-
- /**
- * When a plugin container has been started (which occurs after all plugins are loaded), this
- * method is called to inform the plugin is can begin performing work.
- */
- void start();
-
- /**
- * When a plugin container has been stopped (but before it unloads plugins), this
- * method is called to inform the plugin it should stop performing work and prepare
- * to shutdown.
- */
- void stop();
-
- /**
- * When the plugin container shuts down and it unloads the plugin, this method will be called.
- * This provides an opportunity for the plugin to clean up any global resources it has previously
- * allocated. After this method is called, invocations of this plugin's discovery or
- * resource components will no longer occur.
- */
- void shutdown();
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index 00f3e97..a0cca3f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -64,7 +64,7 @@ public class ServerPluginManager {
* Only plugins that declare their own plugin component will have objects in this cache.
* This is keyed on plugin name.
*/
- private final Map<String, ServerPluginLifecycleListener> pluginComponentCache;
+ private final Map<String, ServerPluginComponent> pluginComponentCache;
/**
* Creates a plugin manager for the given plugin container.
@@ -75,7 +75,7 @@ public class ServerPluginManager {
this.parentPluginContainer = pc;
this.loadedPlugins = new HashMap<String, ServerPluginEnvironment>();
this.pluginContextCache = new HashMap<String, ServerPluginContext>();
- this.pluginComponentCache = new HashMap<String, ServerPluginLifecycleListener>();
+ this.pluginComponentCache = new HashMap<String, ServerPluginComponent>();
}
/**
@@ -120,7 +120,7 @@ public class ServerPluginManager {
log.debug("Loading server plugin [" + pluginName + "] from: " + env.getPluginUrl());
// tell the plugin we are loading it
- ServerPluginLifecycleListener component = createServerPluginComponent(env);
+ ServerPluginComponent component = createServerPluginComponent(env);
if (component != null) {
ServerPluginContext context = getServerPluginContext(env);
log.debug("Initializing plugin component for server plugin [" + pluginName + "]");
@@ -146,9 +146,9 @@ public class ServerPluginManager {
log.debug("Starting plugins");
// tell all plugin components to start
- for (Map.Entry<String, ServerPluginLifecycleListener> entry : this.pluginComponentCache.entrySet()) {
+ for (Map.Entry<String, ServerPluginComponent> entry : this.pluginComponentCache.entrySet()) {
String pluginName = entry.getKey();
- ServerPluginLifecycleListener component = entry.getValue();
+ ServerPluginComponent component = entry.getValue();
ServerPluginEnvironment env = this.loadedPlugins.get(pluginName);
log.debug("Starting plugin component for server plugin [" + pluginName + "]");
ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
@@ -169,9 +169,9 @@ public class ServerPluginManager {
log.debug("Stopping plugins");
// tell all plugin components to stop
- for (Map.Entry<String, ServerPluginLifecycleListener> entry : this.pluginComponentCache.entrySet()) {
+ for (Map.Entry<String, ServerPluginComponent> entry : this.pluginComponentCache.entrySet()) {
String pluginName = entry.getKey();
- ServerPluginLifecycleListener component = entry.getValue();
+ ServerPluginComponent component = entry.getValue();
ServerPluginEnvironment env = this.loadedPlugins.get(pluginName);
log.debug("Stopping plugin component for server plugin [" + pluginName + "]");
ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
@@ -202,7 +202,7 @@ public class ServerPluginManager {
try {
// tell the plugin we are unloading it
- ServerPluginLifecycleListener component = this.pluginComponentCache.get(pluginName);
+ ServerPluginComponent component = this.pluginComponentCache.get(pluginName);
if (component != null) {
log.debug("Shutting down plugin componentfor server plugin [" + pluginName + "]");
ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
@@ -256,7 +256,7 @@ public class ServerPluginManager {
* return <code>null</code> if the plugin has not defined a plugin component.
* <code>null</code> is also returned if the plugin is not initialized yet.
*/
- public ServerPluginLifecycleListener getServerPluginComponent(String pluginName) {
+ public ServerPluginComponent getServerPluginComponent(String pluginName) {
return this.pluginComponentCache.get(pluginName);
}
@@ -323,17 +323,16 @@ public class ServerPluginManager {
*
* @throws Exception if failed to create the instance
*/
- protected ServerPluginLifecycleListener createServerPluginComponent(ServerPluginEnvironment environment)
- throws Exception {
+ protected ServerPluginComponent createServerPluginComponent(ServerPluginEnvironment environment) throws Exception {
String pluginName = environment.getPluginName();
- ServerPluginLifecycleListener instance = null;
+ ServerPluginComponent instance = null;
ServerPluginComponentType componentXml = environment.getPluginDescriptor().getPluginComponent();
if (componentXml != null) {
String className = componentXml.getClazz();
log.debug("Creating plugin component [" + className + "] for plugin [" + pluginName + "]");
- instance = (ServerPluginLifecycleListener) instantiatePluginClass(environment, className);
+ instance = (ServerPluginComponent) instantiatePluginClass(environment, className);
log.debug("Plugin component created [" + instance.getClass() + "] for plugin [" + pluginName + "]");
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
index 457026c..fcdf743 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
@@ -29,7 +29,7 @@ import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
-import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
import org.rhq.enterprise.server.plugin.pc.ServerPluginManager;
import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
@@ -154,17 +154,17 @@ public class TestGenericServerPluginService extends ServerPluginService implemen
* The test plugin manager.
*/
class TestGenericPluginManager extends ServerPluginManager {
- public final Map<String, ServerPluginLifecycleListener> listeners;
+ public final Map<String, ServerPluginComponent> listeners;
public TestGenericPluginManager(TestGenericServerPluginContainer pc) {
super(pc);
- listeners = new HashMap<String, ServerPluginLifecycleListener>();
+ listeners = new HashMap<String, ServerPluginComponent>();
}
@Override
- protected ServerPluginLifecycleListener createServerPluginComponent(ServerPluginEnvironment environment)
+ protected ServerPluginComponent createServerPluginComponent(ServerPluginEnvironment environment)
throws Exception {
- ServerPluginLifecycleListener listener = super.createServerPluginComponent(environment);
+ ServerPluginComponent listener = super.createServerPluginComponent(environment);
listeners.put(environment.getPluginName(), listener);
return listener;
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestLifecycleListener.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestLifecycleListener.java
index c49b22c..0b095e5 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestLifecycleListener.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestLifecycleListener.java
@@ -19,13 +19,13 @@
package org.rhq.enterprise.server.plugin.pc.generic;
import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
-import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
/**
* A sample lifecycle listener for the sample generic plugin. This listener will be
* the main interface the server uses to start and stop the plugin.
*/
-public class TestLifecycleListener implements ServerPluginLifecycleListener {
+public class TestLifecycleListener implements ServerPluginComponent {
public enum LifecycleState {
UNINITIALIZED, INITIALIZED, STARTED, STOPPED
commit 65ae28127f1f3cb7963333c3b09c4b94d00ce133
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 15 01:09:04 2009 -0500
get the new schedule stuff implemented.
this gets it most of the way but its not all the way there yet.
diff --git a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
index de99b3a..0275e01 100644
--- a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
+++ b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
@@ -19,17 +19,14 @@
package org.custom;
-import java.util.Properties;
-
-import org.rhq.enterprise.server.plugin.pc.ScheduledJob;
import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
/**
* A sample lifecycle listener for the sample generic plugin. This listener will be
- * the main interface the server uses to start and stop the plugin.
+ * the main plugin component the server uses to start and stop the plugin.
*/
-public class MyLifecycleListener implements ServerPluginLifecycleListener, ScheduledJob {
+public class MyLifecycleListener implements ServerPluginLifecycleListener {
private ServerPluginContext context;
@@ -50,10 +47,12 @@ public class MyLifecycleListener implements ServerPluginLifecycleListener, Sched
System.out.println("The sample plugin has been shut down!!! : " + this);
}
- @Override
- public void execute(String jobId, ServerPluginLifecycleListener lifecycleListener, Properties callbackData)
- throws Exception {
- System.out.println("The sample plugin scheduled job [" + jobId + "] has triggered!!! : " + this);
+ public void myScheduledJobMethod1() throws Exception {
+ System.out.println("The sample plugin scheduled job [myScheduledJobMethod1] has triggered!!! : " + this);
+ }
+
+ public void myScheduledJobMethod2() throws Exception {
+ System.out.println("The sample plugin scheduled job [myScheduledJobMethod2] has triggered!!! : " + this);
}
@Override
@@ -64,9 +63,7 @@ public class MyLifecycleListener implements ServerPluginLifecycleListener, Sched
StringBuilder str = new StringBuilder();
str.append("plugin-name=").append(this.context.getPluginEnvironment().getPluginName()).append(",");
- str.append("plugin-url=").append(this.context.getPluginEnvironment().getPluginUrl()).append(",");
- str.append("data-dir=").append(this.context.getDataDirectory()).append(",");
- str.append("tmp-dir=").append(this.context.getTemporaryDirectory()); // do not append ,
+ str.append("plugin-url=").append(this.context.getPluginEnvironment().getPluginUrl()); // do not append ,
return str.toString();
}
}
diff --git a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java
index f137cf5..c4e50d3 100644
--- a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java
+++ b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java
@@ -19,21 +19,22 @@
package org.custom;
-import java.util.Properties;
-
-import org.rhq.enterprise.server.plugin.pc.ScheduledJob;
-import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
+import org.rhq.enterprise.server.plugin.pc.ScheduledJobInvocationContext;
/**
- * Example of a scheduled job.
+ * Example of a stateless class that can process scheduled job invocations.
*
* @author John Mazzitelli
*/
-public class MyScheduledJob implements ScheduledJob {
- @Override
- public void execute(String jobId, ServerPluginLifecycleListener lifecycleListener, Properties callbackData)
- throws Exception {
- System.out.println("Sample scheduled job has been triggered! [" + this.getClass() + "] jobId=" + jobId
- + ", lifecycle-listener=" + lifecycleListener);
+public class MyScheduledJob {
+ public void executeWithContext(ScheduledJobInvocationContext jobContext) throws Exception {
+ System.out.println("Sample scheduled job has been triggered! [" + this.getClass() + "] jobId="
+ + jobContext.getJobDefinition().getJobId() + ", methodName="
+ + jobContext.getJobDefinition().getMethodName() + ", callbackData="
+ + jobContext.getJobDefinition().getCallbackData());
+ }
+
+ public void executeNoArg() throws Exception {
+ System.out.println("Sample scheduled job has been triggered! [" + this.getClass() + "] NO CONTEXT!");
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
index efe2100..79e5a89 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -19,6 +19,7 @@
package org.rhq.enterprise.server.plugin.pc;
+import java.lang.reflect.Method;
import java.util.Properties;
import org.apache.commons.logging.Log;
@@ -28,6 +29,8 @@ import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
+import org.jboss.seam.async.Schedule;
+
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -65,9 +68,15 @@ abstract class AbstractJobWrapper implements Job {
/**
* Key to the job data map that indicates which plugin component class should be instantiated
- * in order to process the job. This must implement {@link ScheduledJob}.
+ * in order to process the job. If not specified, the main plugin component instance is used.
+ */
+ public static final String DATAMAP_JOB_CLASS = DATAMAP_LEADER + "jobClass";
+
+ /**
+ * Key to the job data map that indicates which method on the job class should be invoked
+ * to run the job.
*/
- public static final String DATAMAP_SCHEDULED_JOB_CLASS = DATAMAP_LEADER + "scheduledJobClass";
+ public static final String DATAMAP_JOB_METHOD_NAME = DATAMAP_LEADER + "jobMethodName";
/**
* This is the method that quartz calls when the schedule has triggered. This method will
@@ -84,7 +93,8 @@ abstract class AbstractJobWrapper implements Job {
String pluginName = dataMap.getString(DATAMAP_PLUGIN_NAME);
String pluginTypeString = dataMap.getString(DATAMAP_PLUGIN_TYPE);
String jobId = dataMap.getString(DATAMAP_JOB_ID);
- String scheduledJobClass = dataMap.getString(DATAMAP_SCHEDULED_JOB_CLASS);
+ String jobClass = dataMap.getString(DATAMAP_JOB_CLASS);
+ String jobMethodName = dataMap.getString(DATAMAP_JOB_METHOD_NAME);
// obtain the plugin's own callback data from the datamap
Properties callbackData = new Properties();
@@ -110,31 +120,47 @@ abstract class AbstractJobWrapper implements Job {
MasterServerPluginContainer mpc = LookupUtil.getServerPluginService().getMasterPluginContainer();
AbstractTypeServerPluginContainer pc = mpc.getPluginContainerByPluginType(pluginType);
- ScheduledJob pluginJob;
+ Object pluginJobObject;
ServerPluginManager pluginManager = pc.getPluginManager();
ServerPluginEnvironment pluginEnv = pluginManager.getPluginEnvironment(pluginName);
- ServerPluginLifecycleListener lifecycleListener = pluginManager.getServerPluginLifecycleListener(pluginName);
+ ServerPluginLifecycleListener pluginComponent = pluginManager.getServerPluginComponent(pluginName);
- if (scheduledJobClass == null) {
+ if (jobClass == null) {
+ pluginJobObject = pluginComponent;
+ if (pluginJobObject == null) {
+ JobExecutionException jobException = new JobExecutionException(logMsg(pluginName, pluginType, jobId,
+ "no plugin component to process job", null), false);
+ jobException.setUnscheduleAllTriggers(true);
+ throw jobException;
+ }
+ } else {
try {
- pluginJob = (ScheduledJob) lifecycleListener;
- if (pluginJob == null) {
- log.error(logMsg(pluginName, pluginType, jobId, "no lifecycle listener to process job", null));
- throw new UnsupportedOperationException("no lifecycle listener available to process the job");
- }
+ pluginJobObject = pluginManager.instantiatePluginClass(pluginEnv, jobClass);
} catch (Throwable t) {
- // no valid lifecycle listener that implements job interface - we need to unschedule this, do not refire
- log.error(logMsg(pluginName, pluginType, jobId, "invaild lifecycle listener", t));
+ // invalid class - we need to unschedule this, do not refire since it will never work
+ log.error(logMsg(pluginName, pluginType, jobId, "bad schedule job class [" + jobClass + "]", t));
JobExecutionException jobException = new JobExecutionException(t, false);
jobException.setUnscheduleAllTriggers(true);
throw jobException;
}
- } else {
+ }
+
+ // try to find the method to invoke - first, see if the method exists with a parameter
+ // that is the type of our job invocation context. Otherwise, rely on a no-arg method.
+ Method jobMethod;
+ Object[] params;
+
+ try {
+ jobMethod = pluginJobObject.getClass().getMethod(jobMethodName, ScheduledJobInvocationContext.class);
+ params = new Object[1];
+ // params[0] = new ScheduledJobInvocationContext(jobDefinition, pluginContext);
+ } catch (NoSuchMethodException e) {
try {
- pluginJob = (ScheduledJob) pluginManager.instantiatePluginClass(pluginEnv, scheduledJobClass);
+ jobMethod = pluginJobObject.getClass().getMethod(jobMethodName);
+ params = null;
} catch (Throwable t) {
- // invalid class - we need to unschedule this, do not refire since it will never work
- log.error(logMsg(pluginName, pluginType, jobId, "invalid schedule job class", t));
+ // invalid method - we need to unschedule this, do not refire since it will never work
+ log.error(logMsg(pluginName, pluginType, jobId, "bad schedule job method [" + jobMethodName + "]", t));
JobExecutionException jobException = new JobExecutionException(t, false);
jobException.setUnscheduleAllTriggers(true);
throw jobException;
@@ -142,12 +168,11 @@ abstract class AbstractJobWrapper implements Job {
}
// now actually tell the plugin its time to do the scheduled job
-
try {
ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(pluginEnv.getPluginClassLoader());
- pluginJob.execute(jobId, lifecycleListener, callbackData);
+ jobMethod.invoke(pluginJobObject, params);
} finally {
Thread.currentThread().setContextClassLoader(originalContextClassLoader);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index 8384b98..19910d8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -21,7 +21,6 @@ package org.rhq.enterprise.server.plugin.pc;
import java.util.Collection;
import java.util.List;
-import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -30,7 +29,10 @@ import org.quartz.JobDataMap;
import org.rhq.enterprise.server.scheduler.SchedulerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
-import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ScheduledJobType;
+import org.rhq.enterprise.server.xmlschema.CronScheduleType;
+import org.rhq.enterprise.server.xmlschema.PeriodicScheduleType;
+import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
+import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorMetadataParser;
/**
* The abstract superclass for all plugin containers of the different {@link ServerPluginType plugin types}.
@@ -178,8 +180,7 @@ public abstract class AbstractTypeServerPluginContainer {
/**
* If a plugin has scheduled jobs, this method will schedule them now.
* This particular method implementation schedules the global jobs as defined in the
- * plugin descriptors. If a plugin has a global scheduled job on its lifecycle
- * listener, that lifecycle listener will be the job handler class.
+ * plugin descriptors.
*
* Subclasses are free to extend this method to schedule additional plugin jobs, but must
* ensure they call this method so the global scheduled jobs get added to the scheduler.
@@ -193,45 +194,24 @@ public abstract class AbstractTypeServerPluginContainer {
public synchronized void schedulePluginJobs() throws Exception {
if (this.pluginManager != null) {
// process all known plugins and schedule their jobs
+ List<ScheduledJobDefinition> jobs;
for (ServerPluginEnvironment pluginEnv : this.pluginManager.getPluginEnvironments()) {
String pluginName = pluginEnv.getPluginName();
- // First see if the listener has a schedule itself and schedule it if it does.
- // Note that we know if there is no lifecycle listener, then there can't be a listener schedule
- if (this.pluginManager.getServerPluginLifecycleListener(pluginName) != null) {
- Schedule schedule = this.pluginManager.getServerPluginContext(pluginEnv).getSchedule();
- if (schedule != null) {
- try {
- scheduleJob(schedule, pluginName, "__lifecycleListenerJob", null, null);
- } catch (Throwable t) {
- log.warn("Failed to schedule the global plugin job for plugin [" + pluginName + "]", t);
- }
- }
- }
-
- // now schedule all the other jobs defined in the plugin descriptor
- List<ScheduledJobType> jobs = pluginEnv.getPluginDescriptor().getScheduledJob();
- if (jobs != null) {
- for (ScheduledJobType job : jobs) {
- Schedule schedule;
- if (job.getPeriod() != null) {
- schedule = new PeriodicSchedule(job.isConcurrent(), job.getPeriod().longValue());
- } else {
- schedule = new CronSchedule(job.isConcurrent(), job.getCron());
- }
-
- String scheduledJobClass = job.getClazz();
- String jobId = job.getJobId();
- if (scheduledJobClass != null) {
+ try {
+ // TODO: we need to read the config from the DB, and use thoses job defs instead of the ones from the descriptor
+ jobs = ServerPluginDescriptorMetadataParser.getScheduledJobs(pluginEnv.getPluginDescriptor());
+ if (jobs != null) {
+ for (ScheduledJobDefinition job : jobs) {
try {
- scheduleJob(schedule, pluginName, jobId, scheduledJobClass, null);
+ scheduleJob(job, pluginName);
} catch (Throwable t) {
- log.warn("Failed to schedule job [" + jobId + "] for plugin [" + pluginName + "]", t);
+ log.warn("Failed to schedule job [" + job + "] for plugin [" + pluginName + "]", t);
}
- } else {
- log.warn("Scheduled job [" + jobId + "] in plugin [" + pluginName + "] is missing class");
}
}
+ } catch (Throwable t) {
+ log.warn("Failed to get scheduled jobs for plugin [" + pluginName + "]", t);
}
}
} else {
@@ -262,26 +242,19 @@ public abstract class AbstractTypeServerPluginContainer {
}
/**
- * Schedules a job for periodic execution.
+ * Schedules a job for periodic execution. Note that if the <code>schedule</code> indicates the
+ * job is not enabled, this method returns immediately as a no-op.
*
* @param schedule instructs how the job should be scheduled
* @param pluginName the name of the plugin scheduling the job
- * @param jobId a unique ID that identifies the job within the plugin (jobIds across plugins need not be unique)
- * @param scheduledJobClass the plugin component class name that implements {@link ScheduledJob} that will perform
- * the work for the job. If <code>null</code>, the lifecycle listener instance will be
- * used (note: if <code>null</code>, it means whatever listener instance was used to initialize
- * the plugin is the same instance that will handle the job; a new instance of the listener
- * class is not created. This allows a plugin to have a stateful object be periodically
- * invoked for each job invocation, as opposed to having a new object instantiated for
- * each job invocation).
- * @param callbackData if not <code>null</code>, this is a map of properties that will be passed to the scheduled
- * job - it is Properties to force both the keys and values to be strings, since that is how
- * we tell quartz to store the data
*
* @throws Exception if failed to schedule the job
*/
- protected void scheduleJob(Schedule schedule, String pluginName, String jobId, String scheduledJobClass,
- Properties callbackData) throws Exception {
+ protected void scheduleJob(ScheduledJobDefinition schedule, String pluginName) throws Exception {
+
+ if (!schedule.isEnabled()) {
+ return;
+ }
String groupName = pluginName;
boolean rescheduleIfExists = true; // just in case the parameters change, we'll always want to reschedule it if it exists
@@ -289,7 +262,7 @@ public abstract class AbstractTypeServerPluginContainer {
// determine which quartz job class we should be using, based on the concurrency needs of the schedule
Class<? extends Job> jobClass;
- if (schedule.isConcurrent()) {
+ if (schedule.getScheduleType().isConcurrent()) {
jobClass = ConcurrentJobWrapper.class;
} else {
jobClass = StatefulJobWrapper.class;
@@ -299,29 +272,30 @@ public abstract class AbstractTypeServerPluginContainer {
JobDataMap jobData = new JobDataMap();
jobData.put(AbstractJobWrapper.DATAMAP_PLUGIN_NAME, pluginName);
jobData.put(AbstractJobWrapper.DATAMAP_PLUGIN_TYPE, getSupportedServerPluginType().stringify());
- jobData.put(AbstractJobWrapper.DATAMAP_JOB_ID, jobId);
- if (scheduledJobClass != null) {
- jobData.put(AbstractJobWrapper.DATAMAP_SCHEDULED_JOB_CLASS, scheduledJobClass);
+ jobData.put(AbstractJobWrapper.DATAMAP_JOB_ID, schedule.getJobId());
+ jobData.put(AbstractJobWrapper.DATAMAP_JOB_METHOD_NAME, schedule.getMethodName());
+ if (schedule.getClassName() != null) {
+ jobData.put(AbstractJobWrapper.DATAMAP_JOB_CLASS, schedule.getClassName());
}
- if (callbackData != null) {
- jobData.putAll(callbackData);
+ if (schedule.getCallbackData() != null) {
+ jobData.putAll(schedule.getCallbackData());
}
// schedule the job now
SchedulerLocal scheduler = LookupUtil.getSchedulerBean();
- if (schedule instanceof CronSchedule) {
- String cronExpression = ((CronSchedule) schedule).getCronExpression();
- log.info("Scheduling server plugin cron job: jobName=" + jobId + ", groupName=" + groupName + ", jobClass="
- + jobClass + ", cron=" + cronExpression);
- scheduler.scheduleCronJob(jobId, groupName, jobData, jobClass, rescheduleIfExists, isVolatile,
- cronExpression);
+ if (schedule.getScheduleType() instanceof CronScheduleType) {
+ String cronExpression = ((CronScheduleType) schedule.getScheduleType()).getCronExpression();
+ log.info("Scheduling server plugin cron job: jobName=" + schedule.getJobId() + ", groupName=" + groupName
+ + ", jobClass=" + jobClass + ", cron=" + cronExpression);
+ scheduler.scheduleCronJob(schedule.getJobId(), groupName, jobData, jobClass, rescheduleIfExists,
+ isVolatile, cronExpression);
} else {
long initialDelay = 10000L; // arbitrary - wait a small bit of time before triggering the job
- long interval = ((PeriodicSchedule) schedule).getPeriod();
- log.info("Scheduling server plugin periodic job: jobName=" + jobId + ", groupName=" + groupName
- + ", jobClass=" + jobClass + ", interval=" + interval);
- scheduler.scheduleRepeatingJob(jobId, groupName, jobData, jobClass, rescheduleIfExists, isVolatile,
- initialDelay, interval);
+ long interval = ((PeriodicScheduleType) schedule.getScheduleType()).getPeriod();
+ log.info("Scheduling server plugin periodic job: jobName=" + schedule.getJobId() + ", groupName="
+ + groupName + ", jobClass=" + jobClass + ", interval=" + interval);
+ scheduler.scheduleRepeatingJob(schedule.getJobId(), groupName, jobData, jobClass, rescheduleIfExists,
+ isVolatile, initialDelay, interval);
}
return;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java
new file mode 100644
index 0000000..e363018
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJobInvocationContext.java
@@ -0,0 +1,47 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
+
+/**
+ * A scheduled job's invocation method can take a single argument of this type.
+ * If this is the case, the scheduled job's method will be passed an object of this type enabling
+ * the job being invoked to be given information about the invocation.
+ *
+ * @author John Mazzitelli
+ */
+public class ScheduledJobInvocationContext {
+ private final ScheduledJobDefinition jobDefinition;
+ private final ServerPluginContext pluginContext;
+
+ public ScheduledJobInvocationContext(ScheduledJobDefinition jobDefinition, ServerPluginContext pluginContext) {
+ this.jobDefinition = jobDefinition;
+ this.pluginContext = pluginContext;
+ }
+
+ public ScheduledJobDefinition getJobDefinition() {
+ return jobDefinition;
+ }
+
+ public ServerPluginContext getPluginContext() {
+ return pluginContext;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
index f0c8488..83799c3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
@@ -20,8 +20,10 @@
package org.rhq.enterprise.server.plugin.pc;
import java.io.File;
+import java.util.List;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
/**
* A global context containing information about a server-side plugin.
@@ -35,7 +37,7 @@ public class ServerPluginContext {
private final File temporaryDirectory;
private final File dataDirectory;
private final Configuration pluginConfiguration;
- private final Schedule schedule;
+ private final List<ScheduledJobDefinition> schedules;
/**
* Creates a new {@link ServerPluginContext} object. The plugin container is responsible for instantiating these
@@ -45,14 +47,19 @@ public class ServerPluginContext {
* @param dataDirectory a directory where plugins can store persisted data that survives server restarts
* @param tmpDirectory a temporary directory for plugin use
* @param pluginConfiguration the configuration for the plugin itself
- * @param schedule if not <code>null</code>, the plugin will be invoked periodically via the schedule facet
+ * @param schedules if not <code>null</code>, the plugin will be invoked periodically via these schedules
*/
public ServerPluginContext(ServerPluginEnvironment env, File dataDirectory, File tmpDirectory,
- Configuration pluginConfiguration, Schedule schedule) {
+ Configuration pluginConfiguration, List<ScheduledJobDefinition> schedules) {
this.pluginEnvironment = env;
this.dataDirectory = dataDirectory;
this.pluginConfiguration = pluginConfiguration;
- this.schedule = schedule;
+
+ if (schedules != null && schedules.size() == 0) {
+ schedules = null; // null means no schedules
+ }
+ this.schedules = schedules;
+
if (tmpDirectory == null) {
this.temporaryDirectory = new File(System.getProperty("java.io.tmpdir"), "SERVERPLUGIN_TMP");
this.temporaryDirectory.mkdirs();
@@ -105,13 +112,13 @@ public class ServerPluginContext {
}
/**
- * The schedule in which the plugin should be periodically invoked via the schedule job facet.
- * When this is non-null, the plugin's lifecycle listener must be prepared to be periodically
+ * The schedules in which the plugin component should be periodically invoked.
+ * When this is non-null, the plugin's component must be prepared to be periodically
* invoked by the plugin container's scheduler.
*
* @return the schedule, or <code>null</code> if the plugin should not be scheduled
*/
- public Schedule getSchedule() {
- return this.schedule;
+ public List<ScheduledJobDefinition> getSchedules() {
+ return this.schedules;
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginLifecycleListener.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginLifecycleListener.java
index bb7b05f..f427d73 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginLifecycleListener.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginLifecycleListener.java
@@ -27,7 +27,7 @@ package org.rhq.enterprise.server.plugin.pc;
* for plugin developers to allocate global resources needed by all plugin components and
* a place to clean up those resources.
*
- * Lifecycle listeners are required of generic server plugins because they provide
+ * Plugin components are required of generic server plugins because they provide
* the only mechanism to start and stop.
*
* @author John Mazzitelli
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index 42ce6af..00f3e97 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -23,17 +23,17 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.rhq.core.clientapi.agent.metadata.ConfigurationMetadataParser;
-import org.rhq.core.clientapi.agent.metadata.InvalidPluginDescriptorException;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
-import org.rhq.enterprise.server.xmlschema.generated.serverplugin.LifecycleListenerType;
-import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ScheduleType;
+import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
+import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorMetadataParser;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginComponentType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
@@ -61,10 +61,10 @@ public class ServerPluginManager {
/**
* Cached instances of objects used to initialize and shutdown individual plugins.
- * Only plugins that declare their own lifecycle listener will have objects in this cache.
+ * Only plugins that declare their own plugin component will have objects in this cache.
* This is keyed on plugin name.
*/
- private final Map<String, ServerPluginLifecycleListener> pluginLifecycleListenerCache;
+ private final Map<String, ServerPluginLifecycleListener> pluginComponentCache;
/**
* Creates a plugin manager for the given plugin container.
@@ -75,7 +75,7 @@ public class ServerPluginManager {
this.parentPluginContainer = pc;
this.loadedPlugins = new HashMap<String, ServerPluginEnvironment>();
this.pluginContextCache = new HashMap<String, ServerPluginContext>();
- this.pluginLifecycleListenerCache = new HashMap<String, ServerPluginLifecycleListener>();
+ this.pluginComponentCache = new HashMap<String, ServerPluginLifecycleListener>();
}
/**
@@ -102,7 +102,7 @@ public class ServerPluginManager {
this.loadedPlugins.clear();
this.pluginContextCache.clear();
- this.pluginLifecycleListenerCache.clear();
+ this.pluginComponentCache.clear();
return;
}
@@ -120,23 +120,23 @@ public class ServerPluginManager {
log.debug("Loading server plugin [" + pluginName + "] from: " + env.getPluginUrl());
// tell the plugin we are loading it
- ServerPluginLifecycleListener listener = createServerPluginLifecycleListener(env);
- if (listener != null) {
+ ServerPluginLifecycleListener component = createServerPluginComponent(env);
+ if (component != null) {
ServerPluginContext context = getServerPluginContext(env);
- log.debug("Initializing lifecycle listener for server plugin [" + pluginName + "]");
+ log.debug("Initializing plugin component for server plugin [" + pluginName + "]");
ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(env.getPluginClassLoader());
- listener.initialize(context);
+ component.initialize(context);
} catch (Throwable t) {
- throw new Exception("Lifecycle listener failed to initialize plugin", t);
+ throw new Exception("Plugin component failed to initialize plugin", t);
} finally {
Thread.currentThread().setContextClassLoader(originalContextClassLoader);
}
- this.pluginLifecycleListenerCache.put(pluginName, listener);
+ this.pluginComponentCache.put(pluginName, component);
}
- // note that we only cache it if the lifecycle listener was successful
+ // note that we only cache it if the plugin component was successful
this.loadedPlugins.put(pluginName, env);
return;
@@ -145,18 +145,18 @@ public class ServerPluginManager {
public void startPlugins() {
log.debug("Starting plugins");
- // tell all lifecycle listeners to start
- for (Map.Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
+ // tell all plugin components to start
+ for (Map.Entry<String, ServerPluginLifecycleListener> entry : this.pluginComponentCache.entrySet()) {
String pluginName = entry.getKey();
- ServerPluginLifecycleListener listener = entry.getValue();
+ ServerPluginLifecycleListener component = entry.getValue();
ServerPluginEnvironment env = this.loadedPlugins.get(pluginName);
- log.debug("Starting lifecycle listener for server plugin [" + pluginName + "]");
+ log.debug("Starting plugin component for server plugin [" + pluginName + "]");
ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(env.getPluginClassLoader());
- listener.start();
+ component.start();
} catch (Throwable t) {
- log.warn("Lifecycle listener failed to start plugin [" + pluginName + "]", t);
+ log.warn("Plugin component failed to start plugin [" + pluginName + "]", t);
} finally {
Thread.currentThread().setContextClassLoader(originalContextClassLoader);
}
@@ -168,18 +168,18 @@ public class ServerPluginManager {
public void stopPlugins() {
log.debug("Stopping plugins");
- // tell all lifecycle listeners to stop
- for (Map.Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
+ // tell all plugin components to stop
+ for (Map.Entry<String, ServerPluginLifecycleListener> entry : this.pluginComponentCache.entrySet()) {
String pluginName = entry.getKey();
- ServerPluginLifecycleListener listener = entry.getValue();
+ ServerPluginLifecycleListener component = entry.getValue();
ServerPluginEnvironment env = this.loadedPlugins.get(pluginName);
- log.debug("Stopping lifecycle listener for server plugin [" + pluginName + "]");
+ log.debug("Stopping plugin component for server plugin [" + pluginName + "]");
ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(env.getPluginClassLoader());
- listener.stop();
+ component.stop();
} catch (Throwable t) {
- log.warn("Lifecycle listener failed to stop plugin [" + pluginName + "]", t);
+ log.warn("Plugin component failed to stop plugin [" + pluginName + "]", t);
} finally {
Thread.currentThread().setContextClassLoader(originalContextClassLoader);
}
@@ -202,18 +202,18 @@ public class ServerPluginManager {
try {
// tell the plugin we are unloading it
- ServerPluginLifecycleListener listener = this.pluginLifecycleListenerCache.get(pluginName);
- if (listener != null) {
- log.debug("Shutting down lifecycle listener for server plugin [" + pluginName + "]");
+ ServerPluginLifecycleListener component = this.pluginComponentCache.get(pluginName);
+ if (component != null) {
+ log.debug("Shutting down plugin componentfor server plugin [" + pluginName + "]");
ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(env.getPluginClassLoader());
- listener.shutdown();
+ component.shutdown();
} catch (Throwable t) {
- throw new Exception("Plugin Lifecycle Listener failed to initialize plugin", t);
+ throw new Exception("Plugin plugin componentfailed to initialize plugin", t);
} finally {
Thread.currentThread().setContextClassLoader(originalContextClassLoader);
- this.pluginLifecycleListenerCache.remove(pluginName);
+ this.pluginComponentCache.remove(pluginName);
}
}
} finally {
@@ -247,17 +247,17 @@ public class ServerPluginManager {
}
/**
- * Returns the lifecycle listener instance that is responsible for initializing and managing
- * the plugin. This will return <code>null</code> if a plugin has not defined a lifecycle listener.
+ * Returns the main plugin component instance that is responsible for initializing and managing
+ * the plugin. This will return <code>null</code> if a plugin has not defined a plugin component.
*
- * @param pluginName the name of the plugin whose lifecycle listener is to be returned
+ * @param pluginName the name of the plugin whose plugin component is to be returned
*
- * @return the lifecycle listener instance that initialized and is managing a plugin. Will
- * return <code>null</code> if the plugin has not defined a lifecycle listener.
+ * @return the plugin component instance that initialized and is managing a plugin. Will
+ * return <code>null</code> if the plugin has not defined a plugin component.
* <code>null</code> is also returned if the plugin is not initialized yet.
*/
- public ServerPluginLifecycleListener getServerPluginLifecycleListener(String pluginName) {
- return this.pluginLifecycleListenerCache.get(pluginName);
+ public ServerPluginLifecycleListener getServerPluginComponent(String pluginName) {
+ return this.pluginComponentCache.get(pluginName);
}
public AbstractTypeServerPluginContainer getParentPluginContainer() {
@@ -285,63 +285,56 @@ public class ServerPluginManager {
File dataDir = new File(masterConfig.getDataDirectory(), pluginName);
File tmpDir = masterConfig.getTemporaryDirectory();
- // TODO: today we have no way in the UI to customize the plugin config values
- // for now, just use the defaults as defined in the descriptor
- Configuration config = null;
- try {
- ConfigurationDefinition configDef = ConfigurationMetadataParser.parse(pluginName, pluginDescriptor
- .getPluginConfiguration());
- config = configDef.getDefaultTemplate().createConfiguration();
- } catch (InvalidPluginDescriptorException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
+ Configuration plugnConfig;
+ List<ScheduledJobDefinition> schedules;
- Schedule schedule = null;
- if (pluginDescriptor.getLifecycleListener() != null) {
- ScheduleType scheduleType = pluginDescriptor.getLifecycleListener().getSchedule();
- if (scheduleType != null) {
- boolean concurrent = scheduleType.isConcurrent();
- if (scheduleType.getPeriod() != null) {
- schedule = new PeriodicSchedule(concurrent, scheduleType.getPeriod().longValue());
- } else {
- schedule = new CronSchedule(concurrent, scheduleType.getCron());
- }
- }
+ try {
+ // TODO: today we have no way in the UI to customize the plugin config values
+ // for now, just use the defaults as defined in the descriptor
+ ConfigurationDefinition configDef = ServerPluginDescriptorMetadataParser
+ .getPluginConfigurationDefinition(pluginDescriptor);
+ plugnConfig = configDef.getDefaultTemplate().createConfiguration();
+
+ // TODO: today we have no way in the UI to customize the schedules
+ // for now, just use the defaults as defined in the descriptor
+ schedules = ServerPluginDescriptorMetadataParser.getScheduledJobs(pluginDescriptor);
+ } catch (Exception e) {
+ // TODO need proper exception handling
+ throw new RuntimeException(e);
}
- context = new ServerPluginContext(env, dataDir, tmpDir, config, schedule);
+ context = new ServerPluginContext(env, dataDir, tmpDir, plugnConfig, schedules);
this.pluginContextCache.put(pluginName, context);
return context;
}
/**
- * This will create a new {@link ServerPluginLifecycleListener} instance for that is used to
- * initialize and shutdown a particular server plugin. If there is no plugin lifecycle listener
+ * This will create a new {@link ServerPluginComponent} instance for that is used to
+ * initialize and shutdown a particular server plugin. If there is no plugin component
* configured for the given plugin, <code>null</code> is returned.
*
* The new object will be loaded in the plugin's specific classloader.
*
- * @param pluginName the name of the plugin whose listener is to be retrieved
+ * @param pluginName the name of the plugin whose main component is to be retrieved
* @param environment the environment in which the plugin will execute
*
* @return a new object loaded in the proper plugin classloader that can initialize/shutdown the plugin,
- * or <code>null</code> if there is no plugin lifecycle listener to be associated with the given plugin
+ * or <code>null</code> if there is no plugin component to be associated with the given plugin
*
* @throws Exception if failed to create the instance
*/
- protected ServerPluginLifecycleListener createServerPluginLifecycleListener(ServerPluginEnvironment environment)
+ protected ServerPluginLifecycleListener createServerPluginComponent(ServerPluginEnvironment environment)
throws Exception {
String pluginName = environment.getPluginName();
ServerPluginLifecycleListener instance = null;
- LifecycleListenerType lifecycleListener = environment.getPluginDescriptor().getLifecycleListener();
- if (lifecycleListener != null) {
- String className = lifecycleListener.getClazz();
- log.debug("Creating plugin lifecycle listener [" + className + "] for plugin [" + pluginName + "]");
+ ServerPluginComponentType componentXml = environment.getPluginDescriptor().getPluginComponent();
+ if (componentXml != null) {
+ String className = componentXml.getClazz();
+ log.debug("Creating plugin component [" + className + "] for plugin [" + pluginName + "]");
instance = (ServerPluginLifecycleListener) instantiatePluginClass(environment, className);
- log.debug("Lifecycle listener created [" + instance.getClass() + "] for plugin [" + pluginName + "]");
+ log.debug("Plugin component created [" + instance.getClass() + "] for plugin [" + pluginName + "]");
}
return instance;
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
index 3a2067f..a9c0ee4 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
@@ -22,6 +22,7 @@ package org.rhq.enterprise.server.plugin.pc.generic;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
+import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
@@ -31,13 +32,12 @@ import org.testng.annotations.Test;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.util.stream.StreamUtil;
-import org.rhq.enterprise.server.plugin.pc.PeriodicSchedule;
-import org.rhq.enterprise.server.plugin.pc.Schedule;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.State;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericPluginManager;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener.LifecycleState;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
@Test
public class GenericServerPluginTest extends AbstractEJB3Test {
@@ -65,24 +65,21 @@ public class GenericServerPluginTest extends AbstractEJB3Test {
TestGenericServerPluginContainer pc = this.pluginService.genericPC;
assert pc.state == State.STARTED;
TestGenericPluginManager pm = (TestGenericPluginManager) pc.getPluginManager();
- TestLifecycleListener listener = (TestLifecycleListener) pm.listeners.values().iterator().next();
- assert listener.state == LifecycleState.STARTED;
+ TestLifecycleListener component = (TestLifecycleListener) pm.listeners.values().iterator().next();
+ assert component.state == LifecycleState.STARTED;
// make sure the context is correct
- Configuration config = listener.context.getPluginConfiguration();
+ Configuration config = component.context.getPluginConfiguration();
assert config != null;
assert config.getSimple("plugin-simple-prop-1") != null;
- Schedule schedule = listener.context.getSchedule();
- assert schedule != null;
- assert schedule.isConcurrent() == false;
- assert schedule instanceof PeriodicSchedule;
- assert ((PeriodicSchedule) schedule).getPeriod() == 60000L;
+ List<ScheduledJobDefinition> schedules = component.context.getSchedules();
+ assert schedules == null;
// make sure everything is shutdown
this.pluginService.stopMasterPluginContainer();
assert pc.state == State.UNINITIALIZED;
- assert listener.state == LifecycleState.UNINITIALIZED;
+ assert component.state == LifecycleState.UNINITIALIZED;
}
private File createPluginJar(String jarName, String descriptorXmlFilename) throws Exception {
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
index b6822e0..457026c 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
@@ -162,9 +162,9 @@ public class TestGenericServerPluginService extends ServerPluginService implemen
}
@Override
- protected ServerPluginLifecycleListener createServerPluginLifecycleListener(ServerPluginEnvironment environment)
+ protected ServerPluginLifecycleListener createServerPluginComponent(ServerPluginEnvironment environment)
throws Exception {
- ServerPluginLifecycleListener listener = super.createServerPluginLifecycleListener(environment);
+ ServerPluginLifecycleListener listener = super.createServerPluginComponent(environment);
listeners.put(environment.getPluginName(), listener);
return listener;
}
diff --git a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ScheduledJobDefinition.java b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ScheduledJobDefinition.java
index 40b45b9..a12f7f1 100644
--- a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ScheduledJobDefinition.java
+++ b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ScheduledJobDefinition.java
@@ -29,6 +29,7 @@ public class ScheduledJobDefinition {
private final String jobId;
private final boolean enabled;
private final String methodName;
+ private final String className;
private final AbstractScheduleType scheduleType;
private final Properties callbackData;
@@ -37,6 +38,7 @@ public class ScheduledJobDefinition {
this.jobId = jobId;
this.enabled = enabled;
+ this.className = null; // TODO: for future.. add class to schedule xml schema to support stateless job classes
this.methodName = methodName;
this.scheduleType = scheduleType;
this.callbackData = callbackData;
@@ -50,6 +52,22 @@ public class ScheduledJobDefinition {
return this.enabled;
}
+ /**
+ * The plugin class name that that will perform the work for the job.
+ * If <code>null</code>, the plugin component instance will be used
+ * (i.e. if <code>null</code>, it means the plugin component instance that was used to initialize
+ * the plugin is the same instance that will handle the job; a new instance of the plugin component
+ * class is not created. This allows a plugin to have a stateful object be periodically
+ * invoked for each job invocation, as opposed to having a new object instantiated for
+ * each job invocation).
+ *
+ * @return the class name that will do the work of the job
+ */
+ public String getClassName() {
+ // if null, then it means use the plugin component instance
+ return this.className;
+ }
+
public String getMethodName() {
return this.methodName;
}
@@ -61,4 +79,9 @@ public class ScheduledJobDefinition {
public Properties getCallbackData() {
return this.callbackData;
}
+
+ @Override
+ public String toString() {
+ return this.getClass().getSimpleName() + ": job-id=" + this.jobId;
+ }
}
commit f820e20b6f9dd86de640cd75318cb529d6792ddf
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sat Nov 14 16:28:18 2009 -0500
totally revamp the scheduling metadata.
scheduling is now more powerful by allowing user-defined jobs
to be created and allows users to configure everything about pre-defined
jobs while being able to re-use our config GUI component.
this completely breaks the pc branch, it is uncompilable - breaking
more eggs to make a better omelet.
diff --git a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
index f00dbc8..7141a89 100644
--- a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -10,20 +10,51 @@
xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
xmlns:c="urn:xmlns:rhq-configuration">
- <serverplugin:lifecycle-listener class="MyLifecycleListener">
- <serverplugin:schedule concurrent="true">
- <serverplugin:period>30000</serverplugin:period>
- </serverplugin:schedule>
- </serverplugin:lifecycle-listener>
+ <serverplugin:plugin-component class="MyLifecycleListener" />
- <serverplugin:scheduled-job jobId="first-scheduled-job" concurrent="false" class="MyScheduledJob">
- <serverplugin:cron>0 0/5 * * * ?</serverplugin:cron>
- </serverplugin:scheduled-job>
-
- <serverplugin:scheduled-job jobId="sample-job-2" concurrent="true" class="MyScheduledJob">
- <serverplugin:period>60000</serverplugin:period>
- </serverplugin:scheduled-job>
+ <serverplugin:scheduled-jobs>
+ <!-- notice that we use the map name as the methodName -->
+ <c:map-property name="myScheduledJobMethod1">
+ <c:simple-property name="enabled" type="boolean" required="true" default="true" summary="true" description="Whether or not the job should be scheduled"/>
+ <c:simple-property name="scheduleType" type="string" required="true" default="cron" summary="true" description="Indicates when the schedule triggers">
+ <c:property-options>
+ <c:option value="periodic"/>
+ <c:option value="cron" default="true"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="scheduleTrigger" type="string" required="true" default="0 0/5 * * * ?" summary="true" description="Based on the schedule type, this is either the period, in milliseconds, or the cron expression"/>
+ <c:simple-property name="concurrent" type="boolean" required="false" default="false" summary="true" description="Whether or not the job can be run multiple times concurrently"/>
+ </c:map-property>
+
+ <!-- notice we only want this job to be periodic - do not allow for cron -->
+ <!-- notice we always want this to be concurrent -->
+ <!-- notice that we define our methodName in a property, overriding the map name default (its not summary so you don't see it in the main UI) -->
+ <c:map-property name="anotherJobMapHere" description="This describes what this job does">
+ <c:simple-property name="methodName" type="string" required="true" readOnly="true" default="myScheduledJobMethod2" summary="false" />
+ <c:simple-property name="scheduleType" type="string" required="true" readOnly="true" default="periodic" summary="true" description="Indicates when the schedule triggers" />
+ <c:simple-property name="scheduleTrigger" type="string" required="true" default="60000" summary="true" description="Period, in milliseconds, that the job triggers"/>
+ <c:simple-property name="concurrent" type="boolean" required="true" readOnly="true" default="true" summary="true" description="Whether or not the job can be run multiple times concurrently"/>
+ <c:simple-property name="custom1" type="boolean" required="true" default="true" summary="true" description="A custom boolean for callback data"/>
+ <c:simple-property name="anothercustom2" type="long" required="true" default="12345" summary="true" description="A custom long for callback data"/>
+ </c:map-property>
+
+ <c:list-property name="myUserDefinedJobs" description="A list of user-defined scheduled jobs">
+ <c:map-property name="myUserDefinedJob" description="A user-defined scheduled job">
+ <c:simple-property name="methodName" type="string" required="true" default="" summary="true" description="The method to call on the plugin component when the schedule triggers" />
+ <c:simple-property name="enabled" type="boolean" required="true" default="true" summary="true" description="Whether or not the job should be scheduled"/>
+ <c:simple-property name="scheduleType" type="string" required="true" default="periodic" summary="true" description="Indicates when the schedule triggers">
+ <c:property-options>
+ <c:option value="periodic" default="true"/>
+ <c:option value="cron" />
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="scheduleTrigger" type="string" required="true" default="600000" summary="true" description="Based on the schedule type, this is either the period, in milliseconds, or the cron expression"/>
+ <c:simple-property name="concurrent" type="boolean" required="true" default="false" summary="true" description="Whether or not the job can be run multiple times concurrently"/>
+ </c:map-property>
+ </c:list-property>
+ </serverplugin:scheduled-jobs>
+ <!-- custom global config - unrelated to schedules -->
<serverplugin:plugin-configuration>
<c:simple-property name="myCustomProperty" type="string" required="true"
description="A property my plugin needs to be properly configured" />
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/CronSchedule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/CronSchedule.java
deleted file mode 100644
index b5c7435..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/CronSchedule.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2009 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.plugin.pc;
-
-/**
- * A schedule that triggers based on a cron expression.
- *
- * @author John Mazzitelli
- */
-public class CronSchedule extends Schedule {
- private final String cronExpression;
-
- public CronSchedule(boolean concurrent, String cronExpression) {
- super(concurrent);
- this.cronExpression = cronExpression;
- }
-
- public String getCronExpression() {
- return this.cronExpression;
- }
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PeriodicSchedule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PeriodicSchedule.java
deleted file mode 100644
index 2ff75ba..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PeriodicSchedule.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2009 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.plugin.pc;
-
-/**
- * A schedule that triggers periodically every certain number of milliseconds.
- *
- * @author John Mazzitelli
- */
-public class PeriodicSchedule extends Schedule {
- private final long period;
-
- public PeriodicSchedule(boolean concurrent, long period) {
- super(concurrent);
- this.period = period;
- }
-
- public long getPeriod() {
- return this.period;
- }
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/Schedule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/Schedule.java
deleted file mode 100644
index c985f92..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/Schedule.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2009 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.plugin.pc;
-
-/**
- * Defines a schedule for a server plugin component.
- *
- * @author John Mazzitelli
- */
-public abstract class Schedule {
- private final boolean concurrent;
-
- /**
- * Builds the schedule object.
- *
- * @param concurrent if true, multiple jobs can run concurrently. If false, only one
- * scheduled job will run at any one time across the RHQ Server cloud.
- */
- public Schedule(boolean concurrent) {
- this.concurrent = concurrent;
- }
-
- /**
- * If true, multiple jobs can execute at any one time. If false, only a single job will be allowed
- * to run at any one time (across all servers in the RHQ server cloud). Even if the schedule
- * is triggered multiple times, if a job is still running, any future jobs that are triggered will
- * be delayed.
- *
- * @return concurrent flag
- */
- public boolean isConcurrent() {
- return concurrent;
- }
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java
deleted file mode 100644
index b71ff23..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2009 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.plugin.pc;
-
-import java.util.Properties;
-
-/**
- * An interface to be implemented by any server plugin component that needs to be scheduled.
- *
- * @author John Mazzitelli
- */
-public interface ScheduledJob {
- /**
- * Called when the job triggers.
- *
- * @param jobId the job identifier that was used when creating the job
- * @param lifecycleListener if the plugin has a lifecycle listener, this will be it.
- * Use this object to obtain the plugin context and any other
- * stateful plugin data specific to the plugin being invoked.
- * This may be <code>null</code> if the plugin did not define
- * a global lifecycle listener.
- * @param callbackData a map of data that was used when creating the job whose values are
- * passed back to this method as they were when the job was created.
- *
- * @throws Exception on any error that should cause the schedule to not fire. If an exception
- * is thrown, the schedule will not trigger again until the plugin is restarted
- */
- void execute(String jobId, ServerPluginLifecycleListener lifecycleListener, Properties callbackData)
- throws Exception;
-}
diff --git a/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml b/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml
index 7904ed0..26a2646 100644
--- a/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml
+++ b/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml
@@ -9,11 +9,8 @@
xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
xmlns:c="urn:xmlns:rhq-configuration">
- <serverplugin:lifecycle-listener class="org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener">
- <serverplugin:schedule concurrent="false">
- <serverplugin:period>60000</serverplugin:period>
- </serverplugin:schedule>
- </serverplugin:lifecycle-listener>
+ <serverplugin:plugin-component class="org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener">
+ </serverplugin:plugin-component>
<serverplugin:plugin-configuration>
<c:simple-property name="plugin-simple-prop-1" defaultValue="prop1value" required="true" />
diff --git a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/AbstractScheduleType.java b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/AbstractScheduleType.java
new file mode 100644
index 0000000..cb30ded
--- /dev/null
+++ b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/AbstractScheduleType.java
@@ -0,0 +1,64 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.xmlschema;
+
+/**
+ * Defines a type of schedule for a server plugin job.
+ *
+ * @author John Mazzitelli
+ */
+
+public abstract class AbstractScheduleType {
+ private final String typeName;
+ private final boolean concurrent;
+
+ /**
+ * Builds the schedule type.
+ *
+ * @param concurrent if true, multiple jobs can run concurrently. If false, only one
+ * scheduled job will run at any one time across the RHQ Server cloud.
+ * @param typeName the name of the concrete schedule type (subclasses must provide this)
+ */
+ public AbstractScheduleType(boolean concurrent, String typeName) {
+ this.typeName = typeName;
+ this.concurrent = concurrent;
+ }
+
+ /**
+ * The name that identifies this type of schedule.
+ *
+ * @return type name string
+ */
+ public String getTypeName() {
+ return this.typeName;
+ }
+
+ /**
+ * If true, multiple jobs can execute at any one time. If false, only a single job will be allowed
+ * to run at any one time (across all servers in the RHQ Server cloud). Even if the schedule
+ * is triggered multiple times, if a job is still running, any future jobs that are triggered will
+ * be delayed.
+ *
+ * @return concurrent flag
+ */
+ public boolean isConcurrent() {
+ return this.concurrent;
+ }
+}
diff --git a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/CronScheduleType.java b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/CronScheduleType.java
new file mode 100644
index 0000000..ab72af1
--- /dev/null
+++ b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/CronScheduleType.java
@@ -0,0 +1,40 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.xmlschema;
+
+/**
+ * A schedule that triggers based on a cron expression.
+ *
+ * @author John Mazzitelli
+ */
+public class CronScheduleType extends AbstractScheduleType {
+ public static final String TYPE_NAME = "cron";
+
+ private final String cronExpression;
+
+ public CronScheduleType(boolean concurrent, String cronExpression) {
+ super(concurrent, TYPE_NAME);
+ this.cronExpression = cronExpression;
+ }
+
+ public String getCronExpression() {
+ return this.cronExpression;
+ }
+}
diff --git a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/PeriodicScheduleType.java b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/PeriodicScheduleType.java
new file mode 100644
index 0000000..321ceda
--- /dev/null
+++ b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/PeriodicScheduleType.java
@@ -0,0 +1,40 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.xmlschema;
+
+/**
+ * A schedule type whose jobs are triggered periodically every certain number of milliseconds.
+ *
+ * @author John Mazzitelli
+ */
+public class PeriodicScheduleType extends AbstractScheduleType {
+ public static final String TYPE_NAME = "periodic";
+
+ private final long period;
+
+ public PeriodicScheduleType(boolean concurrent, long period) {
+ super(concurrent, TYPE_NAME);
+ this.period = period;
+ }
+
+ public long getPeriod() {
+ return this.period;
+ }
+}
diff --git a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ScheduledJobDefinition.java b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ScheduledJobDefinition.java
new file mode 100644
index 0000000..40b45b9
--- /dev/null
+++ b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ScheduledJobDefinition.java
@@ -0,0 +1,64 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.xmlschema;
+
+import java.util.Properties;
+
+/**
+ * Provides information about a server plugin scheduled job.
+ *
+ * @author John Mazzitelli
+ */
+public class ScheduledJobDefinition {
+ private final String jobId;
+ private final boolean enabled;
+ private final String methodName;
+ private final AbstractScheduleType scheduleType;
+ private final Properties callbackData;
+
+ public ScheduledJobDefinition(String jobId, boolean enabled, String methodName, AbstractScheduleType scheduleType,
+ Properties callbackData) {
+
+ this.jobId = jobId;
+ this.enabled = enabled;
+ this.methodName = methodName;
+ this.scheduleType = scheduleType;
+ this.callbackData = callbackData;
+ }
+
+ public String getJobId() {
+ return this.jobId;
+ }
+
+ public boolean isEnabled() {
+ return this.enabled;
+ }
+
+ public String getMethodName() {
+ return this.methodName;
+ }
+
+ public AbstractScheduleType getScheduleType() {
+ return this.scheduleType;
+ }
+
+ public Properties getCallbackData() {
+ return this.callbackData;
+ }
+}
diff --git a/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorMetadataParser.java b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorMetadataParser.java
new file mode 100644
index 0000000..0c81095
--- /dev/null
+++ b/modules/enterprise/server/xml-schemas/src/main/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorMetadataParser.java
@@ -0,0 +1,242 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.xmlschema;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.rhq.core.clientapi.agent.metadata.ConfigurationMetadataParser;
+import org.rhq.core.clientapi.agent.metadata.InvalidPluginDescriptorException;
+import org.rhq.core.clientapi.descriptor.configuration.ConfigurationDescriptor;
+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.core.domain.configuration.definition.ConfigurationTemplate;
+import org.rhq.core.domain.configuration.definition.PropertyDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
+
+/**
+ * Provides methods to parse the server plugin descriptors.
+ *
+ * @author John Mazzitelli
+ */
+public class ServerPluginDescriptorMetadataParser {
+
+ // pre-defined property names for schedule definitions
+ private static final String SCHEDULED_JOB_PROP_NAME_ENABLED = "enabled";
+ private static final String SCHEDULED_JOB_PROP_NAME_METHOD_NAME = "methodName";
+ private static final String SCHEDULED_JOB_PROP_NAME_CONCURRENT = "concurrent";
+ private static final String SCHEDULED_JOB_PROP_NAME_SCHEDULE_TYPE = "scheduleType";
+ private static final String SCHEDULED_JOB_PROP_NAME_SCHEDULE_TRIGGER = "scheduleTrigger";
+
+ /**
+ * Returns the global configuration definition for the plugin. This does not include any scheduled
+ * job information - see {@link #getScheduledJobs(ServerPluginDescriptorType)} for that.
+ *
+ * @param descriptor
+ *
+ * @return the plugin configuration definition, or <code>null</code> if the descriptor did not define plugin config.
+ *
+ * @throws Exception if the plugin descriptor was invalid
+ */
+ public static ConfigurationDefinition getPluginConfigurationDefinition(ServerPluginDescriptorType descriptor)
+ throws Exception {
+
+ ConfigurationDefinition config = null;
+ ConfigurationDescriptor configXml = descriptor.getPluginConfiguration();
+ if (configXml != null) {
+ config = ConfigurationMetadataParser.parse(descriptor.getName(), configXml);
+ }
+ return config;
+ }
+
+ /**
+ * Given a descriptor, this will parse it and return any scheduled jobs that it finds.
+ * This essentially gives you a list of the pre-defined jobs, prior to a user customizing
+ * them with their own settings.
+ *
+ * @param descriptor
+ *
+ * @return list of jobs that are defined, will be empty if no jobs are defined.
+ *
+ * @throws Exception if the plugin descriptor was invalid
+ */
+ public static List<ScheduledJobDefinition> getScheduledJobs(ServerPluginDescriptorType descriptor) throws Exception {
+ List<ScheduledJobDefinition> jobs = new ArrayList<ScheduledJobDefinition>();
+
+ ConfigurationDescriptor configXml = descriptor.getScheduledJobs();
+ if (configXml != null) {
+ ConfigurationDefinition config = ConfigurationMetadataParser.parse(descriptor.getName(), configXml);
+ for (PropertyDefinition propDef : config.getPropertyDefinitions().values()) {
+ ScheduledJobDefinition jobDef = getScheduledJob(propDef);
+ if (jobDef != null) {
+ jobs.add(jobDef);
+ }
+ }
+ }
+
+ return jobs;
+ }
+
+ private static ScheduledJobDefinition getScheduledJob(PropertyDefinition mapDef) throws Exception {
+ ScheduledJobDefinition job = null;
+
+ // if the definition is not a map, it can't be a schedule
+ if (mapDef instanceof PropertyDefinitionMap) {
+ PropertyDefinitionMap jobMapDef = (PropertyDefinitionMap) mapDef;
+ ConfigurationTemplate defaultTemplate = jobMapDef.getConfigurationDefinition().getDefaultTemplate();
+ PropertyMap defaults = defaultTemplate.getConfiguration().getMap(mapDef.getName());
+ // prepare some defaults if the schedule didn't define some of these
+ // we assume:
+ // the map name is the methodName that will be invoked
+ // the schedule is always enabled
+ // the schedule is never concurrent
+ // the schedule is a periodic schedule that triggers every 10 minutes
+ // the schedule has no callback data
+ String methodName = defaults.getSimpleValue(SCHEDULED_JOB_PROP_NAME_METHOD_NAME, mapDef.getName());
+ String enabledStr = defaults.getSimpleValue(SCHEDULED_JOB_PROP_NAME_ENABLED, "true");
+ String concurrentStr = defaults.getSimpleValue(SCHEDULED_JOB_PROP_NAME_CONCURRENT, "false");
+ String scheduleTypeStr = defaults.getSimpleValue(SCHEDULED_JOB_PROP_NAME_SCHEDULE_TYPE,
+ PeriodicScheduleType.TYPE_NAME);
+ String scheduleTriggerStr = defaults.getSimpleValue(SCHEDULED_JOB_PROP_NAME_SCHEDULE_TRIGGER, "600000");
+
+ String jobId = jobMapDef.getName();
+ boolean enabled = Boolean.parseBoolean(enabledStr);
+ boolean concurrent = Boolean.parseBoolean(concurrentStr);
+
+ AbstractScheduleType scheduleType;
+ if (PeriodicScheduleType.TYPE_NAME.equalsIgnoreCase(scheduleTypeStr)) {
+ scheduleType = new PeriodicScheduleType(concurrent, Long.parseLong(scheduleTriggerStr));
+ } else if (CronScheduleType.TYPE_NAME.equalsIgnoreCase(scheduleTypeStr)) {
+ scheduleType = new CronScheduleType(concurrent, scheduleTriggerStr);
+ } else {
+ throw new InvalidPluginDescriptorException("Invalid schedule type: " + scheduleTypeStr);
+ }
+
+ // the callback data will contain all simple properties in the schedule job map
+ Properties callbackData = new Properties();
+ Map<String, PropertyDefinition> allPropDefs = jobMapDef.getPropertyDefinitions();
+ for (PropertyDefinition currentPropDef : allPropDefs.values()) {
+ if (currentPropDef instanceof PropertyDefinitionSimple) {
+ String currentPropDefName = currentPropDef.getName();
+ callbackData.setProperty(currentPropDefName, defaults.getSimpleValue(currentPropDefName, null));
+ }
+ }
+
+ job = new ScheduledJobDefinition(jobId, enabled, methodName, scheduleType, callbackData);
+ }
+
+ return job;
+ }
+
+ /**
+ * Given a configuration, this will return any scheduled jobs that are defined in it.
+ * This essentially gives you a list of the jobs that may be different from the descriptor's
+ * pre-defined jobs due to a user customizing them with their own settings.
+ *
+ * @param jobsConfig the configuration with the scheduled job information
+ *
+ * @return list of jobs that are defined, will be empty if no jobs are defined.
+ *
+ * @throws Exception if the configuration was invalid
+ */
+ public static List<ScheduledJobDefinition> getScheduledJobs(Configuration scheduledJobsConfig) throws Exception {
+
+ List<ScheduledJobDefinition> jobs = new ArrayList<ScheduledJobDefinition>();
+
+ if (scheduledJobsConfig != null) {
+ for (Property prop : scheduledJobsConfig.getProperties()) {
+ ScheduledJobDefinition jobDef = getScheduledJob(prop);
+ if (jobDef != null) {
+ jobs.add(jobDef);
+ } else {
+ // this might be a list-o-maps containing a list of user-define jobs
+ if (prop instanceof PropertyList) {
+ PropertyList listOfJobs = (PropertyList) prop;
+ for (Property listItem : listOfJobs.getList()) {
+ jobDef = getScheduledJob(listItem);
+ if (jobDef != null) {
+ jobs.add(jobDef);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return jobs;
+ }
+
+ private static ScheduledJobDefinition getScheduledJob(Property map) throws Exception {
+ ScheduledJobDefinition job = null;
+
+ // if the definition is not a map, it can't be a schedule
+ if (map instanceof PropertyMap) {
+ PropertyMap jobMap = (PropertyMap) map;
+ // prepare some defaults if the schedule didn't define some of these
+ // we assume:
+ // the map name is the methodName that will be invoked
+ // the schedule is always enabled
+ // the schedule is never concurrent
+ // the schedule is a periodic schedule that triggers every 10 minutes
+ // the schedule has no callback data
+ String methodName = jobMap.getSimpleValue(SCHEDULED_JOB_PROP_NAME_METHOD_NAME, map.getName());
+ String enabledStr = jobMap.getSimpleValue(SCHEDULED_JOB_PROP_NAME_ENABLED, "true");
+ String concurrentStr = jobMap.getSimpleValue(SCHEDULED_JOB_PROP_NAME_CONCURRENT, "false");
+ String scheduleTypeStr = jobMap.getSimpleValue(SCHEDULED_JOB_PROP_NAME_SCHEDULE_TYPE,
+ PeriodicScheduleType.TYPE_NAME);
+ String scheduleTriggerStr = jobMap.getSimpleValue(SCHEDULED_JOB_PROP_NAME_SCHEDULE_TRIGGER, "600000");
+
+ String jobId = jobMap.getName();
+ boolean enabled = Boolean.parseBoolean(enabledStr);
+ boolean concurrent = Boolean.parseBoolean(concurrentStr);
+
+ AbstractScheduleType scheduleType;
+ if (PeriodicScheduleType.TYPE_NAME.equalsIgnoreCase(scheduleTypeStr)) {
+ scheduleType = new PeriodicScheduleType(concurrent, Long.parseLong(scheduleTriggerStr));
+ } else if (CronScheduleType.TYPE_NAME.equalsIgnoreCase(scheduleTypeStr)) {
+ scheduleType = new CronScheduleType(concurrent, scheduleTriggerStr);
+ } else {
+ throw new InvalidPluginDescriptorException("Invalid schedule type: " + scheduleTypeStr);
+ }
+
+ // the callback data will contain all simple properties in the schedule job map
+ Properties callbackData = new Properties();
+ Map<String, Property> allProps = jobMap.getMap();
+ for (Property currentProp : allProps.values()) {
+ if (currentProp instanceof PropertySimple) {
+ String currentPropName = currentProp.getName();
+ callbackData.setProperty(currentPropName, jobMap.getSimpleValue(currentPropName, null));
+ }
+ }
+
+ job = new ScheduledJobDefinition(jobId, enabled, methodName, scheduleType, callbackData);
+ }
+
+ return job;
+ }
+}
diff --git a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
index 2791fee..81e2e01 100644
--- a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
+++ b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
@@ -14,10 +14,7 @@
<xs:annotation>
<xs:documentation>
Schema for all server-side plugins. All server side plugin types
- will define their own schema that get embedded in this schema.
- Since there are only a strictly defined number of plugin types,
- each plugin type's schema will be explicitly included in this
- schema, under the plugin element's choice definition.
+ will define their own schema that extend this schema.
</xs:documentation>
<xs:appinfo>
<jaxb:schemaBindings>
@@ -31,7 +28,7 @@
<xs:documentation>
Root element of a server-side plugin descriptor. All server side plugins
will have this as their root element; however, child elements of this
- root element will be plugin-type-specific. Note this is an abstract element,
+ root element can be plugin-type-specific. Note this is an abstract element,
it will actually be substituted with other elements of the concrete plugin types.
</xs:documentation>
<xs:appinfo>
@@ -42,22 +39,43 @@
<xs:complexType name="ServerPluginDescriptorType">
<xs:sequence minOccurs="0" maxOccurs="1">
- <xs:element name="lifecycle-listener" minOccurs="0" maxOccurs="1" type="serverplugin:LifecycleListenerType">
+ <xs:element name="plugin-component" minOccurs="0" maxOccurs="1" type="serverplugin:ServerPluginComponentType">
<xs:annotation>
<xs:documentation>
- A class that performs global initialization and shutdown of the plugin. If specified,
- this class will be notified when the plugin is loaded and unloaded. This provides a place
- for plugin developers to allocate global resources needed by all plugin components and
- a place to clean up those resources. It can also be scheduled to perform periodic work.
- A lifecycle listener object is stateful - the instance lives for as long as the plugin
+ A class that will be notified when the plugin is started and stopped. This provides a place
+ for plugin developers to allocate global resources needed by the plugin and
+ a place to clean up those resources. This component can also be scheduled to perform periodic work.
+ The plugin component object is stateful - the instance lives for as long as the plugin
is initialized.
</xs:documentation>
</xs:annotation>
</xs:element>
- <xs:element name="scheduled-job" minOccurs="0" maxOccurs="unbounded" type="serverplugin:ScheduledJobType">
+ <xs:element name="scheduled-jobs" minOccurs="0" maxOccurs="1" type="config:configuration">
<xs:annotation>
<xs:documentation>
- A scheduled job that is called to periodically perform work on behalf of the plugin.
+ Scheduled jobs are pre-defined here in this special configuration. The schema
+ for this element is the same as the general configuration, however, this
+ has special semantics that require special properties to be defined.
+ If you use this element, it must contain map properties where each map:
+ 1) has a name that is a method name of the plugin component. This method
+ name identifies what is called on the plugin component when the schedule triggers.
+ You may override this by defining a simple property called "methodName".
+ 2) has simple properties called "scheduleType" and "scheduleTrigger" where
+ "scheduleType" is either "cron" or "periodic" and "scheduleTrigger" is either
+ the cron expression or a time period in milliseconds.
+ 3) has a simple property called "concurrent" of type boolean to indicate if
+ multiple invocations of the scheduled job are allowed to
+ occur at the same time. If false, only one invocation will ever run at any
+ one time. This means that if a schedule triggers again while the previous
+ scheduled invocation is still running, the second invocation will be delayed
+ until after the previous invocation completes. If there is more than one
+ RHQ Server in the system, and this is false, you can be assured that only
+ a single server will handle the invocation at any one time (i.e. multiple servers
+ will not run invocations at the same time).
+ 4) has any other simple properties that will be used as custom callback data properties.
+ You may additionally define one list-of-maps property which can be used to allow a user
+ to define their own custom jobs. The list-of-maps must contain a map property definition
+ that follows the same rules as described above.
</xs:documentation>
</xs:annotation>
</xs:element>
@@ -123,93 +141,17 @@
</xs:attribute>
</xs:complexType>
- <xs:complexType name="LifecycleListenerType">
- <xs:sequence>
- <xs:element name="schedule" minOccurs="0" maxOccurs="1" type="serverplugin:ScheduleType">
- <xs:annotation>
- <xs:documentation>
- A schedule that defines when and how often to invoke the plugin listener. This is optional; only
- those plugins that need to do work periodically will define a schedule.
- </xs:documentation>
- </xs:annotation>
- </xs:element>
- </xs:sequence>
+ <xs:complexType name="ServerPluginComponentType">
<xs:attribute name="class" type="serverplugin:classNameType" use="required">
<xs:annotation>
<xs:documentation>
The class that will be instantiated. This is a stateful object, once initialized, the same
- instance will be used to start, stop and shutdown the plugin.
+ instance will be notified when the plugin is started, stopped or when schedules are triggered.
</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
- <xs:complexType name="ScheduleType">
- <xs:sequence minOccurs="0" maxOccurs="1">
- <xs:choice>
- <xs:element name="period" type="xs:long">
- <xs:annotation>
- <xs:documentation>
- A time period, in milliseconds, that define how often the schedule will trigger.
- </xs:documentation>
- </xs:annotation>
- </xs:element>
- <xs:element name="cron" type="xs:string">
- <xs:annotation>
- <xs:documentation>
- A "cron expression" which defines when the schedule should fire. A cron expression can be evaluated
- to mean things such as: "At 8:00am every Monday through Friday" or "At 1:30am every last Friday of the month".
- The cron expression syntax follows the rules defined by Quartz - see
- http://www.opensymphony.com/quartz/api/org/quartz/CronExpression.html
- </xs:documentation>
- </xs:annotation>
- </xs:element>
- </xs:choice>
- </xs:sequence>
- <xs:attribute name="concurrent" type="xs:boolean" use="optional" default="true">
- <xs:annotation>
- <xs:documentation>
- If true, multiple invocations of the scheduled job are allowed to
- occur at the same time. If false, only one invocation will ever run at any
- one time. This means that if a schedule triggers again while the previous
- scheduled invocation is still running, the second invocation will be delayed
- until after the previous invocation completes. If there is more than one
- RHQ Server in the system, and this is false, you can be assured that only
- a single server will handle the invocation at any one time (i.e. multiple servers
- will not run invocations at the same time).
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:complexType>
-
- <xs:complexType name="ScheduledJobType">
- <xs:complexContent>
- <xs:extension base="serverplugin:ScheduleType">
- <xs:attribute name="jobId" type="xs:string" use="required">
- <xs:annotation>
- <xs:documentation>
- A unique identifier for this job. Job IDs need to be unique
- within a plugin. When the scheduled job is invoked, this job ID
- will be passed to it.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="class" type="serverplugin:classNameType" use="required">
- <xs:annotation>
- <xs:documentation>
- The classname of the ScheduledJob implementation that will be instantiated
- whenever the schedule is triggered. This job instance will not be stateful,
- a new instance of the class is created for each schedule trigger. Each job
- invocation is handed a reference to the plugin's lifecycle listener (if one
- was defined for the plugin), thus providing a way to obtain stateful
- information from the plugin.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- </xs:extension>
- </xs:complexContent>
- </xs:complexType>
-
<xs:simpleType name="classNameType">
<xs:restriction base="xs:string">
<xs:whiteSpace value="collapse" />
diff --git a/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java b/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
index 3e1247d..f38a541 100644
--- a/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
+++ b/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
@@ -37,10 +37,9 @@ import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
import org.rhq.core.clientapi.descriptor.configuration.ConfigurationDescriptor;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.util.stream.StreamUtil;
-import org.rhq.enterprise.server.xmlschema.generated.serverplugin.LifecycleListenerType;
-import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ScheduleType;
-import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ScheduledJobType;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginComponentType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.alert.AlertPluginDescriptorType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.generic.GenericPluginDescriptorType;
@@ -71,24 +70,48 @@ public class ServerPluginDescriptorUtilTest {
assert descriptor.getDescription().equals("generic description");
assert descriptor.getPackage().equals("generic.package");
- LifecycleListenerType lifecycleListener = descriptor.getLifecycleListener();
- ScheduleType schedule = lifecycleListener.getSchedule();
- assert lifecycleListener.getClazz().equals("generic.plugin.lifecycle.listener");
- assert schedule.getCron().equals("0 15 10 ? * MON-FRI");
- assert schedule.getPeriod() == null;
-
- List<ScheduledJobType> scheduledJobs = descriptor.getScheduledJob();
- scheduledJobs.get(0).getJobId().equals("generic-job-1");
- scheduledJobs.get(0).getClazz().equals("generic.scheduled.job1");
- scheduledJobs.get(0).getPeriod().equals("123");
- scheduledJobs.get(1).getJobId().equals("generic-job-2");
- scheduledJobs.get(1).getClazz().equals("generic.scheduled.job2");
- scheduledJobs.get(1).getCron().equals("0 30 11 ? * WED-FRI");
-
- ConfigurationDescriptor config = descriptor.getPluginConfiguration();
+ ServerPluginComponentType pluginComponent = descriptor.getPluginComponent();
+ assert pluginComponent.getClazz().equals("generic.plugin.component");
+
+ List<ScheduledJobDefinition> scheduledJobs = ServerPluginDescriptorMetadataParser.getScheduledJobs(descriptor);
+ assert scheduledJobs.size() == 3;
+
+ ScheduledJobDefinition jobItem;
+
+ jobItem = scheduledJobs.get(0);
+ assert jobItem.getJobId().equals("myFirstJob");
+ assert jobItem.getMethodName().equals("methodNameFoo");
+ assert !jobItem.isEnabled();
+ assert !jobItem.getScheduleType().isConcurrent();
+ assert jobItem.getScheduleType() instanceof CronScheduleType;
+ assert ((CronScheduleType) jobItem.getScheduleType()).getCronExpression().equals("0 15 10 ? * MON-FRI");
+ assert jobItem.getCallbackData().size() == 7 : jobItem.getCallbackData();
+ assert jobItem.getCallbackData().getProperty("custom1").equals("true");
+ assert jobItem.getCallbackData().getProperty("anothercustom2").equals("12345");
+ assert jobItem.getCallbackData().getProperty("methodName").equals("methodNameFoo"); // just proves we get the built-in data, too
+
+ jobItem = scheduledJobs.get(1);
+ assert jobItem.getJobId().equals("anotherMethod");
+ assert jobItem.getMethodName().equals("anotherMethod");
+ assert jobItem.isEnabled();
+ assert jobItem.getScheduleType().isConcurrent();
+ assert jobItem.getScheduleType() instanceof PeriodicScheduleType;
+ assert ((PeriodicScheduleType) jobItem.getScheduleType()).getPeriod() == 59999L;
+ assert jobItem.getCallbackData().size() == 3 : jobItem.getCallbackData();
+
+ jobItem = scheduledJobs.get(2);
+ assert jobItem.getJobId().equals("allDefaultsJob");
+ assert jobItem.getMethodName().equals("allDefaultsJob");
+ assert jobItem.isEnabled();
+ assert !jobItem.getScheduleType().isConcurrent();
+ assert jobItem.getScheduleType() instanceof PeriodicScheduleType;
+ assert ((PeriodicScheduleType) jobItem.getScheduleType()).getPeriod() == 600000L;
+ assert jobItem.getCallbackData().size() == 0 : jobItem.getCallbackData();
+
+ ConfigurationDefinition config;
+ config = ServerPluginDescriptorMetadataParser.getPluginConfigurationDefinition(descriptor);
assert config != null;
- assert config.getConfigurationProperty().get(0).getValue().getName().equals("prop1");
-
+ assert config.getPropertyDefinitionSimple("prop1") != null;
return;
}
@@ -105,17 +128,20 @@ public class ServerPluginDescriptorUtilTest {
assert descriptor.getDescription().equals("alert plugin wotgorilla?");
assert descriptor.getPackage().equals("org.alert.package.name.here");
- LifecycleListenerType lifecycleListener = descriptor.getLifecycleListener();
- ScheduleType schedule = lifecycleListener.getSchedule();
- assert lifecycleListener.getClazz().equals("alertPluginLifecycleListener");
- assert schedule.getCron() == null;
- assert schedule.getPeriod().longValue() == 1000L;
+ ServerPluginComponentType pluginComponent = descriptor.getPluginComponent();
+ assert pluginComponent.getClazz().equals("alertPluginComponent");
+
+ assert descriptor.getScheduledJobs() == null;
+ assert ServerPluginDescriptorMetadataParser.getScheduledJobs(descriptor).size() == 0;
- assert descriptor.getScheduledJob().size() == 0;
+ ConfigurationDescriptor configDescriptor = descriptor.getPluginConfiguration();
+ assert configDescriptor != null;
+ assert configDescriptor.getConfigurationProperty().get(0).getValue().getName().equals("alertprop1");
- ConfigurationDescriptor config = descriptor.getPluginConfiguration();
+ ConfigurationDefinition config;
+ config = ServerPluginDescriptorMetadataParser.getPluginConfigurationDefinition(descriptor);
assert config != null;
- assert config.getConfigurationProperty().get(0).getValue().getName().equals("alertprop1");
+ assert config.getPropertyDefinitionSimple("alertprop1") != null;
}
private ServerPluginDescriptorType parseTestXml(String testXml) throws Exception {
diff --git a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-alert.xml b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-alert.xml
index b7affce..021030f 100644
--- a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-alert.xml
+++ b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-alert.xml
@@ -11,11 +11,7 @@
xmlns:c="urn:xmlns:rhq-configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <serverplugin:lifecycle-listener class="alertPluginLifecycleListener">
- <serverplugin:schedule>
- <serverplugin:period>1000</serverplugin:period>
- </serverplugin:schedule>
- </serverplugin:lifecycle-listener>
+ <serverplugin:plugin-component class="alertPluginComponent" />
<serverplugin:plugin-configuration>
<c:simple-property name="alertprop1" />
diff --git a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
index fcb58ca..e4b37a9 100644
--- a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
+++ b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
@@ -11,23 +11,54 @@
xmlns:c="urn:xmlns:rhq-configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
- <serverplugin:lifecycle-listener class="generic.plugin.lifecycle.listener">
- <serverplugin:schedule>
- <!-- Fire at 10:15am every weekday -->
- <serverplugin:cron>0 15 10 ? * MON-FRI</serverplugin:cron>
- </serverplugin:schedule>
- </serverplugin:lifecycle-listener>
+ <serverplugin:plugin-component class="generic.plugin.component" />
- <serverplugin:scheduled-job jobId="generic-job-1" class="generic.scheduled.job1" concurrent="false">
- <serverplugin:period>123</serverplugin:period>
- </serverplugin:scheduled-job>
+ <serverplugin:scheduled-jobs>
+ <c:map-property name="myFirstJob" >
+ <c:simple-property name="methodName" type="string" required="true" default="methodNameFoo" summary="true" description="The method to invoke"/>
+ <c:simple-property name="enabled" type="boolean" required="true" default="false" summary="true" description="Whether or not the job should be scheduled"/>
+ <c:simple-property name="scheduleType" type="string" required="true" default="cron" summary="true" description="Indicates when the schedule triggers">
+ <c:property-options>
+ <c:option value="periodic"/>
+ <c:option value="cron" default="true"/>
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="scheduleTrigger" type="string" required="true" default="0 15 10 ? * MON-FRI" summary="true" description="Based on the schedule type, this is either the period, in milliseconds, or the cron expression"/>
+ <c:simple-property name="concurrent" type="boolean" required="false" default="false" summary="true" description="Whether or not the job can be run multiple times concurrently"/>
+ <c:simple-property name="custom1" type="boolean" required="true" default="true" summary="true" description="A custom boolean for callback data"/>
+ <c:simple-property name="anothercustom2" type="long" required="true" default="12345" summary="true" description="A custom long for callback data"/>
+ </c:map-property>
+
+ <!-- notice we only want this job to be periodic - do not allow for cron -->
+ <!-- notice we always want this to be concurrent -->
+ <!-- it is always enabled, no need to specify a enabled prop - we assume true -->
+ <c:map-property name="anotherMethod" >
+ <c:simple-property name="scheduleType" type="string" required="true" readOnly="true" default="periodic" summary="true" description="Indicates when the schedule triggers" />
+ <c:simple-property name="scheduleTrigger" type="string" required="true" default="59999" summary="true" description="Period, in milliseconds, that the job triggers"/>
+ <c:simple-property name="concurrent" type="boolean" required="true" readOnly="true" default="true" summary="true" description="Whether or not the job can be run multiple times concurrently"/>
+ </c:map-property>
+
+ <c:map-property name="allDefaultsJob"></c:map-property>
- <serverplugin:scheduled-job jobId="generic-job-2" class="generic.scheduled.job2" concurrent="true">
- <!-- Fire at 11:30am every wed-thru-fri -->
- <serverplugin:cron>0 30 11 ? * WED-FRI</serverplugin:cron>
- </serverplugin:scheduled-job>
-
- <serverplugin:plugin-configuration>
- <c:simple-property name="prop1" />
+ <c:list-property name="myUserDefinedJobs" description="A list of user-defined scheduled jobs">
+ <c:map-property name="myUserDefinedJob" description="A user-defined scheduled job">
+ <c:simple-property name="methodName" type="string" required="true" default="" summary="true" description="The method to call on the plugin component when the schedule triggers" />
+ <c:simple-property name="enabled" type="boolean" required="true" default="true" summary="true" description="Whether or not the job should be scheduled"/>
+ <c:simple-property name="scheduleType" type="string" required="true" default="periodic" summary="true" description="Indicates when the schedule triggers">
+ <c:property-options>
+ <c:option value="periodic" default="true"/>
+ <c:option value="cron" />
+ </c:property-options>
+ </c:simple-property>
+ <c:simple-property name="scheduleTrigger" type="string" required="true" default="12345" summary="true" description="Based on the schedule type, this is either the period, in milliseconds, or the cron expression"/>
+ <c:simple-property name="concurrent" type="boolean" required="true" default="false" summary="true" description="Whether or not the job can be run multiple times concurrently"/>
+ </c:map-property>
+ </c:list-property>
+
+ </serverplugin:scheduled-jobs>
+
+ <serverplugin:plugin-configuration>
+ <!-- custom global config - unrelated to schedules -->
+ <c:simple-property name="prop1" type="string" required="true" default="prop1value" />
</serverplugin:plugin-configuration>
</generic-plugin>
commit 325d781604e37c7c195e5d21f17dc52d7e8f7f9e
Author: John Matthews <jmatthew(a)redhat.com>
Date: Sat Nov 14 14:55:42 2009 -0500
560 - changes for distribution sync.
Looks like more work is needed on package syncs.
Package syncs do not appear to be working, Distribution Syncs were tested by
commenting out package sync code from ContentProviderManager.
Distribution syncs tested against rhel-i386-server-5, metadata is synced and populated in database
kickstart files are fetched from RHN and stored
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
index 1158f97..adc4b5a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
@@ -76,6 +76,7 @@ import org.rhq.core.domain.content.RepoPackageVersion;
import org.rhq.core.domain.content.Distribution;
import org.rhq.core.domain.content.DistributionFile;
import org.rhq.core.domain.content.DistributionType;
+import org.rhq.core.domain.content.RepoDistribution;
import org.rhq.core.domain.content.composite.LoadedPackageBitsComposite;
import org.rhq.core.domain.content.composite.PackageVersionFile;
import org.rhq.core.domain.content.composite.PackageVersionMetadataComposite;
@@ -86,6 +87,7 @@ import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.PageOrdering;
import org.rhq.core.domain.util.PersistenceUtility;
+import org.rhq.core.domain.criteria.RepoCriteria;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.core.util.stream.StreamUtil;
@@ -103,6 +105,8 @@ import org.rhq.enterprise.server.plugin.pc.content.RepoDetails;
import org.rhq.enterprise.server.plugin.pc.content.DistributionSyncReport;
import org.rhq.enterprise.server.plugin.pc.content.DistributionDetails;
import org.rhq.enterprise.server.plugin.pc.content.DistributionFileDetails;
+import org.rhq.enterprise.server.plugin.pc.content.ContentProvider;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionSource;
import org.rhq.enterprise.server.resource.ProductVersionManagerLocal;
/**
@@ -671,6 +675,84 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
@RequiredPermission(Permission.MANAGE_INVENTORY)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
@TransactionTimeout(45 * 60)
+ public void downloadDistributionBits(Subject subject, ContentSource contentSource) {
+ try {
+ log.debug("downloadDistributionBits invoked");
+ DistributionManagerLocal distManager = LookupUtil.getDistributionManagerLocal();
+ ContentServerPluginContainer pc = ContentManagerHelper.getPluginContainer();
+ int contentSourceId = contentSource.getId();
+ ContentProviderManager cpMgr = pc.getAdapterManager();
+ ContentProvider provider = cpMgr.getIsolatedContentProvider(contentSource.getId());
+ assert (provider instanceof DistributionSource);
+ DistributionSource distSource = (DistributionSource)provider;
+
+ //
+ // Following same sort of workaround done in ContentProviderManager for synchronizeContentSource
+ // Assume this will need to be updated when we place syncing in repo layer
+ //
+ RepoCriteria reposForContentSource = new RepoCriteria();
+ reposForContentSource.addFilterContentSourceIds(contentSourceId);
+ reposForContentSource.addFilterCandidate(false); // Don't sync distributions for candidates
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ List<Repo> repos = repoManager.findReposByCriteria(overlord, reposForContentSource);
+ log.debug("downloadDistributionBits found " + repos.size() + " repos associated with this contentSourceId "
+ + contentSourceId);
+ for (Repo repo: repos) {
+ log.debug("downloadDistributionBits operating on repo: " + repo.getName() + " id = " + repo.getId());
+ // Look up Distributions associated with this ContentSource.
+ PageControl pageControl = PageControl.getUnlimitedInstance();
+ log.debug("Looking up existing distributions for repoId: " + repo.getId());
+ List<Distribution> dists = repoManager.findAssociatedDistributions(overlord, repo.getId(), pageControl);
+ log.debug("Found " + dists.size() + " Distributions for repoId " + repo.getId());
+
+ for (Distribution dist: dists) {
+ log.debug("Looking up DistributionFiles for dist: " + dist);
+ List<DistributionFile> distFiles = distManager.getDistributionFilesByDistId(dist.getId());
+ log.debug("Found " + distFiles.size() + " DistributionFiles");
+ for (DistributionFile dFile: distFiles) {
+ String relPath = dist.getBasePath() + "/" + dFile.getRelativeFilename();
+ File outputFile =
+ getDistLocalFileAndCreateParentDir(dist.getLabel(), relPath);
+ log.debug("Checking if file exists at: " + outputFile.getAbsolutePath());
+ if (outputFile.exists()) {
+ log.debug("File " + outputFile.getAbsolutePath() + " exists, checking md5sum");
+ String expectedMD5 = (dFile.getMd5sum() != null) ? dFile.getMd5sum() : "<unspecified MD5>";
+ String actualMD5 = MessageDigestGenerator.getDigestString(outputFile);
+ if (!expectedMD5.trim().toLowerCase().equals(actualMD5.toLowerCase())) {
+ log.error("Expected [" + expectedMD5 + "] versus actual [" +
+ actualMD5 + "] md5sums for file " + outputFile.getAbsolutePath() +
+ " do not match.");
+ log.error("Need to re-fetch file. Will download from DistributionSource" +
+ " and overwrite local file.");
+ } else {
+ log.info(outputFile + " exists and md5sum matches [" + actualMD5 +
+ "] no need to re-download");
+ continue; // skip the download from bitsStream
+ }
+ }
+ log.debug("Attempting download of " + dFile.getRelativeFilename() +
+ " from contentSourceId " + contentSourceId);
+ String remoteFetchLoc = distSource.getRemoteLocation(repo.getName(), dist.getLabel(),
+ dFile.getRelativeFilename());
+ InputStream bitsStream = pc.getAdapterManager().loadDistributionFileBits(contentSourceId,
+ remoteFetchLoc);
+ StreamUtil.copy(bitsStream, new FileOutputStream(outputFile), true);
+ bitsStream = null;
+ log.debug("DistributionFile has been downloaded to: " + outputFile.getAbsolutePath());
+ }
+ }
+ }
+ }
+ catch (Exception e) {
+ log.error(e);
+ e.printStackTrace();
+ }
+ }
+
+
+ @RequiredPermission(Permission.MANAGE_INVENTORY)
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ @TransactionTimeout(45 * 60)
public PackageBits downloadPackageBits(Subject subject, PackageVersionContentSource pvcs) {
PackageVersionContentSourcePK pk = pvcs.getPackageVersionContentSourcePK();
int contentSourceId = pk.getContentSource().getId();
@@ -1073,6 +1155,50 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
@SuppressWarnings("unchecked")
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public ContentSourceSyncResults _mergeContentSourceSyncReportADD(ContentSource contentSource,
+ DistributionSyncReport report, ContentSourceSyncResults syncResults, StringBuilder progress) {
+
+ DistributionManagerLocal distManager = LookupUtil.getDistributionManagerLocal();
+ RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ List<DistributionDetails> newDetails = report.getDistributions();
+ for (DistributionDetails detail: newDetails) {
+ try {
+
+ log.debug("Attempting to create new distribution based off of: " + detail);
+ DistributionType distType = distManager.getDistributionTypeByName(detail.getDistributionType());
+ Distribution newDist = distManager.createDistribution(overlord, detail.getLabel(),
+ detail.getDistributionPath(), distType);
+ log.debug("Created new distribution: " + newDist);
+ Repo repo = repoManager.getRepo(overlord, report.getRepoId());
+ RepoDistribution repoDist = new RepoDistribution(repo, newDist);
+ log.debug("Created new mapping of RepoDistribution repoId = " + repo.getId() +
+ ", distId = " + newDist.getId());
+ entityManager.persist(repoDist);
+ List<DistributionFileDetails> files = detail.getFiles();
+ for (DistributionFileDetails f: files) {
+ log.debug("Creating DistributionFile for: " + f);
+ DistributionFile df = new DistributionFile(newDist, f.getRelativeFilename(), f.getMd5sum());
+ df.setLastModified(f.getLastModified());
+ entityManager.persist(df);
+ entityManager.flush();
+ }
+ }
+ catch (DistributionException e) {
+ progress.append("Caught exception when trying to add: " + detail.getLabel() + "\n");
+ progress.append("Error is: " + e.getMessage());
+ syncResults.setResults(progress.toString());
+ syncResults = contentSourceManager.mergeContentSourceSyncResults(syncResults);
+ log.error(e);
+ }
+ }
+ return syncResults;
+ }
+
+
+
+ @SuppressWarnings("unchecked")
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public ContentSourceSyncResults _mergeContentSourceSyncReportADD(ContentSource contentSource,
Collection<ContentProviderPackageDetails> newPackages,
Map<ContentProviderPackageDetailsKey, PackageVersionContentSource> previous,
ContentSourceSyncResults syncResults, StringBuilder progress, int addCount) {
@@ -1287,40 +1413,6 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
}
- @SuppressWarnings("unchecked")
- @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
- public ContentSourceSyncResults _mergeContentSourceSyncReportADD(ContentSource contentSource,
- DistributionSyncReport report, ContentSourceSyncResults syncResults, StringBuilder progress) {
-
- DistributionManagerLocal distManager = LookupUtil.getDistributionManagerLocal();
- Subject overlord = LookupUtil.getSubjectManager().getOverlord();
- List<DistributionDetails> newDetails = report.getDistributions();
- for (DistributionDetails detail: newDetails) {
- try {
- DistributionType distType = new DistributionType();
- distType.setName(detail.getDistributionType());
- distType.setDescription(detail.getDescription());
- Distribution newDist = distManager.createDistribution(overlord, detail.getLabel(),
- detail.getDistributionPath(), distType);
- List<DistributionFileDetails> files = detail.getFiles();
- for (DistributionFileDetails f: files) {
- DistributionFile df = new DistributionFile(newDist, f.getRelativeFilename(), f.getMd5sum());
- df.setLastModified(f.getLastModified());
- entityManager.persist(df);
- }
- }
- catch (DistributionException e) {
- progress.append("Caught exception when trying to add: " + detail.getLabel() + "\n");
- progress.append("Error is: " + e.getMessage());
- syncResults.setResults(progress.toString());
- syncResults = contentSourceManager.mergeContentSourceSyncResults(syncResults);
- log.error(e);
- }
- }
- return syncResults;
- }
-
-
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public ContentSourceSyncResults _mergeContentSourceSyncReportUPDATE(ContentSource contentSource,
PackageSyncReport report, Map<ContentProviderPackageDetailsKey, PackageVersionContentSource> previous,
@@ -1720,6 +1812,24 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
return same;
}
+ private File getDistributionFileBitsLocalFilesystemFile(String distLabel, String fileName) {
+ final String filesystemProperty = "rhq.server.content.filesystem";
+ String filesystem = System.getProperty(filesystemProperty);
+
+ if (filesystem == null) {
+ throw new IllegalStateException("Server is misconfigured - missing system property '" + filesystemProperty
+ + "'. Don't know where distribution bits are stored.");
+ }
+
+ // allow the configuration to use ${} system property replacement strings
+ filesystem = StringPropertyReplacer.replaceProperties(filesystem);
+
+ String loc = "dists/" + distLabel;
+ File parentDir = new File(filesystem, loc);
+ File distBitsFile = new File(parentDir, fileName);
+ return distBitsFile;
+ }
+
private File getPackageBitsLocalFilesystemFile(int packageVersionId, String fileName) {
final String filesystemProperty = "rhq.server.content.filesystem";
String filesystem = System.getProperty(filesystemProperty);
@@ -1754,6 +1864,25 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
return packageBitsFile;
}
+
+ private File getDistLocalFileAndCreateParentDir(String distLabel, String fileName) throws Exception {
+
+ File distBitsFile = getDistributionFileBitsLocalFilesystemFile(distLabel, fileName);
+ File parentDir = distBitsFile.getParentFile();
+
+ if (!parentDir.isDirectory()) {
+ if (!parentDir.exists()) {
+ parentDir.mkdirs();
+ }
+
+ if (!parentDir.isDirectory()) {
+ throw new Exception("Cannot create content filesystem directory [" + parentDir
+ + "] for distribution bits storage.");
+ }
+ }
+ return distBitsFile;
+ }
+
private File getPackageBitsLocalFileAndCreateParentDir(int packageVersionId, String fileName) throws Exception {
File packageBitsFile = getPackageBitsLocalFilesystemFile(packageVersionId, fileName);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java
index 6364d5c..cea083c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java
@@ -300,6 +300,16 @@ public interface ContentSourceManagerLocal {
PageList<PackageVersionContentSource> getUnloadedPackageVersionsFromContentSource(Subject subject,
int contentSourceId, PageControl pc);
+
+ /**
+ * This will download all the distribution bits associated with a specific content source.
+ *
+ * @param subject
+ * @param contentSource
+ */
+ void downloadDistributionBits(Subject subject, ContentSource contentSource);
+
+
/**
* Given a {@link PackageVersionContentSource} which contains the ID of a content source, an ID of a package
* version, and the location of that package version on the remote content source repo, this will download the
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java
index e07ca48..0675382 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java
@@ -163,6 +163,28 @@ public class DistributionManagerBean implements DistributionManagerLocal, Distri
}
/**
+ * Returns a DistributionType for given name
+ * @param name name of distribution type
+ * @return distribution type from db
+ */
+ @SuppressWarnings("unchecked")
+ public DistributionType getDistributionTypeByName(String name) {
+ Query query = entityManager.createNamedQuery(DistributionType.QUERY_FIND_BY_NAME);
+
+ query.setParameter("name", name);
+ List<DistributionType> results = query.getResultList();
+
+ if (results.size() > 0) {
+ return results.get(0);
+ } else {
+ return null;
+ }
+
+ }
+
+
+
+ /**
* Returns a list of available distribution files for requested distribution
* @param distId
* @return A list of Distributionfile objects associated to a given distribution
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerLocal.java
index 10b0fd8..212630d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerLocal.java
@@ -95,4 +95,11 @@ public interface DistributionManagerLocal {
*
*/
void deleteDistributionFilesByDistId(Subject subject, int distid);
+
+ /**
+ * Returns a DistributionType for given name
+ * @param name name of distribution type
+ * @return distribution type from db
+ */
+ DistributionType getDistributionTypeByName(String name);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerRemote.java
index 6707075..70c3237 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerRemote.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerRemote.java
@@ -119,5 +119,12 @@ public interface DistributionManagerRemote {
void deleteDistributionFilesByDistId(@WebParam(name = "subject") Subject subject, //
@WebParam(name = "distid") int distid);
+ /**
+ * Returns a DistributionType for given name
+ * @param name name of distribution type
+ * @return distribution type from db
+ */
+ @WebMethod
+ DistributionType getDistributionTypeByName(@WebParam(name = "name") String name);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
index 937ba2a..f84309b 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
@@ -100,6 +100,32 @@ public class ContentProviderManager {
return inputStream;
}
+
+ /**
+ * Asks that the adapter responsible for the given content source return a stream to the DistributionFile
+ * bits for the DistributionFile at the given location.
+ *
+ * @param contentSourceId the adapter for this content source will be used to stream the bits
+ * @param location where the adapter can find the DistributionFile bits on the content source
+ *
+ * @return the stream to the DistributionFile bits
+ *
+ * @throws Exception if the adapter failed to load the bits
+ */
+ public InputStream loadDistributionFileBits(int contentSourceId, String location) throws Exception {
+ ContentProvider adapter = getIsolatedContentProvider(contentSourceId);
+
+ DistributionSource distSource = (DistributionSource) adapter;
+ InputStream inputStream = distSource.getInputStream(location);
+
+ if (inputStream == null) {
+ throw new Exception("Adapter for content source [" + contentSourceId
+ + "] failed to give us a stream to the distribution file at location [" + location + "]");
+ }
+
+ return inputStream;
+ }
+
/**
* Asks the provider responsible for the given content source to synchronize with its remote repository. This will
* not attempt to load any package bits - it only synchronizes the repos and package version information. Note
@@ -195,7 +221,6 @@ public class ContentProviderManager {
// Temporary functionality: loop for all repos that use this content source
for (Repo repo : repos) {
-
// Convert the existing package list for this repo into DTOs for the API
// --------------------------------------------
List<PackageVersionContentSource> existingPVCS; // what we already know about this content source
@@ -244,6 +269,7 @@ public class ContentProviderManager {
start = System.currentTimeMillis();
results = contentSourceManager.mergeContentSourceSyncReport(contentSource, report, keyPVCSMap, results);
+
}
// let's reset our progress string to the full results including the text added by the merge
@@ -258,17 +284,23 @@ public class ContentProviderManager {
results.setStatus(ContentSourceSyncStatus.SUCCESS);
results = contentSourceManager.mergeContentSourceSyncResults(results);
}
+
+ log.info("Checking if provider: " + provider + " is a DistributionSource");
if (provider instanceof DistributionSource) {
log.info("synchronizeContentSource(" + contentSourceId + "): this source is a DistributionSource");
log.info("We will skip the sync for now until PackageSource is working.");
- /**
+
DistributionSource distSource = (DistributionSource) provider;
RepoCriteria reposForContentSource = new RepoCriteria();
reposForContentSource.addFilterContentSourceIds(contentSourceId);
+ reposForContentSource.addFilterCandidate(false); // Don't sync packages for candidates
List<Repo> repos = repoManager.findReposByCriteria(overlord, reposForContentSource);
// Temporary functionality: loop for all repos that use this content source
for (Repo repo : repos) {
+ log.info("ContentProviderManager::synchronizeContentSource DistributionSource would be syncing repo: " + repo.getName());
+
+
start = System.currentTimeMillis();
PageControl pc = PageControl.getUnlimitedInstance();
@@ -280,7 +312,7 @@ public class ContentProviderManager {
progress.append(new Date()).append(": ");
progress.append("Asking content source to update the list of packages...");
- DistributionSyncReport distReport = new DistributionSyncReport();
+ DistributionSyncReport distReport = new DistributionSyncReport(repo.getId());
List<DistributionDetails> distDetails = new ArrayList<DistributionDetails>(dists.size());
translateDomainToDto(dists, distDetails);
@@ -294,20 +326,13 @@ public class ContentProviderManager {
start = System.currentTimeMillis();
- distSource.synchronizeDistribution(distReport, distDetails);
+ distSource.synchronizeDistribution(repo.getName(), distReport, distDetails);
log.info("synchronizeDistributions: [" + contentSource.getName() + "]: got sync report from adapter=["
+ distReport + "] (" + (System.currentTimeMillis() - start) + ")ms");
progress.append("new=").append(distReport.getDistributions().size());
- //TODO: Consider Update case, i.e. rhel-5-u2 was prev synced, and now a
- // single DistributionFile has changed
progress.append(", deleted=").append(distReport.getDeletedDistributions().size()).append('\n');
- //progress.append(new Date()).append(": ");
- //progress.append("FULL SUMMARY FOLLOWS:").append('\n');
- //progress.append(distReport.getSummary()).append('\n');
- //progress.append(new Date()).append(": ");
- //progress.append("Merging the updated list of packages to database").append('\n');
results.setResults(progress.toString());
results = contentSourceManager.mergeContentSourceSyncResults(results);
start = System.currentTimeMillis();
@@ -324,7 +349,7 @@ public class ContentProviderManager {
results.setResults(progress.toString());
results.setStatus(ContentSourceSyncStatus.SUCCESS);
results = contentSourceManager.mergeContentSourceSyncResults(results);
- */
+
}
} catch (Throwable t) {
if (results != null) {
@@ -544,7 +569,7 @@ public class ContentProviderManager {
*
* @throws RuntimeException if there is no content source with the given ID
*/
- protected ContentProvider getIsolatedContentProvider(int contentProviderId) throws RuntimeException {
+ public ContentProvider getIsolatedContentProvider(int contentProviderId) throws RuntimeException {
synchronized (this.adapters) {
for (ContentSource contentSource : this.adapters.keySet()) {
if (contentSource.getId() == contentProviderId) {
@@ -594,6 +619,9 @@ public class ContentProviderManager {
if (adapter instanceof PackageSource) {
ifacesList.add(PackageSource.class);
}
+ if (adapter instanceof DistributionSource) {
+ ifacesList.add(DistributionSource.class);
+ }
Class<?>[] ifaces = ifacesList.toArray(new Class<?>[ifacesList.size()]);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionDetails.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionDetails.java
index 80ed9b9..ad4af2a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionDetails.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionDetails.java
@@ -140,4 +140,8 @@ public class DistributionDetails {
public void setDistributionPath(String distpath) {
this.distpath = distpath;
}
+
+ public String toString() {
+ return "DistributionType = " + distType + ", label = " + label + ", path = " + distpath;
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionFileDetails.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionFileDetails.java
index 02e3816..f7955dc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionFileDetails.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionFileDetails.java
@@ -75,4 +75,9 @@ public class DistributionFileDetails
{
this.md5sum = md5sumIn;
}
+
+ public String toString() {
+ return "filePath = " + relativeFilename + ", lastModified = " + lastModified + ", md5Sum = " + md5sum;
+ }
}
+
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java
index 931c4b5..feb0dce 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java
@@ -54,5 +54,14 @@ public interface DistributionSource {
*/
InputStream getInputStream(String location) throws Exception;
+ /**
+ *
+ * @param repoName Name of repository
+ * @param label Distribution Label
+ * @param relativeFilename relative path of file to fetch
+ * @return a remote location that can be passed into getInputStream to fetch a file from this source.
+ */
+ String getRemoteLocation(String repoName, String label, String relativeFilename);
+
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSyncReport.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSyncReport.java
index c59b1f8..77af8d2 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSyncReport.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSyncReport.java
@@ -34,8 +34,21 @@ import java.util.Collection;
public class DistributionSyncReport {
private List<DistributionDetails> distros = new ArrayList<DistributionDetails>();
private List<DistributionDetails> deletedDistros = new ArrayList<DistributionDetails>();
+ private int repoId;
+
+ public int getRepoId()
+ {
+ return repoId;
+ }
+
+ public void setRepoId(int repoIdIn)
+ {
+ this.repoId = repoIdIn;
+ }
+
+ public DistributionSyncReport(int repoIdIn) {
+ repoId = repoIdIn;
- public DistributionSyncReport() {
}
public List<DistributionDetails> getDistributions() {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/ContentSourceSyncJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/ContentSourceSyncJob.java
index 7489314..3d8e7ce 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/ContentSourceSyncJob.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/ContentSourceSyncJob.java
@@ -36,6 +36,7 @@ import org.rhq.core.domain.content.ContentSourceType;
import org.rhq.core.domain.content.DownloadMode;
import org.rhq.core.domain.content.PackageVersionContentSource;
import org.rhq.core.domain.content.PackageVersionContentSourcePK;
+import org.rhq.core.domain.content.Distribution;
import org.rhq.core.domain.util.PageControl;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
@@ -204,6 +205,20 @@ public class ContentSourceSyncJob implements StatefulJob {
+ "The downloads started at [" + new Date(start) + "] and ended at [" + new Date() + "]");
}
+ // Get DistributionSource bits.
+ // Note: We are ignoring LazyLoad for Distributions, we will always perform an eager fetch for the "bits".
+ if (!completed) {
+ log.info("Content source [" + contentSourceName + "] is currently being synchronized already. "
+ + "Please wait for the current sync job to finish. [DistributionSync]");
+ } else {
+ log.info("Content source [" + contentSourceName + "] is fully synchronized now. "
+ + "Downloading all Distribution bits now.");
+ long start = System.currentTimeMillis();
+ contentManager.downloadDistributionBits(overlord, contentSource);
+ log.info("All distribution bits for content source [" + contentSourceName + "] have been downloaded."
+ + "The downloads started at [" + new Date(start) + "] and ended at [" + new Date() + "]");
+ }
+
return;
}
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
index b2b0497..271397f 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
@@ -74,7 +74,7 @@ public class RHNHelper {
this.rhndata = new RhnComm(baseurl);
this.rhndownload = new RhnDownloader(baseurl);
this.systemid = systemIdIn;
- this.distributionType = "Kickstart";
+ this.distributionType = "kickstart";
}
@@ -289,7 +289,7 @@ public class RHNHelper {
* @param ksFilePath path to kickstart file
* @return a valid url location to fetch the rpm from.
*/
- private String constructKickstartFileUrl(String channelName, String ksTreeLabel, String ksFilePath) {
+ public String constructKickstartFileUrl(String channelName, String ksTreeLabel, String ksFilePath) {
String appendurl = "/SAT/$RHN/" + channelName + "/getKickstartFile/" + ksTreeLabel + "/" + ksFilePath;
return baseurl + appendurl;
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
index 005bf52..1b1a0b0 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
@@ -291,4 +291,10 @@ public class RHNProvider implements ContentProvider, PackageSource, RepoSource,
return path;
}
+ /**
+ * @inheritDoc
+ */
+ public String getRemoteLocation(String repoName, String label, String relativeFilename) {
+ return helper.constructKickstartFileUrl(repoName, label, relativeFilename);
+ }
}
commit 5055fb6516e924c4681736266f49c67ee6a433cf
Author: Pradeep Kilambi <pkilambi(a)redhat.com>
Date: Sat Nov 14 10:43:22 2009 -0500
Adding a separate identifier to please hibernate from assuming two distribution objects have same identifier
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index 9ac94d7..b7b94ce 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -22,7 +22,7 @@
<properties>
<scm.module.path>modules/core/dbutils/</scm.module.path>
- <db.schema.version>2.66</db.schema.version>
+ <db.schema.version>2.68</db.schema.version>
</properties>
<dependencies>
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml
index d7c510b..61eaeff 100644
--- a/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml
+++ b/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml
@@ -356,10 +356,13 @@
</table>
<table name="RHQ_DISTRIBUTION_FILE">
- <column name="DISTRIBUTION_ID" type="INTEGER" primarykey="true" required="true" references="RHQ_DISTRIBUTION"/>
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="DISTRIBUTION_ID" type="INTEGER" required="true" references="RHQ_DISTRIBUTION"/>
<column name="RELATIVE_FILENAME" size="256" type="VARCHAR2" required="true"/>
+ <!--<column name="FILE_SIZE" type="NUMBER" required="true"/>-->
<column name="MD5SUM" size="64" type="VARCHAR2" required="true"/>
<column name="LAST_MODIFIED" type="LONG" required="true"/>
+ <!--<column name="CTIME" type="LONG" required="true"/>-->
<index name="RHQ_DISTRIBUTION_FILE_IDX" unique="true">
<field ref="DISTRIBUTION_ID"/>
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 ad4fe56..d615fb0 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -2122,6 +2122,25 @@
</schema-directSQL>
</schemaSpec>
+ <schemaSpec version="2.68">
+ <schema-createSequence name="RHQ_DISTRIBUTION_FILE_SEQ" initial="10001" />
+ <schema-directSQL>
+ <statement>
+ ALTER TABLE RHQ_DISTRIBUTION_FILE DROP CONSTRAINT RHQ_DISTRIBUTION_FILE_PKEY
+ </statement>
+ </schema-directSQL>
+
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="ID" columnType="INTEGER" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="ID" nullable="false" />
+
+ <schema-directSQL>
+ <statement>
+ ALTER TABLE RHQ_DISTRIBUTION_FILE ALTER COLUMN ID SET DEFAULT NEXTVAL('RHQ_DISTRIBUTION_FILE_ID_SEQ')
+ </statement>
+ </schema-directSQL>
+ </schemaSpec>
+
+
</dbupgrade>
</target>
</project>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Distribution.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Distribution.java
index a7507fc..0556f77 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Distribution.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Distribution.java
@@ -147,11 +147,12 @@ public class Distribution implements Serializable {
@Override
public String toString() {
- return String.format("Distribtuion [label=%s, Type=%s, basePath=%s]", label, distributionType, base_path);
+ return String.format("Distribution [label=%s, Type=%s, basePath=%s]", label, distributionType, base_path);
}
@Override
public boolean equals(Object o) {
+
if (this == o) {
return true;
}
@@ -166,7 +167,7 @@ public class Distribution implements Serializable {
Distribution kstree = (Distribution) o;
- if ((label != null) ? (!label.equals(kstree.label)) : (kstree.label != null)) {
+ if ((getLabel() != null) ? (!getLabel().equals(kstree.getLabel())) : (kstree.getLabel() != null)) {
return false;
}
@@ -187,7 +188,7 @@ public class Distribution implements Serializable {
public int hashCode() {
final int prime = 31;
int result = 1;
- result = (prime * result) + ((label == null) ? 0 : label.hashCode());
+ result = (prime * result) + ((getLabel() == null) ? 0 : getLabel().hashCode());
return result;
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFile.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFile.java
index 267f69a..6826442 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFile.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFile.java
@@ -24,15 +24,18 @@ package org.rhq.core.domain.content;
import java.util.Date;
+import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
import javax.persistence.Id;
-import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.PrePersist;
+import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
/**
@@ -41,10 +44,11 @@ import javax.persistence.Table;
* @author Pradeep Kilambi
*/
@Entity
-(a)IdClass(DistributionFilePK.class)
+//(a)IdClass(DistributionFilePK.class)
@NamedQueries( {
@NamedQuery(name = DistributionFile.SELECT_BY_DIST_ID, query = "SELECT df from DistributionFile df WHERE df.distribution.id = :distId"),
@NamedQuery(name = DistributionFile.DELETE_BY_DIST_ID, query = "DELETE DistributionFile df WHERE df.distribution.id = :distId") })
+@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_DISTRIBUTION_FILE_ID_SEQ")
@Table(name = "RHQ_DISTRIBUTION_FILE")
public class DistributionFile {
public static final String SELECT_BY_DIST_ID = "DistributionFile.selectByDistId";
@@ -58,9 +62,13 @@ public class DistributionFile {
* @IdClass.
*/
+ @Column(name = "ID", nullable = false)
+ @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ")
@Id
- @ManyToOne
- @JoinColumn(name = "DISTRIBUTION_ID", referencedColumnName = "ID", nullable = false, insertable = false, updatable = false)
+ private int id;
+
+ @JoinColumn(name = "DISTRIBUTION_ID", referencedColumnName = "ID", nullable = false)
+ @ManyToOne(cascade = { CascadeType.MERGE, CascadeType.PERSIST })
private Distribution distribution;
@Column(name = "RELATIVE_FILENAME", nullable = false)
@@ -89,6 +97,16 @@ public class DistributionFile {
this.distribution = pk.getDistribution();
}
+ // Public --------------------------------------------
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
public long getLastModified() {
return last_modified;
}
@@ -139,27 +157,24 @@ public class DistributionFile {
@Override
public int hashCode() {
int result = 1;
- result = (31 * result) + ((distribution == null) ? 0 : distribution.hashCode());
+ result = (31 * result) + ((getDistribution() == null) ? 0 : getDistribution().hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
if ((obj == null) || (!(obj instanceof DistributionFile))) {
return false;
}
- final DistributionFile other = (DistributionFile) obj;
+ DistributionFile other = (DistributionFile) obj;
- if (distribution == null) {
- if (distribution != null) {
+ if (getDistribution() == null) {
+ if (getDistribution() != null) {
return false;
}
- } else if (!distribution.equals(other.distribution)) {
+ } else if (!getDistribution().equals(other.getDistribution())) {
return false;
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFilePK.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFilePK.java
index 525d3aa..8551963 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFilePK.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFilePK.java
@@ -26,7 +26,6 @@ package org.rhq.core.domain.content;
import java.io.Serializable;
import javax.persistence.JoinColumn;
-import javax.persistence.ManyToOne;
public class DistributionFilePK implements Serializable {
private static final long serialVersionUID = 1L;
@@ -36,9 +35,7 @@ public class DistributionFilePK implements Serializable {
* even though this class is an @IdClass and it should not need the mappings here. The mappings belong in the
* entity itself.
*/
-
@JoinColumn(name = "DISTRIBUTION_ID", referencedColumnName = "ID", nullable = false)
- @ManyToOne
private Distribution distribution;
public DistributionFilePK() {
@@ -64,7 +61,7 @@ public class DistributionFilePK implements Serializable {
@Override
public int hashCode() {
int result = 1;
- result = (31 * result) + ((distribution == null) ? 0 : distribution.hashCode());
+ result = (31 * result) + ((getDistribution() == null) ? 0 : getDistribution().hashCode());
return result;
}
@@ -80,11 +77,11 @@ public class DistributionFilePK implements Serializable {
final DistributionFilePK other = (DistributionFilePK) obj;
- if (distribution == null) {
- if (other.distribution != null) {
+ if (getDistribution() == null) {
+ if (other.getDistribution() != null) {
return false;
}
- } else if (!distribution.equals(other.distribution)) {
+ } else if (!getDistribution().equals(other.getDistribution())) {
return false;
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java
index fd33580..e24f39c 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java
@@ -63,7 +63,6 @@ public class DistributionManagerBeanTest extends AbstractEJB3Test {
assert distro == null;
}
- @Test(enabled = ENABLED)
public void testDistributionFiles() throws Exception {
String kslabel = "testCreateDeleteRepo";
String kspath = "/tmp";
@@ -71,16 +70,13 @@ public class DistributionManagerBeanTest extends AbstractEJB3Test {
Distribution distro = distManager.getDistributionByLabel(kslabel);
DistributionFile distfile = new DistributionFile(distro, "vmlinux", "d41d8cd98f00b204e9800998ecf8427e");
-
EntityManager em = getEntityManager();
em.persist(distfile);
Query query = em.createNamedQuery(distfile.SELECT_BY_DIST_ID);
query.setParameter("distId", distro.getId());
List<DistributionFile> results = query.getResultList();
-
assert results.size() != 0;
-
Query querydel = em.createNamedQuery(distfile.DELETE_BY_DIST_ID);
querydel.setParameter("distId", distro.getId());
commit 693feb3abce32782dd4e76589c6e7c92fdf69a8c
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 13 20:06:03 2009 -0500
Squashed commit of the following:
commit 9d7e958c1524f2505cf244f58ce6a965e50483ed
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 13 20:02:47 2009 -0500
out! out! damned tabs!
add // so formatters don't mess up Plugin class
commit 915386f33a63ef8112a967b039f9d97135752a5b
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri Nov 13 12:18:38 2009 -0500
not changed, maybe resolving a line terminator issue
commit a08036a99b543cfbc25208061543c9a9d8663466
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 13 02:49:54 2009 -0500
Conflicts:
etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
why did these conflicts happen when I got no conflicts merging the same thing in the pc branch (where pc and master were identical, diff showed nothing different between pc and master)
commit f6d790e73caa5c3714768660656da69fb49e2653
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 18:42:51 2009 -0500
Squashed commit of the following:
commit 4176765871d06b37895dc72269233687325eaa87
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 17:20:20 2009 -0500
get the plugin jobs to be scheduled properly in quartz
commit 08644de029a313e09673870395bf0a5f8607098b
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 11:47:39 2009 -0500
fix the operation names in the rhq server plugin
commit 8075b0b26d1c2514ff7a1c831491a51d8a2909c8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 03:22:06 2009 -0500
Squashed commit of the following:
commit d3dfc1a52b0414bd67f50ed9c881c8c3e33e9a1e
Merge: 2cd6ba1 ad45fe5
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 22:38:00 2009 -0500
Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq
commit 2cd6ba182ee07849e2ccd06be6c962b879f45112
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 16:33:18 2009 -0500
Allow clean install to still copy over the license file.
This patch moves the license file from the server container module to the ear module. It is copied over in the dev profile only.
commit 9d93844a860e54c2a012644975ccee198c76f9a6
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 02:53:23 2009 -0500
actually schedule the jobs in quartz
commit 25c0a3e27d9969368230277cb5a33633dbbdb897
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 02:06:54 2009 -0500
add plugin context to the job interface
commit c14822a979ab9e130dfc08279ae6ca342bd591bf
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 01:45:23 2009 -0500
provide an API to schedule jobs
commit a1c36f7c4efb5fd4e78c246c9e270bb55901e883
Merge: ccb085f d3dfc1a
Author: Partha Aji <paji(a)redhat.com>
Date: Thu Nov 12 12:26:11 2009 -0500
Merge branch 'master' into linux-config
commit ccb085f89d6a36787da1c570fbb7006672de68f9
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Thu Nov 12 11:45:14 2009 -0500
remove experimental hosts-augeas plugin, which is no longer needed
commit 6a676af5fd6af0c2fafd3faf5fc24a119bbceb72
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Thu Nov 12 11:18:13 2009 -0500
get hosts plugin integration tests passing on Windows
commit cb288a8321d659c8839328066f5c50f4e548a4ba
Author: Partha Aji <paji(a)redhat.com>
Date: Thu Nov 12 10:09:55 2009 -0500
Removed the augeas test jar dep from aliases pom since its going to be built as part of core
commit 3b6e81de84ba5b3ec4af37fd7c1ba7afafe65d8a
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 20:38:51 2009 -0500
Added Load and Update tests for the alias component
commit 771b96fc5e2213dc8bcba4bb0991aefe1556bd37
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 19:50:04 2009 -0500
added aliaseses to .classpath
commit 7e8a1621b6990bd4d673c49dda47ad910d0eaab3
Merge: 15a3b45 ad45fe5
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 19:42:58 2009 -0500
Merge branch 'master' into linux-config
commit 15a3b45d91942fdcccef99a20e422c857834ae0a
Author: Ian P. Springer <ips(a)jetengine.springer.net>
Date: Wed Nov 11 18:48:34 2009 -0500
fix several bugs in augeas and hosts plugins to get hosts+samba+sudoers integration tests passing on Linux; update test log4j.xml in all augeas-based plugins
commit 06eb2ee352c198385e2797d4e3c9816a59ba0c02
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Nov 11 11:31:46 2009 -0500
Augeas-based ResourceComponents now handle it as gracefully as possible when Augeas is not installed on the Agent system
commit d391bb6be98bfeabfaa06f25fbf33cf67ea85f06
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Nov 11 10:19:44 2009 -0500
refactor so that config tests are skipped if Augeas is not available, so tests will pass on systems without Augeas (e.g. Windows boxes)
commit 62f8c89cd2fcc882f6783c8530ac4cf46f7cec34
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 10:06:08 2009 -0500
Revert "Fixed test cases related to samba and sudoer plugins"
Looks like there is a better way to achieve the same.. Waiing for ips'
commit
This reverts commit 6d666b6987f1c58732851a57560ec93ba21c4cc5.
commit 7d952067685d548fc7b26bf7a8a272cece448484
Merge: 6d666b6 46d0de1
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 00:53:22 2009 -0500
Merge branch 'master' into hope
commit 6d666b6987f1c58732851a57560ec93ba21c4cc5
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 00:51:04 2009 -0500
Fixed test cases related to samba and sudoer plugins
commit d7e80500786e7ac9318b9b47587f2304776a871b
Author: Partha Aji <paji(a)redhat.com>
Date: Tue Nov 10 15:41:58 2009 -0500
Added a couple of checks to make sure augeas base paths are generated before unit tests are run
commit 3435feb11104bb06ba8db0589763e144e34391e6
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Tue Nov 10 14:26:37 2009 -0500
change package of AbstractAugeasConfigurationComponentTest class from org.rhq.plugins.augeas to org.rhq.plugins.augeas.test to match its location on the filesystem
commit 78a696197265d0a51dee542711342cecb4caa287
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Tue Nov 10 13:19:44 2009 -0500
move augeas base test class in augeas plugin from src/test/ to src/main/ to allow mvn -Dmaven.test.skip=true to be run from project root without failures in samba/sudoers/etc. plugins because mvn cannot find the augeas plugin test jar
commit f0d7e99c5c82f43da612d4708bc2909f36e9a23b
Merge: b895aba 961fba0
Author: Partha Aji <paji(a)redhat.com>
Date: Mon Nov 9 17:21:16 2009 -0500
Merge branch 'master' into linux-config
commit b895aba9016245fe4d7f31180f30507955e66a34
Author: Shannon Hughes <shughes(a)scooby.rdu.redhat.com>
Date: Mon Nov 9 15:53:28 2009 -0500
modifying aliases agueas paths
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 e317d58..af17a6d 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -17,13 +17,13 @@
</echo>
<dbupgrade jdbcUrl="${jdbc.url}"
- jdbcUser="${jdbc.user}"
- jdbcPassword="${jdbc.password}"
- valueColumn="PROPERTY_VALUE"
- table="RHQ_SYSTEM_CONFIG"
- keyColumn="PROPERTY_KEY"
- keyMatch="DB_SCHEMA_VERSION"
- targetSchemaVersion="${target.schema.version}">
+ jdbcUser="${jdbc.user}"
+ jdbcPassword="${jdbc.password}"
+ valueColumn="PROPERTY_VALUE"
+ table="RHQ_SYSTEM_CONFIG"
+ keyColumn="PROPERTY_KEY"
+ keyMatch="DB_SCHEMA_VERSION"
+ targetSchemaVersion="${target.schema.version}">
<schemaSpec version="2.0">
<!-- Empty initial schema to avoid install failure on default latest schema version -->
@@ -870,15 +870,15 @@
<schema-directSQL>
<statement desc="Unscheduling auto-baseline job from Quartz - removing trigger">
DELETE FROM rhq_qrtz_triggers
- WHERE trigger_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
+ WHERE trigger_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
</statement>
<statement desc="Unscheduling auto-baseline job from Quartz - removing simple trigger">
DELETE FROM rhq_qrtz_simple_triggers
- WHERE trigger_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
+ WHERE trigger_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
</statement>
<statement desc="Unscheduling auto-baseline job from Quartz - removing job details">
DELETE FROM rhq_qrtz_job_details
- WHERE job_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
+ WHERE job_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
</statement>
</schema-directSQL>
</schemaSpec>
@@ -1089,7 +1089,7 @@
<schema-directSQL>
<statement desc="Populating values for new column RHQ_MEASUREMENT_DEF.RAW_NUMERIC_TYPE">
UPDATE RHQ_MEASUREMENT_DEF md
- SET RAW_NUMERIC_TYPE = (SELECT NUMERIC_TYPE FROM RHQ_MEASUREMENT_DEF
+ SET RAW_NUMERIC_TYPE = (SELECT NUMERIC_TYPE FROM RHQ_MEASUREMENT_DEF
WHERE NAME = md.NAME AND RESOURCE_TYPE_ID = md.RESOURCE_TYPE_ID AND (NUMERIC_TYPE = 1 OR NUMERIC_TYPE = 2))
WHERE NUMERIC_TYPE = 0
</statement>
@@ -1468,7 +1468,7 @@
<schema-addColumn table="RHQ_ALERT_DEFINITION" column="RESOURCE_GROUP_ID" columnType="INTEGER" />
<schema-addColumn table="RHQ_ALERT_DEFINITION" column="GROUP_ALERT_DEF_ID" columnType="INTEGER" />
</schemaSpec>
-
+
<schemaSpec version="2.59">
<schema-directSQL>
<statement desc="Creating table RHQ_RAW_CONFIG">
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index 0c8336b..fe704bc 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -61,7 +61,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.help, " //
+ " p.md5, " //
+ " p.version, " //
- + " p.ampsVersion, "
+ + " p.ampsVersion, " //
+ " p.ctime, " //
+ " p.mtime) " //
+ " FROM Plugin AS p " //
@@ -79,7 +79,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.help, " //
+ " p.md5, " //
+ " p.version, " //
- + " p.ampsVersion, "
+ + " p.ampsVersion, " //
+ " p.ctime, " //
+ " p.mtime) " //
+ " FROM Plugin AS p "), //
@@ -93,7 +93,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.enabled = :enabled, " //
+ " p.help = :help, " //
+ " p.version = :version, " //
- + " p.ampsVersion = :ampsVersion,"
+ + " p.ampsVersion = :ampsVersion," //
+ " p.path = :path, " //
+ " p.md5 = :md5, " //
+ " p.mtime = :mtime " //
@@ -111,7 +111,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.help, " //
+ " p.md5, " //
+ " p.version, " //
- + " p.ampsVersion, "
+ + " p.ampsVersion, " //
+ " p.ctime, " //
+ " p.mtime) " //
+ " FROM Plugin p " //
@@ -451,4 +451,4 @@ public class Plugin implements Serializable {
public String toString() {
return "Plugin[id=" + id + ", name=" + name + ", md5=" + md5 + "]";
}
-}
\ No newline at end of file
+}
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml
index eac2995..339a4ea 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml
@@ -1,163 +1,163 @@
-<?xml version="1.0"?>
-
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:h="http://java.sun.com/jsf/html"
- xmlns:f="http://java.sun.com/jsf/core"
- xmlns:ui="http://java.sun.com/jsf/facelets"
- xmlns:c="http://java.sun.com/jstl/core"
- xmlns:a4j="http://richfaces.org/a4j"
- xmlns:onc="http://jboss.org/on/component"
- xmlns:rich="http://richfaces.ajax4jsf.org/rich">
-
-<head>
- <title>${msg["product.shortName"]} - #{(!empty pageTitle) ? pageTitle : defaultPageTitle}</title>
-
- <ui:insert name="metaHeaders"></ui:insert>
-
- <link rel="stylesheet" type="text/css" media="screen" href="/css/win.css"/>
- <link rel="stylesheet" type="text/css" media="screen" href="/css/form-style.css"/>
- <link rel="stylesheet" type="text/css" media="screen" href="/css/menu.css"/>
-
- <script type="text/javascript" src="/js/functions.js"></script>
- <script type="text/javascript" src="/js/prototype.js"></script>
- <script type="text/javascript" src="/js/window.js"></script>
- <script type="text/javascript" src="/js/effects.js"></script>
- <!--<script type="text/javascript" src="/js/debug.js"></script>-->
- <script type="text/javascript" src="/js/formValues.js"></script>
- <script type="text/javascript" src="/js/rhq.js"></script>
- <script type="text/javascript" src="/js/popup.js"></script>
- <script type="text/javascript" src="/js/iframeSSI.js">
- /***********************************************
- * IFrame SSI script II- © Dynamic Drive DHTML code library (http://www.dynamicdrive.com)
- * Visit DynamicDrive.com for hundreds of original DHTML scripts
- * This notice must stay intact for legal use
- ***********************************************/
- </script>
-
- <link href="/css/theme/default.css" rel="stylesheet" type="text/css"/>
- <link href="/css/theme/alphacube.css" rel="stylesheet" type="text/css"/>
- <link href="/css/theme/debug.css" rel="stylesheet" type="text/css"/>
-
- <link rel="icon" type="image/png" href="/images/favicon.png"/>
- <link rel="apple-touch-icon" href="/images/favicon.png"/>
-
- <!-- Trims up the headers of RF toggle panel headers -->
- <style type="text/css">
- .BlockTitle {
- padding-top: 3px;
- padding-bottom: 3px;
- }
- HTML, BODY { overflow: hidden; }
- </style>
-
- <link rel="stylesheet" type="text/css" media="screen" href="/css/tabular.css"/>
- <link rel="stylesheet" type="text/css" media="screen" href="/css/layout.css"/>
-
- <script type="text/javascript">
- var imagePath = "/images/";
- </script>
-
-</head>
-
-<body bgcolor="#FFFFFF" style="height: 100%;">
-
-<ui:remove>
- <!-- Set the content type to "text/html" (overriding the default of "application/xhtml+xml") to force
-Firefox and other Gecko-based browsers to render the page in "Almost Standards" (i.e. transitional) mode. -->
-</ui:remove>
-<f:view contentType="text/html">
-
-
- <f:loadBundle basename="ApplicationResources" var="msg"/>
-
- <!-- =================== PAGE HEADER =================== -->
-
- <script language="javascript" type="text/javascript">
- //this has to be defined before the resize trackers inside
- //the PageBody element because they depend on the values
- //computed inside this tracker function.
- WindowResizeTracker.addListener(function() {
- var header = $('PageHeader');
- var borderHeight = 2; //set in the inline style of div PageHeader
-
- if (Prototype.Browser.IE) {
- header.style.height = WindowResizeTracker.currentSizes.windowHeight + 'px';
- } else {
- header.style.height = (WindowResizeTracker.currentSizes.windowHeight - borderHeight) + 'px';
- }
- header.style.width = WindowResizeTracker.currentSizes.windowWidth + 'px';
-
- var body = $('PageBody');
- //27 = menu height (and the top position of PageBody)
- body.style.height = (WindowResizeTracker.currentSizes.windowHeight - 27 - borderHeight) + 'px';
- body.style.width = header.style.width;
-
- document.body.style.height = WindowResizeTracker.currentSizes.windowHeight + 'px';
- });
- </script>
- <!-- work around for IE and its broken box model. Without the concrete height value, the nav pane will shrink on hover. -->
- <!--[if IE]>
- <div id="PageHeader" style="border-bottom: 2px solid #999; position: absolute; top: 0; bottom: 0; left: 0; right: 0; height: 100%">
- <![endif]-->
- <!--[if !IE]><!-->
- <div id="PageHeader" style="border-bottom: 2px solid #999; position: absolute; top: 0; bottom: 0; left: 0; right: 0;">
- <!--<![endif]-->
-
- <ui:include src="/rhq/common/menu/menu.xhtml"/>
-
- <!-- work around for IE and its broken box model. Without the concrete height value, the nav pane will shrink on hover. -->
- <!--[if IE]>
- <div id="PageBody" style="width: 100%; position: absolute; top: 27px; bottom: 0; height: 100%;">
- <![endif]-->
- <!--[if !IE]><!-->
- <div id="PageBody" style="width: 100%; position: absolute; top: 27px; bottom: 0;">
- <!--<![endif]-->
- <ui:insert name="body-area">Default Page Body</ui:insert>
- </div>
-
- </div>
-
-
-
- <!-- =================== BODY =================== -->
-
-
- <div id="about" class="dialog" style="display: none; position: absolute; top: 0; left: 0;">
- <div class="DisplayContent" style="margin: 0;">
- <div style="margin:5px">
- <p class="compact">
- <span class="DisplaySubhead">${msg['footer.aboutLink']}</span><br/>
- <span class="DisplayLabel">${msg['footer.version']}: ${msg['product.version']}</span><br/>
- <span class="DisplayLabel">${msg['footer.buildNumber']}: ${msg['product.buildNumber']}</span>
- </p>
-
- <p class="compact">
- <f:verbatim>${msg['footer.copyright']}</f:verbatim> ${msg['about.Copyright.Content']}
- </p>
-
- <p class="compact">
- ${msg['about.MoreInfo.Label']}<br/>
- <a href="mailto:${msg['about.MoreInfo.LinkSales']}">${msg['about.MoreInfo.LinkSales']}</a><br/>
- <a href="mailto:${msg['about.MoreInfo.LinkSupport']}">${msg['about.MoreInfo.LinkSupport']}</a>
- </p>
- </div>
- </div>
- </div>
-
- <!-- work-around to enable us to embed richfaces components inside the onc:simpleTrigger;
-without this, the page will throw a javascript error "{blah} is not defined" or
-"{yadda} is not a constructor", and the pop-up action will not work -->
- <rich:calendar rendered="false"/>
- <rich:inputNumberSpinner rendered="false"/>
-
-</f:view>
-
-<script type="text/javascript">
- addWindowOnLoadEvent(disableConditionalButtons);
-</script>
-
-</body>
-</html>
+<?xml version="1.0"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jstl/core"
+ xmlns:a4j="http://richfaces.org/a4j"
+ xmlns:onc="http://jboss.org/on/component"
+ xmlns:rich="http://richfaces.ajax4jsf.org/rich">
+
+<head>
+ <title>${msg["product.shortName"]} - #{(!empty pageTitle) ? pageTitle : defaultPageTitle}</title>
+
+ <ui:insert name="metaHeaders"></ui:insert>
+
+ <link rel="stylesheet" type="text/css" media="screen" href="/css/win.css"/>
+ <link rel="stylesheet" type="text/css" media="screen" href="/css/form-style.css"/>
+ <link rel="stylesheet" type="text/css" media="screen" href="/css/menu.css"/>
+
+ <script type="text/javascript" src="/js/functions.js"></script>
+ <script type="text/javascript" src="/js/prototype.js"></script>
+ <script type="text/javascript" src="/js/window.js"></script>
+ <script type="text/javascript" src="/js/effects.js"></script>
+ <!--<script type="text/javascript" src="/js/debug.js"></script>-->
+ <script type="text/javascript" src="/js/formValues.js"></script>
+ <script type="text/javascript" src="/js/rhq.js"></script>
+ <script type="text/javascript" src="/js/popup.js"></script>
+ <script type="text/javascript" src="/js/iframeSSI.js">
+ /***********************************************
+ * IFrame SSI script II- © Dynamic Drive DHTML code library (http://www.dynamicdrive.com)
+ * Visit DynamicDrive.com for hundreds of original DHTML scripts
+ * This notice must stay intact for legal use
+ ***********************************************/
+ </script>
+
+ <link href="/css/theme/default.css" rel="stylesheet" type="text/css"/>
+ <link href="/css/theme/alphacube.css" rel="stylesheet" type="text/css"/>
+ <link href="/css/theme/debug.css" rel="stylesheet" type="text/css"/>
+
+ <link rel="icon" type="image/png" href="/images/favicon.png"/>
+ <link rel="apple-touch-icon" href="/images/favicon.png"/>
+
+ <!-- Trims up the headers of RF toggle panel headers -->
+ <style type="text/css">
+ .BlockTitle {
+ padding-top: 3px;
+ padding-bottom: 3px;
+ }
+ HTML, BODY { overflow: hidden; }
+ </style>
+
+ <link rel="stylesheet" type="text/css" media="screen" href="/css/tabular.css"/>
+ <link rel="stylesheet" type="text/css" media="screen" href="/css/layout.css"/>
+
+ <script type="text/javascript">
+ var imagePath = "/images/";
+ </script>
+
+</head>
+
+<body bgcolor="#FFFFFF" style="height: 100%;">
+
+<ui:remove>
+ <!-- Set the content type to "text/html" (overriding the default of "application/xhtml+xml") to force
+Firefox and other Gecko-based browsers to render the page in "Almost Standards" (i.e. transitional) mode. -->
+</ui:remove>
+<f:view contentType="text/html">
+
+
+ <f:loadBundle basename="ApplicationResources" var="msg"/>
+
+ <!-- =================== PAGE HEADER =================== -->
+
+ <script language="javascript" type="text/javascript">
+ //this has to be defined before the resize trackers inside
+ //the PageBody element because they depend on the values
+ //computed inside this tracker function.
+ WindowResizeTracker.addListener(function() {
+ var header = $('PageHeader');
+ var borderHeight = 2; //set in the inline style of div PageHeader
+
+ if (Prototype.Browser.IE) {
+ header.style.height = WindowResizeTracker.currentSizes.windowHeight + 'px';
+ } else {
+ header.style.height = (WindowResizeTracker.currentSizes.windowHeight - borderHeight) + 'px';
+ }
+ header.style.width = WindowResizeTracker.currentSizes.windowWidth + 'px';
+
+ var body = $('PageBody');
+ //27 = menu height (and the top position of PageBody)
+ body.style.height = (WindowResizeTracker.currentSizes.windowHeight - 27 - borderHeight) + 'px';
+ body.style.width = header.style.width;
+
+ document.body.style.height = WindowResizeTracker.currentSizes.windowHeight + 'px';
+ });
+ </script>
+ <!-- work around for IE and its broken box model. Without the concrete height value, the nav pane will shrink on hover. -->
+ <!--[if IE]>
+ <div id="PageHeader" style="border-bottom: 2px solid #999; position: absolute; top: 0; bottom: 0; left: 0; right: 0; height: 100%">
+ <![endif]-->
+ <!--[if !IE]><!-->
+ <div id="PageHeader" style="border-bottom: 2px solid #999; position: absolute; top: 0; bottom: 0; left: 0; right: 0;">
+ <!--<![endif]-->
+
+ <ui:include src="/rhq/common/menu/menu.xhtml"/>
+
+ <!-- work around for IE and its broken box model. Without the concrete height value, the nav pane will shrink on hover. -->
+ <!--[if IE]>
+ <div id="PageBody" style="width: 100%; position: absolute; top: 27px; bottom: 0; height: 100%;">
+ <![endif]-->
+ <!--[if !IE]><!-->
+ <div id="PageBody" style="width: 100%; position: absolute; top: 27px; bottom: 0;">
+ <!--<![endif]-->
+ <ui:insert name="body-area">Default Page Body</ui:insert>
+ </div>
+
+ </div>
+
+
+
+ <!-- =================== BODY =================== -->
+
+
+ <div id="about" class="dialog" style="display: none; position: absolute; top: 0; left: 0;">
+ <div class="DisplayContent" style="margin: 0;">
+ <div style="margin:5px">
+ <p class="compact">
+ <span class="DisplaySubhead">${msg['footer.aboutLink']}</span><br/>
+ <span class="DisplayLabel">${msg['footer.version']}: ${msg['product.version']}</span><br/>
+ <span class="DisplayLabel">${msg['footer.buildNumber']}: ${msg['product.buildNumber']}</span>
+ </p>
+
+ <p class="compact">
+ <f:verbatim>${msg['footer.copyright']}</f:verbatim> ${msg['about.Copyright.Content']}
+ </p>
+
+ <p class="compact">
+ ${msg['about.MoreInfo.Label']}<br/>
+ <a href="mailto:${msg['about.MoreInfo.LinkSales']}">${msg['about.MoreInfo.LinkSales']}</a><br/>
+ <a href="mailto:${msg['about.MoreInfo.LinkSupport']}">${msg['about.MoreInfo.LinkSupport']}</a>
+ </p>
+ </div>
+ </div>
+ </div>
+
+ <!-- work-around to enable us to embed richfaces components inside the onc:simpleTrigger;
+without this, the page will throw a javascript error "{blah} is not defined" or
+"{yadda} is not a constructor", and the pop-up action will not work -->
+ <rich:calendar rendered="false"/>
+ <rich:inputNumberSpinner rendered="false"/>
+
+</f:view>
+
+<script type="text/javascript">
+ addWindowOnLoadEvent(disableConditionalButtons);
+</script>
+
+</body>
+</html>
commit 9d7e958c1524f2505cf244f58ce6a965e50483ed
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 13 20:02:47 2009 -0500
out! out! damned tabs!
add // so formatters don't mess up Plugin class
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 e317d58..af17a6d 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -17,13 +17,13 @@
</echo>
<dbupgrade jdbcUrl="${jdbc.url}"
- jdbcUser="${jdbc.user}"
- jdbcPassword="${jdbc.password}"
- valueColumn="PROPERTY_VALUE"
- table="RHQ_SYSTEM_CONFIG"
- keyColumn="PROPERTY_KEY"
- keyMatch="DB_SCHEMA_VERSION"
- targetSchemaVersion="${target.schema.version}">
+ jdbcUser="${jdbc.user}"
+ jdbcPassword="${jdbc.password}"
+ valueColumn="PROPERTY_VALUE"
+ table="RHQ_SYSTEM_CONFIG"
+ keyColumn="PROPERTY_KEY"
+ keyMatch="DB_SCHEMA_VERSION"
+ targetSchemaVersion="${target.schema.version}">
<schemaSpec version="2.0">
<!-- Empty initial schema to avoid install failure on default latest schema version -->
@@ -870,15 +870,15 @@
<schema-directSQL>
<statement desc="Unscheduling auto-baseline job from Quartz - removing trigger">
DELETE FROM rhq_qrtz_triggers
- WHERE trigger_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
+ WHERE trigger_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
</statement>
<statement desc="Unscheduling auto-baseline job from Quartz - removing simple trigger">
DELETE FROM rhq_qrtz_simple_triggers
- WHERE trigger_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
+ WHERE trigger_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
</statement>
<statement desc="Unscheduling auto-baseline job from Quartz - removing job details">
DELETE FROM rhq_qrtz_job_details
- WHERE job_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
+ WHERE job_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
</statement>
</schema-directSQL>
</schemaSpec>
@@ -1089,7 +1089,7 @@
<schema-directSQL>
<statement desc="Populating values for new column RHQ_MEASUREMENT_DEF.RAW_NUMERIC_TYPE">
UPDATE RHQ_MEASUREMENT_DEF md
- SET RAW_NUMERIC_TYPE = (SELECT NUMERIC_TYPE FROM RHQ_MEASUREMENT_DEF
+ SET RAW_NUMERIC_TYPE = (SELECT NUMERIC_TYPE FROM RHQ_MEASUREMENT_DEF
WHERE NAME = md.NAME AND RESOURCE_TYPE_ID = md.RESOURCE_TYPE_ID AND (NUMERIC_TYPE = 1 OR NUMERIC_TYPE = 2))
WHERE NUMERIC_TYPE = 0
</statement>
@@ -1468,7 +1468,7 @@
<schema-addColumn table="RHQ_ALERT_DEFINITION" column="RESOURCE_GROUP_ID" columnType="INTEGER" />
<schema-addColumn table="RHQ_ALERT_DEFINITION" column="GROUP_ALERT_DEF_ID" columnType="INTEGER" />
</schemaSpec>
-
+
<schemaSpec version="2.59">
<schema-directSQL>
<statement desc="Creating table RHQ_RAW_CONFIG">
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index 0c8336b..fe704bc 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -61,7 +61,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.help, " //
+ " p.md5, " //
+ " p.version, " //
- + " p.ampsVersion, "
+ + " p.ampsVersion, " //
+ " p.ctime, " //
+ " p.mtime) " //
+ " FROM Plugin AS p " //
@@ -79,7 +79,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.help, " //
+ " p.md5, " //
+ " p.version, " //
- + " p.ampsVersion, "
+ + " p.ampsVersion, " //
+ " p.ctime, " //
+ " p.mtime) " //
+ " FROM Plugin AS p "), //
@@ -93,7 +93,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.enabled = :enabled, " //
+ " p.help = :help, " //
+ " p.version = :version, " //
- + " p.ampsVersion = :ampsVersion,"
+ + " p.ampsVersion = :ampsVersion," //
+ " p.path = :path, " //
+ " p.md5 = :md5, " //
+ " p.mtime = :mtime " //
@@ -111,7 +111,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.help, " //
+ " p.md5, " //
+ " p.version, " //
- + " p.ampsVersion, "
+ + " p.ampsVersion, " //
+ " p.ctime, " //
+ " p.mtime) " //
+ " FROM Plugin p " //
@@ -451,4 +451,4 @@ public class Plugin implements Serializable {
public String toString() {
return "Plugin[id=" + id + ", name=" + name + ", md5=" + md5 + "]";
}
-}
\ No newline at end of file
+}
commit 36beb6ecce46f14cdb3ab7602cf0467cefe1c0eb
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Fri Nov 13 12:15:09 2009 -0800
method rename to fix a mispelling identified by jdob
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java
index 9c4afa1..3e8e315 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java
@@ -63,7 +63,7 @@ public class ListReposUIBean extends PagedDataTableUIBean {
Integer[] repoIds = getIntegerArray(selected);
if (repoIds.length > 0) {
- int syncCount = repoManager.syncronizeRepos(subject, repoIds);
+ int syncCount = repoManager.synchronizeRepos(subject, repoIds);
if (syncCount > 0) {
FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Synchronizing [" + syncCount
+ "] content sources.");
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDetailsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDetailsUIBean.java
index f5231db..4fe6cfd 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDetailsUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDetailsUIBean.java
@@ -49,7 +49,7 @@ public class RepoDetailsUIBean {
public String sync() {
Subject subject = EnterpriseFacesContextUtility.getSubject();
Integer[] repoIds = { FacesContextUtility.getRequiredRequestParameter("id", Integer.class) };
- int syncCount = LookupUtil.getRepoManagerLocal().syncronizeRepos(subject, repoIds);
+ int syncCount = LookupUtil.getRepoManagerLocal().synchronizeRepos(subject, repoIds);
if (syncCount > 0) {
FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "The repository is syncing.");
} else {
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 20accf2..bb83c94 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
@@ -900,7 +900,7 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
}
@Override
- public int syncronizeRepos(Subject subject, Integer[] repoIds) {
+ public int synchronizeRepos(Subject subject, Integer[] repoIds) {
int syncCount = 0;
for (Integer id : repoIds) {
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 c260fc5..7ed6c66 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
@@ -280,6 +280,6 @@ public interface RepoManagerLocal {
* @param repoIds to syncronize
* @return count of the number of repositories synced.
*/
- int syncronizeRepos(Subject subject, Integer[] repoIds);
+ int synchronizeRepos(Subject subject, Integer[] repoIds);
}
\ 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 dda5c50..6eff16a 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
@@ -266,6 +266,6 @@ public interface RepoManagerRemote {
@WebParam(name = "pageControl") PageControl pc);
@WebMethod
- int syncronizeRepos(@WebParam(name = "subject") Subject subject, @WebParam(name = "repoIds") Integer[] repoIds);
+ int synchronizeRepos(@WebParam(name = "subject") Subject subject, @WebParam(name = "repoIds") Integer[] repoIds);
}
\ 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 57927ec..8587e51 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
@@ -287,8 +287,8 @@ public class WebservicesManagerBean implements WebservicesRemote {
}
@Override
- public int syncronizeRepos(Subject subject, Integer[] repoIds) {
- return repoManager.syncronizeRepos(subject, repoIds);
+ public int synchronizeRepos(Subject subject, Integer[] repoIds) {
+ return repoManager.synchronizeRepos(subject, repoIds);
}
//REPOMANAGER: END ----------------------------------
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
index a6c08c6..36e0943 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
@@ -101,19 +101,24 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
@Test(enabled = ENABLED)
public void testSyncRepos() throws Exception {
- Repo repo = new Repo("testSyncStatus");
- repoManager.createRepo(overlord, repo).getId();
- Integer[] ids = { repo.getId() };
- int syncCount = repoManager.syncronizeRepos(overlord, ids);
-
- assert syncCount == 0;
-
- ContentSourceType cst = new ContentSourceType("testSyncStatus");
- ContentSource cs = new ContentSource("testSyncStatus", cst);
- repo.addContentSource(cs);
- syncCount = repoManager.syncronizeRepos(overlord, ids);
-
- assert syncCount == 1;
+ try {
+ Repo repo = new Repo("testSyncStatus");
+ repoManager.createRepo(overlord, repo);
+ Integer[] ids = { repo.getId() };
+ int syncCount = repoManager.synchronizeRepos(overlord, ids);
+
+ assert syncCount == 0;
+
+ ContentSourceType cst = new ContentSourceType("testSyncStatus");
+ ContentSource cs = new ContentSource("testSyncStatus", cst);
+ repo.addContentSource(cs);
+ syncCount = repoManager.synchronizeRepos(overlord, ids);
+
+ assert syncCount == 1;
+ } catch (Throwable t) {
+ System.out.println("ERROR: " + t);
+ t.printStackTrace();
+ }
}
commit 920845bd11497a6e714ed71e8ce4a4f3c78f6ac0
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Fri Nov 13 13:03:57 2009 -0500
Small cleanup
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
index 1484e33..74842dc 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
@@ -373,7 +373,7 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
// -> Verify the correct repos were requested in the package sync
List<String> reposRequestedInSync = testProvider.getReposRequestedInSync();
- assert reposRequestedInSync.size() == 2;
+ assert reposRequestedInSync.size() == reposThatShouldBeSyncced.size();
assert reposRequestedInSync.containsAll(reposThatShouldBeSyncced);
}
commit 46e393936f2f398a1b06c75effd13a852653b1f5
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Fri Nov 13 12:40:20 2009 -0500
Updated test to ensure the correct repos are being used in the package sync calls
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersion.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersion.java
index c8faa9e..7d9b0d9 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersion.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersion.java
@@ -307,7 +307,7 @@ public class PackageVersion implements Serializable {
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Configuration extraProperties;
- @OneToMany(mappedBy = "packageVersion", fetch = FetchType.LAZY)
+ @OneToMany(mappedBy = "packageVersion", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private Set<RepoPackageVersion> repoPackageVersions;
// this mapping is here mainly to support our JPA queries
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
index 4e2282e..1484e33 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
@@ -23,10 +23,12 @@
package org.rhq.enterprise.server.plugin.pc.content;
import java.io.InputStream;
+import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
+import java.util.HashSet;
import javax.persistence.EntityManager;
import javax.persistence.Query;
@@ -70,16 +72,23 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
private static final String PACKAGE_VERSION = "1.0";
private static final String PACKAGE_ARCH = "noarch";
+ private static final String CUSTOM_IMPORTED_REPO_NAME = "customImportedRepo";
private static final String EXISTING_IMPORTED_REPO_NAME = "testRepoImportedExisting";
private static final String EXISTING_CANDIDATE_REPO_NAME = "testRepoCandidateExisting";
private static final String PREVIOUS_CANDIDATE_REPO_NAME = "testPreviousCandidate";
+ private TestContentProvider testProvider = new TestContentProvider();
+
// The following variables need to be cleaned up at the end of the test
private ContentSourceType testSourceType;
- private ContentSource testSource;
+ private ContentSource syncSource; // Source that is syncced in this test
+ private ContentSource nonSyncSource; // Existing source NOT being syncced in this test
+
+ private Repo nonCandidateOnOtherSource; // Should NOT appear in the sync packages call since its a different source
+
private PackageType testPackageType;
private ResourceType testResourceType;
@@ -106,6 +115,7 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
EntityManager entityManager = getEntityManager();
ContentSourceManagerLocal contentManager = LookupUtil.getContentSourceManager();
+ RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
Subject overlord = subjectManager.getOverlord();
@@ -113,9 +123,21 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
testSourceType = new ContentSourceType("testType");
entityManager.persist(testSourceType);
- // Add a content source to the DB to hang the sync against
- testSource = new ContentSource("testSource", testSourceType);
- contentManager.simpleCreateContentSource(overlord, testSource);
+ // Add a content source to sync in this test
+ syncSource = new ContentSource("testSource1", testSourceType);
+ contentManager.simpleCreateContentSource(overlord, syncSource);
+ entityManager.flush();
+
+ // Add an extra content source that isn't being syncced
+ nonSyncSource = new ContentSource("testSource2", testSourceType);
+ contentManager.simpleCreateContentSource(overlord, nonSyncSource);
+ entityManager.flush();
+
+ // Add existing repo against other source (this shouldn't show up in the request for packages)
+ nonCandidateOnOtherSource = new Repo("nonCandidateOnOtherSource");
+ nonCandidateOnOtherSource.setCandidate(false);
+ nonCandidateOnOtherSource.addContentSource(nonSyncSource);
+ repoManager.createRepo(overlord, nonCandidateOnOtherSource);
// Create a sample package type that will be used for packages sync'd in the test
testResourceType = new ResourceType(RESOURCE_TYPE_NAME, PLUGIN_NAME, ResourceCategory.PLATFORM, null);
@@ -158,17 +180,25 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
// First disassociate packages from the content source
entityManager.createNamedQuery(PackageVersionContentSource.DELETE_BY_CONTENT_SOURCE_ID).setParameter(
- "contentSourceId", testSource.getId()).executeUpdate();
+ "contentSourceId", syncSource.getId()).executeUpdate();
// Delete any packages created in this test
for (Integer packageId : packagesToDelete) {
PackageVersion deleteMe = entityManager.find(PackageVersion.class, packageId);
entityManager.remove(deleteMe);
}
+ entityManager.flush();
+
+ // Delete the existing repos
+ nonCandidateOnOtherSource = entityManager.find(Repo.class, nonCandidateOnOtherSource.getId());
+ entityManager.remove(nonCandidateOnOtherSource);
// Delete the source that was created
- testSource = entityManager.find(ContentSource.class, testSource.getId());
- entityManager.remove(testSource);
+ syncSource = entityManager.find(ContentSource.class, syncSource.getId());
+ entityManager.remove(syncSource);
+
+ nonSyncSource = entityManager.find(ContentSource.class, nonSyncSource.getId());
+ entityManager.remove(nonSyncSource);
// Delete the fake package type
testPackageType = entityManager.find(PackageType.class, testPackageType.getId());
@@ -201,27 +231,39 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
TestContentProviderManager providerManager = new TestContentProviderManager();
+ Set<String> reposThatShouldBeSyncced = new HashSet();
+
// -> Add an already imported repo to the system so it already exists when the report introduces it
Repo existingImportedRepo = new Repo(EXISTING_IMPORTED_REPO_NAME);
existingImportedRepo.setCandidate(false);
- existingImportedRepo.addContentSource(testSource);
+ existingImportedRepo.addContentSource(syncSource);
repoManager.createRepo(overlord, existingImportedRepo);
+ reposThatShouldBeSyncced.add(EXISTING_IMPORTED_REPO_NAME);
+
+ // -> Add an already imported repo that wasn't introduced from the report; a user created repo
+ Repo customImportedRepo = new Repo(CUSTOM_IMPORTED_REPO_NAME);
+ customImportedRepo.setCandidate(false);
+ customImportedRepo.addContentSource(syncSource);
+ repoManager.createRepo(overlord, customImportedRepo);
+
+ reposThatShouldBeSyncced.add(CUSTOM_IMPORTED_REPO_NAME);
+
// -> Simulate a candidate repo from a previous import that will be in this report as well
Repo existingCandidateRepo = new Repo(EXISTING_CANDIDATE_REPO_NAME);
existingCandidateRepo.setCandidate(true);
- existingCandidateRepo.addContentSource(testSource);
+ existingCandidateRepo.addContentSource(syncSource);
repoManager.createCandidateRepo(overlord, existingCandidateRepo);
// -> Simulate a candidate repo from a previous import that will *NOT* be in this report
Repo previousRepo = new Repo(PREVIOUS_CANDIDATE_REPO_NAME);
previousRepo.setCandidate(true);
- previousRepo.addContentSource(testSource);
+ previousRepo.addContentSource(syncSource);
repoManager.createCandidateRepo(overlord, previousRepo);
// Test
// --------------------------------------------
- boolean completed = providerManager.synchronizeContentSource(testSource.getId());
+ boolean completed = providerManager.synchronizeContentSource(syncSource.getId());
assert completed;
// Verify RepoGroups
@@ -289,6 +331,11 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
assert retrievedRepos.size() == 1;
reposToDelete.add(retrievedRepos.get(0).getId());
+ // -> Repo that was imported but not in the report (i.e. a user created repo)
+ retrievedRepos = repoManager.getRepoByName(CUSTOM_IMPORTED_REPO_NAME);
+ assert retrievedRepos.size() == 1;
+ reposToDelete.add(retrievedRepos.get(0).getId());
+
// -> Repo that was already a candidate in the system (make sure it's not added again)
retrievedRepos = repoManager.getRepoByName(EXISTING_CANDIDATE_REPO_NAME);
assert retrievedRepos.size() == 1;
@@ -324,6 +371,10 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
tx.rollback();
}
+ // -> Verify the correct repos were requested in the package sync
+ List<String> reposRequestedInSync = testProvider.getReposRequestedInSync();
+ assert reposRequestedInSync.size() == 2;
+ assert reposRequestedInSync.containsAll(reposThatShouldBeSyncced);
}
/**
@@ -331,6 +382,8 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
*/
private class TestContentProvider implements ContentProvider, PackageSource, RepoSource {
+ private List<String> reposRequestedInSync = new ArrayList<String>();
+
public RepoImportReport importRepos() throws Exception {
RepoImportReport report = new RepoImportReport();
@@ -370,6 +423,8 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
public void synchronizePackages(String repoName, PackageSyncReport report,
Collection<ContentProviderPackageDetails> existingPackages) throws Exception {
+ reposRequestedInSync.add(repoName);
+
ContentProviderPackageDetailsKey key1 = new ContentProviderPackageDetailsKey(PACKAGE_NAME, PACKAGE_VERSION,
PACKAGE_TYPE_NAME, PACKAGE_ARCH, RESOURCE_TYPE_NAME, PLUGIN_NAME);
ContentProviderPackageDetails pkg1 = new ContentProviderPackageDetails(key1);
@@ -391,8 +446,14 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
}
public InputStream getInputStream(String location) throws Exception {
- // No-op
- return null;
+ String fakeBits = "Totally fake bits";
+ ByteArrayInputStream bis = new ByteArrayInputStream(fakeBits.getBytes());
+
+ return bis;
+ }
+
+ public List<String> getReposRequestedInSync() {
+ return reposRequestedInSync;
}
}
@@ -402,8 +463,6 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
*/
private class TestContentProviderManager extends ContentProviderManager {
- private ContentProvider testProvider = new TestContentProvider();
-
protected ContentProvider getIsolatedContentProvider(int contentProviderId) throws RuntimeException {
return testProvider;
}
commit 0c91d17795ba6c5dc6b2c78048ea6382315862e0
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Fri Nov 13 12:26:56 2009 -0500
Fixed query to only attempt to sync packages for imported repos
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
index be3fe54..937ba2a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
@@ -189,6 +189,7 @@ public class ContentProviderManager {
RepoCriteria reposForContentSource = new RepoCriteria();
reposForContentSource.addFilterContentSourceIds(contentSourceId);
+ reposForContentSource.addFilterCandidate(false); // Don't sync packages for candidates
List<Repo> repos = repoManager.findReposByCriteria(overlord, reposForContentSource);
commit 915386f33a63ef8112a967b039f9d97135752a5b
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Fri Nov 13 12:18:38 2009 -0500
not changed, maybe resolving a line terminator issue
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml
index eac2995..339a4ea 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml
@@ -1,163 +1,163 @@
-<?xml version="1.0"?>
-
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml"
- xmlns:h="http://java.sun.com/jsf/html"
- xmlns:f="http://java.sun.com/jsf/core"
- xmlns:ui="http://java.sun.com/jsf/facelets"
- xmlns:c="http://java.sun.com/jstl/core"
- xmlns:a4j="http://richfaces.org/a4j"
- xmlns:onc="http://jboss.org/on/component"
- xmlns:rich="http://richfaces.ajax4jsf.org/rich">
-
-<head>
- <title>${msg["product.shortName"]} - #{(!empty pageTitle) ? pageTitle : defaultPageTitle}</title>
-
- <ui:insert name="metaHeaders"></ui:insert>
-
- <link rel="stylesheet" type="text/css" media="screen" href="/css/win.css"/>
- <link rel="stylesheet" type="text/css" media="screen" href="/css/form-style.css"/>
- <link rel="stylesheet" type="text/css" media="screen" href="/css/menu.css"/>
-
- <script type="text/javascript" src="/js/functions.js"></script>
- <script type="text/javascript" src="/js/prototype.js"></script>
- <script type="text/javascript" src="/js/window.js"></script>
- <script type="text/javascript" src="/js/effects.js"></script>
- <!--<script type="text/javascript" src="/js/debug.js"></script>-->
- <script type="text/javascript" src="/js/formValues.js"></script>
- <script type="text/javascript" src="/js/rhq.js"></script>
- <script type="text/javascript" src="/js/popup.js"></script>
- <script type="text/javascript" src="/js/iframeSSI.js">
- /***********************************************
- * IFrame SSI script II- © Dynamic Drive DHTML code library (http://www.dynamicdrive.com)
- * Visit DynamicDrive.com for hundreds of original DHTML scripts
- * This notice must stay intact for legal use
- ***********************************************/
- </script>
-
- <link href="/css/theme/default.css" rel="stylesheet" type="text/css"/>
- <link href="/css/theme/alphacube.css" rel="stylesheet" type="text/css"/>
- <link href="/css/theme/debug.css" rel="stylesheet" type="text/css"/>
-
- <link rel="icon" type="image/png" href="/images/favicon.png"/>
- <link rel="apple-touch-icon" href="/images/favicon.png"/>
-
- <!-- Trims up the headers of RF toggle panel headers -->
- <style type="text/css">
- .BlockTitle {
- padding-top: 3px;
- padding-bottom: 3px;
- }
- HTML, BODY { overflow: hidden; }
- </style>
-
- <link rel="stylesheet" type="text/css" media="screen" href="/css/tabular.css"/>
- <link rel="stylesheet" type="text/css" media="screen" href="/css/layout.css"/>
-
- <script type="text/javascript">
- var imagePath = "/images/";
- </script>
-
-</head>
-
-<body bgcolor="#FFFFFF" style="height: 100%;">
-
-<ui:remove>
- <!-- Set the content type to "text/html" (overriding the default of "application/xhtml+xml") to force
-Firefox and other Gecko-based browsers to render the page in "Almost Standards" (i.e. transitional) mode. -->
-</ui:remove>
-<f:view contentType="text/html">
-
-
- <f:loadBundle basename="ApplicationResources" var="msg"/>
-
- <!-- =================== PAGE HEADER =================== -->
-
- <script language="javascript" type="text/javascript">
- //this has to be defined before the resize trackers inside
- //the PageBody element because they depend on the values
- //computed inside this tracker function.
- WindowResizeTracker.addListener(function() {
- var header = $('PageHeader');
- var borderHeight = 2; //set in the inline style of div PageHeader
-
- if (Prototype.Browser.IE) {
- header.style.height = WindowResizeTracker.currentSizes.windowHeight + 'px';
- } else {
- header.style.height = (WindowResizeTracker.currentSizes.windowHeight - borderHeight) + 'px';
- }
- header.style.width = WindowResizeTracker.currentSizes.windowWidth + 'px';
-
- var body = $('PageBody');
- //27 = menu height (and the top position of PageBody)
- body.style.height = (WindowResizeTracker.currentSizes.windowHeight - 27 - borderHeight) + 'px';
- body.style.width = header.style.width;
-
- document.body.style.height = WindowResizeTracker.currentSizes.windowHeight + 'px';
- });
- </script>
- <!-- work around for IE and its broken box model. Without the concrete height value, the nav pane will shrink on hover. -->
- <!--[if IE]>
- <div id="PageHeader" style="border-bottom: 2px solid #999; position: absolute; top: 0; bottom: 0; left: 0; right: 0; height: 100%">
- <![endif]-->
- <!--[if !IE]><!-->
- <div id="PageHeader" style="border-bottom: 2px solid #999; position: absolute; top: 0; bottom: 0; left: 0; right: 0;">
- <!--<![endif]-->
-
- <ui:include src="/rhq/common/menu/menu.xhtml"/>
-
- <!-- work around for IE and its broken box model. Without the concrete height value, the nav pane will shrink on hover. -->
- <!--[if IE]>
- <div id="PageBody" style="width: 100%; position: absolute; top: 27px; bottom: 0; height: 100%;">
- <![endif]-->
- <!--[if !IE]><!-->
- <div id="PageBody" style="width: 100%; position: absolute; top: 27px; bottom: 0;">
- <!--<![endif]-->
- <ui:insert name="body-area">Default Page Body</ui:insert>
- </div>
-
- </div>
-
-
-
- <!-- =================== BODY =================== -->
-
-
- <div id="about" class="dialog" style="display: none; position: absolute; top: 0; left: 0;">
- <div class="DisplayContent" style="margin: 0;">
- <div style="margin:5px">
- <p class="compact">
- <span class="DisplaySubhead">${msg['footer.aboutLink']}</span><br/>
- <span class="DisplayLabel">${msg['footer.version']}: ${msg['product.version']}</span><br/>
- <span class="DisplayLabel">${msg['footer.buildNumber']}: ${msg['product.buildNumber']}</span>
- </p>
-
- <p class="compact">
- <f:verbatim>${msg['footer.copyright']}</f:verbatim> ${msg['about.Copyright.Content']}
- </p>
-
- <p class="compact">
- ${msg['about.MoreInfo.Label']}<br/>
- <a href="mailto:${msg['about.MoreInfo.LinkSales']}">${msg['about.MoreInfo.LinkSales']}</a><br/>
- <a href="mailto:${msg['about.MoreInfo.LinkSupport']}">${msg['about.MoreInfo.LinkSupport']}</a>
- </p>
- </div>
- </div>
- </div>
-
- <!-- work-around to enable us to embed richfaces components inside the onc:simpleTrigger;
-without this, the page will throw a javascript error "{blah} is not defined" or
-"{yadda} is not a constructor", and the pop-up action will not work -->
- <rich:calendar rendered="false"/>
- <rich:inputNumberSpinner rendered="false"/>
-
-</f:view>
-
-<script type="text/javascript">
- addWindowOnLoadEvent(disableConditionalButtons);
-</script>
-
-</body>
-</html>
+<?xml version="1.0"?>
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jstl/core"
+ xmlns:a4j="http://richfaces.org/a4j"
+ xmlns:onc="http://jboss.org/on/component"
+ xmlns:rich="http://richfaces.ajax4jsf.org/rich">
+
+<head>
+ <title>${msg["product.shortName"]} - #{(!empty pageTitle) ? pageTitle : defaultPageTitle}</title>
+
+ <ui:insert name="metaHeaders"></ui:insert>
+
+ <link rel="stylesheet" type="text/css" media="screen" href="/css/win.css"/>
+ <link rel="stylesheet" type="text/css" media="screen" href="/css/form-style.css"/>
+ <link rel="stylesheet" type="text/css" media="screen" href="/css/menu.css"/>
+
+ <script type="text/javascript" src="/js/functions.js"></script>
+ <script type="text/javascript" src="/js/prototype.js"></script>
+ <script type="text/javascript" src="/js/window.js"></script>
+ <script type="text/javascript" src="/js/effects.js"></script>
+ <!--<script type="text/javascript" src="/js/debug.js"></script>-->
+ <script type="text/javascript" src="/js/formValues.js"></script>
+ <script type="text/javascript" src="/js/rhq.js"></script>
+ <script type="text/javascript" src="/js/popup.js"></script>
+ <script type="text/javascript" src="/js/iframeSSI.js">
+ /***********************************************
+ * IFrame SSI script II- © Dynamic Drive DHTML code library (http://www.dynamicdrive.com)
+ * Visit DynamicDrive.com for hundreds of original DHTML scripts
+ * This notice must stay intact for legal use
+ ***********************************************/
+ </script>
+
+ <link href="/css/theme/default.css" rel="stylesheet" type="text/css"/>
+ <link href="/css/theme/alphacube.css" rel="stylesheet" type="text/css"/>
+ <link href="/css/theme/debug.css" rel="stylesheet" type="text/css"/>
+
+ <link rel="icon" type="image/png" href="/images/favicon.png"/>
+ <link rel="apple-touch-icon" href="/images/favicon.png"/>
+
+ <!-- Trims up the headers of RF toggle panel headers -->
+ <style type="text/css">
+ .BlockTitle {
+ padding-top: 3px;
+ padding-bottom: 3px;
+ }
+ HTML, BODY { overflow: hidden; }
+ </style>
+
+ <link rel="stylesheet" type="text/css" media="screen" href="/css/tabular.css"/>
+ <link rel="stylesheet" type="text/css" media="screen" href="/css/layout.css"/>
+
+ <script type="text/javascript">
+ var imagePath = "/images/";
+ </script>
+
+</head>
+
+<body bgcolor="#FFFFFF" style="height: 100%;">
+
+<ui:remove>
+ <!-- Set the content type to "text/html" (overriding the default of "application/xhtml+xml") to force
+Firefox and other Gecko-based browsers to render the page in "Almost Standards" (i.e. transitional) mode. -->
+</ui:remove>
+<f:view contentType="text/html">
+
+
+ <f:loadBundle basename="ApplicationResources" var="msg"/>
+
+ <!-- =================== PAGE HEADER =================== -->
+
+ <script language="javascript" type="text/javascript">
+ //this has to be defined before the resize trackers inside
+ //the PageBody element because they depend on the values
+ //computed inside this tracker function.
+ WindowResizeTracker.addListener(function() {
+ var header = $('PageHeader');
+ var borderHeight = 2; //set in the inline style of div PageHeader
+
+ if (Prototype.Browser.IE) {
+ header.style.height = WindowResizeTracker.currentSizes.windowHeight + 'px';
+ } else {
+ header.style.height = (WindowResizeTracker.currentSizes.windowHeight - borderHeight) + 'px';
+ }
+ header.style.width = WindowResizeTracker.currentSizes.windowWidth + 'px';
+
+ var body = $('PageBody');
+ //27 = menu height (and the top position of PageBody)
+ body.style.height = (WindowResizeTracker.currentSizes.windowHeight - 27 - borderHeight) + 'px';
+ body.style.width = header.style.width;
+
+ document.body.style.height = WindowResizeTracker.currentSizes.windowHeight + 'px';
+ });
+ </script>
+ <!-- work around for IE and its broken box model. Without the concrete height value, the nav pane will shrink on hover. -->
+ <!--[if IE]>
+ <div id="PageHeader" style="border-bottom: 2px solid #999; position: absolute; top: 0; bottom: 0; left: 0; right: 0; height: 100%">
+ <![endif]-->
+ <!--[if !IE]><!-->
+ <div id="PageHeader" style="border-bottom: 2px solid #999; position: absolute; top: 0; bottom: 0; left: 0; right: 0;">
+ <!--<![endif]-->
+
+ <ui:include src="/rhq/common/menu/menu.xhtml"/>
+
+ <!-- work around for IE and its broken box model. Without the concrete height value, the nav pane will shrink on hover. -->
+ <!--[if IE]>
+ <div id="PageBody" style="width: 100%; position: absolute; top: 27px; bottom: 0; height: 100%;">
+ <![endif]-->
+ <!--[if !IE]><!-->
+ <div id="PageBody" style="width: 100%; position: absolute; top: 27px; bottom: 0;">
+ <!--<![endif]-->
+ <ui:insert name="body-area">Default Page Body</ui:insert>
+ </div>
+
+ </div>
+
+
+
+ <!-- =================== BODY =================== -->
+
+
+ <div id="about" class="dialog" style="display: none; position: absolute; top: 0; left: 0;">
+ <div class="DisplayContent" style="margin: 0;">
+ <div style="margin:5px">
+ <p class="compact">
+ <span class="DisplaySubhead">${msg['footer.aboutLink']}</span><br/>
+ <span class="DisplayLabel">${msg['footer.version']}: ${msg['product.version']}</span><br/>
+ <span class="DisplayLabel">${msg['footer.buildNumber']}: ${msg['product.buildNumber']}</span>
+ </p>
+
+ <p class="compact">
+ <f:verbatim>${msg['footer.copyright']}</f:verbatim> ${msg['about.Copyright.Content']}
+ </p>
+
+ <p class="compact">
+ ${msg['about.MoreInfo.Label']}<br/>
+ <a href="mailto:${msg['about.MoreInfo.LinkSales']}">${msg['about.MoreInfo.LinkSales']}</a><br/>
+ <a href="mailto:${msg['about.MoreInfo.LinkSupport']}">${msg['about.MoreInfo.LinkSupport']}</a>
+ </p>
+ </div>
+ </div>
+ </div>
+
+ <!-- work-around to enable us to embed richfaces components inside the onc:simpleTrigger;
+without this, the page will throw a javascript error "{blah} is not defined" or
+"{yadda} is not a constructor", and the pop-up action will not work -->
+ <rich:calendar rendered="false"/>
+ <rich:inputNumberSpinner rendered="false"/>
+
+</f:view>
+
+<script type="text/javascript">
+ addWindowOnLoadEvent(disableConditionalButtons);
+</script>
+
+</body>
+</html>
commit 31d3b78dddd1a529d710a48ce7b70837ad3337b4
Merge: 6f764c1... a08036a...
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Fri Nov 13 09:11:01 2009 -0800
Merge branch 'master' into content
diff --cc modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
index 57ba0ec,d5836ef..afae482
--- a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
+++ b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
@@@ -48,9 -47,8 +48,9 @@@ public class SambaComponentTest extend
return "Samba Server";
}
+
@Override
- protected Configuration getChangedResourceConfig() {
+ protected Configuration getUpdatedResourceConfig() {
Configuration config = new Configuration();
config.put(new PropertySimple("workgroup", "DUMBCHANGE"));
commit a08036a99b543cfbc25208061543c9a9d8663466
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 13 02:49:54 2009 -0500
Conflicts:
etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
why did these conflicts happen when I got no conflicts merging the same thing in the pc branch (where pc and master were identical, diff showed nothing different between pc and master)
diff --git a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java
new file mode 100644
index 0000000..f137cf5
--- /dev/null
+++ b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java
@@ -0,0 +1,39 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.custom;
+
+import java.util.Properties;
+
+import org.rhq.enterprise.server.plugin.pc.ScheduledJob;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
+
+/**
+ * Example of a scheduled job.
+ *
+ * @author John Mazzitelli
+ */
+public class MyScheduledJob implements ScheduledJob {
+ @Override
+ public void execute(String jobId, ServerPluginLifecycleListener lifecycleListener, Properties callbackData)
+ throws Exception {
+ System.out.println("Sample scheduled job has been triggered! [" + this.getClass() + "] jobId=" + jobId
+ + ", lifecycle-listener=" + lifecycleListener);
+ }
+}
diff --git a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
index 57f19cc..f00dbc8 100644
--- a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -16,6 +16,14 @@
</serverplugin:schedule>
</serverplugin:lifecycle-listener>
+ <serverplugin:scheduled-job jobId="first-scheduled-job" concurrent="false" class="MyScheduledJob">
+ <serverplugin:cron>0 0/5 * * * ?</serverplugin:cron>
+ </serverplugin:scheduled-job>
+
+ <serverplugin:scheduled-job jobId="sample-job-2" concurrent="true" class="MyScheduledJob">
+ <serverplugin:period>60000</serverplugin:period>
+ </serverplugin:scheduled-job>
+
<serverplugin:plugin-configuration>
<c:simple-property name="myCustomProperty" type="string" required="true"
description="A property my plugin needs to be properly configured" />
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index 606da06..8384b98 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -20,6 +20,7 @@
package org.rhq.enterprise.server.plugin.pc;
import java.util.Collection;
+import java.util.List;
import java.util.Properties;
import org.apache.commons.logging.Log;
@@ -29,6 +30,7 @@ import org.quartz.JobDataMap;
import org.rhq.enterprise.server.scheduler.SchedulerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ScheduledJobType;
/**
* The abstract superclass for all plugin containers of the different {@link ServerPluginType plugin types}.
@@ -175,9 +177,9 @@ public abstract class AbstractTypeServerPluginContainer {
/**
* If a plugin has scheduled jobs, this method will schedule them now.
- * This particular method implementation schedules the global job as defined in the
- * plugin descriptors. If a plugin has a global scheduled job, its lifecycle listener
- * will be the job handler class.
+ * This particular method implementation schedules the global jobs as defined in the
+ * plugin descriptors. If a plugin has a global scheduled job on its lifecycle
+ * listener, that lifecycle listener will be the job handler class.
*
* Subclasses are free to extend this method to schedule additional plugin jobs, but must
* ensure they call this method so the global scheduled jobs get added to the scheduler.
@@ -190,20 +192,47 @@ public abstract class AbstractTypeServerPluginContainer {
*/
public synchronized void schedulePluginJobs() throws Exception {
if (this.pluginManager != null) {
- // if there are any global schedules defined, schedule them now.
- // note that we know if there is no lifecycle listener, then there can't be a global schedule
+ // process all known plugins and schedule their jobs
for (ServerPluginEnvironment pluginEnv : this.pluginManager.getPluginEnvironments()) {
String pluginName = pluginEnv.getPluginName();
+
+ // First see if the listener has a schedule itself and schedule it if it does.
+ // Note that we know if there is no lifecycle listener, then there can't be a listener schedule
if (this.pluginManager.getServerPluginLifecycleListener(pluginName) != null) {
Schedule schedule = this.pluginManager.getServerPluginContext(pluginEnv).getSchedule();
if (schedule != null) {
try {
- scheduleJob(schedule, pluginName, "__globalScheduleJob", null, null);
+ scheduleJob(schedule, pluginName, "__lifecycleListenerJob", null, null);
} catch (Throwable t) {
log.warn("Failed to schedule the global plugin job for plugin [" + pluginName + "]", t);
}
}
}
+
+ // now schedule all the other jobs defined in the plugin descriptor
+ List<ScheduledJobType> jobs = pluginEnv.getPluginDescriptor().getScheduledJob();
+ if (jobs != null) {
+ for (ScheduledJobType job : jobs) {
+ Schedule schedule;
+ if (job.getPeriod() != null) {
+ schedule = new PeriodicSchedule(job.isConcurrent(), job.getPeriod().longValue());
+ } else {
+ schedule = new CronSchedule(job.isConcurrent(), job.getCron());
+ }
+
+ String scheduledJobClass = job.getClazz();
+ String jobId = job.getJobId();
+ if (scheduledJobClass != null) {
+ try {
+ scheduleJob(schedule, pluginName, jobId, scheduledJobClass, null);
+ } catch (Throwable t) {
+ log.warn("Failed to schedule job [" + jobId + "] for plugin [" + pluginName + "]", t);
+ }
+ } else {
+ log.warn("Scheduled job [" + jobId + "] in plugin [" + pluginName + "] is missing class");
+ }
+ }
+ }
}
} else {
throw new Exception("Cannot schedule plugins jobs; plugin container is not initialized yet");
@@ -251,8 +280,8 @@ public abstract class AbstractTypeServerPluginContainer {
*
* @throws Exception if failed to schedule the job
*/
- protected void scheduleJob(Schedule schedule, String pluginName, String jobId,
- Class<? extends ScheduledJob> scheduledJobClass, Properties callbackData) throws Exception {
+ protected void scheduleJob(Schedule schedule, String pluginName, String jobId, String scheduledJobClass,
+ Properties callbackData) throws Exception {
String groupName = pluginName;
boolean rescheduleIfExists = true; // just in case the parameters change, we'll always want to reschedule it if it exists
@@ -272,7 +301,7 @@ public abstract class AbstractTypeServerPluginContainer {
jobData.put(AbstractJobWrapper.DATAMAP_PLUGIN_TYPE, getSupportedServerPluginType().stringify());
jobData.put(AbstractJobWrapper.DATAMAP_JOB_ID, jobId);
if (scheduledJobClass != null) {
- jobData.put(AbstractJobWrapper.DATAMAP_SCHEDULED_JOB_CLASS, scheduledJobClass.getName());
+ jobData.put(AbstractJobWrapper.DATAMAP_SCHEDULED_JOB_CLASS, scheduledJobClass);
}
if (callbackData != null) {
jobData.putAll(callbackData);
@@ -281,7 +310,7 @@ public abstract class AbstractTypeServerPluginContainer {
// schedule the job now
SchedulerLocal scheduler = LookupUtil.getSchedulerBean();
if (schedule instanceof CronSchedule) {
- String cronExpression = ((CronSchedule) scheduler).getCronExpression();
+ String cronExpression = ((CronSchedule) schedule).getCronExpression();
log.info("Scheduling server plugin cron job: jobName=" + jobId + ", groupName=" + groupName + ", jobClass="
+ jobClass + ", cron=" + cronExpression);
scheduler.scheduleCronJob(jobId, groupName, jobData, jobClass, rescheduleIfExists, isVolatile,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index 1c31b8d..42ce6af 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -339,14 +339,9 @@ public class ServerPluginManager {
LifecycleListenerType lifecycleListener = environment.getPluginDescriptor().getLifecycleListener();
if (lifecycleListener != null) {
String className = lifecycleListener.getClazz();
- String pkg = environment.getPluginDescriptor().getPackage();
- if ((className.indexOf('.') == -1) && (pkg != null)) {
- className = pkg + '.' + className;
- }
-
log.debug("Creating plugin lifecycle listener [" + className + "] for plugin [" + pluginName + "]");
instance = (ServerPluginLifecycleListener) instantiatePluginClass(environment, className);
- log.debug("Created plugin lifecycle listener [" + className + "] for plugin [" + pluginName + "]");
+ log.debug("Lifecycle listener created [" + instance.getClass() + "] for plugin [" + pluginName + "]");
}
return instance;
@@ -365,6 +360,11 @@ public class ServerPluginManager {
ClassLoader loader = environment.getPluginClassLoader();
+ String pkg = environment.getPluginDescriptor().getPackage();
+ if ((className.indexOf('.') == -1) && (pkg != null)) {
+ className = pkg + '.' + className;
+ }
+
log.debug("Loading server plugin class [" + className + "]...");
try {
diff --git a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
index 88c0022..2791fee 100644
--- a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
+++ b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
@@ -49,6 +49,15 @@
this class will be notified when the plugin is loaded and unloaded. This provides a place
for plugin developers to allocate global resources needed by all plugin components and
a place to clean up those resources. It can also be scheduled to perform periodic work.
+ A lifecycle listener object is stateful - the instance lives for as long as the plugin
+ is initialized.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="scheduled-job" minOccurs="0" maxOccurs="unbounded" type="serverplugin:ScheduledJobType">
+ <xs:annotation>
+ <xs:documentation>
+ A scheduled job that is called to periodically perform work on behalf of the plugin.
</xs:documentation>
</xs:annotation>
</xs:element>
@@ -173,6 +182,34 @@
</xs:attribute>
</xs:complexType>
+ <xs:complexType name="ScheduledJobType">
+ <xs:complexContent>
+ <xs:extension base="serverplugin:ScheduleType">
+ <xs:attribute name="jobId" type="xs:string" use="required">
+ <xs:annotation>
+ <xs:documentation>
+ A unique identifier for this job. Job IDs need to be unique
+ within a plugin. When the scheduled job is invoked, this job ID
+ will be passed to it.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="class" type="serverplugin:classNameType" use="required">
+ <xs:annotation>
+ <xs:documentation>
+ The classname of the ScheduledJob implementation that will be instantiated
+ whenever the schedule is triggered. This job instance will not be stateful,
+ a new instance of the class is created for each schedule trigger. Each job
+ invocation is handed a reference to the plugin's lifecycle listener (if one
+ was defined for the plugin), thus providing a way to obtain stateful
+ information from the plugin.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
<xs:simpleType name="classNameType">
<xs:restriction base="xs:string">
<xs:whiteSpace value="collapse" />
diff --git a/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java b/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
index 7f2029d..3e1247d 100644
--- a/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
+++ b/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
@@ -26,6 +26,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
+import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
@@ -39,6 +40,7 @@ import org.rhq.core.clientapi.descriptor.configuration.ConfigurationDescriptor;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.LifecycleListenerType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ScheduleType;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ScheduledJobType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.alert.AlertPluginDescriptorType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.generic.GenericPluginDescriptorType;
@@ -75,6 +77,14 @@ public class ServerPluginDescriptorUtilTest {
assert schedule.getCron().equals("0 15 10 ? * MON-FRI");
assert schedule.getPeriod() == null;
+ List<ScheduledJobType> scheduledJobs = descriptor.getScheduledJob();
+ scheduledJobs.get(0).getJobId().equals("generic-job-1");
+ scheduledJobs.get(0).getClazz().equals("generic.scheduled.job1");
+ scheduledJobs.get(0).getPeriod().equals("123");
+ scheduledJobs.get(1).getJobId().equals("generic-job-2");
+ scheduledJobs.get(1).getClazz().equals("generic.scheduled.job2");
+ scheduledJobs.get(1).getCron().equals("0 30 11 ? * WED-FRI");
+
ConfigurationDescriptor config = descriptor.getPluginConfiguration();
assert config != null;
assert config.getConfigurationProperty().get(0).getValue().getName().equals("prop1");
@@ -101,6 +111,8 @@ public class ServerPluginDescriptorUtilTest {
assert schedule.getCron() == null;
assert schedule.getPeriod().longValue() == 1000L;
+ assert descriptor.getScheduledJob().size() == 0;
+
ConfigurationDescriptor config = descriptor.getPluginConfiguration();
assert config != null;
assert config.getConfigurationProperty().get(0).getValue().getName().equals("alertprop1");
diff --git a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
index a72f0a3..fcb58ca 100644
--- a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
+++ b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
@@ -18,6 +18,15 @@
</serverplugin:schedule>
</serverplugin:lifecycle-listener>
+ <serverplugin:scheduled-job jobId="generic-job-1" class="generic.scheduled.job1" concurrent="false">
+ <serverplugin:period>123</serverplugin:period>
+ </serverplugin:scheduled-job>
+
+ <serverplugin:scheduled-job jobId="generic-job-2" class="generic.scheduled.job2" concurrent="true">
+ <!-- Fire at 11:30am every wed-thru-fri -->
+ <serverplugin:cron>0 30 11 ? * WED-FRI</serverplugin:cron>
+ </serverplugin:scheduled-job>
+
<serverplugin:plugin-configuration>
<c:simple-property name="prop1" />
</serverplugin:plugin-configuration>
commit a21942e33503e985bb258b024223d00c911b1385
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 13 02:42:00 2009 -0500
Squashed commit of the following:
commit 7d94cc85d6110c1ae24e9e4f36348bb91040e02c
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 13 02:36:04 2009 -0500
schedule the jobs defined in the plugin descriptor
commit 33e88822380918dfd0eb59859fe211fcc6bb201e
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 20:08:46 2009 -0500
add a sample scheduled job
commit 9715f86f668f5625f8c3e65c090d1e7d93439423
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 19:55:20 2009 -0500
add schema to specify 0, 1 or more scheduled jobs in a plugin descriptor
commit 5a27491de9e0470035e0eca320eb2496bf76fc66
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 18:53:40 2009 -0500
Squashed commit of the following:
commit f6d790e73caa5c3714768660656da69fb49e2653
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 18:42:51 2009 -0500
Squashed commit of the following:
commit 4176765871d06b37895dc72269233687325eaa87
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 17:20:20 2009 -0500
get the plugin jobs to be scheduled properly in quartz
commit 08644de029a313e09673870395bf0a5f8607098b
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 11:47:39 2009 -0500
fix the operation names in the rhq server plugin
commit 8075b0b26d1c2514ff7a1c831491a51d8a2909c8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 03:22:06 2009 -0500
Squashed commit of the following:
commit d3dfc1a52b0414bd67f50ed9c881c8c3e33e9a1e
Merge: 2cd6ba1 ad45fe5
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 22:38:00 2009 -0500
Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq
commit 2cd6ba182ee07849e2ccd06be6c962b879f45112
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 16:33:18 2009 -0500
Allow clean install to still copy over the license file.
This patch moves the license file from the server container module to the ear module. It is copied over in the dev profile only.
commit 9d93844a860e54c2a012644975ccee198c76f9a6
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 02:53:23 2009 -0500
actually schedule the jobs in quartz
commit 25c0a3e27d9969368230277cb5a33633dbbdb897
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 02:06:54 2009 -0500
add plugin context to the job interface
commit c14822a979ab9e130dfc08279ae6ca342bd591bf
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 01:45:23 2009 -0500
provide an API to schedule jobs
commit a1c36f7c4efb5fd4e78c246c9e270bb55901e883
Merge: ccb085f d3dfc1a
Author: Partha Aji <paji(a)redhat.com>
Date: Thu Nov 12 12:26:11 2009 -0500
Merge branch 'master' into linux-config
commit ccb085f89d6a36787da1c570fbb7006672de68f9
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Thu Nov 12 11:45:14 2009 -0500
remove experimental hosts-augeas plugin, which is no longer needed
commit 6a676af5fd6af0c2fafd3faf5fc24a119bbceb72
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Thu Nov 12 11:18:13 2009 -0500
get hosts plugin integration tests passing on Windows
commit cb288a8321d659c8839328066f5c50f4e548a4ba
Author: Partha Aji <paji(a)redhat.com>
Date: Thu Nov 12 10:09:55 2009 -0500
Removed the augeas test jar dep from aliases pom since its going to be built as part of core
commit d3dfc1a52b0414bd67f50ed9c881c8c3e33e9a1e
Merge: 2cd6ba1 ad45fe5
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 22:38:00 2009 -0500
Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq
commit 3b6e81de84ba5b3ec4af37fd7c1ba7afafe65d8a
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 20:38:51 2009 -0500
Added Load and Update tests for the alias component
commit 771b96fc5e2213dc8bcba4bb0991aefe1556bd37
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 19:50:04 2009 -0500
added aliaseses to .classpath
commit 7e8a1621b6990bd4d673c49dda47ad910d0eaab3
Merge: 15a3b45 ad45fe5
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 19:42:58 2009 -0500
Merge branch 'master' into linux-config
commit 15a3b45d91942fdcccef99a20e422c857834ae0a
Author: Ian P. Springer <ips(a)jetengine.springer.net>
Date: Wed Nov 11 18:48:34 2009 -0500
fix several bugs in augeas and hosts plugins to get hosts+samba+sudoers integration tests passing on Linux; update test log4j.xml in all augeas-based plugins
commit 2cd6ba182ee07849e2ccd06be6c962b879f45112
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 16:33:18 2009 -0500
Allow clean install to still copy over the license file.
This patch moves the license file from the server container module to the ear module. It is copied over in the dev profile only.
commit 06eb2ee352c198385e2797d4e3c9816a59ba0c02
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Nov 11 11:31:46 2009 -0500
Augeas-based ResourceComponents now handle it as gracefully as possible when Augeas is not installed on the Agent system
commit d391bb6be98bfeabfaa06f25fbf33cf67ea85f06
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Nov 11 10:19:44 2009 -0500
refactor so that config tests are skipped if Augeas is not available, so tests will pass on systems without Augeas (e.g. Windows boxes)
commit 62f8c89cd2fcc882f6783c8530ac4cf46f7cec34
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 10:06:08 2009 -0500
Revert "Fixed test cases related to samba and sudoer plugins"
Looks like there is a better way to achieve the same.. Waiing for ips'
commit
This reverts commit 6d666b6987f1c58732851a57560ec93ba21c4cc5.
commit 7d952067685d548fc7b26bf7a8a272cece448484
Merge: 6d666b6 46d0de1
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 00:53:22 2009 -0500
Merge branch 'master' into hope
commit 6d666b6987f1c58732851a57560ec93ba21c4cc5
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 00:51:04 2009 -0500
Fixed test cases related to samba and sudoer plugins
commit d7e80500786e7ac9318b9b47587f2304776a871b
Author: Partha Aji <paji(a)redhat.com>
Date: Tue Nov 10 15:41:58 2009 -0500
Added a couple of checks to make sure augeas base paths are generated before unit tests are run
commit 3435feb11104bb06ba8db0589763e144e34391e6
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Tue Nov 10 14:26:37 2009 -0500
change package of AbstractAugeasConfigurationComponentTest class from org.rhq.plugins.augeas to org.rhq.plugins.augeas.test to match its location on the filesystem
commit 78a696197265d0a51dee542711342cecb4caa287
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Tue Nov 10 13:19:44 2009 -0500
move augeas base test class in augeas plugin from src/test/ to src/main/ to allow mvn -Dmaven.test.skip=true to be run from project root without failures in samba/sudoers/etc. plugins because mvn cannot find the augeas plugin test jar
commit f0d7e99c5c82f43da612d4708bc2909f36e9a23b
Merge: b895aba 961fba0
Author: Partha Aji <paji(a)redhat.com>
Date: Mon Nov 9 17:21:16 2009 -0500
Merge branch 'master' into linux-config
commit b895aba9016245fe4d7f31180f30507955e66a34
Author: Shannon Hughes <shughes(a)scooby.rdu.redhat.com>
Date: Mon Nov 9 15:53:28 2009 -0500
modifying aliases agueas paths
diff --git a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java
new file mode 100644
index 0000000..f137cf5
--- /dev/null
+++ b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyScheduledJob.java
@@ -0,0 +1,39 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.custom;
+
+import java.util.Properties;
+
+import org.rhq.enterprise.server.plugin.pc.ScheduledJob;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
+
+/**
+ * Example of a scheduled job.
+ *
+ * @author John Mazzitelli
+ */
+public class MyScheduledJob implements ScheduledJob {
+ @Override
+ public void execute(String jobId, ServerPluginLifecycleListener lifecycleListener, Properties callbackData)
+ throws Exception {
+ System.out.println("Sample scheduled job has been triggered! [" + this.getClass() + "] jobId=" + jobId
+ + ", lifecycle-listener=" + lifecycleListener);
+ }
+}
diff --git a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
index 57f19cc..f00dbc8 100644
--- a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -16,6 +16,14 @@
</serverplugin:schedule>
</serverplugin:lifecycle-listener>
+ <serverplugin:scheduled-job jobId="first-scheduled-job" concurrent="false" class="MyScheduledJob">
+ <serverplugin:cron>0 0/5 * * * ?</serverplugin:cron>
+ </serverplugin:scheduled-job>
+
+ <serverplugin:scheduled-job jobId="sample-job-2" concurrent="true" class="MyScheduledJob">
+ <serverplugin:period>60000</serverplugin:period>
+ </serverplugin:scheduled-job>
+
<serverplugin:plugin-configuration>
<c:simple-property name="myCustomProperty" type="string" required="true"
description="A property my plugin needs to be properly configured" />
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index 606da06..8384b98 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -20,6 +20,7 @@
package org.rhq.enterprise.server.plugin.pc;
import java.util.Collection;
+import java.util.List;
import java.util.Properties;
import org.apache.commons.logging.Log;
@@ -29,6 +30,7 @@ import org.quartz.JobDataMap;
import org.rhq.enterprise.server.scheduler.SchedulerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ScheduledJobType;
/**
* The abstract superclass for all plugin containers of the different {@link ServerPluginType plugin types}.
@@ -175,9 +177,9 @@ public abstract class AbstractTypeServerPluginContainer {
/**
* If a plugin has scheduled jobs, this method will schedule them now.
- * This particular method implementation schedules the global job as defined in the
- * plugin descriptors. If a plugin has a global scheduled job, its lifecycle listener
- * will be the job handler class.
+ * This particular method implementation schedules the global jobs as defined in the
+ * plugin descriptors. If a plugin has a global scheduled job on its lifecycle
+ * listener, that lifecycle listener will be the job handler class.
*
* Subclasses are free to extend this method to schedule additional plugin jobs, but must
* ensure they call this method so the global scheduled jobs get added to the scheduler.
@@ -190,20 +192,47 @@ public abstract class AbstractTypeServerPluginContainer {
*/
public synchronized void schedulePluginJobs() throws Exception {
if (this.pluginManager != null) {
- // if there are any global schedules defined, schedule them now.
- // note that we know if there is no lifecycle listener, then there can't be a global schedule
+ // process all known plugins and schedule their jobs
for (ServerPluginEnvironment pluginEnv : this.pluginManager.getPluginEnvironments()) {
String pluginName = pluginEnv.getPluginName();
+
+ // First see if the listener has a schedule itself and schedule it if it does.
+ // Note that we know if there is no lifecycle listener, then there can't be a listener schedule
if (this.pluginManager.getServerPluginLifecycleListener(pluginName) != null) {
Schedule schedule = this.pluginManager.getServerPluginContext(pluginEnv).getSchedule();
if (schedule != null) {
try {
- scheduleJob(schedule, pluginName, "__globalScheduleJob", null, null);
+ scheduleJob(schedule, pluginName, "__lifecycleListenerJob", null, null);
} catch (Throwable t) {
log.warn("Failed to schedule the global plugin job for plugin [" + pluginName + "]", t);
}
}
}
+
+ // now schedule all the other jobs defined in the plugin descriptor
+ List<ScheduledJobType> jobs = pluginEnv.getPluginDescriptor().getScheduledJob();
+ if (jobs != null) {
+ for (ScheduledJobType job : jobs) {
+ Schedule schedule;
+ if (job.getPeriod() != null) {
+ schedule = new PeriodicSchedule(job.isConcurrent(), job.getPeriod().longValue());
+ } else {
+ schedule = new CronSchedule(job.isConcurrent(), job.getCron());
+ }
+
+ String scheduledJobClass = job.getClazz();
+ String jobId = job.getJobId();
+ if (scheduledJobClass != null) {
+ try {
+ scheduleJob(schedule, pluginName, jobId, scheduledJobClass, null);
+ } catch (Throwable t) {
+ log.warn("Failed to schedule job [" + jobId + "] for plugin [" + pluginName + "]", t);
+ }
+ } else {
+ log.warn("Scheduled job [" + jobId + "] in plugin [" + pluginName + "] is missing class");
+ }
+ }
+ }
}
} else {
throw new Exception("Cannot schedule plugins jobs; plugin container is not initialized yet");
@@ -251,8 +280,8 @@ public abstract class AbstractTypeServerPluginContainer {
*
* @throws Exception if failed to schedule the job
*/
- protected void scheduleJob(Schedule schedule, String pluginName, String jobId,
- Class<? extends ScheduledJob> scheduledJobClass, Properties callbackData) throws Exception {
+ protected void scheduleJob(Schedule schedule, String pluginName, String jobId, String scheduledJobClass,
+ Properties callbackData) throws Exception {
String groupName = pluginName;
boolean rescheduleIfExists = true; // just in case the parameters change, we'll always want to reschedule it if it exists
@@ -272,7 +301,7 @@ public abstract class AbstractTypeServerPluginContainer {
jobData.put(AbstractJobWrapper.DATAMAP_PLUGIN_TYPE, getSupportedServerPluginType().stringify());
jobData.put(AbstractJobWrapper.DATAMAP_JOB_ID, jobId);
if (scheduledJobClass != null) {
- jobData.put(AbstractJobWrapper.DATAMAP_SCHEDULED_JOB_CLASS, scheduledJobClass.getName());
+ jobData.put(AbstractJobWrapper.DATAMAP_SCHEDULED_JOB_CLASS, scheduledJobClass);
}
if (callbackData != null) {
jobData.putAll(callbackData);
@@ -281,7 +310,7 @@ public abstract class AbstractTypeServerPluginContainer {
// schedule the job now
SchedulerLocal scheduler = LookupUtil.getSchedulerBean();
if (schedule instanceof CronSchedule) {
- String cronExpression = ((CronSchedule) scheduler).getCronExpression();
+ String cronExpression = ((CronSchedule) schedule).getCronExpression();
log.info("Scheduling server plugin cron job: jobName=" + jobId + ", groupName=" + groupName + ", jobClass="
+ jobClass + ", cron=" + cronExpression);
scheduler.scheduleCronJob(jobId, groupName, jobData, jobClass, rescheduleIfExists, isVolatile,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index 1c31b8d..42ce6af 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -339,14 +339,9 @@ public class ServerPluginManager {
LifecycleListenerType lifecycleListener = environment.getPluginDescriptor().getLifecycleListener();
if (lifecycleListener != null) {
String className = lifecycleListener.getClazz();
- String pkg = environment.getPluginDescriptor().getPackage();
- if ((className.indexOf('.') == -1) && (pkg != null)) {
- className = pkg + '.' + className;
- }
-
log.debug("Creating plugin lifecycle listener [" + className + "] for plugin [" + pluginName + "]");
instance = (ServerPluginLifecycleListener) instantiatePluginClass(environment, className);
- log.debug("Created plugin lifecycle listener [" + className + "] for plugin [" + pluginName + "]");
+ log.debug("Lifecycle listener created [" + instance.getClass() + "] for plugin [" + pluginName + "]");
}
return instance;
@@ -365,6 +360,11 @@ public class ServerPluginManager {
ClassLoader loader = environment.getPluginClassLoader();
+ String pkg = environment.getPluginDescriptor().getPackage();
+ if ((className.indexOf('.') == -1) && (pkg != null)) {
+ className = pkg + '.' + className;
+ }
+
log.debug("Loading server plugin class [" + className + "]...");
try {
diff --git a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
index 88c0022..2791fee 100644
--- a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
+++ b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
@@ -49,6 +49,15 @@
this class will be notified when the plugin is loaded and unloaded. This provides a place
for plugin developers to allocate global resources needed by all plugin components and
a place to clean up those resources. It can also be scheduled to perform periodic work.
+ A lifecycle listener object is stateful - the instance lives for as long as the plugin
+ is initialized.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="scheduled-job" minOccurs="0" maxOccurs="unbounded" type="serverplugin:ScheduledJobType">
+ <xs:annotation>
+ <xs:documentation>
+ A scheduled job that is called to periodically perform work on behalf of the plugin.
</xs:documentation>
</xs:annotation>
</xs:element>
@@ -173,6 +182,34 @@
</xs:attribute>
</xs:complexType>
+ <xs:complexType name="ScheduledJobType">
+ <xs:complexContent>
+ <xs:extension base="serverplugin:ScheduleType">
+ <xs:attribute name="jobId" type="xs:string" use="required">
+ <xs:annotation>
+ <xs:documentation>
+ A unique identifier for this job. Job IDs need to be unique
+ within a plugin. When the scheduled job is invoked, this job ID
+ will be passed to it.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="class" type="serverplugin:classNameType" use="required">
+ <xs:annotation>
+ <xs:documentation>
+ The classname of the ScheduledJob implementation that will be instantiated
+ whenever the schedule is triggered. This job instance will not be stateful,
+ a new instance of the class is created for each schedule trigger. Each job
+ invocation is handed a reference to the plugin's lifecycle listener (if one
+ was defined for the plugin), thus providing a way to obtain stateful
+ information from the plugin.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
<xs:simpleType name="classNameType">
<xs:restriction base="xs:string">
<xs:whiteSpace value="collapse" />
diff --git a/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java b/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
index 7f2029d..3e1247d 100644
--- a/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
+++ b/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
@@ -26,6 +26,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
+import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
@@ -39,6 +40,7 @@ import org.rhq.core.clientapi.descriptor.configuration.ConfigurationDescriptor;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.LifecycleListenerType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ScheduleType;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ScheduledJobType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.alert.AlertPluginDescriptorType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.generic.GenericPluginDescriptorType;
@@ -75,6 +77,14 @@ public class ServerPluginDescriptorUtilTest {
assert schedule.getCron().equals("0 15 10 ? * MON-FRI");
assert schedule.getPeriod() == null;
+ List<ScheduledJobType> scheduledJobs = descriptor.getScheduledJob();
+ scheduledJobs.get(0).getJobId().equals("generic-job-1");
+ scheduledJobs.get(0).getClazz().equals("generic.scheduled.job1");
+ scheduledJobs.get(0).getPeriod().equals("123");
+ scheduledJobs.get(1).getJobId().equals("generic-job-2");
+ scheduledJobs.get(1).getClazz().equals("generic.scheduled.job2");
+ scheduledJobs.get(1).getCron().equals("0 30 11 ? * WED-FRI");
+
ConfigurationDescriptor config = descriptor.getPluginConfiguration();
assert config != null;
assert config.getConfigurationProperty().get(0).getValue().getName().equals("prop1");
@@ -101,6 +111,8 @@ public class ServerPluginDescriptorUtilTest {
assert schedule.getCron() == null;
assert schedule.getPeriod().longValue() == 1000L;
+ assert descriptor.getScheduledJob().size() == 0;
+
ConfigurationDescriptor config = descriptor.getPluginConfiguration();
assert config != null;
assert config.getConfigurationProperty().get(0).getValue().getName().equals("alertprop1");
diff --git a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
index a72f0a3..fcb58ca 100644
--- a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
+++ b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
@@ -18,6 +18,15 @@
</serverplugin:schedule>
</serverplugin:lifecycle-listener>
+ <serverplugin:scheduled-job jobId="generic-job-1" class="generic.scheduled.job1" concurrent="false">
+ <serverplugin:period>123</serverplugin:period>
+ </serverplugin:scheduled-job>
+
+ <serverplugin:scheduled-job jobId="generic-job-2" class="generic.scheduled.job2" concurrent="true">
+ <!-- Fire at 11:30am every wed-thru-fri -->
+ <serverplugin:cron>0 30 11 ? * WED-FRI</serverplugin:cron>
+ </serverplugin:scheduled-job>
+
<serverplugin:plugin-configuration>
<c:simple-property name="prop1" />
</serverplugin:plugin-configuration>
commit 6f764c1ab85d0f0fc20d7e9f846b764de726a309
Author: John Matthews <jmatthew(a)redhat.com>
Date: Fri Nov 13 01:30:13 2009 -0500
560 - partial work to add sync of distributions to ContentProviderManager
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFile.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFile.java
index 30493a5..267f69a 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFile.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFile.java
@@ -93,6 +93,10 @@ public class DistributionFile {
return last_modified;
}
+ public void setLastModified(long lastModifiedIn) {
+ this.last_modified = lastModifiedIn;
+ }
+
public Distribution getDistribution() {
return distribution;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
index 73b1fcf..1158f97 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
@@ -73,6 +73,9 @@ import org.rhq.core.domain.content.ProductVersionPackageVersion;
import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.content.RepoContentSource;
import org.rhq.core.domain.content.RepoPackageVersion;
+import org.rhq.core.domain.content.Distribution;
+import org.rhq.core.domain.content.DistributionFile;
+import org.rhq.core.domain.content.DistributionType;
import org.rhq.core.domain.content.composite.LoadedPackageBitsComposite;
import org.rhq.core.domain.content.composite.PackageVersionFile;
import org.rhq.core.domain.content.composite.PackageVersionMetadataComposite;
@@ -87,6 +90,7 @@ import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.enterprise.server.RHQConstants;
+import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.authz.RequiredPermission;
import org.rhq.enterprise.server.plugin.pc.content.ContentProviderManager;
@@ -96,6 +100,9 @@ import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.content.InitializationException;
import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
import org.rhq.enterprise.server.plugin.pc.content.RepoDetails;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionSyncReport;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionDetails;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionFileDetails;
import org.rhq.enterprise.server.resource.ProductVersionManagerLocal;
/**
@@ -839,6 +846,49 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
@TransactionAttribute(TransactionAttributeType.SUPPORTS)
// we really want NEVER, but support tests that might be in a tx
+ public ContentSourceSyncResults mergeContentSourceSyncReport(ContentSource contentSource, DistributionSyncReport report,
+ ContentSourceSyncResults syncResults) {
+ try {
+ StringBuilder progress = new StringBuilder();
+ if (syncResults.getResults() != null) {
+ progress.append(syncResults.getResults());
+ }
+
+ //////////////////
+ // REMOVE
+ syncResults = contentSourceManager._mergeContentSourceSyncReportREMOVE(contentSource, report, syncResults, progress);
+
+ //////////////////
+ // ADD
+ syncResults = contentSourceManager._mergeContentSourceSyncReportADD(contentSource, report, syncResults, progress);
+
+ // if we added/updated/deleted anything, change the last modified time of all repos
+ // that get content from this content source
+ if ((report.getDistributions().size() > 0) || (report.getDeletedDistributions().size() > 0)) {
+ contentSourceManager._mergeContentSourceSyncReportUpdateRepo(contentSource.getId());
+ }
+
+ // let our sync results object know that we completed the merge
+ // don't mark it as successful yet, let the caller do that
+ progress.append(new Date()).append(": ").append("MERGE COMPLETE.\n");
+ syncResults.setResults(progress.toString());
+ syncResults = contentSourceManager.mergeContentSourceSyncResults(syncResults);
+ } catch (Throwable t) {
+ // ThrowableUtil will dump SQL nextException messages, too
+ String errorMsg = "Could not process sync report from [" + contentSource + "]. Cause: "
+ + ThrowableUtil.getAllMessages(t);
+ log.error(errorMsg);
+ throw new RuntimeException(errorMsg, t);
+ }
+
+ return syncResults;
+ }
+
+
+
+
+ @TransactionAttribute(TransactionAttributeType.SUPPORTS)
+ // we really want NEVER, but support tests that might be in a tx
public ContentSourceSyncResults mergeContentSourceSyncReport(ContentSource contentSource, PackageSyncReport report,
Map<ContentProviderPackageDetailsKey, PackageVersionContentSource> previous,
ContentSourceSyncResults syncResults) {
@@ -992,6 +1042,34 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
return syncResults;
}
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public ContentSourceSyncResults _mergeContentSourceSyncReportREMOVE(ContentSource contentSource,
+ DistributionSyncReport report, ContentSourceSyncResults syncResults, StringBuilder progress) {
+
+ progress.append(new Date()).append(": ").append("Removing");
+ syncResults.setResults(progress.toString());
+ syncResults = contentSourceManager.mergeContentSourceSyncResults(syncResults);
+
+ DistributionManagerLocal distManager = LookupUtil.getDistributionManagerLocal();
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+
+ // remove all distributions that are no longer available on the remote repository
+ for (DistributionDetails doomedDetails: report.getDeletedDistributions()) {
+ Distribution doomedDist = distManager.getDistributionByLabel(doomedDetails.getLabel());
+ distManager.deleteDistributionByDistId(overlord, doomedDist.getId());
+ distManager.deleteDistributionFilesByDistId(overlord, doomedDist.getId());
+ progress.append("Removed distribution & distribution files for: " + doomedDetails.getLabel());
+ syncResults.setResults(progress.toString());
+ syncResults = contentSourceManager.mergeContentSourceSyncResults(syncResults);
+ }
+
+ progress.append("Finished Distribution removal...").append('\n');
+ syncResults.setResults(progress.toString());
+ syncResults = contentSourceManager.mergeContentSourceSyncResults(syncResults);
+
+ return syncResults;
+ }
+
@SuppressWarnings("unchecked")
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public ContentSourceSyncResults _mergeContentSourceSyncReportADD(ContentSource contentSource,
@@ -1208,6 +1286,41 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
return syncResults;
}
+
+ @SuppressWarnings("unchecked")
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public ContentSourceSyncResults _mergeContentSourceSyncReportADD(ContentSource contentSource,
+ DistributionSyncReport report, ContentSourceSyncResults syncResults, StringBuilder progress) {
+
+ DistributionManagerLocal distManager = LookupUtil.getDistributionManagerLocal();
+ Subject overlord = LookupUtil.getSubjectManager().getOverlord();
+ List<DistributionDetails> newDetails = report.getDistributions();
+ for (DistributionDetails detail: newDetails) {
+ try {
+ DistributionType distType = new DistributionType();
+ distType.setName(detail.getDistributionType());
+ distType.setDescription(detail.getDescription());
+ Distribution newDist = distManager.createDistribution(overlord, detail.getLabel(),
+ detail.getDistributionPath(), distType);
+ List<DistributionFileDetails> files = detail.getFiles();
+ for (DistributionFileDetails f: files) {
+ DistributionFile df = new DistributionFile(newDist, f.getRelativeFilename(), f.getMd5sum());
+ df.setLastModified(f.getLastModified());
+ entityManager.persist(df);
+ }
+ }
+ catch (DistributionException e) {
+ progress.append("Caught exception when trying to add: " + detail.getLabel() + "\n");
+ progress.append("Error is: " + e.getMessage());
+ syncResults.setResults(progress.toString());
+ syncResults = contentSourceManager.mergeContentSourceSyncResults(syncResults);
+ log.error(e);
+ }
+ }
+ return syncResults;
+ }
+
+
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public ContentSourceSyncResults _mergeContentSourceSyncReportUPDATE(ContentSource contentSource,
PackageSyncReport report, Map<ContentProviderPackageDetailsKey, PackageVersionContentSource> previous,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java
index 98be5ff..6364d5c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java
@@ -43,6 +43,7 @@ import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails
import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetailsKey;
import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
import org.rhq.enterprise.server.plugin.pc.content.RepoDetails;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionSyncReport;
/**
* Interface that provides access to the {@link ContentSource} objects deployed in the server, allowing the callers to
@@ -393,6 +394,19 @@ public interface ContentSourceManagerLocal {
Map<ContentProviderPackageDetailsKey, PackageVersionContentSource> previous,
ContentSourceSyncResults syncResults);
+ /**
+ * After a sync has happened, this is responsible for persisting the results.
+ *
+ * @param contentSource content source that was just sync'ed
+ * @param report information on what the current inventory should look like
+ * @param syncResults sync results object that should be updated to track this method's progress
+ *
+ * @return the updated syncResults that includes more summary information in the results string that indicates what
+ * was done
+ */
+ ContentSourceSyncResults mergeContentSourceSyncReport(ContentSource contentSource, DistributionSyncReport report,
+ ContentSourceSyncResults syncResults);
+
void _mergeContentSourceSyncReportUpdateRepo(int contentSourceId);
ContentSourceSyncResults _mergeContentSourceSyncReportREMOVE(ContentSource contentSource, PackageSyncReport report,
@@ -408,6 +422,12 @@ public interface ContentSourceManagerLocal {
Map<ContentProviderPackageDetailsKey, PackageVersionContentSource> previous,
ContentSourceSyncResults syncResults, StringBuilder progress);
+ ContentSourceSyncResults _mergeContentSourceSyncReportREMOVE(ContentSource contentSource, DistributionSyncReport report,
+ ContentSourceSyncResults syncResults, StringBuilder progress);
+
+ ContentSourceSyncResults _mergeContentSourceSyncReportADD(ContentSource contentSource,
+ DistributionSyncReport report, ContentSourceSyncResults syncResults, StringBuilder progress);
+
/**
* Requests all {@link PackageVersion#getMetadata() metadata} for all package versions that the given resource
* component is subscribed to (see {@link Repo#getResources()}. The returned object has the metadata bytes that
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
index 30f9277..be3fe54 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
@@ -44,6 +44,8 @@ import org.rhq.core.domain.content.Package;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.core.domain.content.PackageVersionContentSource;
import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.content.Distribution;
+import org.rhq.core.domain.content.DistributionFile;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
@@ -51,6 +53,7 @@ import org.rhq.core.domain.criteria.RepoCriteria;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
import org.rhq.enterprise.server.content.RepoManagerLocal;
+import org.rhq.enterprise.server.content.DistributionManagerLocal;
import org.rhq.enterprise.server.content.metadata.ContentSourceMetadataManagerLocal;
import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
import org.rhq.enterprise.server.plugin.pc.content.metadata.ContentSourcePluginMetadataManager;
@@ -254,6 +257,74 @@ public class ContentProviderManager {
results.setStatus(ContentSourceSyncStatus.SUCCESS);
results = contentSourceManager.mergeContentSourceSyncResults(results);
}
+ if (provider instanceof DistributionSource) {
+ log.info("synchronizeContentSource(" + contentSourceId + "): this source is a DistributionSource");
+ log.info("We will skip the sync for now until PackageSource is working.");
+ /**
+ DistributionSource distSource = (DistributionSource) provider;
+ RepoCriteria reposForContentSource = new RepoCriteria();
+ reposForContentSource.addFilterContentSourceIds(contentSourceId);
+ List<Repo> repos = repoManager.findReposByCriteria(overlord, reposForContentSource);
+
+ // Temporary functionality: loop for all repos that use this content source
+ for (Repo repo : repos) {
+ start = System.currentTimeMillis();
+
+ PageControl pc = PageControl.getUnlimitedInstance();
+ log.debug("Looking up existing distributions for repoId: " + repo.getId());
+ List<Distribution> dists = repoManager.findAssociatedDistributions(overlord, repo.getId(), pc);
+ log.debug("Found " + dists.size() + " Distributions for repoId " + repo.getId());
+
+ progress.append(dists.size()).append('\n');
+ progress.append(new Date()).append(": ");
+ progress.append("Asking content source to update the list of packages...");
+
+ DistributionSyncReport distReport = new DistributionSyncReport();
+ List<DistributionDetails> distDetails = new ArrayList<DistributionDetails>(dists.size());
+ translateDomainToDto(dists, distDetails);
+
+ distSource.synchronizeDistribution(repo.getName(), distReport, distDetails);
+
+ log.info("synchronizeDistributions: [" + contentSource.getName() + "]: loaded existing list of size=["
+ + dists.size() + "] (" + (System.currentTimeMillis() - start) + ")ms");
+
+ results.setResults(progress.toString());
+ results = contentSourceManager.mergeContentSourceSyncResults(results);
+ start = System.currentTimeMillis();
+
+
+ distSource.synchronizeDistribution(distReport, distDetails);
+ log.info("synchronizeDistributions: [" + contentSource.getName() + "]: got sync report from adapter=["
+ + distReport + "] (" + (System.currentTimeMillis() - start) + ")ms");
+
+ progress.append("new=").append(distReport.getDistributions().size());
+ //TODO: Consider Update case, i.e. rhel-5-u2 was prev synced, and now a
+ // single DistributionFile has changed
+
+ progress.append(", deleted=").append(distReport.getDeletedDistributions().size()).append('\n');
+ //progress.append(new Date()).append(": ");
+ //progress.append("FULL SUMMARY FOLLOWS:").append('\n');
+ //progress.append(distReport.getSummary()).append('\n');
+ //progress.append(new Date()).append(": ");
+ //progress.append("Merging the updated list of packages to database").append('\n');
+ results.setResults(progress.toString());
+ results = contentSourceManager.mergeContentSourceSyncResults(results);
+ start = System.currentTimeMillis();
+ results = contentSourceManager.mergeContentSourceSyncReport(contentSource, distReport, results);
+ }
+ // let's reset our progress string to the full results including the text added by the merge
+ progress.setLength(0);
+ progress.append(results.getResults());
+
+ log.info("synchronizeDistributions: [" + contentSource.getName() + "]: report has been merged ("
+ + (System.currentTimeMillis() - start) + ")ms");
+
+ progress.append(new Date()).append(": ").append("DONE.");
+ results.setResults(progress.toString());
+ results.setStatus(ContentSourceSyncStatus.SUCCESS);
+ results = contentSourceManager.mergeContentSourceSyncResults(results);
+ */
+ }
} catch (Throwable t) {
if (results != null) {
// try to reload the results in case it was updated by the SLSB before the exception happened
@@ -620,6 +691,24 @@ public class ContentProviderManager {
}
}
+ private void translateDomainToDto(List<Distribution>dists, List<DistributionDetails> distDetails) {
+ DistributionManagerLocal distManager = LookupUtil.getDistributionManagerLocal();
+
+ for (Distribution d: dists) {
+ DistributionDetails detail = new DistributionDetails(d.getLabel(), d.getDistributionType().getName());
+ detail.setLabel(d.getLabel());
+ detail.setDistributionPath(d.getBasePath());
+ detail.setDescription(d.getDistributionType().getDescription());
+ List<DistributionFile> files = distManager.getDistributionFilesByDistId(d.getId());
+ for (DistributionFile f: files) {
+ DistributionFileDetails dfd =
+ new DistributionFileDetails(f.getRelativeFilename(), f.getLastModified(), f.getMd5sum());
+ detail.addFile(dfd);
+ }
+ distDetails.add(detail);
+ }
+ }
+
/**
* This will handle invocations to an object ensuring that the call is isolated to within the appropriate
* classloader.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java
index 0ae61f7..931c4b5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java
@@ -36,11 +36,13 @@ public interface DistributionSource {
/**
* Requests that this distribution source perform a synchronization with its external repository.
*
+ * @param repoName repo name used to look up distributions
* @param report used to accumulate the collection of distros
* @throws Exception if the source is unable to perform the synchronization, for instance if the external
* source cannot be connected to.
*/
- void synchronizeDistribution(DistributionSyncReport report, Collection<DistributionDetails> existingDistros)
+ void synchronizeDistribution(String repoName, DistributionSyncReport report,
+ Collection<DistributionDetails> existingDistros)
throws Exception;
/**
commit 239970c7375d4c422668f6a3af3447c121514760
Author: John Matthews <jmatthew(a)redhat.com>
Date: Fri Nov 13 01:28:47 2009 -0500
Updated RHNProvider to use passed in repo name for synchronize Packages/Distributions.
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
index 2554b30..b2b0497 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
@@ -165,7 +165,18 @@ public class RHNHelper {
* @throws XmlRpcException on xmlrpc faults
*/
public List<String> getChannelKickstartLabels() throws IOException, XmlRpcException {
- return getSyncableKickstartLabels(Arrays.asList(this.repolabel));
+ return getChannelKickstartLabels(this.repolabel);
+ }
+
+ /**
+ * Get List of kickstart labels for the channel associated to this instance.
+ * @param channelName channel name
+ * @return List of all kickstart labels associate to the channel
+ * @throws IOException on io errors on systemid reads
+ * @throws XmlRpcException on xmlrpc faults
+ */
+ public List<String> getChannelKickstartLabels(String channelName) throws IOException, XmlRpcException {
+ return getSyncableKickstartLabels(Arrays.asList(channelName));
}
/**
@@ -174,13 +185,23 @@ public class RHNHelper {
* @throws IOException on io errors on systemid reads
* @throws XmlRpcException on xmlrpc faults
*/
-
- public ArrayList getChannelPackages() throws IOException, XmlRpcException {
+ public List<String> getChannelPackages() throws IOException, XmlRpcException {
+ return getChannelPackages(this.repolabel);
+ }
+
+ /**
+ * Get List of packagesIds for Given Channels
+ * @param channelName channel name
+ * @return List of all package ids associated to the channel
+ * @throws IOException on io errors on systemid reads
+ * @throws XmlRpcException on xmlrpc faults
+ */
+ public List<String> getChannelPackages(String channelName) throws IOException, XmlRpcException {
ArrayList<String> allPackages = new ArrayList();
log.info("Systemid: " + this.systemid);
log.info("repolist: " + this.repolabel);
- List<RhnChannelType> channels = rhndata.getChannels(this.systemid, Arrays.asList(this.repolabel));
+ List<RhnChannelType> channels = rhndata.getChannels(this.systemid, Arrays.asList(channelName));
for (RhnChannelType channel : channels) {
String packages = channel.getPackages();
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
index 7cbc0b9..005bf52 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
@@ -169,7 +169,7 @@ public class RHNProvider implements ContentProvider, PackageSource, RepoSource,
// sync now
try {
summary.markStarted();
- ArrayList pkgIds = helper.getChannelPackages();
+ List<String> pkgIds = helper.getChannelPackages(repoName);
log.info("RHNProvider:: helper.getChannelPackages returned " + pkgIds.size() + " packages");
for (ContentProviderPackageDetails p : helper.getPackageDetails(pkgIds)) {
log.debug("Processing package at (" + p.getLocation());
@@ -199,7 +199,8 @@ public class RHNProvider implements ContentProvider, PackageSource, RepoSource,
/**
* @inheritDoc
*/
- public void synchronizeDistribution(DistributionSyncReport report, Collection<DistributionDetails> existingDistros) throws Exception {
+ public void synchronizeDistribution(String repoName, DistributionSyncReport report,
+ Collection<DistributionDetails> existingDistros) throws Exception {
// Goal:
// This method will create the metadata representing what kickstart tree files need to be downloaded.
@@ -214,7 +215,7 @@ public class RHNProvider implements ContentProvider, PackageSource, RepoSource,
List<String> deletedDistros = new ArrayList<String>(); //Existing distros we want to remove.
deletedDistros.addAll(existingLabels);
- List<String> availableLabels = helper.getChannelKickstartLabels();
+ List<String> availableLabels = helper.getChannelKickstartLabels(repoName);
log.debug("Found " + availableLabels.size() + " available kickstart trees");
for (String label: availableLabels) {
log.debug("Processing kickstart: " + label);
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelperTest.java b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelperTest.java
index 582b41f..b07f2e8 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelperTest.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelperTest.java
@@ -58,7 +58,7 @@ public class RHNHelperTest extends BaseRHNTest {
public void testGetChannelPackages() throws Exception {
boolean success = true;
try {
- ArrayList pkgIds = helper.getChannelPackages();
+ List<String> pkgIds = helper.getChannelPackages();
assertTrue(pkgIds.size() > 0);
} catch (Exception e) {
e.printStackTrace();
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java
index 8d93636..3a2f1e3 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java
@@ -148,7 +148,7 @@ public class RHNProviderTest
List<ContentProviderPackageDetails> existingPackages = new ArrayList<ContentProviderPackageDetails>();
try {
provider.initializeForTest(config);
- provider.synchronizePackages("testRepo", report, existingPackages);
+ provider.synchronizePackages(channelName, report, existingPackages);
}
catch (Exception e) {
e.printStackTrace();
@@ -172,7 +172,7 @@ public class RHNProviderTest
Configuration config = getConfiguration(channelName);
try {
provider.initializeForTest(config);
- provider.synchronizeDistribution(report, existingDistro);
+ provider.synchronizeDistribution(channelName, report, existingDistro);
}
catch (Exception e) {
e.printStackTrace();
commit 0394b457fa2ee58973f26a598f3eea4bb8e42345
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Thu Nov 12 16:41:03 2009 -0800
807 - adding sync methods to repo beans
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java
index c392eac..9c4afa1 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java
@@ -18,9 +18,6 @@
*/
package org.rhq.enterprise.gui.content;
-import java.util.Iterator;
-import java.util.Set;
-
import javax.faces.application.FacesMessage;
import javax.faces.model.DataModel;
@@ -28,7 +25,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.content.ContentSource;
import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
@@ -64,31 +60,16 @@ public class ListReposUIBean extends PagedDataTableUIBean {
public String syncSelectedContentSources() {
Subject subject = EnterpriseFacesContextUtility.getSubject();
String[] selected = getSelectedRepos();
- Integer[] ids = getIntegerArray(selected);
- int syncCount = 0;
- if (ids.length > 0) {
- try {
- for (Integer id : ids) {
- Repo r = repoManager.getRepo(subject, id);
- Set<ContentSource> sources = r.getContentSources();
- Iterator<ContentSource> i = sources.iterator();
- while (i.hasNext()) {
- ContentSource source = i.next();
- contentSourceManager.synchronizeAndLoadContentSource(subject, source.getId());
- syncCount++;
- log.debug("Initiating sync: " + source.getId());
- }
- }
- if (syncCount > 0) {
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Synchronizing [" + syncCount
- + "] content sources.");
- } else {
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO,
- "Selected Repositories have no content to sync.");
- }
- } catch (Exception e) {
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, "Failed to synchronized content sources.",
- e);
+ Integer[] repoIds = getIntegerArray(selected);
+
+ if (repoIds.length > 0) {
+ int syncCount = repoManager.syncronizeRepos(subject, repoIds);
+ if (syncCount > 0) {
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Synchronizing [" + syncCount
+ + "] content sources.");
+ } else {
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO,
+ "Selected Repositories have no content to sync.");
}
}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDetailsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDetailsUIBean.java
index 6dd552b..f5231db 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDetailsUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDetailsUIBean.java
@@ -24,8 +24,8 @@ import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.content.Repo;
import org.rhq.core.gui.util.FacesContextUtility;
import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
-import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.content.ContentException;
+import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
public class RepoDetailsUIBean {
@@ -40,6 +40,24 @@ public class RepoDetailsUIBean {
return "edit";
}
+ public String getSyncStatus() {
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
+ Integer id = FacesContextUtility.getRequiredRequestParameter("id", Integer.class);
+ return LookupUtil.getRepoManagerLocal().calculateSyncStatus(subject, id);
+ }
+
+ public String sync() {
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
+ Integer[] repoIds = { FacesContextUtility.getRequiredRequestParameter("id", Integer.class) };
+ int syncCount = LookupUtil.getRepoManagerLocal().syncronizeRepos(subject, repoIds);
+ if (syncCount > 0) {
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "The repository is syncing.");
+ } else {
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Nothing to sync for this Repository.");
+ }
+ return "success";
+ }
+
public String save() {
Subject subject = EnterpriseFacesContextUtility.getSubject();
RepoManagerLocal manager = LookupUtil.getRepoManagerLocal();
@@ -65,6 +83,7 @@ public class RepoDetailsUIBean {
Integer id = FacesContextUtility.getRequiredRequestParameter("id", Integer.class);
RepoManagerLocal manager = LookupUtil.getRepoManagerLocal();
this.repo = manager.getRepo(subject, id);
+ this.repo.setSyncStatus(manager.calculateSyncStatus(subject, id));
}
}
}
\ No newline at end of file
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml
index 483fd6f..3f58f82 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml
@@ -83,6 +83,12 @@
</h:outputText>
</td>
</tr>
+ <tr>
+ <td align="right"><b>Syncronization Status:</b></td>
+ <td align="left">
+ <h:outputText value="#{RepoDetailsUIBean.repo.syncStatus}"/>
+ </td>
+ </tr>
</table>
</rich:panel>
@@ -90,6 +96,9 @@
<h:commandButton rendered="${mode ne 'edit'}"
value="EDIT" action="#{RepoDetailsUIBean.edit}"
alt="Edit" styleClass="buttonmed" id="editButton"/>
+ <h:commandButton rendered="${mode ne 'edit'}"
+ value="SYNCHRONIZE" action="#{RepoDetailsUIBean.sync}"
+ alt="Synchronize" styleClass="buttonmed" id="syncButton"/>
<h:commandButton rendered="${mode eq 'edit'}"
value="SAVE" action="#{RepoDetailsUIBean.save}"
alt="Save" styleClass="buttonmed" id="saveButton"/>
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 8788038..20accf2 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
@@ -899,4 +899,23 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
return null;
}
+ @Override
+ public int syncronizeRepos(Subject subject, Integer[] repoIds) {
+ int syncCount = 0;
+
+ for (Integer id : repoIds) {
+ Repo r = this.getRepo(subject, id);
+ Set<ContentSource> sources = r.getContentSources();
+ Iterator<ContentSource> i = sources.iterator();
+ while (i.hasNext()) {
+ ContentSource source = i.next();
+ contentSourceManager.synchronizeAndLoadContentSource(subject, source.getId());
+ syncCount++;
+ log.debug("Initiating sync: " + source.getId());
+ }
+ }
+
+ return syncCount;
+ }
+
}
\ No newline at end of file
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 d2f5c80..c260fc5 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
@@ -275,4 +275,11 @@ public interface RepoManagerLocal {
*/
PageList<Distribution> findAssociatedDistributions(Subject subject, int repoid, PageControl pc);
+ /**
+ * Syncronize the content associated with the repoIds passed in.
+ * @param repoIds to syncronize
+ * @return count of the number of repositories synced.
+ */
+ int syncronizeRepos(Subject subject, Integer[] repoIds);
+
}
\ 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 0b31bed..dda5c50 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
@@ -265,4 +265,7 @@ public interface RepoManagerRemote {
@WebParam(name = "repoId") int repoId, //
@WebParam(name = "pageControl") PageControl pc);
+ @WebMethod
+ int syncronizeRepos(@WebParam(name = "subject") Subject subject, @WebParam(name = "repoIds") Integer[] repoIds);
+
}
\ 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 6728210..57927ec 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
@@ -286,6 +286,11 @@ public class WebservicesManagerBean implements WebservicesRemote {
return repoManager.findPackageVersionsInRepoByCriteria(subject, criteria);
}
+ @Override
+ public int syncronizeRepos(Subject subject, Integer[] repoIds) {
+ return repoManager.syncronizeRepos(subject, repoIds);
+ }
+
//REPOMANAGER: END ----------------------------------
//CONFIGURATIONMANAGER: BEGIN ----------------------------------
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
index 755c2b6..a6c08c6 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
@@ -100,6 +100,24 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
}
@Test(enabled = ENABLED)
+ public void testSyncRepos() throws Exception {
+ Repo repo = new Repo("testSyncStatus");
+ repoManager.createRepo(overlord, repo).getId();
+ Integer[] ids = { repo.getId() };
+ int syncCount = repoManager.syncronizeRepos(overlord, ids);
+
+ assert syncCount == 0;
+
+ ContentSourceType cst = new ContentSourceType("testSyncStatus");
+ ContentSource cs = new ContentSource("testSyncStatus", cst);
+ repo.addContentSource(cs);
+ syncCount = repoManager.syncronizeRepos(overlord, ids);
+
+ assert syncCount == 1;
+
+ }
+
+ @Test(enabled = ENABLED)
public void testSyncStatus() throws Exception {
Repo repo = new Repo("testSyncStatus");
repoManager.createRepo(overlord, repo).getId();
commit ed82ea0bb7efb05eb5b97d4db21b0797604720cb
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 18:52:03 2009 -0500
Squashed commit of the following:
commit f6d790e73caa5c3714768660656da69fb49e2653
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 18:42:51 2009 -0500
Squashed commit of the following:
commit 4176765871d06b37895dc72269233687325eaa87
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 17:20:20 2009 -0500
get the plugin jobs to be scheduled properly in quartz
commit 08644de029a313e09673870395bf0a5f8607098b
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 11:47:39 2009 -0500
fix the operation names in the rhq server plugin
commit 8075b0b26d1c2514ff7a1c831491a51d8a2909c8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 03:22:06 2009 -0500
Squashed commit of the following:
commit d3dfc1a52b0414bd67f50ed9c881c8c3e33e9a1e
Merge: 2cd6ba1 ad45fe5
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 22:38:00 2009 -0500
Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq
commit 2cd6ba182ee07849e2ccd06be6c962b879f45112
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 16:33:18 2009 -0500
Allow clean install to still copy over the license file.
This patch moves the license file from the server container module to the ear module. It is copied over in the dev profile only.
commit 9d93844a860e54c2a012644975ccee198c76f9a6
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 02:53:23 2009 -0500
actually schedule the jobs in quartz
commit 25c0a3e27d9969368230277cb5a33633dbbdb897
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 02:06:54 2009 -0500
add plugin context to the job interface
commit c14822a979ab9e130dfc08279ae6ca342bd591bf
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 01:45:23 2009 -0500
provide an API to schedule jobs
commit a1c36f7c4efb5fd4e78c246c9e270bb55901e883
Merge: ccb085f d3dfc1a
Author: Partha Aji <paji(a)redhat.com>
Date: Thu Nov 12 12:26:11 2009 -0500
Merge branch 'master' into linux-config
commit ccb085f89d6a36787da1c570fbb7006672de68f9
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Thu Nov 12 11:45:14 2009 -0500
remove experimental hosts-augeas plugin, which is no longer needed
commit 6a676af5fd6af0c2fafd3faf5fc24a119bbceb72
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Thu Nov 12 11:18:13 2009 -0500
get hosts plugin integration tests passing on Windows
commit cb288a8321d659c8839328066f5c50f4e548a4ba
Author: Partha Aji <paji(a)redhat.com>
Date: Thu Nov 12 10:09:55 2009 -0500
Removed the augeas test jar dep from aliases pom since its going to be built as part of core
commit 3b6e81de84ba5b3ec4af37fd7c1ba7afafe65d8a
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 20:38:51 2009 -0500
Added Load and Update tests for the alias component
commit 771b96fc5e2213dc8bcba4bb0991aefe1556bd37
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 19:50:04 2009 -0500
added aliaseses to .classpath
commit 7e8a1621b6990bd4d673c49dda47ad910d0eaab3
Merge: 15a3b45 ad45fe5
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 19:42:58 2009 -0500
Merge branch 'master' into linux-config
commit 15a3b45d91942fdcccef99a20e422c857834ae0a
Author: Ian P. Springer <ips(a)jetengine.springer.net>
Date: Wed Nov 11 18:48:34 2009 -0500
fix several bugs in augeas and hosts plugins to get hosts+samba+sudoers integration tests passing on Linux; update test log4j.xml in all augeas-based plugins
commit 06eb2ee352c198385e2797d4e3c9816a59ba0c02
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Nov 11 11:31:46 2009 -0500
Augeas-based ResourceComponents now handle it as gracefully as possible when Augeas is not installed on the Agent system
commit d391bb6be98bfeabfaa06f25fbf33cf67ea85f06
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Nov 11 10:19:44 2009 -0500
refactor so that config tests are skipped if Augeas is not available, so tests will pass on systems without Augeas (e.g. Windows boxes)
commit 62f8c89cd2fcc882f6783c8530ac4cf46f7cec34
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 10:06:08 2009 -0500
Revert "Fixed test cases related to samba and sudoer plugins"
Looks like there is a better way to achieve the same.. Waiing for ips'
commit
This reverts commit 6d666b6987f1c58732851a57560ec93ba21c4cc5.
commit 7d952067685d548fc7b26bf7a8a272cece448484
Merge: 6d666b6 46d0de1
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 00:53:22 2009 -0500
Merge branch 'master' into hope
commit 6d666b6987f1c58732851a57560ec93ba21c4cc5
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 00:51:04 2009 -0500
Fixed test cases related to samba and sudoer plugins
commit d7e80500786e7ac9318b9b47587f2304776a871b
Author: Partha Aji <paji(a)redhat.com>
Date: Tue Nov 10 15:41:58 2009 -0500
Added a couple of checks to make sure augeas base paths are generated before unit tests are run
commit 3435feb11104bb06ba8db0589763e144e34391e6
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Tue Nov 10 14:26:37 2009 -0500
change package of AbstractAugeasConfigurationComponentTest class from org.rhq.plugins.augeas to org.rhq.plugins.augeas.test to match its location on the filesystem
commit 78a696197265d0a51dee542711342cecb4caa287
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Tue Nov 10 13:19:44 2009 -0500
move augeas base test class in augeas plugin from src/test/ to src/main/ to allow mvn -Dmaven.test.skip=true to be run from project root without failures in samba/sudoers/etc. plugins because mvn cannot find the augeas plugin test jar
commit f0d7e99c5c82f43da612d4708bc2909f36e9a23b
Merge: b895aba 961fba0
Author: Partha Aji <paji(a)redhat.com>
Date: Mon Nov 9 17:21:16 2009 -0500
Merge branch 'master' into linux-config
commit b895aba9016245fe4d7f31180f30507955e66a34
Author: Shannon Hughes <shughes(a)scooby.rdu.redhat.com>
Date: Mon Nov 9 15:53:28 2009 -0500
modifying aliases agueas paths
diff --git a/.classpath b/.classpath
index f4a074e..1be8e0d 100644
--- a/.classpath
+++ b/.classpath
@@ -97,7 +97,9 @@
<classpathentry kind="src" path="modules/plugins/apt/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/hosts/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/hosts/src/test/java"/>
- <classpathentry kind="src" path="modules/plugins/virt/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/virt/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/aliases/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/aliases/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/snmptrapd/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/script/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/antlr-config/src/main/antlr3"/>
diff --git a/modules/plugins/aliases/pom.xml b/modules/plugins/aliases/pom.xml
index e2f5ee4..f04f6ae 100644
--- a/modules/plugins/aliases/pom.xml
+++ b/modules/plugins/aliases/pom.xml
@@ -35,15 +35,6 @@
<artifactId>rhq-augeas-plugin</artifactId>
<version>${project.version}</version>
</dependency>
-
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-augeas-plugin</artifactId>
- <version>${project.version}</version>
- <type>test-jar</type>
- <scope>test</scope>
- </dependency>
-
</dependencies>
<build>
diff --git a/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml
index a937098..01f5862 100644
--- a/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml
@@ -28,7 +28,7 @@
default="/etc/aliases"
description="the absolute paths of the configuration files, delimited with pipe characters"/>
<c:simple-property name="resourceConfigurationRootNode" required="true" readOnly="true"
- default="/files/etc/aliases/*"/>
+ default="/files/etc/aliases"/>
</plugin-configuration>
<resource-configuration>
diff --git a/modules/plugins/aliases/src/test/java/org/rhq/plugins/aliases/AliasesComponentTest.java b/modules/plugins/aliases/src/test/java/org/rhq/plugins/aliases/AliasesComponentTest.java
index 4071fb4..27d6f0c 100644
--- a/modules/plugins/aliases/src/test/java/org/rhq/plugins/aliases/AliasesComponentTest.java
+++ b/modules/plugins/aliases/src/test/java/org/rhq/plugins/aliases/AliasesComponentTest.java
@@ -18,13 +18,11 @@
*/
package org.rhq.plugins.aliases;
-import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
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.pc.PluginContainer;
-import org.rhq.plugins.augeas.AbstractAugeasConfigurationComponentTest;
+import org.rhq.plugins.augeas.test.AbstractAugeasConfigurationComponentTest;
/**
* An integration test for {@link AliasesComponent}.
@@ -32,12 +30,12 @@ import org.rhq.plugins.augeas.AbstractAugeasConfigurationComponentTest;
public class AliasesComponentTest extends AbstractAugeasConfigurationComponentTest {
@Override
protected String getPluginName() {
- return "Hosts";
+ return "Aliases";
}
@Override
protected String getResourceTypeName() {
- return "Hosts File";
+ return "Aliases File";
}
@Override
@@ -48,54 +46,52 @@ public class AliasesComponentTest extends AbstractAugeasConfigurationComponentTe
PropertyMap entry;
- entry = new PropertyMap("*[canonical]");
- entry.put(new PropertySimple("ipaddr", "127.0.0.1"));
- entry.put(new PropertySimple("canonical", "localhost"));
- entry.put(new PropertySimple("alias", "localhost.localdomain\nlocalhost4\nlocalhost4.localdomain4"));
+ entry = new PropertyMap("*[name]");
+ entry.put(new PropertySimple("name", "bin"));
+ entry.put(new PropertySimple("value", "root"));
entries.getList().add(entry);
- entry = new PropertyMap("*[canonical]");
- entry.put(new PropertySimple("ipaddr", "::1"));
- entry.put(new PropertySimple("canonical", "localhost"));
- entry.put(new PropertySimple("alias", "localhost.localdomain\nlocalhost6\nlocalhost6.localdomain6"));
+ entry = new PropertyMap("*[name]");
+ entry.put(new PropertySimple("name", "daemon"));
+ entry.put(new PropertySimple("value", "root"));
entries.getList().add(entry);
- entry = new PropertyMap("*[canonical]");
- entry.put(new PropertySimple("ipaddr", "1.1.1.1"));
- entry.put(new PropertySimple("canonical", "one-one-one-one.com"));
- entry.put(new PropertySimple("alias", null));
+ entry = new PropertyMap("*[name]");
+ entry.put(new PropertySimple("name", "adm"));
+ entry.put(new PropertySimple("value", "root"));
entries.getList().add(entry);
- entry = new PropertyMap("*[canonical]");
- entry.put(new PropertySimple("ipaddr", "2.2.2.2"));
- entry.put(new PropertySimple("canonical", "two-two-two-two.com"));
- entry.put(new PropertySimple("alias", "alias"));
+ entry = new PropertyMap("*[name]");
+ entry.put(new PropertySimple("name", "lp"));
+ entry.put(new PropertySimple("value", "root"));
entries.getList().add(entry);
- entry = new PropertyMap("*[canonical]");
- entry.put(new PropertySimple("ipaddr", "3.3.3.3"));
- entry.put(new PropertySimple("canonical", "three-three-three-three.com"));
- entry.put(new PropertySimple("alias", "alias1\nalias2"));
+ entry = new PropertyMap("*[name]");
+ entry.put(new PropertySimple("name", "sync"));
+ entry.put(new PropertySimple("value", "root"));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("*[name]");
+ entry.put(new PropertySimple("name", "shutdown"));
+ entry.put(new PropertySimple("value", "root"));
entries.getList().add(entry);
return config;
}
- private boolean supportsFacet(Class<?> facetInterface) {
- PluginMetadataManager manager = PluginContainer.getInstance().getPluginManager().getMetadataManager();
- String componentClass = manager.getComponentClass(getResourceType());
+ @Override
+ protected Configuration getUpdatedResourceConfig() {
+ Configuration config = new Configuration();
+ PropertyList entries = new PropertyList(".");
+ config.put(entries);
+
+ PropertyMap entry;
- try {
- return facetInterface.isAssignableFrom(Class.forName(componentClass));
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException("Could not find component class " + componentClass, e);
- }
- }
+ entry = new PropertyMap("*[name]");
+ entry.put(new PropertySimple("name", "shutdown"));
+ entry.put(new PropertySimple("value", "parthaa"));
+ entries.getList().add(entry);
- @Override
- protected Configuration getChangedResourceConfig() {
- // TODO Auto-generated method stub
- //TODO NEED TO FIX THIS
- return null;
+ return config;
}
}
diff --git a/modules/plugins/augeas/pom.xml b/modules/plugins/augeas/pom.xml
index 28f3cc5..657766c 100644
--- a/modules/plugins/augeas/pom.xml
+++ b/modules/plugins/augeas/pom.xml
@@ -23,10 +23,23 @@
<dependency>
<groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-core-plugin-container</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
<artifactId>rhq-platform-plugin</artifactId>
<version>${project.version}</version>
</dependency>
-
+
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <version>5.9</version>
+ <classifier>jdk15</classifier>
+ </dependency>
+
<dependency>
<groupId>net.augeas</groupId>
<artifactId>augeas</artifactId>
@@ -48,7 +61,7 @@
<version>2.0</version>
<executions>
<execution>
- <id>copy-jna-jar</id>
+ <id>copy-plugin-libs</id>
<phase>process-resources</phase>
<goals>
<goal>copy</goal>
@@ -74,17 +87,6 @@
</execution>
</executions>
</plugin>
-
- <plugin>
- <artifactId>maven-jar-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>test-jar</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
index aa0223e..a47423e 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
@@ -69,54 +69,45 @@ import org.rhq.plugins.augeas.helper.Glob;
*/
public class AugeasConfigurationComponent<T extends ResourceComponent> implements ResourceComponent<T>,
ConfigurationFacet, CreateChildResourceFacet, DeleteResourceFacet {
+ /* Plugin config prop names */
public static final String INCLUDE_GLOBS_PROP = "configurationFilesInclusionPatterns";
public static final String EXCLUDE_GLOBS_PROP = "configurationFilesExclusionPatterns";
public static final String RESOURCE_CONFIGURATION_ROOT_NODE_PROP = "resourceConfigurationRootNode";
public static final String AUGEAS_MODULE_NAME_PROP = "augeasModuleName";
public static final String AUGEAS_ROOT_PATH_PROP = "augeasRootPath";
- public static final String DEFAULT_AUGEAS_ROOT_PATH = File.listRoots()[0].getPath();
-
private static final boolean IS_WINDOWS = (File.separatorChar == '\\');
+ public static final String DEFAULT_AUGEAS_ROOT_PATH = (IS_WINDOWS) ? "C:/" : "/";
private static final String AUGEAS_LOAD_PATH = "/usr/share/augeas/lenses";
private final Log log = LogFactory.getLog(this.getClass());
private ResourceContext<T> resourceContext;
+ private String resourceDescription;
private List<String> includeGlobs;
private List<String> excludeGlobs;
private Augeas augeas;
private AugeasNode resourceConfigRootNode;
private String augeasRootPath;
-
- public static String getAugeasRootPath() {
- if (System.getProperty(AUGEAS_ROOT_PATH_PROP) != null) {
- return System.getProperty(AUGEAS_ROOT_PATH_PROP);
- }
- return DEFAULT_AUGEAS_ROOT_PATH;
- }
-
+
public void start(ResourceContext<T> resourceContext) throws InvalidPluginConfigurationException, Exception {
this.resourceContext = resourceContext;
- Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
+ this.resourceDescription = this.resourceContext.getResourceType() + " Resource with key ["
+ + this.resourceContext.getResourceKey() + "]";
+ initGlobs();
- this.augeasRootPath = getAugeasRootPath();
+ Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
+ this.augeasRootPath = pluginConfig.getSimpleValue(AUGEAS_ROOT_PATH_PROP, DEFAULT_AUGEAS_ROOT_PATH);
log.debug("Augeas Root Path = \"" + this.augeasRootPath + "\"");
- initGlobs(pluginConfig);
-
- this.augeas = createAugeas();
-
- if (this.augeas != null) {
- String resourceConfigRootPath = getResourceConfigurationRootPath();
- if (resourceConfigRootPath.indexOf(AugeasNode.SEPARATOR_CHAR) != 0) {
- // root path is relative - make it absolute
- this.resourceConfigRootNode = new AugeasNode("/files/", resourceConfigRootPath);
+ if (isAugeasAvailable()) {
+ initAugeas();
+ } else {
+ if (IS_WINDOWS) {
+ log.debug("Augeas not found - this is expected, since Augeas is not currently available for Windows.");
} else {
- // root path is already absolute
- this.resourceConfigRootNode = new AugeasNode(resourceConfigRootPath);
+ log.warn("Augeas not found - if on Fedora or RHEL, `yum install augeas`.");
}
-
}
}
@@ -132,6 +123,8 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
}
public Configuration loadResourceConfiguration() throws Exception {
+ abortIfAugeasNotAvailable();
+
// Load the config file from disk and build a tree representation of it.
loadConfigurationFiles(this.augeas);
@@ -146,14 +139,25 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
loadProperty(propDef, resourceConfig, this.augeas, this.resourceConfigRootNode);
}
+ // This will add error messages to any PropertySimples with invalid values, so they can be displayed by the GUI.
+ validateResourceConfiguration(new ConfigurationUpdateReport(resourceConfig));
return resourceConfig;
}
public void updateResourceConfiguration(ConfigurationUpdateReport report) {
+ try
+ {
+ abortIfAugeasNotAvailable();
+ }
+ catch (Exception e)
+ {
+ report.setErrorMessage(e.getLocalizedMessage());
+ return;
+ }
+
if (!validateResourceConfiguration(report)) {
- log.debug("Validation of updated Resource configuration for " + this.getResourceContext().getResourceType()
- + " Resource with key '" + this.getResourceContext().getResourceKey()
- + "' failed with the following errors: " + report.getErrorMessage());
+ log.debug("Validation of updated Resource configuration for " + this.resourceDescription
+ + " failed with the following errors: " + report.getErrorMessage());
report.setStatus(ConfigurationUpdateStatus.FAILURE);
return;
}
@@ -280,7 +284,12 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
}
public ResourceContext<T> getResourceContext() {
- return resourceContext;
+ return this.resourceContext;
+ }
+
+ public String getResourceDescription()
+ {
+ return this.resourceDescription;
}
public List<File> getConfigurationFiles() {
@@ -297,11 +306,7 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
String augeasModuleName = pluginConfig.getSimpleValue(AUGEAS_MODULE_NAME_PROP, null);
if (augeasModuleName == null) {
- return null;
- }
-
- if (!initAugeasJnaProxy()) {
- return null;
+ throw new IllegalStateException("Plugin config property '" + AUGEAS_MODULE_NAME_PROP + "' is required.");
}
Augeas augeas;
@@ -320,19 +325,16 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
loadConfigurationFiles(augeas);
} catch (RuntimeException e) {
augeas = null;
- log.warn("Failed to initialize Augeas Java API.", e);
+ log.error("Failed to initialize Augeas Java API.", e);
}
return augeas;
}
- private boolean initAugeasJnaProxy() {
+ protected boolean isAugeasAvailable() {
Aug aug;
try {
aug = Aug.INSTANCE;
- } catch (NoClassDefFoundError e) {
- if (!IS_WINDOWS) {
- log.warn("Augeas shared library not found. If on Fedora or RHEL, yum install augeas.");
- }
+ } catch (Error e) {
return false;
}
if (log.isTraceEnabled()) {
@@ -613,9 +615,11 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
}
}
- private void initGlobs(Configuration pluginConfiguration) {
- PropertySimple includes = pluginConfiguration.getSimple(INCLUDE_GLOBS_PROP);
- PropertySimple excludes = pluginConfiguration.getSimple(EXCLUDE_GLOBS_PROP);
+ private void initGlobs() {
+ Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
+
+ PropertySimple includes = pluginConfig.getSimple(INCLUDE_GLOBS_PROP);
+ PropertySimple excludes = pluginConfig.getSimple(EXCLUDE_GLOBS_PROP);
includeGlobs = new ArrayList<String>();
excludeGlobs = new ArrayList<String>();
@@ -658,4 +662,41 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
return summary.toString();
}
+
+ protected void initAugeas() {
+ this.augeas = createAugeas();
+ String resourceConfigRootPath = getResourceConfigurationRootPath();
+ if (resourceConfigRootPath.indexOf(AugeasNode.SEPARATOR_CHAR) != 0) {
+ // root path is relative - make it absolute
+ this.resourceConfigRootNode = new AugeasNode("/files/", resourceConfigRootPath);
+ } else {
+ // root path is already absolute
+ this.resourceConfigRootNode = new AugeasNode(resourceConfigRootPath);
+ }
+ log.debug("Resource Config Root Node = \"" + this.resourceConfigRootNode + "\"");
+ }
+
+ private void abortIfAugeasNotAvailable()
+ throws Exception
+ {
+ if (getAugeas() == null) {
+ if (isAugeasAvailable()) {
+ initAugeas();
+ if (getAugeas() == null) {
+ throw new Exception("Failed to initialize Augeas Java API.");
+ }
+ } else {
+ String message;
+ if (IS_WINDOWS) {
+ message = "Configuration of " + getResourceContext().getResourceType().getName()
+ + " Resources is not supported on Windows.";
+ } else {
+ message = "Configuration of " + getResourceContext().getResourceType().getName()
+ + " Resources requires that the Augeas shared library be installed on the Agent system."
+ + " If on Fedora or RHEL, `yum install augeas`.";
+ }
+ throw new Exception(message);
+ }
+ }
+ }
}
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
index cea1974..8d533a4 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
@@ -117,7 +117,8 @@ public class AugeasConfigurationDiscoveryComponent<T extends ResourceComponent>
PropertySimple excludeGlobsProp = pluginConfiguration
.getSimple(AugeasConfigurationComponent.EXCLUDE_GLOBS_PROP);
- String augeasRootPath = AugeasConfigurationComponent.getAugeasRootPath();
+ String augeasRootPath = pluginConfiguration.getSimpleValue(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP,
+ AugeasConfigurationComponent.DEFAULT_AUGEAS_ROOT_PATH);
File root = new File(augeasRootPath);
List<String> includeGlobs = getGlobList(includeGlobsProp);
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java
index 0a2fc52..5fa0ebf 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java
@@ -62,6 +62,13 @@ public class Glob {
* @return the list of matches
*/
public static List<File> match(File parentPath, String globPattern) {
+ if (!parentPath.exists()) {
+ throw new IllegalArgumentException("Path '" + parentPath + "' does not exist.");
+ }
+ if (!parentPath.isDirectory()) {
+ throw new IllegalArgumentException("Path '" + parentPath + "' is not a directory.");
+ }
+
String rootPortion = rootPortion(globPattern);
globPattern = globPattern.substring(rootPortion.length());
@@ -75,7 +82,7 @@ public class Glob {
}
if (specialCharIdx > 0) {
- //now search for the first path separator preceeding the special char
+ //now search for the first path separator preceding the special char
int globParentIdx = globPattern.lastIndexOf(File.separatorChar, specialCharIdx);
if (globParentIdx > 0) {
//move the parent path down to the nearest parent of the wildcard part of the
@@ -88,8 +95,13 @@ public class Glob {
} else {
globPattern = parentPath.getAbsolutePath() + globPattern;
}
-
- return Arrays.asList(parentPath.listFiles(new GlobFilter(globPattern)));
+
+ globPattern = new File(globPattern).getAbsolutePath();
+ File[] files = parentPath.listFiles(new GlobFilter(globPattern));
+ if (files == null) {
+ throw new IllegalStateException("Could not list files in " + parentPath);
+ }
+ return Arrays.asList(files);
}
public static List<File> matchAll(File parentPath, String... globPattern) {
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
new file mode 100644
index 0000000..4084023
--- /dev/null
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
@@ -0,0 +1,287 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2009 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.augeas.test;
+
+import static org.testng.Assert.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.rhq.core.clientapi.agent.PluginContainerException;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
+import org.rhq.core.pluginapi.util.FileUtils;
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
+import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+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.configuration.ConfigurationManager;
+import org.rhq.core.pc.inventory.InventoryManager;
+import org.rhq.core.pc.plugin.FileSystemPluginFinder;
+import org.rhq.core.pc.plugin.PluginManager;
+import org.rhq.core.util.file.FileUtil;
+import org.rhq.plugins.augeas.AugeasConfigurationComponent;
+
+import net.augeas.jna.Aug;
+
+/**
+ * A base class for integration tests for instances of {@link AugeasConfigurationComponent}.
+ *
+ * @author Ian Springer
+ */
+public abstract class AbstractAugeasConfigurationComponentTest {
+ public static final String TEST_GROUP = "linux-config";
+ private static final File ITEST_DIR = new File("target/itest");
+ private static final long ONE_WEEK_IN_SECONDS = 60L * 60 * 24;
+ protected static final boolean IS_WINDOWS = (File.separatorChar == '\\');
+
+ protected static final File AUGEAS_ROOT;
+ static {
+ String tmpDirPath = System.getProperty("java.io.tmpdir");
+ File tmpDir = new File(tmpDirPath);
+ AUGEAS_ROOT = new File(tmpDir, "rhq-itest-augeas-root-path");
+ }
+
+ private final Log log = LogFactory.getLog(this.getClass());
+
+ @BeforeSuite(groups = TEST_GROUP)
+ public void start() {
+ if (!isResourceConfigSupported()) {
+ String message;
+ if (IS_WINDOWS) {
+ message = "Augeas is not available on Windows. Augeas-based configuration functionality will *not* be tested.";
+ } else {
+ message = "Augeas not found. If on Fedora or RHEL, `yum install augeas`. Augeas-based configuration functionality will *not* be tested.";
+ }
+ System.out.println(message);
+ }
+ try {
+ PluginContainerConfiguration pcConfig = createPluginContainerConfiguration();
+ PluginContainer.getInstance().setConfiguration(pcConfig);
+
+ System.out.println("Starting plugin container...");
+ PluginContainer pluginContainer = PluginContainer.getInstance();
+ pluginContainer.initialize();
+ Set<String> pluginNames = pluginContainer.getPluginManager().getMetadataManager().getPluginNames();
+ System.out.println("Plugin container started with the following plugins: " + pluginNames);
+
+ System.out.println("Updating Augeas root in default plugin config...");
+ ResourceType resourceType = getResourceType();
+ ConfigurationDefinition pluginConfigDef = resourceType.getPluginConfigurationDefinition();
+ ConfigurationTemplate defaultPluginConfigTemplate = pluginConfigDef.getDefaultTemplate();
+ Configuration defaultPluginConfig = defaultPluginConfigTemplate.getConfiguration();
+ tweakDefaultPluginConfig(defaultPluginConfig);
+ resetConfigFiles(defaultPluginConfig);
+
+ InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
+ System.out.println("Executing server discovery scan...");
+ inventoryManager.executeServerScanImmediately();
+ System.out.println("Executing service discovery scan...");
+ inventoryManager.executeServiceScanImmediately();
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Failed to initialize the plugin container.", e);
+ }
+ }
+
+ @BeforeTest(groups = TEST_GROUP)
+ public void resetConfigFiles() throws IOException {
+ resetConfigFiles(getResource().getPluginConfiguration());
+ }
+
+ @Test(groups = TEST_GROUP)
+ public void testResourceConfigLoad() throws Exception {
+ ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
+ Resource resource = getResource();
+ Configuration resourceConfig;
+ try
+ {
+ resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
+ Configuration expectedResourceConfig = getExpectedResourceConfig();
+ assert resourceConfig.equals(expectedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
+ + expectedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
+ }
+ catch (PluginContainerException e)
+ {
+ if (isResourceConfigSupported()) {
+ throw e;
+ }
+ }
+ }
+
+ @Test(groups = TEST_GROUP)
+ public void testResourceConfigUpdate() throws Exception {
+ ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
+ Resource resource = getResource();
+ Configuration updatedResourceConfig = getUpdatedResourceConfig();
+ ConfigurationUpdateRequest updateRequest = new ConfigurationUpdateRequest(0, updatedResourceConfig,
+ resource.getId());
+ configurationManager.updateResourceConfiguration(updateRequest);
+
+ if (isResourceConfigSupported()) {
+ // Give the component and the managed resource some time to properly persist the update.
+ Thread.sleep(500);
+
+ Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
+ assert resourceConfig.equals(updatedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
+ + updatedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
+ }
+ }
+
+ @AfterSuite(groups = TEST_GROUP)
+ public void stop() {
+ deleteAugeasRootDir();
+ System.out.println("Stopping plugin container...");
+ PluginContainer.getInstance().shutdown();
+ System.out.println("Plugin container stopped.");
+ }
+
+ protected abstract String getPluginName();
+
+ protected abstract String getResourceTypeName();
+
+ protected abstract Configuration getExpectedResourceConfig();
+
+ protected abstract Configuration getUpdatedResourceConfig();
+
+ protected PluginContainerConfiguration createPluginContainerConfiguration()
+ throws IOException
+ {
+ PluginContainerConfiguration pcConfig = new PluginContainerConfiguration();
+ File pluginsDir = new File(ITEST_DIR, "plugins");
+ pcConfig.setPluginFinder(new FileSystemPluginFinder(pluginsDir));
+ pcConfig.setPluginDirectory(pluginsDir);
+ pcConfig.setInsideAgent(false);
+ pcConfig.setCreateResourceClassloaders(true);
+
+ // Set initial delays for all scheduled scans to one week to effectively disable them.
+ pcConfig.setServerDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setServiceDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setAvailabilityScanInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setConfigurationDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setContentDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+
+ File tmpDir = new File(ITEST_DIR, "tmp");
+ tmpDir.mkdirs();
+ if (!tmpDir.isDirectory() || !tmpDir.canWrite()) {
+ throw new IOException("Failed to create temporary directory (" + tmpDir + ").");
+ }
+ pcConfig.setTemporaryDirectory(tmpDir);
+ return pcConfig;
+ }
+
+ protected static ResourceType getResourceType(String resourceTypeName, String pluginName) {
+ PluginManager pluginManager = PluginContainer.getInstance().getPluginManager();
+ PluginMetadataManager pluginMetadataManager = pluginManager.getMetadataManager();
+ return pluginMetadataManager.getType(resourceTypeName, pluginName);
+ }
+
+ protected final ResourceType getResourceType() {
+ return getResourceType(getResourceTypeName(), getPluginName());
+ }
+
+ protected Resource getResource() {
+ InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
+ ResourceType resourceType = getResourceType();
+ Set<Resource> resources = inventoryManager.getResourcesWithType(resourceType);
+ if (resources.isEmpty()) {
+ return null;
+ }
+ if (resources.size() > 1) {
+ throw new IllegalStateException("Found more than one " + resourceType.getName()
+ + " Resource - expected there to be exactly one - resources: " + resources);
+ }
+ return resources.iterator().next();
+ }
+
+ protected void resetConfigFiles(Configuration pluginConfig) throws IOException {
+ deleteAugeasRootDir();
+ AUGEAS_ROOT.mkdirs();
+ String includes = pluginConfig.getSimpleValue(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP, null);
+ if (includes != null) {
+ List<String> includeGlobs = new ArrayList<String>();
+ includeGlobs.addAll(Arrays.asList(includes.split("\\s*\\|\\s*")));
+ for (String includeGlob : includeGlobs) {
+ String resourcePath;
+ if (IS_WINDOWS) {
+ resourcePath = includeGlob.replace('\\', '/');
+ int colonIndex = resourcePath.indexOf(':');
+ if (colonIndex != -1) {
+ resourcePath = resourcePath.substring(colonIndex + 1);
+ }
+ } else {
+ resourcePath = includeGlob;
+ }
+ InputStream inputStream = this.getClass().getResourceAsStream(resourcePath);
+ if (inputStream != null) {
+ File outputFile = new File(AUGEAS_ROOT, resourcePath);
+ outputFile.getParentFile().mkdirs();
+ FileUtil.writeFile(inputStream, outputFile);
+ }
+ }
+ }
+ }
+
+ protected boolean isResourceConfigSupported() {
+ return isAugeasAvailable();
+ }
+
+ protected void tweakDefaultPluginConfig(Configuration defaultPluginConfig)
+ {
+ PropertySimple rootPathProp = new PropertySimple(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP,
+ AUGEAS_ROOT);
+ defaultPluginConfig.put(rootPathProp);
+ }
+
+ private boolean isAugeasAvailable() {
+ try {
+ Aug aug = Aug.INSTANCE;
+ return true;
+ } catch (Error e) {
+ return false;
+ }
+ }
+
+ private void deleteAugeasRootDir() {
+ try
+ {
+ FileUtils.purge(AUGEAS_ROOT, true);
+ }
+ catch (IOException e)
+ {
+ log.warn("Failed to delete Augeas root dir (" + AUGEAS_ROOT + ").");
+ }
+ }
+}
diff --git a/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java
deleted file mode 100644
index e8f5ef3..0000000
--- a/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2009 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.augeas;
-
-import static org.testng.Assert.fail;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-
-import org.testng.annotations.AfterSuite;
-import org.testng.annotations.BeforeSuite;
-import org.testng.annotations.Test;
-
-import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
-import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
-import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.configuration.PropertySimple;
-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.configuration.ConfigurationManager;
-import org.rhq.core.pc.inventory.InventoryManager;
-import org.rhq.core.pc.plugin.FileSystemPluginFinder;
-import org.rhq.core.pc.plugin.PluginManager;
-import org.rhq.core.util.file.FileUtil;
-
-/**
- * An base class for integration tests for instances of {@link AugeasConfigurationComponent}.
- *
- * @author Ian Springer
- */
-public abstract class AbstractAugeasConfigurationComponentTest {
- public static final String TEST_GROUP = "linux-config";
- private static final File ITEST_DIR = new File("target/itest");
- private static final long ONE_WEEK_IN_SECONDS = 60L * 60 * 24;
-
- @BeforeSuite(groups = TEST_GROUP)
- public void start() {
- try {
- PluginContainerConfiguration pcConfig = new PluginContainerConfiguration();
- File pluginsDir = new File(ITEST_DIR, "plugins");
- pcConfig.setPluginFinder(new FileSystemPluginFinder(pluginsDir));
- pcConfig.setPluginDirectory(pluginsDir);
- pcConfig.setInsideAgent(false);
- pcConfig.setCreateResourceClassloaders(true);
-
- // Set initial delays for all scheduled scans to one week to effectively disable them.
- pcConfig.setServerDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
- pcConfig.setServiceDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
- pcConfig.setAvailabilityScanInitialDelay(ONE_WEEK_IN_SECONDS);
- pcConfig.setConfigurationDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
- pcConfig.setContentDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
-
- File tmpDir = new File(ITEST_DIR, "tmp");
- tmpDir.mkdirs();
- if (!tmpDir.isDirectory() || !tmpDir.canWrite()) {
- throw new IOException("Failed to create temporary directory (" + tmpDir + ").");
- }
- pcConfig.setTemporaryDirectory(tmpDir);
- PluginContainer.getInstance().setConfiguration(pcConfig);
- System.out.println("Starting PC...");
- PluginContainer.getInstance().initialize();
- Set<String> pluginNames = PluginContainer.getInstance().getPluginManager().getMetadataManager()
- .getPluginNames();
- System.out.println("PC started with the following plugins: " + pluginNames);
- } catch (Exception e) {
- e.printStackTrace();
- fail("Failed to start the plugin container.", e);
- }
- }
-
- @BeforeSuite(dependsOnMethods = "start", groups = TEST_GROUP)
- public void updatePluginConfiguration() {
- try {
- System.out.println("Updating Augeas root in plugin configuration...");
-
- // We need to have the Resource inventoried in order to update its plugin config.
- InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
- ResourceType resourceType = getResourceType();
- switch (resourceType.getCategory()) {
- case SERVICE:
- System.out.println("Executing platform service scan to discover " + resourceType + " Resource...");
- inventoryManager.performServiceScan(inventoryManager.getPlatform().getId());
- break;
- case SERVER:
- System.out.println("Executing server scan to discover " + resourceType + " Resource...");
- inventoryManager.executeServerScanImmediately();
- break;
- case PLATFORM:
- throw new IllegalStateException("Huh? Using Augeas to configure a platform?");
- }
- resetAugeasConfigs();
- Resource resource = getResource();
- Configuration pluginConfig = resource.getPluginConfiguration();
- inventoryManager.updatePluginConfiguration(resource.getId(), pluginConfig);
- } catch (Exception e) {
- fail("Failed to update Augeas root in plugin configuration.", e);
- }
- }
-
- public void resetAugeasConfigs() throws IOException {
- String tmpDirPath = System.getProperty("java.io.tmpdir");
- File tmpDir = new File(tmpDirPath);
- File augeasRootPath = new File(tmpDir, "rhq-itest-augeas-root-path");
- if (!augeasRootPath.exists()) {
- augeasRootPath.mkdirs();
- }
- System.setProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP, augeasRootPath.getAbsolutePath());
- Resource resource = getResource();
- Configuration pluginConfig = resource.getPluginConfiguration();
- PropertySimple includes = pluginConfig.getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP);
- List<String> includeGlobs = new ArrayList<String>();
- includeGlobs.addAll(Arrays.asList(includes.getStringValue().split("\\s*\\|\\s*")));
- for (String includeGlob : includeGlobs) {
- InputStream inputStream = this.getClass().getResourceAsStream(includeGlob);
- if (inputStream != null) {
- File outputFile = new File(augeasRootPath, includeGlob);
- outputFile.getParentFile().mkdirs();
- FileUtil.writeFile(inputStream, outputFile);
- }
- }
- }
-
- @AfterSuite(groups = TEST_GROUP)
- public void stop() {
- System.clearProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP);
- System.out.println("Stopping PC...");
- PluginContainer.getInstance().shutdown();
- System.out.println("PC stopped.");
- }
-
- @Test(groups = TEST_GROUP)
- public void testResourceConfigLoad() throws Exception {
- if (getResourceType().getResourceConfigurationDefinition() != null) {
- ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
- Resource resource = getResource();
- Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
- Configuration expectedResourceConfig = getExpectedResourceConfig();
- assert resourceConfig.equals(expectedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
- + expectedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
- }
- }
-
- protected abstract Configuration getExpectedResourceConfig();
-
- protected abstract Configuration getChangedResourceConfig();
-
- protected static ResourceType getResourceType(String resourceTypeName, String pluginName) {
- PluginManager pluginManager = PluginContainer.getInstance().getPluginManager();
- PluginMetadataManager pluginMetadataManager = pluginManager.getMetadataManager();
- return pluginMetadataManager.getType(resourceTypeName, pluginName);
- }
-
- protected final ResourceType getResourceType() {
- return getResourceType(getResourceTypeName(), getPluginName());
- }
-
- protected abstract String getPluginName();
-
- protected abstract String getResourceTypeName();
-
- protected Resource getResource() {
- InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
- ResourceType resourceType = getResourceType();
- Set<Resource> resources = inventoryManager.getResourcesWithType(resourceType);
- if (resources.isEmpty()) {
- return null;
- }
- if (resources.size() > 1) {
- throw new IllegalStateException("Found more than one " + resourceType.getName()
- + " Resource - expected there to be exactly one - resources: " + resources);
- }
- return resources.iterator().next();
- }
-
- @Test(groups = TEST_GROUP)
- public void testResourceConfigUpdate() throws Exception {
- if (getResourceType().getResourceConfigurationDefinition() != null) {
- try {
- ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
- Resource resource = getResource();
- Configuration updatedResourceConfig = getChangedResourceConfig();
- configurationManager.updateResourceConfiguration(new ConfigurationUpdateRequest(0,
- updatedResourceConfig, resource.getId()));
-
- //give the component and the managed resource some time to properly persist the update
- Thread.sleep(500);
-
- Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
- assert resourceConfig.equals(updatedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
- + updatedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
- } finally {
- resetAugeasConfigs();
- }
- }
- }
-}
diff --git a/modules/plugins/hosts-augeas/pom.xml b/modules/plugins/hosts-augeas/pom.xml
deleted file mode 100644
index 0927981..0000000
--- a/modules/plugins/hosts-augeas/pom.xml
+++ /dev/null
@@ -1,218 +0,0 @@
-<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-plugins-parent</artifactId>
- <version>1.4.0-SNAPSHOT</version>
- </parent>
-
- <groupId>org.rhq</groupId>
- <artifactId>rhq-hosts-augeas-plugin</artifactId>
- <packaging>jar</packaging>
-
- <name>RHQ Augeas-based Hosts Plugin</name>
- <description>A plugin for managing the *nix hosts service</description>
-
- <scm>
- <connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/plugins/hosts-augeas</connection>
- <developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/plugins/hosts-augeas</developerConnection>
- </scm>
-
- <properties>
- <scm.module.path>modules/plugins/hosts/</scm.module.path>
- </properties>
-
- <dependencies>
-
- <dependency>
- <groupId>net.augeas</groupId>
- <artifactId>augeas</artifactId>
- <version>0.0.1</version>
- </dependency>
-
- <dependency>
- <groupId>com.sun.jna</groupId>
- <artifactId>jna</artifactId>
- <version>3.0.9</version>
- </dependency>
-
- </dependencies>
-
- <profiles>
- <profile>
- <id>integration-tests</id>
- <activation>
- <property>
- <name>maven.test.skip</name>
- <value>!true</value>
- </property>
- </activation>
-
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-antrun-plugin</artifactId>
- <executions>
- <execution>
- <phase>pre-integration-test</phase>
- <configuration>
- <tasks>
- <echo>Setting up plugin dependencies for ${project.artifactId}-${project.version}.jar...
- </echo>
- <property name="settings.localRepository" location="${user.home}/.m2/repository" />
- <mkdir dir="target/itest" />
- <mkdir dir="target/itest/plugins" />
- <mkdir dir="target/itest/lib" />
- <copy toDir="target/itest/plugins" flatten="true">
- <fileset dir="${settings.localRepository}/">
- <include name="org/rhq/rhq-platform-plugin/${project.version}/rhq-platform-plugin-${project.version}.jar" />
- </fileset>
- <fileset dir="${project.build.directory}">
- <include name="${project.artifactId}-${project.version}.jar" />
- </fileset>
- </copy>
- <unzip dest="target/itest/lib">
- <fileset dir="${settings.localRepository}/org/hyperic/sigar-dist/${sigar.version}" includes="*.zip" />
- <patternset>
- <include name="**/lib/sigar.jar" />
- <include name="**/lib/bcel*.jar" />
- <include name="**/lib/*.so" />
- <include name="**/lib/*.sl" />
- <include name="**/lib/*.dll" />
- <include name="**/lib/*.dylib" />
- </patternset>
- </unzip>
- <move todir="target/itest/lib" flatten="true">
- <fileset dir="target/itest/lib">
- <include name="**/lib/*" />
- </fileset>
- </move>
- <delete dir="target/itest/lib/hyperic-sigar-${sigar.version}" />
- </tasks>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
-
- <!-- Integration testing voodoo to load and test this plugin with its plugin dependencies -->
- <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>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
- <!--<argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
- <systemProperties>
- <property>
- <name>project.artifactId</name>
- <value>${project.artifactId}</value>
- </property>
- <property>
- <name>project.version</name>
- <value>${project.version}</value>
- </property>
- </systemProperties>
- </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.deploymentDir>
- ${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/rhq-downloads/rhq-plugins
- </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>deploy-jar-meta-inf</id>
- <phase>package</phase>
- <configuration>
- <tasks>
- <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>
- </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>
-
- </profiles>
-
-</project>
diff --git a/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/HostsAugeasComponent.java b/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/HostsAugeasComponent.java
deleted file mode 100644
index 4f81218..0000000
--- a/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/HostsAugeasComponent.java
+++ /dev/null
@@ -1,260 +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.plugins.hosts;
-
-import java.io.File;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Date;
-import java.util.Set;
-
-import net.augeas.Augeas;
-
-import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
-import org.rhq.core.domain.configuration.Property;
-import org.rhq.core.pluginapi.inventory.ResourceComponent;
-import org.rhq.core.pluginapi.inventory.ResourceContext;
-import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
-import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
-import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
-import org.rhq.core.domain.measurement.AvailabilityType;
-import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.configuration.PropertySimple;
-import org.rhq.core.domain.configuration.PropertyList;
-import org.rhq.core.domain.configuration.PropertyMap;
-import org.rhq.plugins.hosts.util.AugeasUtility;
-
-/**
- * @author Jason Dobies, Ian Springer
- */
-public class HostsAugeasComponent implements ResourceComponent, ConfigurationFacet {
-
- private ResourceContext resourceContext;
- private File hostsFile;
-
- public void start(ResourceContext resourceContext) throws InvalidPluginConfigurationException, Exception {
- this.resourceContext = resourceContext;
-
- Configuration pluginConfiguration = resourceContext.getPluginConfiguration();
-
- PropertySimple hostsPathProperty = pluginConfiguration.getSimple("hosts-path");
-
- if (hostsPathProperty == null) {
- throw new InvalidPluginConfigurationException("Hosts path not found in the plugin configuration, cannot start resource component");
- }
-
- String hostsPath = hostsPathProperty.getStringValue();
-
- hostsFile = new File(hostsPath);
-
- if (!hostsFile.exists()) {
- throw new InvalidPluginConfigurationException("Hosts file not found at specified location: " + hostsPath);
- }
- }
-
- public void stop() {
- }
-
- public AvailabilityType getAvailability() {
- if (hostsFile == null) {
- return AvailabilityType.DOWN;
- }
-
- return hostsFile.exists() ? AvailabilityType.UP : AvailabilityType.DOWN;
- }
-
- public Configuration loadResourceConfiguration() throws Exception {
- Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
- return loadResourceConfiguration(pluginConfig);
- }
-
- Configuration loadResourceConfiguration(Configuration pluginConfig) throws Exception {
- Augeas augeas = createAugeas(pluginConfig);
- List<String> entryPaths = getEntryPaths(pluginConfig, augeas);
-
- Configuration resourceConfig = new Configuration();
- resourceConfig.setNotes("Loaded from Augeas at " + new Date());
-
- PropertyList entriesList = new PropertyList("entries");
- resourceConfig.put(entriesList);
-
- for (String entryPath : entryPaths) {
- String ip = augeas.get(entryPath + "/ipaddr");
- String canonical = augeas.get(entryPath + "/canonical");
- List<String> aliasPaths = augeas.match(entryPath + "/alias[*]");
-
- PropertyMap entry = new PropertyMap("entry");
- entry.put(new PropertySimple("ipAddress", ip));
- entry.put(new PropertySimple("canonicalName", canonical));
- if (!aliasPaths.isEmpty()) {
- StringBuilder aliasesPropValue = new StringBuilder();
- for (String aliasPath : aliasPaths) {
- String alias = augeas.get(aliasPath);
- aliasesPropValue.append(alias).append("\n");
- }
- // Chop the final newline char.
- aliasesPropValue.deleteCharAt(aliasesPropValue.length() - 1);
- entry.put(new PropertySimple("aliases", aliasesPropValue));
- }
- entriesList.add(entry);
- }
-
- return resourceConfig;
- }
-
- public void updateResourceConfiguration(ConfigurationUpdateReport report) {
- Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
- Augeas augeas;
- try {
- augeas = createAugeas(pluginConfig);
- }
- catch (Exception e) {
- throw new RuntimeException("Failed to create Augeas object.", e);
- }
-
- PropertySimple augeasTreeNodeProperty = pluginConfig.getSimple("augeas-hosts-path");
- if (augeasTreeNodeProperty == null) {
- throw new IllegalStateException("Augeas tree node not specified for hosts, cannot retrieve configuration");
- }
- String hostsPath = augeasTreeNodeProperty.getStringValue();
-
- Set<String> originalEntryPaths = new HashSet<String>(augeas.match("/files/etc/hosts/*"));
- Set<String> updatedEntryPaths = new HashSet<String>();
-
- Configuration resourceConfig = report.getConfiguration();
- PropertyList entriesList = resourceConfig.getList("entries");
- for (Property entryProp : entriesList.getList()) {
- PropertyMap entry = (PropertyMap)entryProp;
- String ipAddress = entry.getSimple("ipAddress").getStringValue();
- String canonicalName = entry.getSimple("canonicalName").getStringValue();
- String aliases = entry.getSimpleValue("aliases", null);
- Set<String> aliasSet;
- if (aliases == null) {
- aliasSet = null;
- } else {
- String[] aliasArray = aliases.trim().split("\\s+");
- aliasSet = new LinkedHashSet<String>(aliasArray.length);
- for (String alias : aliasArray) {
- aliasSet.add(alias);
- }
- }
-
- int newEntryIndex = 0;
- String newEntryPathPattern = hostsPath + "/0%d";
-
- String nameFilter = "/files/etc/hosts/*/canonical";
- List<String> namePaths = AugeasUtility.matchFilter(augeas, nameFilter, canonicalName);
- if (!namePaths.isEmpty()) {
- // overwrite existing entry
-
- // name
- String namePath = namePaths.get(0);
- augeas.set(namePath, canonicalName);
-
- String entryPath = AugeasUtility.getParentPath(namePath);
- updatedEntryPaths.add(entryPath);
-
- // IP
- String ipPath = entryPath + "/ipaddr";
- augeas.set(ipPath, canonicalName);
-
- // aliases
- // remove existing alias nodes first
- String aliasExpression = entryPath + "/alias[*]";
- List<String> aliasPaths = augeas.match(aliasExpression);
- for (String aliasPath : aliasPaths) {
- augeas.remove(aliasPath);
- }
- // then add the new ones
- String aliasPathPattern = entryPath + "/alias[%d]";
- int i = 1;
- for (String alias : aliasSet) {
- String aliasPath = String.format(aliasPathPattern, i++);
- augeas.set(aliasPath, alias);
- }
- } else {
- // no existing entry w/ this canonical name - add a new entry
- String newEntryPath = String.format(newEntryPathPattern, newEntryIndex++);
- augeas.set(newEntryPath + "/ipaddr", ipAddress);
- augeas.set(newEntryPath + "/canonical", canonicalName);
- String aliasPathPattern = newEntryPath + "/alias[%d]";
- int i = 1;
- for (String alias : aliasSet) {
- String aliasPath = String.format(aliasPathPattern, i++);
- augeas.set(aliasPath, alias);
- }
- }
-
- }
-
- // Remove any entries from the Augeas tree that are not present in the updated Configuration.
- for (String originalEntryPath : originalEntryPaths) {
- if (!updatedEntryPaths.contains(originalEntryPath)) {
- augeas.remove(originalEntryPath);
- }
- }
-
- // TODO: Backup the original file.
-
- // Write the updated Augeas tree out to the /etc/hosts file.
- augeas.save();
-
- // If we got this far, we've succeeded in out mission.
- report.setStatus(ConfigurationUpdateStatus.SUCCESS);
-
- return;
- }
-
- private Augeas createAugeas(Configuration pluginConfiguration) throws Exception {
- PropertySimple lensesPathProperty = pluginConfiguration.getSimple("lenses-path");
-
- if (lensesPathProperty == null) {
- throw new Exception("Lenses path not found in plugin configuration, cannot retrieve configuration");
- }
-
- PropertySimple rootPathProperty = pluginConfiguration.getSimple("root-path");
-
- if (rootPathProperty == null) {
- throw new Exception("Root path not found in plugin configuration, cannot retrieve configuration");
- }
-
- String lensesPath = lensesPathProperty.getStringValue();
- String rootPath = rootPathProperty.getStringValue();
-
- Augeas augeas = new Augeas(rootPath, lensesPath, Augeas.NONE);
- return augeas;
- }
-
- private List<String> getEntryPaths(Configuration pluginConfiguration, Augeas augeas) throws Exception {
- // Find out where to look for the hosts tree
- PropertySimple augeasTreeNodeProperty = pluginConfiguration.getSimple("augeas-hosts-path");
- if (augeasTreeNodeProperty == null) {
- throw new Exception("Augeas tree node not specified for hosts, cannot retrieve configuration");
- }
- String hostsTreeNode = augeasTreeNodeProperty.getStringValue();
-
- // Request data from augeas
- List<String> matches = augeas.match(hostsTreeNode);
- if (matches.size() == 0) {
- throw new Exception("Unable to load hosts data from augeas");
- }
- return matches;
- }
-}
diff --git a/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/HostsAugeasDiscoveryComponent.java b/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/HostsAugeasDiscoveryComponent.java
deleted file mode 100644
index 4b7ac66..0000000
--- a/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/HostsAugeasDiscoveryComponent.java
+++ /dev/null
@@ -1,50 +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.plugins.hosts;
-
-import java.io.File;
-import java.util.HashSet;
-import java.util.Set;
-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;
-
-/**
- * @author Jason Dobies
- */
-public class HostsAugeasDiscoveryComponent implements ResourceDiscoveryComponent {
-
- public Set discoverResources(ResourceDiscoveryContext discoveryContext)
- throws InvalidPluginConfigurationException, Exception {
-
- Set<DiscoveredResourceDetails> details = new HashSet<DiscoveredResourceDetails>();
-
- File hostsFile = new File("/etc/hosts");
- if (hostsFile.exists()) {
- DiscoveredResourceDetails resource =
- new DiscoveredResourceDetails(discoveryContext.getResourceType(), hostsFile.getPath(),
- "Hosts File", null, "Hosts File", discoveryContext.getDefaultPluginConfiguration(), null);
-
- details.add(resource);
- }
-
- return details;
- }
-}
diff --git a/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/util/AugeasUtility.java b/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/util/AugeasUtility.java
deleted file mode 100644
index 44daf86..0000000
--- a/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/util/AugeasUtility.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Jopr Management Platform
- * Copyright (C) 2005-2009 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.hosts.util;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import net.augeas.Augeas;
-
-/**
- * @author Ian Springer
- */
-public class AugeasUtility {
- public static String getParentPath(String path) {
- String trimmedPath = trimTrailingSlashes(path);
- if (trimmedPath.equals("/")) {
- return "/";
- }
- int lastSlashIndex = trimmedPath.lastIndexOf("/");
- String parentPath = trimmedPath.substring(0, lastSlashIndex);
- return parentPath;
- }
-
- public static List<String> matchFilter(Augeas augeas, String expression, String value) {
- List<String> matches = new ArrayList<String>();
- List<String> paths = augeas.match(expression);
- for (String path : paths) {
- String pathValue = augeas.get(path);
- if (pathValue.equals(value)) {
- matches.add(path);
- }
- }
- return matches;
- }
-
- private static String trimTrailingSlashes(String path) {
- int trailingSlashCount = 0;
- for (int i = path.length() - 1; i > 0; i--) {
- if (path.charAt(i) == '/') {
- trailingSlashCount++;
- }
- }
- String trimmedPath;
- if (trailingSlashCount > 0) {
- trimmedPath = path.substring(0, path.length() - trailingSlashCount);
- } else {
- trimmedPath = path;
- }
- return trimmedPath;
- }
-
- // prevent instantiation
- private AugeasUtility() {
- }
-}
diff --git a/modules/plugins/hosts-augeas/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/hosts-augeas/src/main/resources/META-INF/rhq-plugin.xml
deleted file mode 100644
index c98d62f..0000000
--- a/modules/plugins/hosts-augeas/src/main/resources/META-INF/rhq-plugin.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<plugin name="HostsAugeas"
- displayName="Hosts Server"
- description="Support for *nix hosts service"
- package="org.rhq.plugins.hosts"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns="urn:xmlns:rhq-plugin"
- xmlns:c="urn:xmlns:rhq-configuration">
-
- <depends plugin="Augeas"/>
-
- <service name="Hosts"
- description="The static table lookup for host names"
- discovery="HostsAugeasDiscoveryComponent"
- class="HostsAugeasComponent">
-
- <runs-inside>
- <parent-resource-type name="Linux" plugin="Platforms"/>
- <parent-resource-type name="Windows" plugin="Platforms"/>
- <parent-resource-type name="Solaris" plugin="Platforms"/>
- <parent-resource-type name="HP-UX" plugin="Platforms"/>
- <parent-resource-type name="AIX" plugin="Platforms"/>
- <parent-resource-type name="FreeBSD" plugin="Platforms"/>
- <parent-resource-type name="Mac OS X" plugin="Platforms"/>
- <parent-resource-type name="Java" plugin="Platforms"/>
- </runs-inside>
-
- <plugin-configuration>
- <c:group name="augeas" displayName="Augeas Settings">
- <c:simple-property name="lenses-path" displayName="Augeas Lenses Path"
- default="/usr/local/share/augeas/lenses" required="true"
- description="Full path to the augeas lenses directory. Example: /usr/local/share/augeas/lenses"/>
- <c:simple-property name="root-path" displayName="Augeas Root Path" default="/" required="true"
- description="Path from which augeas should begin to search for configuration files. Example: /"/>
- </c:group>
- <c:group name="hosts" displayName="Hosts Settings">
- <c:simple-property name="hosts-path" displayName="Hosts File Path" required="true"
- default="/etc/hosts" description="Location of the hosts file."/>
- <c:simple-property name="augeas-hosts-path" displayName="Augeas Hosts Tree Path" required="true"
- default="/files/etc/hosts/*" description="Augeas tree location of the hosts configuration values."/>
- </c:group>
- </plugin-configuration>
-
- <resource-configuration>
- <c:list-property name="entries">
- <c:map-property name="entry">
- <c:simple-property name="ipAddress" displayName="IP Address" type="string" required="true" activationPolicy="immediate"
- description="The IP address of the host entry. The address may be an IPv4 address (e.g., 192.168.1.10) or an IPv6 address (e.g., fec0:0:0:bebe::2)."/>
- <c:simple-property name="canonicalName" displayName="Canonical Host Name" type="string" required="true" activationPolicy="immediate"
- description="The canonical host name to refer to the IP address. Host names may contain only alphanumeric characters, minus signs ('-'), and periods ('.'). They must begin with an alphabetic character and end with an alphanumeric character. (e.g., foo.mydomain.org)"/>
- <c:simple-property name="aliases" displayName="Aliases" type="longString" required="false" activationPolicy="immediate"
- description="Optional aliases provide for name changes, alternate spellings, shorter host names, or generic host names (e.g., localhost); aliases should be newline or space separated)."/>
- </c:map-property>
- </c:list-property>
- </resource-configuration>
-
- </service>
-
-</plugin>
\ No newline at end of file
diff --git a/modules/plugins/hosts-augeas/src/test/java/org/rhq/plugins/hosts/HostsAugeasComponentTest.java b/modules/plugins/hosts-augeas/src/test/java/org/rhq/plugins/hosts/HostsAugeasComponentTest.java
deleted file mode 100644
index 17edecc..0000000
--- a/modules/plugins/hosts-augeas/src/test/java/org/rhq/plugins/hosts/HostsAugeasComponentTest.java
+++ /dev/null
@@ -1,86 +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.plugins.hosts;
-
-import java.util.Collection;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.testng.annotations.BeforeSuite;
-import org.testng.annotations.Test;
-
-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;
-
-/**
- * @author Jason Dobies
- */
-public class HostsAugeasComponentTest {
-
- private HostsAugeasComponent component = new HostsAugeasComponent();
-
- private Configuration pluginConfiguration = new Configuration();
-
- private final Log log = LogFactory.getLog(this.getClass());
-
- @BeforeSuite
- public void initPluginConfiguration() throws Exception {
- pluginConfiguration.put(new PropertySimple("lenses-path", "/usr/local/share/augeas/lenses"));
- pluginConfiguration.put(new PropertySimple("root-path", "/"));
- pluginConfiguration.put(new PropertySimple("hosts-path", "/etc/hosts"));
- pluginConfiguration.put(new PropertySimple("augeas-hosts-path", "/files/etc/hosts/*"));
- }
-
- @Test
- public void loadResourceConfiguration() throws Exception {
- Configuration configuration;
- try {
- configuration = component.loadResourceConfiguration(pluginConfiguration);
- } catch (UnsatisfiedLinkError ule) {
- // Skip tests if augeas not available
- return;
- }
-
- assert configuration != null : "Null configuration returned from load call";
-
- Collection<Property> allProperties = configuration.getProperties();
-
- assert allProperties.size() == 1 : "Incorrect number of properties found. Expected: 1, Found: "
- + allProperties.size();
-
- PropertyList entryList = (PropertyList) allProperties.iterator().next();
-
- for (Property property : entryList.getList()) {
- PropertyMap entry = (PropertyMap) property;
-
- Property ipProperty = entry.get("ip");
- Property canonicalProperty = entry.get("canonical");
-
- assert ipProperty != null : "IP was null in entry";
- assert canonicalProperty != null : "Canonical was null in entry";
-
- log.info("IP: " + ((PropertySimple) ipProperty).getStringValue());
- log.info("Canonical: " + ((PropertySimple) canonicalProperty).getStringValue());
- }
-
- }
-}
diff --git a/modules/plugins/hosts-augeas/src/test/resources/log4j.xml b/modules/plugins/hosts-augeas/src/test/resources/log4j.xml
deleted file mode 100644
index ef41b92..0000000
--- a/modules/plugins/hosts-augeas/src/test/resources/log4j.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
-
- <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
- <param name="Target" value="System.out"/>
- <param name="Threshold" value="DEBUG"/>
-
- <layout class="org.apache.log4j.PatternLayout">
- <!-- The default pattern: Date Priority [Category] Messagen -->
-
- <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
- </layout>
- </appender>
-
- <appender name="FILE" class="org.apache.log4j.RollingFileAppender">
- <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>
-
- <root>
- <appender-ref ref="CONSOLE"/>
- <appender-ref ref="FILE"/>
- </root>
-
-</log4j:configuration>
diff --git a/modules/plugins/hosts/pom.xml b/modules/plugins/hosts/pom.xml
index 3c6522b..2d7452d 100644
--- a/modules/plugins/hosts/pom.xml
+++ b/modules/plugins/hosts/pom.xml
@@ -35,14 +35,6 @@
<artifactId>rhq-augeas-plugin</artifactId>
<version>${project.version}</version>
</dependency>
-
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-augeas-plugin</artifactId>
- <version>${project.version}</version>
- <type>test-jar</type>
- <scope>test</scope>
- </dependency>
</dependencies>
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
index 15374f4..dd29e6e 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
@@ -26,7 +26,10 @@ import java.util.regex.Pattern;
import net.augeas.Augeas;
+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.ConfigurationUpdateStatus;
import org.rhq.core.domain.configuration.Property;
import org.rhq.core.domain.configuration.PropertyList;
import org.rhq.core.domain.configuration.PropertyMap;
@@ -58,6 +61,8 @@ public class HostsComponent extends AugeasConfigurationComponent {
private static final String DOMAIN_NAME_REGEX = "(([a-zA-Z\\d]|[a-zA-Z\\d][a-zA-Z\\d\\-]*[a-zA-Z\\d])\\.)*([A-Za-z]|[A-Za-z][A-Za-z\\d\\-]*[A-Za-z\\d])";
private static final Pattern DOMAIN_NAME_PATTERN = Pattern.compile(DOMAIN_NAME_REGEX);
+ private final Log log = LogFactory.getLog(this.getClass());
+
public void start(ResourceContext resourceContext) throws InvalidPluginConfigurationException, Exception {
super.start(resourceContext);
}
@@ -77,6 +82,8 @@ public class HostsComponent extends AugeasConfigurationComponent {
resourceConfig = super.loadResourceConfiguration();
} else {
resourceConfig = new NonAugeasHostsConfigurationDelegate(this).loadResourceConfiguration();
+ // This will add error messages to any PropertySimples with invalid values, so they can be displayed by the GUI.
+ validateResourceConfiguration(new ConfigurationUpdateReport(resourceConfig));
}
return resourceConfig;
}
@@ -86,6 +93,12 @@ public class HostsComponent extends AugeasConfigurationComponent {
if (getAugeas() != null) {
super.updateResourceConfiguration(report);
} else {
+ if (!validateResourceConfiguration(report)) {
+ log.debug("Validation of updated Resource configuration for " + getResourceDescription()
+ + " failed with the following errors: " + report.getErrorMessage());
+ report.setStatus(ConfigurationUpdateStatus.FAILURE);
+ return;
+ }
new NonAugeasHostsConfigurationDelegate(this).updateResourceConfiguration(report);
}
}
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java
index bfd82a1..a0908b4 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java
@@ -26,23 +26,26 @@ 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.ResourceDiscoveryContext;
+import org.rhq.plugins.augeas.AugeasConfigurationComponent;
import org.rhq.plugins.augeas.AugeasConfigurationDiscoveryComponent;
+import org.rhq.plugins.platform.PlatformComponent;
/**
* The ResourceDiscoveryComponent for the "Hosts File" ResourceType.
*
* @author Ian Springer
*/
-public class HostsDiscoveryComponent extends AugeasConfigurationDiscoveryComponent {
+public class HostsDiscoveryComponent extends AugeasConfigurationDiscoveryComponent<PlatformComponent> {
private static final boolean IS_WINDOWS = (File.separatorChar == '\\');
private final Log log = LogFactory.getLog(this.getClass());
@Override
- public Set discoverResources(ResourceDiscoveryContext discoveryContext) throws InvalidPluginConfigurationException,
+ public Set discoverResources(ResourceDiscoveryContext<PlatformComponent> discoveryContext) throws InvalidPluginConfigurationException,
Exception
{
return super.discoverResources(discoveryContext);
@@ -56,24 +59,25 @@ public class HostsDiscoveryComponent extends AugeasConfigurationDiscoveryCompone
}
@Override
- protected List<String> determineIncludeGlobs(ResourceDiscoveryContext discoveryContext)
+ protected List<String> determineIncludeGlobs(ResourceDiscoveryContext<PlatformComponent> discoveryContext)
{
- File hostsFile;
- if (IS_WINDOWS) {
- File windowsDir = getWindowsDir();
- hostsFile = new File(windowsDir, "system32/drivers/etc/hosts");
+ Configuration defaultPluginConfig = discoveryContext.getDefaultPluginConfiguration();
+ String includeGlobs = defaultPluginConfig.getSimpleValue(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP, null);
+ if (includeGlobs != null) {
+ return super.determineIncludeGlobs(discoveryContext);
} else {
- hostsFile = new File("/etc/hosts");
- }
- return Collections.singletonList(hostsFile.getAbsolutePath());
- }
-
- @Override
- protected List<String> determineExcludeGlobs(ResourceDiscoveryContext discoveryContext) {
- return null;
+ File hostsFile;
+ if (IS_WINDOWS) {
+ File windowsDir = getWindowsDir(discoveryContext);
+ hostsFile = new File(windowsDir, "system32/drivers/etc/hosts");
+ } else {
+ hostsFile = new File("/etc/hosts");
+ }
+ return Collections.singletonList(hostsFile.getPath());
+ }
}
- private File getWindowsDir() {
+ private File getWindowsDir(ResourceDiscoveryContext<PlatformComponent> discoveryContext) {
File windowsDir = null;
String windowsDirPath = System.getenv().get("SystemRoot");
if (windowsDirPath != null) {
@@ -97,6 +101,7 @@ public class HostsDiscoveryComponent extends AugeasConfigurationDiscoveryCompone
if (windowsDir == null) {
throw new IllegalStateException("Failed to determine Windows directory.");
}
+
log.debug("Windows directory: " + windowsDir);
return windowsDir;
}
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/Hosts.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/Hosts.java
index 85f3255..8b3c61f 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/Hosts.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/Hosts.java
@@ -37,12 +37,10 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
- * A set of hosts file entries. The set may contain duplicate entries (i.e. entries for different IP addresses
- * containing the same name, either as the canonical name or as an alias).
+ * A set of hosts file entries.
*
* @author Ian Springer
*/
@@ -50,39 +48,25 @@ public class Hosts {
private static final Log LOG = LogFactory.getLog(Hosts.class);
private Set<HostsEntry> entries = new LinkedHashSet<HostsEntry>();
- private Map<String, Set<HostsEntry>> ipAddressToEntriesMap = new HashMap<String, Set<HostsEntry>>();
- private Map<String, Set<HostsEntry>> nameToEntriesMap = new HashMap<String, Set<HostsEntry>>();
- private Set<String> namesWithDuplicateEntries = new HashSet<String>();
- private Set<String> ipAddressesWithDuplicateEntries = new HashSet<String>();
+ private Map<String, Set<HostsEntry>> nameToIpv4EntriesMap = new HashMap<String, Set<HostsEntry>>();
+ private Map<String, Set<HostsEntry>> nameToIpv6EntriesMap = new HashMap<String, Set<HostsEntry>>();
public Hosts() {
}
public void addEntry(HostsEntry entry) {
this.entries.add(entry);
- String ipAddress = entry.getIpAddress();
- Set<HostsEntry> entriesForIpAddress = this.ipAddressToEntriesMap.get(ipAddress);
- if (entriesForIpAddress == null) {
- entriesForIpAddress = new LinkedHashSet(1);
- this.ipAddressToEntriesMap.put(ipAddress, entriesForIpAddress);
- } else {
- this.ipAddressesWithDuplicateEntries.add(ipAddress);
- }
- entriesForIpAddress.add(entry);
String canonicalName = entry.getCanonicalName();
- updateNameToEntriesMap(entry, canonicalName);
- for (String alias : entry.getAliases()) {
- updateNameToEntriesMap(entry, alias);
- }
+ updateNameToEntriesMaps(entry, canonicalName);
}
- private void updateNameToEntriesMap(HostsEntry entry, String canonicalName) {
- Set<HostsEntry> entriesForCanonicalName = this.nameToEntriesMap.get(canonicalName);
+ private void updateNameToEntriesMaps(HostsEntry entry, String canonicalName) {
+ Map<String, Set<HostsEntry>> nameToEntriesMap = (entry.getIpVersion() == 4) ?
+ this.nameToIpv4EntriesMap : this.nameToIpv6EntriesMap;
+ Set<HostsEntry> entriesForCanonicalName = nameToEntriesMap.get(canonicalName);
if (entriesForCanonicalName == null) {
entriesForCanonicalName = new LinkedHashSet(1);
- this.nameToEntriesMap.put(canonicalName, entriesForCanonicalName);
- } else {
- this.namesWithDuplicateEntries.add(canonicalName);
+ nameToEntriesMap.put(canonicalName, entriesForCanonicalName);
}
entriesForCanonicalName.add(entry);
}
@@ -91,25 +75,16 @@ public class Hosts {
return this.entries;
}
- @NotNull
- public Set<HostsEntry> getEntriesByIpAddress(String ipAddress) {
- Set<HostsEntry> entries = this.ipAddressToEntriesMap.get(ipAddress);
+ public Set<HostsEntry> getIpv4EntriesByName(String canonicalName) {
+ Set<HostsEntry> entries = this.nameToIpv4EntriesMap.get(canonicalName);
return (entries != null) ? entries : Collections.<HostsEntry> emptySet();
}
- public Set<HostsEntry> getEntriesByName(String canonicalName) {
- Set<HostsEntry> entries = this.nameToEntriesMap.get(canonicalName);
+ public Set<HostsEntry> getIpv6EntriesByName(String canonicalName) {
+ Set<HostsEntry> entries = this.nameToIpv6EntriesMap.get(canonicalName);
return (entries != null) ? entries : Collections.<HostsEntry> emptySet();
}
- public Set<String> getIpAddressesWithDuplicateEntries() {
- return this.ipAddressesWithDuplicateEntries;
- }
-
- public Set<String> getNamesWithDuplicateEntries() {
- return this.namesWithDuplicateEntries;
- }
-
public static Hosts load(File hostsFile) throws IOException {
Hosts hosts = new Hosts();
SimpleUnixConfigFileReader reader = new SimpleUnixConfigFileReader(new FileReader(hostsFile));
@@ -130,19 +105,14 @@ public class Hosts {
}
public static void store(Hosts hosts, File hostsFile) throws IOException {
- // Set<String> namesWithDuplicateEntries = hosts.getNamesWithDuplicateEntries();
- // if (!namesWithDuplicateEntries.isEmpty()) {
- // throw new IllegalArgumentException("Hosts contains duplicate entries for the following names: "
- // + namesWithDuplicateEntries);
- // }
-
if (!hostsFile.exists()) {
// If a hosts file doesn't already exist, create an empty one.
FileOutputStream hostsFileWriter = new FileOutputStream(hostsFile);
hostsFileWriter.close();
}
- Set<String> storedCanonicalNames = new HashSet<String>();
+ Set<String> storedIpv4CanonicalNames = new HashSet<String>();
+ Set<String> storedIpv6CanonicalNames = new HashSet<String>();
File newHostsFile = new File(hostsFile.getPath() + "-" + System.currentTimeMillis());
PrintWriter newHostsFileWriter = new PrintWriter(new FileWriter(newHostsFile));
try {
@@ -150,7 +120,8 @@ public class Hosts {
SimpleUnixConfigFileReader hostsFileReader = new SimpleUnixConfigFileReader(new FileReader(hostsFile));
try {
while ((line = hostsFileReader.readLine()) != null) {
- StringBuilder newLine = createNewLine(hosts, hostsFile, line, storedCanonicalNames);
+ StringBuilder newLine = createNewLine(hosts, hostsFile, line, storedIpv4CanonicalNames,
+ storedIpv6CanonicalNames);
if (newLine != null) {
newHostsFileWriter.println(newLine);
}
@@ -161,6 +132,8 @@ public class Hosts {
// Write out any entries for IP addresses that did not have entries in the original file.
for (HostsEntry newEntry : hosts.getEntries()) {
+ Set<String> storedCanonicalNames = (newEntry.getIpVersion() == 4) ? storedIpv4CanonicalNames :
+ storedIpv6CanonicalNames;
if (!storedCanonicalNames.contains(newEntry.getCanonicalName())) {
StringBuilder newLine = new StringBuilder(newEntry.getIpAddress()).append("\t").append(
newEntry.getCanonicalName());
@@ -240,13 +213,16 @@ public class Hosts {
@Nullable
private static StringBuilder createNewLine(Hosts hosts, File hostsFile, SimpleUnixConfigFileLine existingLine,
- Set<String> storedCanonicalNames) {
+ Set<String> storedIpv4CanonicalNames,
+ Set<String> storedIpv6CanonicalNames) {
StringBuilder newLine;
String nonComment = existingLine.getNonComment();
String comment = existingLine.getComment();
HostsEntry existingEntry = parseEntry(nonComment, hostsFile);
if (existingEntry != null) {
- Set<HostsEntry> newEntries = hosts.getEntriesByName(existingEntry.getCanonicalName());
+ Set<HostsEntry> newEntries = (existingEntry.getIpVersion() == 4) ?
+ hosts.getIpv4EntriesByName(existingEntry.getCanonicalName()) :
+ hosts.getIpv6EntriesByName(existingEntry.getCanonicalName());
// TODO: Look up entries for existing entry's aliases too?
if (!newEntries.isEmpty()) {
// replace the existing entry
@@ -261,6 +237,8 @@ public class Hosts {
if (comment != null) {
newLine.append(" #").append(comment);
}
+ Set<String> storedCanonicalNames = (newEntry.getIpVersion() == 4) ? storedIpv4CanonicalNames :
+ storedIpv6CanonicalNames;
storedCanonicalNames.add(newEntry.getCanonicalName());
} else {
LOG.debug("Removing entry [" + existingEntry + "] from hosts file...");
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/HostsEntry.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/HostsEntry.java
index e37b3d2..6c6ad92 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/HostsEntry.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/HostsEntry.java
@@ -30,6 +30,7 @@ import java.util.Set;
*/
public class HostsEntry {
private String ipAddress;
+ private int ipVersion;
private String canonicalName;
private Set<String> aliases;
@@ -38,6 +39,7 @@ public class HostsEntry {
throw new IllegalArgumentException("ipAddress parameter is null.");
}
this.ipAddress = ipAddress;
+ this.ipVersion = (this.ipAddress.indexOf(':') == -1) ? 4 : 6;
if (canonicalName == null) {
throw new IllegalArgumentException("canonicalName parameter is null.");
}
@@ -49,6 +51,11 @@ public class HostsEntry {
return ipAddress;
}
+ public int getIpVersion()
+ {
+ return ipVersion;
+ }
+
public String getCanonicalName() {
return canonicalName;
}
@@ -56,4 +63,10 @@ public class HostsEntry {
public Set<String> getAliases() {
return aliases;
}
+
+ @Override
+ public String toString()
+ {
+ return this.ipAddress + " " + this.getCanonicalName() + " " + this.aliases;
+ }
}
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java
index 8856938..731e532 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java
@@ -24,8 +24,6 @@ import java.util.Date;
import java.util.LinkedHashSet;
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.ConfigurationUpdateStatus;
import org.rhq.core.domain.configuration.Property;
@@ -41,8 +39,6 @@ import org.rhq.plugins.hosts.HostsComponent;
*/
public class NonAugeasHostsConfigurationDelegate implements ConfigurationFacet
{
- private final Log log = LogFactory.getLog(this.getClass());
-
private HostsComponent hostsComponent;
public NonAugeasHostsConfigurationDelegate(HostsComponent hostsComponent) {
@@ -58,54 +54,28 @@ public class NonAugeasHostsConfigurationDelegate implements ConfigurationFacet
PropertyList entriesProp = new PropertyList(".");
resourceConfig.put(entriesProp);
- Set<String> ipAddressesWithDuplicateEntries = hosts.getIpAddressesWithDuplicateEntries();
- if (!ipAddressesWithDuplicateEntries.isEmpty()) {
- log.debug("Hosts file [" + hostsFile + "] contains duplicate entries for the following IP addresses: "
- + ipAddressesWithDuplicateEntries);
- }
- Set<String> namesWithDuplicateEntries = hosts.getNamesWithDuplicateEntries();
- if (!namesWithDuplicateEntries.isEmpty()) {
- log.error("Hosts file [" + hostsFile + "] contains duplicate entries for the following names: "
- + namesWithDuplicateEntries);
- }
-
for (HostsEntry entry : hosts.getEntries()) {
- PropertyMap entryProp = new PropertyMap("entry");
+ PropertyMap entryProp = new PropertyMap("*[canonical]");
entriesProp.add(entryProp);
- PropertySimple ipAddressProp = new PropertySimple("ipaddr", entry.getIpAddress());
- entryProp.put(ipAddressProp);
-
- PropertySimple canonicalNameProp = new PropertySimple("canonical", entry.getCanonicalName());
- if (namesWithDuplicateEntries.contains(entry.getCanonicalName())) {
- canonicalNameProp.setErrorMessage("At the time of loading, there was more than one entry containing this name - please remove or fix duplicate entries before saving.");
- }
- entryProp.put(canonicalNameProp);
-
- StringBuilder aliasesPropValue = new StringBuilder();
- boolean foundDuplicateName = false;
+ entryProp.put(new PropertySimple("ipaddr", entry.getIpAddress()));
+ entryProp.put(new PropertySimple("canonical", entry.getCanonicalName()));
+ StringBuilder aliasPropValue = new StringBuilder();
for (String alias : entry.getAliases()) {
- if (namesWithDuplicateEntries.contains(alias)) {
- foundDuplicateName = true;
- }
- aliasesPropValue.append(alias).append("\n");
+ aliasPropValue.append(alias).append("\n");
}
if (!entry.getAliases().isEmpty()) {
// Chop the final newline char.
- aliasesPropValue.deleteCharAt(aliasesPropValue.length() - 1);
- }
- PropertySimple aliasesProp = new PropertySimple("alias", aliasesPropValue);
- if (foundDuplicateName) {
- aliasesProp.setErrorMessage("At the time of loading, there was more than one entry containing this name - please remove or fix duplicate entries before saving.");
+ aliasPropValue.deleteCharAt(aliasPropValue.length() - 1);
}
- entryProp.put(aliasesProp);
+ entryProp.put(new PropertySimple("alias", aliasPropValue));
}
return resourceConfig;
}
public void updateResourceConfiguration(ConfigurationUpdateReport report) {
- Configuration resourceConfig = report.getConfiguration();
+ Configuration resourceConfig = report.getConfiguration();
Hosts newHosts = new Hosts();
PropertyList entriesProp = resourceConfig.getList(".");
@@ -128,13 +98,6 @@ public class NonAugeasHostsConfigurationDelegate implements ConfigurationFacet
newHosts.addEntry(entry);
}
- Set<String> namesWithDuplicateEntries = newHosts.getNamesWithDuplicateEntries();
- if (!namesWithDuplicateEntries.isEmpty()) {
- report.setErrorMessage("There are duplicate entries for the following names: "
- + namesWithDuplicateEntries);
- return;
- }
-
File hostsFile = (File)this.hostsComponent.getConfigurationFiles().get(0);
try {
Hosts.store(newHosts, hostsFile);
diff --git a/modules/plugins/hosts/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/hosts/src/main/resources/META-INF/rhq-plugin.xml
index eeeb667..a2aef3d 100644
--- a/modules/plugins/hosts/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/hosts/src/main/resources/META-INF/rhq-plugin.xml
@@ -29,10 +29,11 @@
<plugin-configuration>
<c:simple-property name="augeasModuleName" displayName="Augeas Module Name" default="Hosts" required="true" readOnly="true"
- description="the name of the Augeas module/lens to use for loading and updating this resource's configuration"/>
+ description="the name of the Augeas module/lens to use for loading and updating this Resource's configuration"/>
- <c:simple-property name="configurationFilesInclusionPatterns" displayName="Configuration File Paths" required="true" readOnly="true"
- description="the absolute paths of the configuration files, delimited with pipe characters"/>
+ <c:simple-property name="configurationFilesInclusionPatterns"
+ default="/etc/hosts" required="true" readOnly="true"
+ description="the absolute paths of the configuration files, delimited with pipe characters; wildcards are permitted in the last component of the path (e.g. /etc/cron.d/*)"/>
</plugin-configuration>
<resource-configuration>
diff --git a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
index fcaaa7e..6ac7011 100644
--- a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
+++ b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2009 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -18,11 +18,16 @@
*/
package org.rhq.plugins.hosts;
+import java.io.File;
+import java.io.IOException;
+
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.plugins.augeas.AbstractAugeasConfigurationComponentTest;
+import org.rhq.plugins.augeas.AugeasConfigurationComponent;
+import org.rhq.plugins.augeas.test.AbstractAugeasConfigurationComponentTest;
+import org.testng.annotations.BeforeTest;
/**
* An integration test for {@link HostsComponent}.
@@ -30,14 +35,38 @@ import org.rhq.plugins.augeas.AbstractAugeasConfigurationComponentTest;
* @author Ian Springer
*/
public class HostsComponentTest extends AbstractAugeasConfigurationComponentTest {
+ private static final String PLUGIN_NAME = "Hosts";
+ private static final String RESOURCE_TYPE_NAME = "Hosts File";
+
@Override
protected String getPluginName() {
- return "Hosts";
+ return PLUGIN_NAME;
}
@Override
protected String getResourceTypeName() {
- return "Hosts File";
+ return RESOURCE_TYPE_NAME;
+ }
+
+ @Override
+ protected boolean isResourceConfigSupported() {
+ // The hosts plugin will use Augeas if it's available but will fall back to direct file parsing if it's not.
+ return true;
+ }
+
+ @Override
+ protected void tweakDefaultPluginConfig(Configuration defaultPluginConfig)
+ {
+ super.tweakDefaultPluginConfig(defaultPluginConfig);
+ String hostsFilePath = new File("/etc/hosts").getAbsolutePath();
+ defaultPluginConfig.put(new PropertySimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP, hostsFilePath));
+ }
+
+ @BeforeTest
+ @Override
+ public void resetConfigFiles() throws IOException
+ {
+ super.resetConfigFiles();
}
@Override
@@ -82,7 +111,7 @@ public class HostsComponentTest extends AbstractAugeasConfigurationComponentTest
}
@Override
- protected Configuration getChangedResourceConfig() {
+ protected Configuration getUpdatedResourceConfig() {
Configuration config = new Configuration();
PropertyList entries = new PropertyList(".");
config.put(entries);
diff --git a/modules/plugins/hosts/src/test/resources/log4j.xml b/modules/plugins/hosts/src/test/resources/log4j.xml
index 65b7562..8ec981a 100644
--- a/modules/plugins/hosts/src/test/resources/log4j.xml
+++ b/modules/plugins/hosts/src/test/resources/log4j.xml
@@ -25,7 +25,14 @@
</layout>
</appender>
+ <category name="org.rhq.plugins">
+ <priority value="DEBUG"/>
+ </category>
+
<root>
+ <!-- default log priority -->
+ <priority value="INFO"/>
+
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index e78033b..31c5bb9 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -117,6 +117,7 @@
<module>perftest</module>
<module>samba</module>
<module>postfix</module>
+ <module>aliases</module>
<module>snmptrapd</module>
<module>sshd</module>
<module>twitter</module>
diff --git a/modules/plugins/postfix/pom.xml b/modules/plugins/postfix/pom.xml
index 15ffac1..ff5acc4 100644
--- a/modules/plugins/postfix/pom.xml
+++ b/modules/plugins/postfix/pom.xml
@@ -25,25 +25,12 @@
</properties>
<dependencies>
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-platform-plugin</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
+
+ <dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-augeas-plugin</artifactId>
<version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-augeas-plugin</artifactId>
- <version>${project.version}</version>
- <type>test-jar</type>
- <scope>test</scope>
- </dependency>
-
+ </dependency>
</dependencies>
diff --git a/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml
index 87ddf64..9fce0e1 100644
--- a/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml
@@ -37,7 +37,7 @@
<c:simple-property displayName="Banner" name="smtpd_banner" description="SMTP Banner (RFC requires hostname and ESMTP prompt)" default="$myhostname ESMTP" required="true"/>
</c:group>
<c:group name="Security">
- <c:simple-property displayName="Supress VRFY" name="disable_vrfy_command" type="boolean" default="true" required="false" description="Supress Response to SMTP VRFY requests by default"/>
+ <c:simple-property displayName="Suppress VRFY" name="disable_vrfy_command" type="boolean" default="true" required="false" description="Supress Response to SMTP VRFY requests by default"/>
<c:simple-property displayName="Force HELO" name="smtpd_helo_required" type="boolean" default="true" required="false" description="Force clients to start connection with HELO"/>
<c:simple-property displayName="Always send EHLO" name="smtp_always_send_ehlo" type="boolean" default="true" required="true" description="Always send a correct EHLO greeting"/>
<c:simple-property displayName="In Flow Delay" name="in_flow_delay" required="false" description="Number of seconds to delay before accepting messages if arriving faster than delivering"/>
@@ -45,7 +45,6 @@
</c:group>
</resource-configuration>
-
</server>
</plugin>
diff --git a/modules/plugins/postfix/src/test/resources/log4j.xml b/modules/plugins/postfix/src/test/resources/log4j.xml
index ef41b92..8ec981a 100644
--- a/modules/plugins/postfix/src/test/resources/log4j.xml
+++ b/modules/plugins/postfix/src/test/resources/log4j.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
+
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
- <param name="Threshold" value="DEBUG"/>
+ <param name="Threshold" value="ERROR"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Messagen -->
@@ -24,7 +25,14 @@
</layout>
</appender>
+ <category name="org.rhq.plugins">
+ <priority value="DEBUG"/>
+ </category>
+
<root>
+ <!-- default log priority -->
+ <priority value="INFO"/>
+
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
diff --git a/modules/plugins/samba/pom.xml b/modules/plugins/samba/pom.xml
index c93989f..d1376a8 100644
--- a/modules/plugins/samba/pom.xml
+++ b/modules/plugins/samba/pom.xml
@@ -25,25 +25,12 @@
</properties>
<dependencies>
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-platform-plugin</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
+
+ <dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-augeas-plugin</artifactId>
<version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-augeas-plugin</artifactId>
- <version>${project.version}</version>
- <type>test-jar</type>
- <scope>test</scope>
- </dependency>
-
+ </dependency>
</dependencies>
diff --git a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
index 3a091e6..d5836ef 100644
--- a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
+++ b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
@@ -20,7 +20,7 @@ package org.rhq.plugins.samba;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
-import org.rhq.plugins.augeas.AbstractAugeasConfigurationComponentTest;
+import org.rhq.plugins.augeas.test.AbstractAugeasConfigurationComponentTest;
public class SambaComponentTest extends AbstractAugeasConfigurationComponentTest {
@@ -48,7 +48,7 @@ public class SambaComponentTest extends AbstractAugeasConfigurationComponentTest
}
@Override
- protected Configuration getChangedResourceConfig() {
+ protected Configuration getUpdatedResourceConfig() {
Configuration config = new Configuration();
config.put(new PropertySimple("workgroup", "DUMBCHANGE"));
diff --git a/modules/plugins/samba/src/test/resources/log4j.xml b/modules/plugins/samba/src/test/resources/log4j.xml
index ef41b92..8ec981a 100644
--- a/modules/plugins/samba/src/test/resources/log4j.xml
+++ b/modules/plugins/samba/src/test/resources/log4j.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
+
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
- <param name="Threshold" value="DEBUG"/>
+ <param name="Threshold" value="ERROR"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Messagen -->
@@ -24,7 +25,14 @@
</layout>
</appender>
+ <category name="org.rhq.plugins">
+ <priority value="DEBUG"/>
+ </category>
+
<root>
+ <!-- default log priority -->
+ <priority value="INFO"/>
+
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
diff --git a/modules/plugins/sudoers/pom.xml b/modules/plugins/sudoers/pom.xml
index ae7960b..28fbed5 100644
--- a/modules/plugins/sudoers/pom.xml
+++ b/modules/plugins/sudoers/pom.xml
@@ -25,25 +25,13 @@
</properties>
<dependencies>
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-platform-plugin</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
-
+
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-augeas-plugin</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-augeas-plugin</artifactId>
- <version>${project.version}</version>
- <type>test-jar</type>
- <scope>test</scope>
- </dependency>
+
</dependencies>
<profiles>
diff --git a/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java b/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
index 943455d..109e118 100644
--- a/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
+++ b/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
@@ -22,7 +22,7 @@ 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.plugins.augeas.AbstractAugeasConfigurationComponentTest;
+import org.rhq.plugins.augeas.test.AbstractAugeasConfigurationComponentTest;
/**
* @author Partha Aji
@@ -70,7 +70,7 @@ public class SudoersComponentTest extends AbstractAugeasConfigurationComponentTe
}
@Override
- protected Configuration getChangedResourceConfig() {
+ protected Configuration getUpdatedResourceConfig() {
Configuration config = new Configuration();
PropertyList entries = new PropertyList(".");
config.put(entries);
diff --git a/modules/plugins/sudoers/src/test/resources/log4j.xml b/modules/plugins/sudoers/src/test/resources/log4j.xml
index ef41b92..8ec981a 100644
--- a/modules/plugins/sudoers/src/test/resources/log4j.xml
+++ b/modules/plugins/sudoers/src/test/resources/log4j.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
+
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
- <param name="Threshold" value="DEBUG"/>
+ <param name="Threshold" value="ERROR"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Messagen -->
@@ -24,7 +25,14 @@
</layout>
</appender>
+ <category name="org.rhq.plugins">
+ <priority value="DEBUG"/>
+ </category>
+
<root>
+ <!-- default log priority -->
+ <priority value="INFO"/>
+
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
commit 0bab4196326bc4468d7550caffc42a918200568d
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Thu Nov 12 18:49:15 2009 -0500
800 - Work towards the ability to import candidate repos. Still need error handling when the import fails.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
index 8fe6b63..9eb3a35 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
@@ -61,6 +61,7 @@ import org.rhq.core.domain.resource.Resource;
@NamedQuery(name = Repo.QUERY_FIND_BY_NAME, query = "SELECT c FROM Repo c WHERE c.name = :name"),
@NamedQuery(name = Repo.QUERY_FIND_IMPORTED_BY_CONTENT_SOURCE_ID_FETCH_CCS, query = "SELECT c FROM Repo c LEFT JOIN FETCH c.repoContentSources ccs WHERE ccs.contentSource.id = :id AND c.candidate = false"),
@NamedQuery(name = Repo.QUERY_FIND_IMPORTED_BY_CONTENT_SOURCE_ID, query = "SELECT c FROM Repo c LEFT JOIN c.repoContentSources ccs WHERE ccs.contentSource.id = :id AND c.candidate = false"),
+ @NamedQuery(name = Repo.QUERY_FIND_CANDIDATE_BY_CONTENT_SOURCE_ID, query = "SELECT c FROM Repo c LEFT JOIN c.repoContentSources ccs WHERE ccs.contentSource.id = :id AND c.candidate = true"),
@NamedQuery(name = Repo.QUERY_FIND_SUBSCRIBER_RESOURCES, query = "SELECT rc.resource FROM ResourceRepo rc WHERE rc.repo.id = :id"),
@NamedQuery(name = Repo.QUERY_FIND_REPOS_BY_RESOURCE_ID, query = "SELECT c "
+ "FROM ResourceRepo rc JOIN rc.repo c WHERE rc.resource.id = :resourceId "),
@@ -97,6 +98,7 @@ public class Repo implements Serializable, Taggable {
public static final String QUERY_FIND_BY_NAME = "Repo.findByName";
public static final String QUERY_FIND_IMPORTED_BY_CONTENT_SOURCE_ID_FETCH_CCS = "Repo.findByContentSourceIdFetchCCS";
public static final String QUERY_FIND_IMPORTED_BY_CONTENT_SOURCE_ID = "Repo.findByContentSourceId";
+ public static final String QUERY_FIND_CANDIDATE_BY_CONTENT_SOURCE_ID = "Repo.findCandidateByContentSourceId";
public static final String QUERY_FIND_SUBSCRIBER_RESOURCES = "Repo.findSubscriberResources";
public static final String QUERY_FIND_REPOS_BY_RESOURCE_ID = "Repo.findReposByResourceId";
public static final String QUERY_FIND_REPO_COMPOSITES_BY_RESOURCE_ID = "Repo.findRepoCompositesByResourceId";
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
index 42edf8b..14b931f 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
@@ -38,6 +38,8 @@ import org.rhq.enterprise.gui.common.paging.PageControlView;
import org.rhq.enterprise.gui.common.paging.PagedListDataModel;
import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
+import org.rhq.enterprise.server.content.RepoManagerLocal;
+import org.rhq.enterprise.server.content.RepoException;
import org.rhq.enterprise.server.util.LookupUtil;
/**
@@ -96,8 +98,23 @@ public class RepoImportUIBean extends PagedDataTableUIBean {
}
public String importSelected() {
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
String[] selected = getSelectedRepos();
- // TODO: Actually import the repos using a manager bean.
+
+ List<Integer> repoIds = new ArrayList<Integer>(selected.length);
+
+ for (String sRepoId : selected) {
+ repoIds.add(Integer.valueOf(sRepoId));
+ }
+
+ RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
+ try {
+ repoManager.importCandidateRepo(subject, repoIds);
+ }
+ catch (RepoException e) {
+ // TODO: Handle
+ }
+
return "success";
}
@@ -110,8 +127,8 @@ public class RepoImportUIBean extends PagedDataTableUIBean {
public PageList<Repo> fetchPage(PageControl pc) {
Subject subject = EnterpriseFacesContextUtility.getSubject();
ContentSourceManagerLocal manager = LookupUtil.getContentSourceManager();
- // TODO: Replace with call to get 'candidate' repos for provider.
- PageList<Repo> results = manager.getAssociatedRepos(subject, selectedProvider, pc);
+ PageList<Repo> results = manager.getCandidateRepos(subject, selectedProvider, pc);
+
return results;
}
}
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/content-navigation.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/content-navigation.xml
index 0910c04..3e9e4f4 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/content-navigation.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/content-navigation.xml
@@ -216,6 +216,25 @@
</navigation-rule>
+ <navigation-rule>
+ <from-view-id>/rhq/content/importRepos.xhtml</from-view-id>
+
+ <navigation-case>
+ <!-- catch all navigation-case: if any actions return 'success', go here -->
+ <from-outcome>success</from-outcome>
+ <to-view-id>/rhq/content/listRepos.xhtml</to-view-id>
+ <redirect/>
+ </navigation-case>
+
+ <navigation-case>
+ <!-- sorting rule -->
+ <from-outcome>sort</from-outcome>
+ <to-view-id>/rhq/content/importRepos.xhtml</to-view-id>
+ <redirect/>
+ </navigation-case>
+
+ </navigation-rule>
+
<!-- Repo View -->
<navigation-rule>
<from-view-id>/rhq/content/repo.xhtml</from-view-id>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml
index bcc0c8c..a29ca9f 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml
@@ -80,7 +80,7 @@
</rich:column>
<rich:column rendered="#{param.debug}">
<f:facet name="header">
- <onc:sortableColumnHeader sort="cs.id">
+ <onc:sortableColumnHeader sort="c.id">
<h:outputText styleClass="headerText" value="ID" />
</onc:sortableColumnHeader>
</f:facet>
@@ -88,7 +88,7 @@
</rich:column>
<rich:column>
<f:facet name="header">
- <onc:sortableColumnHeader sort="cs.name">
+ <onc:sortableColumnHeader sort="c.name">
<h:outputText styleClass="headerText" value="Name" />
</onc:sortableColumnHeader>
</f:facet>
@@ -104,7 +104,7 @@
<rich:column colspan="#{param.debug ? 6 : 5}" width="100%">
<onc:selectCommandButton action="#{RepoImportUIBean.importSelected}"
value="IMPORT SELECTED"
- target="selectedReposa"
+ target="selectedRepos"
styleClass="on-pager-button buttonsmall"/>
<ui:param name="paginationDataTableName" value="repoTable"/>
<ui:param name="paginationDataModel" value="#{repoModel}"/>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
index fc2e1f3..73b1fcf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
@@ -323,6 +323,22 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
return new PageList<Repo>(results, (int) count, pc);
}
+ public PageList<Repo> getCandidateRepos(Subject subject, int contentSourceId, PageControl pc) {
+ pc.initDefaultOrderingField("c.name");
+
+ Query query = PersistenceUtility
+ .createQueryWithOrderBy(entityManager, Repo.QUERY_FIND_CANDIDATE_BY_CONTENT_SOURCE_ID, pc);
+ Query countQuery = PersistenceUtility.createCountQuery(entityManager, Repo.QUERY_FIND_CANDIDATE_BY_CONTENT_SOURCE_ID);
+
+ query.setParameter("id", contentSourceId);
+ countQuery.setParameter("id", contentSourceId);
+
+ List<Repo> results = query.getResultList();
+ long count = (Long) countQuery.getSingleResult();
+
+ return new PageList<Repo>(results, (int) count, pc);
+ }
+
@SuppressWarnings("unchecked")
@RequiredPermission(Permission.MANAGE_INVENTORY)
public PageList<ContentSourceSyncResults> getContentSourceSyncResults(Subject subject, int contentSourceId,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java
index bf5312d..98be5ff 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java
@@ -130,17 +130,28 @@ public interface ContentSourceManagerLocal {
ContentSource getContentSourceByNameAndType(Subject subject, String name, String typeName);
/**
- * Gets the list of repos that are associated with a given content source.
+ * Gets the list of imported repos that are associated with a given content source.
*
- * @param subject user asking to perform this
- * @param contentSourceId The id of a content source.
- * @param pc pagination controls
+ * @param subject user asking to perform this
+ * @param contentSourceId the id of a content source.
+ * @param pc pagination controls
*
* @return list of associated repos
*/
PageList<Repo> getAssociatedRepos(Subject subject, int contentSourceId, PageControl pc);
/**
+ * Gets the list of candidate repos that are associated with a given content source.
+ *
+ * @param subject user asking to perform this
+ * @param contentSourceId the id of a content source.
+ * @param pc pagination controls
+ *
+ * @return list of candidate repos
+ */
+ PageList<Repo> getCandidateRepos(Subject subject, int contentSourceId, PageControl pc);
+
+ /**
* Allows the caller to page through a list of historical sync results for a content source.
*
* @param subject user asking to perform this
commit f6d790e73caa5c3714768660656da69fb49e2653
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 18:42:51 2009 -0500
Squashed commit of the following:
commit 4176765871d06b37895dc72269233687325eaa87
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 17:20:20 2009 -0500
get the plugin jobs to be scheduled properly in quartz
commit 08644de029a313e09673870395bf0a5f8607098b
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 11:47:39 2009 -0500
fix the operation names in the rhq server plugin
commit 8075b0b26d1c2514ff7a1c831491a51d8a2909c8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 03:22:06 2009 -0500
Squashed commit of the following:
commit d3dfc1a52b0414bd67f50ed9c881c8c3e33e9a1e
Merge: 2cd6ba1 ad45fe5
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 22:38:00 2009 -0500
Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq
commit 2cd6ba182ee07849e2ccd06be6c962b879f45112
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 16:33:18 2009 -0500
Allow clean install to still copy over the license file.
This patch moves the license file from the server container module to the ear module. It is copied over in the dev profile only.
commit 9d93844a860e54c2a012644975ccee198c76f9a6
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 02:53:23 2009 -0500
actually schedule the jobs in quartz
commit 25c0a3e27d9969368230277cb5a33633dbbdb897
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 02:06:54 2009 -0500
add plugin context to the job interface
commit c14822a979ab9e130dfc08279ae6ca342bd591bf
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 01:45:23 2009 -0500
provide an API to schedule jobs
diff --git a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
index a2deeef..de99b3a 100644
--- a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
+++ b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
@@ -19,6 +19,9 @@
package org.custom;
+import java.util.Properties;
+
+import org.rhq.enterprise.server.plugin.pc.ScheduledJob;
import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
@@ -26,7 +29,7 @@ import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
* A sample lifecycle listener for the sample generic plugin. This listener will be
* the main interface the server uses to start and stop the plugin.
*/
-public class MyLifecycleListener implements ServerPluginLifecycleListener {
+public class MyLifecycleListener implements ServerPluginLifecycleListener, ScheduledJob {
private ServerPluginContext context;
@@ -48,6 +51,12 @@ public class MyLifecycleListener implements ServerPluginLifecycleListener {
}
@Override
+ public void execute(String jobId, ServerPluginLifecycleListener lifecycleListener, Properties callbackData)
+ throws Exception {
+ System.out.println("The sample plugin scheduled job [" + jobId + "] has triggered!!! : " + this);
+ }
+
+ @Override
public String toString() {
if (this.context == null) {
return "<no context>";
diff --git a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
index 1e48ef8..57f19cc 100644
--- a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -10,11 +10,15 @@
xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
xmlns:c="urn:xmlns:rhq-configuration">
- <serverplugin:lifecycle-listener class="MyLifecycleListener">
- </serverplugin:lifecycle-listener>
+ <serverplugin:lifecycle-listener class="MyLifecycleListener">
+ <serverplugin:schedule concurrent="true">
+ <serverplugin:period>30000</serverplugin:period>
+ </serverplugin:schedule>
+ </serverplugin:lifecycle-listener>
- <serverplugin:plugin-configuration>
- <c:simple-property name="myCustomProperty" type="string" required="true" description="A property my plugin needs to be properly configured" />
- </serverplugin:plugin-configuration>
+ <serverplugin:plugin-configuration>
+ <c:simple-property name="myCustomProperty" type="string" required="true"
+ description="A property my plugin needs to be properly configured" />
+ </serverplugin:plugin-configuration>
</generic-plugin>
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
index 95c768d..b87c576 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
@@ -54,7 +54,6 @@ import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceUtil;
import org.rhq.enterprise.server.core.plugin.AgentPluginDeploymentScannerMBean;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
-import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
import org.rhq.enterprise.server.scheduler.SchedulerLocal;
import org.rhq.enterprise.server.scheduler.jobs.AsyncResourceDeleteJob;
@@ -384,14 +383,16 @@ public class StartupServlet extends HttpServlet {
log("Cannot schedule data purge job: " + e.getMessage());
}
- // Content Source Sync Jobs
+ // Server Plugin Jobs
try {
ServerPluginServiceManagement mbean = LookupUtil.getServerPluginService();
MasterServerPluginContainer masterPC = mbean.getMasterPluginContainer();
- masterPC.getPluginContainer(ContentServerPluginContainer.class).scheduleSyncJobs();
+ masterPC.scheduleAllPluginJobs();
} catch (Exception e) {
- log("Cannot schedule content source sync jobs: " + e.getMessage());
+ log("Cannot schedule server plugin jobs: " + e.getMessage());
}
+
+ return;
}
/**
@@ -534,7 +535,7 @@ public class StartupServlet extends HttpServlet {
try {
ServerPluginServiceManagement mbean = LookupUtil.getServerPluginService();
- mbean.startMasterPluginContainer();
+ mbean.startMasterPluginContainerWithoutSchedulingJobs();
} catch (Exception e) {
throw new ServletException("Cannot start the master server plugin container!", e);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
new file mode 100644
index 0000000..efe2100
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -0,0 +1,173 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.quartz.Job;
+import org.quartz.JobDataMap;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+import org.rhq.core.util.exception.ThrowableUtil;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * The superclass to the concurrent and stateful job wrappers.
+ * See the subclasses for more information.
+ *
+ * @author John Mazzitelli
+ */
+abstract class AbstractJobWrapper implements Job {
+ private final Log log = LogFactory.getLog(this.getClass());
+
+ /**
+ * All keys prefixed with this leader identify the data map values as our internal values.
+ * Any data map key without this prefix is assumed to be part of the plugin callback data.
+ */
+ private static final String DATAMAP_LEADER = "__";
+
+ /**
+ * Key to the job data map that indicates the plugin that scheduled the job.
+ */
+ public static final String DATAMAP_PLUGIN_NAME = DATAMAP_LEADER + "pluginName";
+
+ /**
+ * Key to the job data map that indicates the type of plugin that scheduled the job.
+ */
+ public static final String DATAMAP_PLUGIN_TYPE = DATAMAP_LEADER + "pluginType";
+
+ /**
+ * Key to the job data map that indicates the ID of the job.
+ * This ID is passed to the plugin container when the job was scheduled, see:
+ * {@link AbstractTypeServerPluginContainer#scheduleJob(Schedule, String, String, ScheduledJob, java.util.Properties)}
+ */
+ public static final String DATAMAP_JOB_ID = DATAMAP_LEADER + "jobId";
+
+ /**
+ * Key to the job data map that indicates which plugin component class should be instantiated
+ * in order to process the job. This must implement {@link ScheduledJob}.
+ */
+ public static final String DATAMAP_SCHEDULED_JOB_CLASS = DATAMAP_LEADER + "scheduledJobClass";
+
+ /**
+ * This is the method that quartz calls when the schedule has triggered. This method will
+ * delegate to the plugin component that is responsible to do work for the plugin.
+ *
+ * @see ScheduledJob#execute(String, Properties)
+ */
+ public void execute(JobExecutionContext context) throws JobExecutionException {
+ log.debug("scheduled server plugin job triggered");
+
+ JobDataMap dataMap = context.getJobDetail().getJobDataMap();
+
+ // obtain our internal values that we need from the datamap
+ String pluginName = dataMap.getString(DATAMAP_PLUGIN_NAME);
+ String pluginTypeString = dataMap.getString(DATAMAP_PLUGIN_TYPE);
+ String jobId = dataMap.getString(DATAMAP_JOB_ID);
+ String scheduledJobClass = dataMap.getString(DATAMAP_SCHEDULED_JOB_CLASS);
+
+ // obtain the plugin's own callback data from the datamap
+ Properties callbackData = new Properties();
+ for (String key : dataMap.getKeys()) {
+ if (!key.startsWith(DATAMAP_LEADER)) {
+ callbackData.setProperty(key, dataMap.getString(key));
+ }
+ }
+
+ // determine what type of plugin is being triggered
+ ServerPluginType pluginType;
+ try {
+ pluginType = new ServerPluginType(pluginTypeString);
+ } catch (Throwable t) {
+ // datamap has an invalid plugin type string - we need to unschedule this, do not refire
+ log.error(logMsg(pluginName, pluginTypeString, jobId, "Datamap had invalid plugin type string", t));
+ JobExecutionException jobException = new JobExecutionException(t, false);
+ jobException.setUnscheduleFiringTrigger(true);
+ throw jobException;
+ }
+
+ // determine which plugin component class will be invoked to perform the work of the job
+ MasterServerPluginContainer mpc = LookupUtil.getServerPluginService().getMasterPluginContainer();
+ AbstractTypeServerPluginContainer pc = mpc.getPluginContainerByPluginType(pluginType);
+
+ ScheduledJob pluginJob;
+ ServerPluginManager pluginManager = pc.getPluginManager();
+ ServerPluginEnvironment pluginEnv = pluginManager.getPluginEnvironment(pluginName);
+ ServerPluginLifecycleListener lifecycleListener = pluginManager.getServerPluginLifecycleListener(pluginName);
+
+ if (scheduledJobClass == null) {
+ try {
+ pluginJob = (ScheduledJob) lifecycleListener;
+ if (pluginJob == null) {
+ log.error(logMsg(pluginName, pluginType, jobId, "no lifecycle listener to process job", null));
+ throw new UnsupportedOperationException("no lifecycle listener available to process the job");
+ }
+ } catch (Throwable t) {
+ // no valid lifecycle listener that implements job interface - we need to unschedule this, do not refire
+ log.error(logMsg(pluginName, pluginType, jobId, "invaild lifecycle listener", t));
+ JobExecutionException jobException = new JobExecutionException(t, false);
+ jobException.setUnscheduleAllTriggers(true);
+ throw jobException;
+ }
+ } else {
+ try {
+ pluginJob = (ScheduledJob) pluginManager.instantiatePluginClass(pluginEnv, scheduledJobClass);
+ } catch (Throwable t) {
+ // invalid class - we need to unschedule this, do not refire since it will never work
+ log.error(logMsg(pluginName, pluginType, jobId, "invalid schedule job class", t));
+ JobExecutionException jobException = new JobExecutionException(t, false);
+ jobException.setUnscheduleAllTriggers(true);
+ throw jobException;
+ }
+ }
+
+ // now actually tell the plugin its time to do the scheduled job
+
+ try {
+ ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(pluginEnv.getPluginClassLoader());
+ pluginJob.execute(jobId, lifecycleListener, callbackData);
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalContextClassLoader);
+ }
+ log.info(logMsg(pluginName, pluginType, jobId, "scheduled job executed", null));
+ } catch (Throwable t) {
+ // any exception thrown out of the job will mean the job is to be unscheduled
+ log.error(logMsg(pluginName, pluginType, jobId, "job threw exception, unscheduling it", t));
+ JobExecutionException jobException = new JobExecutionException(t, false);
+ jobException.setUnscheduleFiringTrigger(true);
+ throw jobException;
+ }
+
+ return;
+ }
+
+ protected String logMsg(String pluginName, Object pluginType, String jobId, String msg, Throwable t) {
+ String s = "Plugin [" + pluginName + "], type=[" + pluginType + "], jobId=[" + jobId + "]: " + msg;
+ if (t != null) {
+ s = s + ". Cause: " + ThrowableUtil.getAllMessages(t);
+ }
+ return s;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index 0d94174..606da06 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -20,9 +20,15 @@
package org.rhq.enterprise.server.plugin.pc;
import java.util.Collection;
+import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.quartz.Job;
+import org.quartz.JobDataMap;
+
+import org.rhq.enterprise.server.scheduler.SchedulerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
/**
* The abstract superclass for all plugin containers of the different {@link ServerPluginType plugin types}.
@@ -168,6 +174,45 @@ public abstract class AbstractTypeServerPluginContainer {
}
/**
+ * If a plugin has scheduled jobs, this method will schedule them now.
+ * This particular method implementation schedules the global job as defined in the
+ * plugin descriptors. If a plugin has a global scheduled job, its lifecycle listener
+ * will be the job handler class.
+ *
+ * Subclasses are free to extend this method to schedule additional plugin jobs, but must
+ * ensure they call this method so the global scheduled jobs get added to the scheduler.
+ *
+ * Note that this is separate from the {@link #start()} method because it is possible that
+ * the plugin container has been started before the scheduler has. In this case, the caller
+ * must wait for the scheduler to be started before this method is called to schedule jobs.
+ *
+ * @throws Exception if failed to schedule jobs
+ */
+ public synchronized void schedulePluginJobs() throws Exception {
+ if (this.pluginManager != null) {
+ // if there are any global schedules defined, schedule them now.
+ // note that we know if there is no lifecycle listener, then there can't be a global schedule
+ for (ServerPluginEnvironment pluginEnv : this.pluginManager.getPluginEnvironments()) {
+ String pluginName = pluginEnv.getPluginName();
+ if (this.pluginManager.getServerPluginLifecycleListener(pluginName) != null) {
+ Schedule schedule = this.pluginManager.getServerPluginContext(pluginEnv).getSchedule();
+ if (schedule != null) {
+ try {
+ scheduleJob(schedule, pluginName, "__globalScheduleJob", null, null);
+ } catch (Throwable t) {
+ log.warn("Failed to schedule the global plugin job for plugin [" + pluginName + "]", t);
+ }
+ }
+ }
+ }
+ } else {
+ throw new Exception("Cannot schedule plugins jobs; plugin container is not initialized yet");
+ }
+
+ return;
+ }
+
+ /**
* This will be called when its time for this plugin container to create its plugin manager.
* Subclasses are free to override this if they need their own specialized plugin manager.
*
@@ -186,4 +231,70 @@ public abstract class AbstractTypeServerPluginContainer {
protected Log getLog() {
return this.log;
}
+
+ /**
+ * Schedules a job for periodic execution.
+ *
+ * @param schedule instructs how the job should be scheduled
+ * @param pluginName the name of the plugin scheduling the job
+ * @param jobId a unique ID that identifies the job within the plugin (jobIds across plugins need not be unique)
+ * @param scheduledJobClass the plugin component class name that implements {@link ScheduledJob} that will perform
+ * the work for the job. If <code>null</code>, the lifecycle listener instance will be
+ * used (note: if <code>null</code>, it means whatever listener instance was used to initialize
+ * the plugin is the same instance that will handle the job; a new instance of the listener
+ * class is not created. This allows a plugin to have a stateful object be periodically
+ * invoked for each job invocation, as opposed to having a new object instantiated for
+ * each job invocation).
+ * @param callbackData if not <code>null</code>, this is a map of properties that will be passed to the scheduled
+ * job - it is Properties to force both the keys and values to be strings, since that is how
+ * we tell quartz to store the data
+ *
+ * @throws Exception if failed to schedule the job
+ */
+ protected void scheduleJob(Schedule schedule, String pluginName, String jobId,
+ Class<? extends ScheduledJob> scheduledJobClass, Properties callbackData) throws Exception {
+
+ String groupName = pluginName;
+ boolean rescheduleIfExists = true; // just in case the parameters change, we'll always want to reschedule it if it exists
+ boolean isVolatile = true; // if plugin is removed, this allows for the schedule to go away upon restart automatically
+
+ // determine which quartz job class we should be using, based on the concurrency needs of the schedule
+ Class<? extends Job> jobClass;
+ if (schedule.isConcurrent()) {
+ jobClass = ConcurrentJobWrapper.class;
+ } else {
+ jobClass = StatefulJobWrapper.class;
+ }
+
+ // build the data map for the job, setting some values we need, plus adding the callback data for the plugin itself
+ JobDataMap jobData = new JobDataMap();
+ jobData.put(AbstractJobWrapper.DATAMAP_PLUGIN_NAME, pluginName);
+ jobData.put(AbstractJobWrapper.DATAMAP_PLUGIN_TYPE, getSupportedServerPluginType().stringify());
+ jobData.put(AbstractJobWrapper.DATAMAP_JOB_ID, jobId);
+ if (scheduledJobClass != null) {
+ jobData.put(AbstractJobWrapper.DATAMAP_SCHEDULED_JOB_CLASS, scheduledJobClass.getName());
+ }
+ if (callbackData != null) {
+ jobData.putAll(callbackData);
+ }
+
+ // schedule the job now
+ SchedulerLocal scheduler = LookupUtil.getSchedulerBean();
+ if (schedule instanceof CronSchedule) {
+ String cronExpression = ((CronSchedule) scheduler).getCronExpression();
+ log.info("Scheduling server plugin cron job: jobName=" + jobId + ", groupName=" + groupName + ", jobClass="
+ + jobClass + ", cron=" + cronExpression);
+ scheduler.scheduleCronJob(jobId, groupName, jobData, jobClass, rescheduleIfExists, isVolatile,
+ cronExpression);
+ } else {
+ long initialDelay = 10000L; // arbitrary - wait a small bit of time before triggering the job
+ long interval = ((PeriodicSchedule) schedule).getPeriod();
+ log.info("Scheduling server plugin periodic job: jobName=" + jobId + ", groupName=" + groupName
+ + ", jobClass=" + jobClass + ", interval=" + interval);
+ scheduler.scheduleRepeatingJob(jobId, groupName, jobData, jobClass, rescheduleIfExists, isVolatile,
+ initialDelay, interval);
+ }
+
+ return;
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java
new file mode 100644
index 0000000..e38d780
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java
@@ -0,0 +1,33 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+/**
+ * The actual quartz job that the plugin container will submit when it needs to invoke
+ * a concurrent scheduled job on behalf of a plugin. This is a normal non-stateful "job"
+ * which tells quartz that it can run multiple jobs concurrently.
+ *
+ * Note that server plugin developers do not extend this class. Instead, developers
+ * need to have their plugin components implement {@link ScheduledJob}.
+ *
+ * @author John Mazzitelli
+ */
+public class ConcurrentJobWrapper extends AbstractJobWrapper {
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index a8696dd..4d0d314 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -194,6 +194,29 @@ public class MasterServerPluginContainer {
}
/**
+ * Asks that all plugin containers schedule jobs now, if needed.
+ * Note that this is separate from the {@link #initialize(MasterServerPluginContainerConfiguration)}
+ * method because it is possible that the master plugin container has been
+ * initialized before the scheduler is started. In this case, the caller must wait for the scheduler to
+ * be started before this method is called to schedule jobs.
+ */
+ public synchronized void scheduleAllPluginJobs() {
+ log.debug("Master server plugin container will schedule all jobs now");
+
+ for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
+ try {
+ pc.schedulePluginJobs();
+ } catch (Exception e) {
+ log.error("Server plugin container for plugin type [" + pc.getSupportedServerPluginType()
+ + "] failed to scheduled some or all of its jobs", e);
+ }
+ }
+
+ log.info("Master server plugin container scheduled all jobs");
+ return;
+ }
+
+ /**
* Returns the configuration that this object was initialized with. If this plugin container was not
* {@link #initialize(MasterServerPluginContainerConfiguration) initialized} or has been {@link #shutdown() shutdown},
* this will return <code>null</code>.
@@ -220,6 +243,7 @@ public class MasterServerPluginContainer {
* @param clazz the class name of the plugin container that the caller wants
* @return the plugin container of the given class (<code>null</code> if none found)
*/
+ @SuppressWarnings("unchecked")
public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainer(Class<T> clazz) {
for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
if (clazz.isInstance(pc)) {
@@ -235,11 +259,22 @@ public class MasterServerPluginContainer {
* @param descriptor descriptor to identify a plugin whose container is to be returned
* @return a plugin container that can handle the plugin with the given descriptor
*/
+ protected synchronized AbstractTypeServerPluginContainer getPluginContainerByPluginType(ServerPluginType pluginType) {
+ AbstractTypeServerPluginContainer pc = this.pluginContainers.get(pluginType);
+ return pc;
+ }
+
+ /**
+ * Given a plugin's descriptor, this will return the plugin container that can manage the plugin.
+ *
+ * @param descriptor descriptor to identify a plugin whose container is to be returned
+ * @return a plugin container that can handle the plugin with the given descriptor
+ */
protected synchronized AbstractTypeServerPluginContainer getPluginContainerByDescriptor(
ServerPluginDescriptorType descriptor) {
ServerPluginType pluginType = new ServerPluginType(descriptor.getClass());
- AbstractTypeServerPluginContainer pc = this.pluginContainers.get(pluginType);
+ AbstractTypeServerPluginContainer pc = getPluginContainerByPluginType(pluginType);
return pc;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java
new file mode 100644
index 0000000..b71ff23
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java
@@ -0,0 +1,47 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import java.util.Properties;
+
+/**
+ * An interface to be implemented by any server plugin component that needs to be scheduled.
+ *
+ * @author John Mazzitelli
+ */
+public interface ScheduledJob {
+ /**
+ * Called when the job triggers.
+ *
+ * @param jobId the job identifier that was used when creating the job
+ * @param lifecycleListener if the plugin has a lifecycle listener, this will be it.
+ * Use this object to obtain the plugin context and any other
+ * stateful plugin data specific to the plugin being invoked.
+ * This may be <code>null</code> if the plugin did not define
+ * a global lifecycle listener.
+ * @param callbackData a map of data that was used when creating the job whose values are
+ * passed back to this method as they were when the job was created.
+ *
+ * @throws Exception on any error that should cause the schedule to not fire. If an exception
+ * is thrown, the schedule will not trigger again until the plugin is restarted
+ */
+ void execute(String jobId, ServerPluginLifecycleListener lifecycleListener, Properties callbackData)
+ throws Exception;
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
index b28c14f..f0c8488 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
@@ -25,6 +25,8 @@ import org.rhq.core.domain.configuration.Configuration;
/**
* A global context containing information about a server-side plugin.
+ *
+ * This is an immutable object, plugins are not allowed to alter these values.
*
* @author John Mazzitelli
*/
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index 4226b12..1c31b8d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -24,7 +24,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
-import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -43,6 +42,7 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
*
* @author John Mazzitelli
*/
+//TODO: need a R/W lock to make this class thread safe
public class ServerPluginManager {
private final Log log = LogFactory.getLog(this.getClass());
@@ -54,6 +54,12 @@ public class ServerPluginManager {
private final Map<String, ServerPluginEnvironment> loadedPlugins;
/**
+ * To avoid having to create contexts multiple times for the same plugin,
+ * contexts are cached here, keyed on plugin name.
+ */
+ private final Map<String, ServerPluginContext> pluginContextCache;
+
+ /**
* Cached instances of objects used to initialize and shutdown individual plugins.
* Only plugins that declare their own lifecycle listener will have objects in this cache.
* This is keyed on plugin name.
@@ -68,6 +74,7 @@ public class ServerPluginManager {
public ServerPluginManager(AbstractTypeServerPluginContainer pc) {
this.parentPluginContainer = pc;
this.loadedPlugins = new HashMap<String, ServerPluginEnvironment>();
+ this.pluginContextCache = new HashMap<String, ServerPluginContext>();
this.pluginLifecycleListenerCache = new HashMap<String, ServerPluginLifecycleListener>();
}
@@ -76,7 +83,7 @@ public class ServerPluginManager {
*
* @throws Exception if failed to initialize
*/
- public synchronized void initialize() throws Exception {
+ public void initialize() throws Exception {
log.debug("Plugin manager initializing");
return; // no-op
}
@@ -85,15 +92,16 @@ public class ServerPluginManager {
* Shuts down this manager. This should be called only after all of its plugins
* have been {@link #unloadPlugin(ServerPluginEnvironment) unloaded}.
*/
- public synchronized void shutdown() {
+ public void shutdown() {
log.debug("Plugin manager shutting down");
if (this.loadedPlugins.size() > 0) {
log.warn("Server plugin manager is being shutdown while some plugins are still loaded: "
+ this.loadedPlugins);
- this.loadedPlugins.clear();
}
+ this.loadedPlugins.clear();
+ this.pluginContextCache.clear();
this.pluginLifecycleListenerCache.clear();
return;
@@ -107,14 +115,14 @@ public class ServerPluginManager {
*
* @throws Exception if the plugin manager cannot load the plugin or deems the plugin invalid
*/
- public synchronized void loadPlugin(ServerPluginEnvironment env) throws Exception {
+ public void loadPlugin(ServerPluginEnvironment env) throws Exception {
String pluginName = env.getPluginName();
log.debug("Loading server plugin [" + pluginName + "] from: " + env.getPluginUrl());
// tell the plugin we are loading it
ServerPluginLifecycleListener listener = createServerPluginLifecycleListener(env);
if (listener != null) {
- ServerPluginContext context = createServerPluginContext(env);
+ ServerPluginContext context = getServerPluginContext(env);
log.debug("Initializing lifecycle listener for server plugin [" + pluginName + "]");
ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
@@ -134,11 +142,11 @@ public class ServerPluginManager {
return;
}
- public synchronized void startPlugins() {
+ public void startPlugins() {
log.debug("Starting plugins");
// tell all lifecycle listeners to start
- for (Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
+ for (Map.Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
String pluginName = entry.getKey();
ServerPluginLifecycleListener listener = entry.getValue();
ServerPluginEnvironment env = this.loadedPlugins.get(pluginName);
@@ -157,11 +165,11 @@ public class ServerPluginManager {
return;
}
- public synchronized void stopPlugins() {
+ public void stopPlugins() {
log.debug("Stopping plugins");
// tell all lifecycle listeners to stop
- for (Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
+ for (Map.Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
String pluginName = entry.getKey();
ServerPluginLifecycleListener listener = entry.getValue();
ServerPluginEnvironment env = this.loadedPlugins.get(pluginName);
@@ -188,7 +196,7 @@ public class ServerPluginManager {
*
* @throws Exception if the plugin manager cannot unload the plugin
*/
- public synchronized void unloadPlugin(ServerPluginEnvironment env) throws Exception {
+ public void unloadPlugin(ServerPluginEnvironment env) throws Exception {
String pluginName = env.getPluginName();
log.debug("Unloading server plugin [" + pluginName + "]");
@@ -221,7 +229,7 @@ public class ServerPluginManager {
*
* @return environments for all the plugins
*/
- public synchronized Collection<ServerPluginEnvironment> getPluginEnvironments() {
+ public Collection<ServerPluginEnvironment> getPluginEnvironments() {
return new ArrayList<ServerPluginEnvironment>(this.loadedPlugins.values());
}
@@ -234,10 +242,24 @@ public class ServerPluginManager {
* @param pluginName the plugin whose environment is to be returned
* @return given plugin's environment
*/
- public synchronized ServerPluginEnvironment getPluginEnvironment(String pluginName) {
+ public ServerPluginEnvironment getPluginEnvironment(String pluginName) {
return this.loadedPlugins.get(pluginName);
}
+ /**
+ * Returns the lifecycle listener instance that is responsible for initializing and managing
+ * the plugin. This will return <code>null</code> if a plugin has not defined a lifecycle listener.
+ *
+ * @param pluginName the name of the plugin whose lifecycle listener is to be returned
+ *
+ * @return the lifecycle listener instance that initialized and is managing a plugin. Will
+ * return <code>null</code> if the plugin has not defined a lifecycle listener.
+ * <code>null</code> is also returned if the plugin is not initialized yet.
+ */
+ public ServerPluginLifecycleListener getServerPluginLifecycleListener(String pluginName) {
+ return this.pluginLifecycleListenerCache.get(pluginName);
+ }
+
public AbstractTypeServerPluginContainer getParentPluginContainer() {
return this.parentPluginContainer;
}
@@ -246,8 +268,16 @@ public class ServerPluginManager {
return this.log;
}
- protected ServerPluginContext createServerPluginContext(ServerPluginEnvironment env) {
+ protected ServerPluginContext getServerPluginContext(ServerPluginEnvironment env) {
+
String pluginName = env.getPluginName();
+ ServerPluginContext context = this.pluginContextCache.get(pluginName);
+
+ // if we already created it, return it immediately and don't create another
+ if (context != null) {
+ return context;
+ }
+
ServerPluginDescriptorType pluginDescriptor = env.getPluginDescriptor();
MasterServerPluginContainer masterPC = this.parentPluginContainer.getMasterServerPluginContainer();
@@ -280,7 +310,8 @@ public class ServerPluginManager {
}
}
- ServerPluginContext context = new ServerPluginContext(env, dataDir, tmpDir, config, schedule);
+ context = new ServerPluginContext(env, dataDir, tmpDir, config, schedule);
+ this.pluginContextCache.put(pluginName, context);
return context;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
index d6bae90..0c80dcb 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
@@ -60,6 +60,7 @@ public class ServerPluginService implements ServerPluginServiceManagement {
if (this.masterPluginContainer == null) {
log.debug("The server plugin service is now starting the master server plugin container");
this.masterPluginContainer = createMasterPluginContainer();
+ this.masterPluginContainer.scheduleAllPluginJobs();
}
return;
@@ -90,6 +91,21 @@ public class ServerPluginService implements ServerPluginServiceManagement {
startMasterPluginContainer();
}
+ public synchronized void startMasterPluginContainerWithoutSchedulingJobs() {
+ if (!this.started) {
+ throw new IllegalStateException(
+ "The server plugin service is not started - cannot start the master plugin container!");
+ }
+
+ // only initialize if not already started; if already started/initialized, just ignore
+ if (this.masterPluginContainer == null) {
+ log.debug("The server plugin service is now starting the master server plugin container!");
+ this.masterPluginContainer = createMasterPluginContainer();
+ }
+
+ return;
+ }
+
public MasterServerPluginContainer getMasterPluginContainer() {
return this.masterPluginContainer;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java
index 8db19a8..490c9fd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java
@@ -45,9 +45,12 @@ public interface ServerPluginServiceManagement {
void stop();
/**
- * Starts the {@link #getMasterPluginContainer() master plugin container} which will load in all plugins and start them. You
- * cannot start the plugin container unless this service has {@link #start() been started}. If the master plugin container
- * {@link #isMasterPluginContainerStarted() is already started}, this does nothing and returns.
+ * Starts the {@link #getMasterPluginContainer() master plugin container} which will load in all plugins, start them and then
+ * schedule all jobs for all plugins. You cannot start the plugin container unless this service has
+ * {@link #start() been started}. If the master plugin container {@link #isMasterPluginContainerStarted() is already started},
+ * this does nothing and returns. You must ensure the job scheduler is started prior to calling this method.
+ *
+ * @see #startMasterPluginContainerWithoutSchedulingJobs()
*/
void startMasterPluginContainer();
@@ -63,6 +66,17 @@ public interface ServerPluginServiceManagement {
void restartMasterPluginContainer();
/**
+ * Similar to {@link #startMasterPluginContainer()}, but this will not tell the master plugin container
+ * to {@link MasterServerPluginContainer#scheduleAllPluginJobs() schedule any jobs} yet. Usually this is only
+ * called when the server itself is starting up and it wants to start the master PC but it has not yet
+ * started the scheduler. In this case, after this method is called, the caller must ensure the scheduler is
+ * started and then tell the master PC to schedule all its plugin jobs.
+ *
+ * @see #startMasterPluginContainer()
+ */
+ void startMasterPluginContainerWithoutSchedulingJobs();
+
+ /**
* Returns the master server plugin container that will be responsible for managing all plugins of all types and their classloaders.
*
* @return the master plugin container, if started. Will be <code>null</code> if not started
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
index f9fe313..feba2fc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
@@ -22,6 +22,7 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
/**
* Defines the types of server-side plugins that are currently supported.
+ * Server side plugin types are identified uniquely by their plugin descriptor types.
*
* @author John Mazzitelli
*/
@@ -35,8 +36,33 @@ public class ServerPluginType {
this.descriptorType = descriptorType;
}
+ /**
+ * Given a string that was returned by a call to {@link #stringify()}, this
+ * will create its server plugin type.
+ *
+ * @param stringifiedType string representation of a server plugin type.
+ *
+ * @throws Exception if the string was invalid
+ */
+ @SuppressWarnings("unchecked")
+ public ServerPluginType(String stringifiedType) throws Exception {
+ this((Class<? extends ServerPluginDescriptorType>) Class.forName(stringifiedType));
+ }
+
public Class<? extends ServerPluginDescriptorType> getDescriptorType() {
- return descriptorType;
+ return this.descriptorType;
+ }
+
+ /**
+ * Returns a "serialized" form of this instance by returning a string
+ * representation of the type. This is not the same as {@link #toString()}.
+ * The returned string can be used to reconstitute the type via
+ * the constructor {@link ServerPluginType#ServerPluginType(String)}.
+ *
+ * @return string representation of this type
+ */
+ public String stringify() {
+ return this.descriptorType.getName();
}
@Override
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java
new file mode 100644
index 0000000..0c6495e
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java
@@ -0,0 +1,35 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import org.quartz.StatefulJob;
+
+/**
+ * The actual quartz job that the plugin container will submit when it needs to invoke
+ * a scheduled job on behalf of a plugin. This is a "stateful job" which tells quartz
+ * that only one job should be invoked at any one time on any server.
+ *
+ * Note that server plugin developers do not extend this class. Instead, developers
+ * need to have their plugin components implement {@link ScheduledJob}.
+ *
+ * @author John Mazzitelli
+ */
+public class StatefulJobWrapper extends AbstractJobWrapper implements StatefulJob {
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
index 3edba4d..e32e858 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
@@ -73,6 +73,13 @@ public class ContentServerPluginContainer extends AbstractTypeServerPluginContai
}
@Override
+ public void schedulePluginJobs() throws Exception {
+ super.schedulePluginJobs();
+ scheduleSyncJobs();
+ return;
+ }
+
+ @Override
public ServerPluginType getSupportedServerPluginType() {
return new ServerPluginType(ContentPluginDescriptorType.class);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerService.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerService.java
index 1398a03..1856fdd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerService.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerService.java
@@ -45,7 +45,7 @@ import org.quartz.impl.StdSchedulerFactory;
import org.quartz.spi.JobFactory;
/**
- * Scheduler MBean service that simply wraps the Quartz scheduler. This expects to wrap Quartz 1.5.2.
+ * Scheduler MBean service that simply wraps the Quartz scheduler.
*/
public class SchedulerService implements SchedulerServiceMBean, MBeanRegistration {
private Log log = LogFactory.getLog(SchedulerService.class);
diff --git a/modules/plugins/rhq-server/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/rhq-server/src/main/resources/META-INF/rhq-plugin.xml
index 0700d83..3b0b5da 100644
--- a/modules/plugins/rhq-server/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/rhq-server/src/main/resources/META-INF/rhq-plugin.xml
@@ -313,15 +313,15 @@
<c:simple-property name="descriptionTemplate" default="Details on the server-side plugin container subsystem"/>
</plugin-configuration>
- <operation name="startMasterPluginContainer" displayName="Start Master Plugin Container"
+ <operation name="startMasterPluginContainer"
description="Starts the master plugin container which will load and initialize all server-side plugins.">
</operation>
- <operation name="stopMasterPluginContainer" displayName="Stop Master Plugin Container"
+ <operation name="stopMasterPluginContainer"
description="Stops the master plugin container which will shutdown all server-side plugins.">
</operation>
- <operation name="restartMasterPluginContainer" displayName="Restart Plugin Container"
+ <operation name="restartMasterPluginContainer"
description="Convienence operation that first stops and then immediately restarts the master plugin container.">
</operation>
commit 9f51347edeb1832781b1c67fd922231ba7f8b71a
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 18:34:15 2009 -0500
why does git refuse to merge this? I have to manually remove it myself
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index 55d88a0..1c31b8d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -162,19 +162,6 @@ public class ServerPluginManager {
}
}
- // if there are any global schedules defined, schedule them now.
- // note that we know if there is no lifecycle listener, then there can't be a schedule
- for (String pluginName : this.pluginLifecycleListenerCache.keySet()) {
- Schedule schedule = getServerPluginContext(this.loadedPlugins.get(pluginName)).getSchedule();
- if (schedule != null) {
- try {
- this.parentPluginContainer.scheduleJob(schedule, pluginName, "__globalScheduleJob", null, null);
- } catch (Throwable t) {
- log.warn("Failed to schedule the global plugin job for plugin [" + pluginName + "]", t);
- }
- }
- }
-
return;
}
commit 706a1efd72d7d4d7b5c080fe6eb15f042934ab93
Merge: 89d475f... 4176765...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 17:34:34 2009 -0500
Merge branch 'mazz' into pc
commit 89d475fa9a173e0a30a74cb52dcec7b0af36b348
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 17:29:39 2009 -0500
Conflicts:
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
diff --git a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
index a2deeef..de99b3a 100644
--- a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
+++ b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
@@ -19,6 +19,9 @@
package org.custom;
+import java.util.Properties;
+
+import org.rhq.enterprise.server.plugin.pc.ScheduledJob;
import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
@@ -26,7 +29,7 @@ import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
* A sample lifecycle listener for the sample generic plugin. This listener will be
* the main interface the server uses to start and stop the plugin.
*/
-public class MyLifecycleListener implements ServerPluginLifecycleListener {
+public class MyLifecycleListener implements ServerPluginLifecycleListener, ScheduledJob {
private ServerPluginContext context;
@@ -48,6 +51,12 @@ public class MyLifecycleListener implements ServerPluginLifecycleListener {
}
@Override
+ public void execute(String jobId, ServerPluginLifecycleListener lifecycleListener, Properties callbackData)
+ throws Exception {
+ System.out.println("The sample plugin scheduled job [" + jobId + "] has triggered!!! : " + this);
+ }
+
+ @Override
public String toString() {
if (this.context == null) {
return "<no context>";
diff --git a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
index 1e48ef8..57f19cc 100644
--- a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -10,11 +10,15 @@
xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
xmlns:c="urn:xmlns:rhq-configuration">
- <serverplugin:lifecycle-listener class="MyLifecycleListener">
- </serverplugin:lifecycle-listener>
+ <serverplugin:lifecycle-listener class="MyLifecycleListener">
+ <serverplugin:schedule concurrent="true">
+ <serverplugin:period>30000</serverplugin:period>
+ </serverplugin:schedule>
+ </serverplugin:lifecycle-listener>
- <serverplugin:plugin-configuration>
- <c:simple-property name="myCustomProperty" type="string" required="true" description="A property my plugin needs to be properly configured" />
- </serverplugin:plugin-configuration>
+ <serverplugin:plugin-configuration>
+ <c:simple-property name="myCustomProperty" type="string" required="true"
+ description="A property my plugin needs to be properly configured" />
+ </serverplugin:plugin-configuration>
</generic-plugin>
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
index 95c768d..b87c576 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
@@ -54,7 +54,6 @@ import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceUtil;
import org.rhq.enterprise.server.core.plugin.AgentPluginDeploymentScannerMBean;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
-import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
import org.rhq.enterprise.server.scheduler.SchedulerLocal;
import org.rhq.enterprise.server.scheduler.jobs.AsyncResourceDeleteJob;
@@ -384,14 +383,16 @@ public class StartupServlet extends HttpServlet {
log("Cannot schedule data purge job: " + e.getMessage());
}
- // Content Source Sync Jobs
+ // Server Plugin Jobs
try {
ServerPluginServiceManagement mbean = LookupUtil.getServerPluginService();
MasterServerPluginContainer masterPC = mbean.getMasterPluginContainer();
- masterPC.getPluginContainer(ContentServerPluginContainer.class).scheduleSyncJobs();
+ masterPC.scheduleAllPluginJobs();
} catch (Exception e) {
- log("Cannot schedule content source sync jobs: " + e.getMessage());
+ log("Cannot schedule server plugin jobs: " + e.getMessage());
}
+
+ return;
}
/**
@@ -534,7 +535,7 @@ public class StartupServlet extends HttpServlet {
try {
ServerPluginServiceManagement mbean = LookupUtil.getServerPluginService();
- mbean.startMasterPluginContainer();
+ mbean.startMasterPluginContainerWithoutSchedulingJobs();
} catch (Exception e) {
throw new ServletException("Cannot start the master server plugin container!", e);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
index 6c39277..efe2100 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -126,7 +126,7 @@ abstract class AbstractJobWrapper implements Job {
// no valid lifecycle listener that implements job interface - we need to unschedule this, do not refire
log.error(logMsg(pluginName, pluginType, jobId, "invaild lifecycle listener", t));
JobExecutionException jobException = new JobExecutionException(t, false);
- jobException.setUnscheduleFiringTrigger(true);
+ jobException.setUnscheduleAllTriggers(true);
throw jobException;
}
} else {
@@ -136,7 +136,7 @@ abstract class AbstractJobWrapper implements Job {
// invalid class - we need to unschedule this, do not refire since it will never work
log.error(logMsg(pluginName, pluginType, jobId, "invalid schedule job class", t));
JobExecutionException jobException = new JobExecutionException(t, false);
- jobException.setUnscheduleFiringTrigger(true);
+ jobException.setUnscheduleAllTriggers(true);
throw jobException;
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index ea0b5a6..606da06 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -174,6 +174,45 @@ public abstract class AbstractTypeServerPluginContainer {
}
/**
+ * If a plugin has scheduled jobs, this method will schedule them now.
+ * This particular method implementation schedules the global job as defined in the
+ * plugin descriptors. If a plugin has a global scheduled job, its lifecycle listener
+ * will be the job handler class.
+ *
+ * Subclasses are free to extend this method to schedule additional plugin jobs, but must
+ * ensure they call this method so the global scheduled jobs get added to the scheduler.
+ *
+ * Note that this is separate from the {@link #start()} method because it is possible that
+ * the plugin container has been started before the scheduler has. In this case, the caller
+ * must wait for the scheduler to be started before this method is called to schedule jobs.
+ *
+ * @throws Exception if failed to schedule jobs
+ */
+ public synchronized void schedulePluginJobs() throws Exception {
+ if (this.pluginManager != null) {
+ // if there are any global schedules defined, schedule them now.
+ // note that we know if there is no lifecycle listener, then there can't be a global schedule
+ for (ServerPluginEnvironment pluginEnv : this.pluginManager.getPluginEnvironments()) {
+ String pluginName = pluginEnv.getPluginName();
+ if (this.pluginManager.getServerPluginLifecycleListener(pluginName) != null) {
+ Schedule schedule = this.pluginManager.getServerPluginContext(pluginEnv).getSchedule();
+ if (schedule != null) {
+ try {
+ scheduleJob(schedule, pluginName, "__globalScheduleJob", null, null);
+ } catch (Throwable t) {
+ log.warn("Failed to schedule the global plugin job for plugin [" + pluginName + "]", t);
+ }
+ }
+ }
+ }
+ } else {
+ throw new Exception("Cannot schedule plugins jobs; plugin container is not initialized yet");
+ }
+
+ return;
+ }
+
+ /**
* This will be called when its time for this plugin container to create its plugin manager.
* Subclasses are free to override this if they need their own specialized plugin manager.
*
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index 878b149..4d0d314 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -194,6 +194,29 @@ public class MasterServerPluginContainer {
}
/**
+ * Asks that all plugin containers schedule jobs now, if needed.
+ * Note that this is separate from the {@link #initialize(MasterServerPluginContainerConfiguration)}
+ * method because it is possible that the master plugin container has been
+ * initialized before the scheduler is started. In this case, the caller must wait for the scheduler to
+ * be started before this method is called to schedule jobs.
+ */
+ public synchronized void scheduleAllPluginJobs() {
+ log.debug("Master server plugin container will schedule all jobs now");
+
+ for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
+ try {
+ pc.schedulePluginJobs();
+ } catch (Exception e) {
+ log.error("Server plugin container for plugin type [" + pc.getSupportedServerPluginType()
+ + "] failed to scheduled some or all of its jobs", e);
+ }
+ }
+
+ log.info("Master server plugin container scheduled all jobs");
+ return;
+ }
+
+ /**
* Returns the configuration that this object was initialized with. If this plugin container was not
* {@link #initialize(MasterServerPluginContainerConfiguration) initialized} or has been {@link #shutdown() shutdown},
* this will return <code>null</code>.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index 70cd665..55d88a0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -42,6 +42,7 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
*
* @author John Mazzitelli
*/
+//TODO: need a R/W lock to make this class thread safe
public class ServerPluginManager {
private final Log log = LogFactory.getLog(this.getClass());
@@ -82,7 +83,7 @@ public class ServerPluginManager {
*
* @throws Exception if failed to initialize
*/
- public synchronized void initialize() throws Exception {
+ public void initialize() throws Exception {
log.debug("Plugin manager initializing");
return; // no-op
}
@@ -91,7 +92,7 @@ public class ServerPluginManager {
* Shuts down this manager. This should be called only after all of its plugins
* have been {@link #unloadPlugin(ServerPluginEnvironment) unloaded}.
*/
- public synchronized void shutdown() {
+ public void shutdown() {
log.debug("Plugin manager shutting down");
if (this.loadedPlugins.size() > 0) {
@@ -114,7 +115,7 @@ public class ServerPluginManager {
*
* @throws Exception if the plugin manager cannot load the plugin or deems the plugin invalid
*/
- public synchronized void loadPlugin(ServerPluginEnvironment env) throws Exception {
+ public void loadPlugin(ServerPluginEnvironment env) throws Exception {
String pluginName = env.getPluginName();
log.debug("Loading server plugin [" + pluginName + "] from: " + env.getPluginUrl());
@@ -141,7 +142,7 @@ public class ServerPluginManager {
return;
}
- public synchronized void startPlugins() {
+ public void startPlugins() {
log.debug("Starting plugins");
// tell all lifecycle listeners to start
@@ -177,7 +178,7 @@ public class ServerPluginManager {
return;
}
- public synchronized void stopPlugins() {
+ public void stopPlugins() {
log.debug("Stopping plugins");
// tell all lifecycle listeners to stop
@@ -208,7 +209,7 @@ public class ServerPluginManager {
*
* @throws Exception if the plugin manager cannot unload the plugin
*/
- public synchronized void unloadPlugin(ServerPluginEnvironment env) throws Exception {
+ public void unloadPlugin(ServerPluginEnvironment env) throws Exception {
String pluginName = env.getPluginName();
log.debug("Unloading server plugin [" + pluginName + "]");
@@ -241,7 +242,7 @@ public class ServerPluginManager {
*
* @return environments for all the plugins
*/
- public synchronized Collection<ServerPluginEnvironment> getPluginEnvironments() {
+ public Collection<ServerPluginEnvironment> getPluginEnvironments() {
return new ArrayList<ServerPluginEnvironment>(this.loadedPlugins.values());
}
@@ -254,7 +255,7 @@ public class ServerPluginManager {
* @param pluginName the plugin whose environment is to be returned
* @return given plugin's environment
*/
- public synchronized ServerPluginEnvironment getPluginEnvironment(String pluginName) {
+ public ServerPluginEnvironment getPluginEnvironment(String pluginName) {
return this.loadedPlugins.get(pluginName);
}
@@ -268,7 +269,7 @@ public class ServerPluginManager {
* return <code>null</code> if the plugin has not defined a lifecycle listener.
* <code>null</code> is also returned if the plugin is not initialized yet.
*/
- public synchronized ServerPluginLifecycleListener getServerPluginLifecycleListener(String pluginName) {
+ public ServerPluginLifecycleListener getServerPluginLifecycleListener(String pluginName) {
return this.pluginLifecycleListenerCache.get(pluginName);
}
@@ -280,7 +281,7 @@ public class ServerPluginManager {
return this.log;
}
- protected synchronized ServerPluginContext getServerPluginContext(ServerPluginEnvironment env) {
+ protected ServerPluginContext getServerPluginContext(ServerPluginEnvironment env) {
String pluginName = env.getPluginName();
ServerPluginContext context = this.pluginContextCache.get(pluginName);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
index d6bae90..0c80dcb 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
@@ -60,6 +60,7 @@ public class ServerPluginService implements ServerPluginServiceManagement {
if (this.masterPluginContainer == null) {
log.debug("The server plugin service is now starting the master server plugin container");
this.masterPluginContainer = createMasterPluginContainer();
+ this.masterPluginContainer.scheduleAllPluginJobs();
}
return;
@@ -90,6 +91,21 @@ public class ServerPluginService implements ServerPluginServiceManagement {
startMasterPluginContainer();
}
+ public synchronized void startMasterPluginContainerWithoutSchedulingJobs() {
+ if (!this.started) {
+ throw new IllegalStateException(
+ "The server plugin service is not started - cannot start the master plugin container!");
+ }
+
+ // only initialize if not already started; if already started/initialized, just ignore
+ if (this.masterPluginContainer == null) {
+ log.debug("The server plugin service is now starting the master server plugin container!");
+ this.masterPluginContainer = createMasterPluginContainer();
+ }
+
+ return;
+ }
+
public MasterServerPluginContainer getMasterPluginContainer() {
return this.masterPluginContainer;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java
index 8db19a8..490c9fd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java
@@ -45,9 +45,12 @@ public interface ServerPluginServiceManagement {
void stop();
/**
- * Starts the {@link #getMasterPluginContainer() master plugin container} which will load in all plugins and start them. You
- * cannot start the plugin container unless this service has {@link #start() been started}. If the master plugin container
- * {@link #isMasterPluginContainerStarted() is already started}, this does nothing and returns.
+ * Starts the {@link #getMasterPluginContainer() master plugin container} which will load in all plugins, start them and then
+ * schedule all jobs for all plugins. You cannot start the plugin container unless this service has
+ * {@link #start() been started}. If the master plugin container {@link #isMasterPluginContainerStarted() is already started},
+ * this does nothing and returns. You must ensure the job scheduler is started prior to calling this method.
+ *
+ * @see #startMasterPluginContainerWithoutSchedulingJobs()
*/
void startMasterPluginContainer();
@@ -63,6 +66,17 @@ public interface ServerPluginServiceManagement {
void restartMasterPluginContainer();
/**
+ * Similar to {@link #startMasterPluginContainer()}, but this will not tell the master plugin container
+ * to {@link MasterServerPluginContainer#scheduleAllPluginJobs() schedule any jobs} yet. Usually this is only
+ * called when the server itself is starting up and it wants to start the master PC but it has not yet
+ * started the scheduler. In this case, after this method is called, the caller must ensure the scheduler is
+ * started and then tell the master PC to schedule all its plugin jobs.
+ *
+ * @see #startMasterPluginContainer()
+ */
+ void startMasterPluginContainerWithoutSchedulingJobs();
+
+ /**
* Returns the master server plugin container that will be responsible for managing all plugins of all types and their classloaders.
*
* @return the master plugin container, if started. Will be <code>null</code> if not started
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
index 3edba4d..e32e858 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
@@ -73,6 +73,13 @@ public class ContentServerPluginContainer extends AbstractTypeServerPluginContai
}
@Override
+ public void schedulePluginJobs() throws Exception {
+ super.schedulePluginJobs();
+ scheduleSyncJobs();
+ return;
+ }
+
+ @Override
public ServerPluginType getSupportedServerPluginType() {
return new ServerPluginType(ContentPluginDescriptorType.class);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerService.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerService.java
index 1398a03..1856fdd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerService.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerService.java
@@ -45,7 +45,7 @@ import org.quartz.impl.StdSchedulerFactory;
import org.quartz.spi.JobFactory;
/**
- * Scheduler MBean service that simply wraps the Quartz scheduler. This expects to wrap Quartz 1.5.2.
+ * Scheduler MBean service that simply wraps the Quartz scheduler.
*/
public class SchedulerService implements SchedulerServiceMBean, MBeanRegistration {
private Log log = LogFactory.getLog(SchedulerService.class);
diff --git a/modules/plugins/rhq-server/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/rhq-server/src/main/resources/META-INF/rhq-plugin.xml
index 0700d83..3b0b5da 100644
--- a/modules/plugins/rhq-server/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/rhq-server/src/main/resources/META-INF/rhq-plugin.xml
@@ -313,15 +313,15 @@
<c:simple-property name="descriptionTemplate" default="Details on the server-side plugin container subsystem"/>
</plugin-configuration>
- <operation name="startMasterPluginContainer" displayName="Start Master Plugin Container"
+ <operation name="startMasterPluginContainer"
description="Starts the master plugin container which will load and initialize all server-side plugins.">
</operation>
- <operation name="stopMasterPluginContainer" displayName="Stop Master Plugin Container"
+ <operation name="stopMasterPluginContainer"
description="Stops the master plugin container which will shutdown all server-side plugins.">
</operation>
- <operation name="restartMasterPluginContainer" displayName="Restart Plugin Container"
+ <operation name="restartMasterPluginContainer"
description="Convienence operation that first stops and then immediately restarts the master plugin container.">
</operation>
commit 4176765871d06b37895dc72269233687325eaa87
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 17:20:20 2009 -0500
get the plugin jobs to be scheduled properly in quartz
diff --git a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
index a2deeef..de99b3a 100644
--- a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
+++ b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
@@ -19,6 +19,9 @@
package org.custom;
+import java.util.Properties;
+
+import org.rhq.enterprise.server.plugin.pc.ScheduledJob;
import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
@@ -26,7 +29,7 @@ import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
* A sample lifecycle listener for the sample generic plugin. This listener will be
* the main interface the server uses to start and stop the plugin.
*/
-public class MyLifecycleListener implements ServerPluginLifecycleListener {
+public class MyLifecycleListener implements ServerPluginLifecycleListener, ScheduledJob {
private ServerPluginContext context;
@@ -48,6 +51,12 @@ public class MyLifecycleListener implements ServerPluginLifecycleListener {
}
@Override
+ public void execute(String jobId, ServerPluginLifecycleListener lifecycleListener, Properties callbackData)
+ throws Exception {
+ System.out.println("The sample plugin scheduled job [" + jobId + "] has triggered!!! : " + this);
+ }
+
+ @Override
public String toString() {
if (this.context == null) {
return "<no context>";
diff --git a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
index 1e48ef8..57f19cc 100644
--- a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -10,11 +10,15 @@
xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
xmlns:c="urn:xmlns:rhq-configuration">
- <serverplugin:lifecycle-listener class="MyLifecycleListener">
- </serverplugin:lifecycle-listener>
+ <serverplugin:lifecycle-listener class="MyLifecycleListener">
+ <serverplugin:schedule concurrent="true">
+ <serverplugin:period>30000</serverplugin:period>
+ </serverplugin:schedule>
+ </serverplugin:lifecycle-listener>
- <serverplugin:plugin-configuration>
- <c:simple-property name="myCustomProperty" type="string" required="true" description="A property my plugin needs to be properly configured" />
- </serverplugin:plugin-configuration>
+ <serverplugin:plugin-configuration>
+ <c:simple-property name="myCustomProperty" type="string" required="true"
+ description="A property my plugin needs to be properly configured" />
+ </serverplugin:plugin-configuration>
</generic-plugin>
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
index 95c768d..b87c576 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java
@@ -54,7 +54,6 @@ import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceUtil;
import org.rhq.enterprise.server.core.plugin.AgentPluginDeploymentScannerMBean;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
-import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
import org.rhq.enterprise.server.scheduler.SchedulerLocal;
import org.rhq.enterprise.server.scheduler.jobs.AsyncResourceDeleteJob;
@@ -384,14 +383,16 @@ public class StartupServlet extends HttpServlet {
log("Cannot schedule data purge job: " + e.getMessage());
}
- // Content Source Sync Jobs
+ // Server Plugin Jobs
try {
ServerPluginServiceManagement mbean = LookupUtil.getServerPluginService();
MasterServerPluginContainer masterPC = mbean.getMasterPluginContainer();
- masterPC.getPluginContainer(ContentServerPluginContainer.class).scheduleSyncJobs();
+ masterPC.scheduleAllPluginJobs();
} catch (Exception e) {
- log("Cannot schedule content source sync jobs: " + e.getMessage());
+ log("Cannot schedule server plugin jobs: " + e.getMessage());
}
+
+ return;
}
/**
@@ -534,7 +535,7 @@ public class StartupServlet extends HttpServlet {
try {
ServerPluginServiceManagement mbean = LookupUtil.getServerPluginService();
- mbean.startMasterPluginContainer();
+ mbean.startMasterPluginContainerWithoutSchedulingJobs();
} catch (Exception e) {
throw new ServletException("Cannot start the master server plugin container!", e);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
index 6c39277..efe2100 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -126,7 +126,7 @@ abstract class AbstractJobWrapper implements Job {
// no valid lifecycle listener that implements job interface - we need to unschedule this, do not refire
log.error(logMsg(pluginName, pluginType, jobId, "invaild lifecycle listener", t));
JobExecutionException jobException = new JobExecutionException(t, false);
- jobException.setUnscheduleFiringTrigger(true);
+ jobException.setUnscheduleAllTriggers(true);
throw jobException;
}
} else {
@@ -136,7 +136,7 @@ abstract class AbstractJobWrapper implements Job {
// invalid class - we need to unschedule this, do not refire since it will never work
log.error(logMsg(pluginName, pluginType, jobId, "invalid schedule job class", t));
JobExecutionException jobException = new JobExecutionException(t, false);
- jobException.setUnscheduleFiringTrigger(true);
+ jobException.setUnscheduleAllTriggers(true);
throw jobException;
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index ea0b5a6..606da06 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -174,6 +174,45 @@ public abstract class AbstractTypeServerPluginContainer {
}
/**
+ * If a plugin has scheduled jobs, this method will schedule them now.
+ * This particular method implementation schedules the global job as defined in the
+ * plugin descriptors. If a plugin has a global scheduled job, its lifecycle listener
+ * will be the job handler class.
+ *
+ * Subclasses are free to extend this method to schedule additional plugin jobs, but must
+ * ensure they call this method so the global scheduled jobs get added to the scheduler.
+ *
+ * Note that this is separate from the {@link #start()} method because it is possible that
+ * the plugin container has been started before the scheduler has. In this case, the caller
+ * must wait for the scheduler to be started before this method is called to schedule jobs.
+ *
+ * @throws Exception if failed to schedule jobs
+ */
+ public synchronized void schedulePluginJobs() throws Exception {
+ if (this.pluginManager != null) {
+ // if there are any global schedules defined, schedule them now.
+ // note that we know if there is no lifecycle listener, then there can't be a global schedule
+ for (ServerPluginEnvironment pluginEnv : this.pluginManager.getPluginEnvironments()) {
+ String pluginName = pluginEnv.getPluginName();
+ if (this.pluginManager.getServerPluginLifecycleListener(pluginName) != null) {
+ Schedule schedule = this.pluginManager.getServerPluginContext(pluginEnv).getSchedule();
+ if (schedule != null) {
+ try {
+ scheduleJob(schedule, pluginName, "__globalScheduleJob", null, null);
+ } catch (Throwable t) {
+ log.warn("Failed to schedule the global plugin job for plugin [" + pluginName + "]", t);
+ }
+ }
+ }
+ }
+ } else {
+ throw new Exception("Cannot schedule plugins jobs; plugin container is not initialized yet");
+ }
+
+ return;
+ }
+
+ /**
* This will be called when its time for this plugin container to create its plugin manager.
* Subclasses are free to override this if they need their own specialized plugin manager.
*
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index 878b149..4d0d314 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -194,6 +194,29 @@ public class MasterServerPluginContainer {
}
/**
+ * Asks that all plugin containers schedule jobs now, if needed.
+ * Note that this is separate from the {@link #initialize(MasterServerPluginContainerConfiguration)}
+ * method because it is possible that the master plugin container has been
+ * initialized before the scheduler is started. In this case, the caller must wait for the scheduler to
+ * be started before this method is called to schedule jobs.
+ */
+ public synchronized void scheduleAllPluginJobs() {
+ log.debug("Master server plugin container will schedule all jobs now");
+
+ for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
+ try {
+ pc.schedulePluginJobs();
+ } catch (Exception e) {
+ log.error("Server plugin container for plugin type [" + pc.getSupportedServerPluginType()
+ + "] failed to scheduled some or all of its jobs", e);
+ }
+ }
+
+ log.info("Master server plugin container scheduled all jobs");
+ return;
+ }
+
+ /**
* Returns the configuration that this object was initialized with. If this plugin container was not
* {@link #initialize(MasterServerPluginContainerConfiguration) initialized} or has been {@link #shutdown() shutdown},
* this will return <code>null</code>.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index 70cd665..1c31b8d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -42,6 +42,7 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
*
* @author John Mazzitelli
*/
+//TODO: need a R/W lock to make this class thread safe
public class ServerPluginManager {
private final Log log = LogFactory.getLog(this.getClass());
@@ -82,7 +83,7 @@ public class ServerPluginManager {
*
* @throws Exception if failed to initialize
*/
- public synchronized void initialize() throws Exception {
+ public void initialize() throws Exception {
log.debug("Plugin manager initializing");
return; // no-op
}
@@ -91,7 +92,7 @@ public class ServerPluginManager {
* Shuts down this manager. This should be called only after all of its plugins
* have been {@link #unloadPlugin(ServerPluginEnvironment) unloaded}.
*/
- public synchronized void shutdown() {
+ public void shutdown() {
log.debug("Plugin manager shutting down");
if (this.loadedPlugins.size() > 0) {
@@ -114,7 +115,7 @@ public class ServerPluginManager {
*
* @throws Exception if the plugin manager cannot load the plugin or deems the plugin invalid
*/
- public synchronized void loadPlugin(ServerPluginEnvironment env) throws Exception {
+ public void loadPlugin(ServerPluginEnvironment env) throws Exception {
String pluginName = env.getPluginName();
log.debug("Loading server plugin [" + pluginName + "] from: " + env.getPluginUrl());
@@ -141,7 +142,7 @@ public class ServerPluginManager {
return;
}
- public synchronized void startPlugins() {
+ public void startPlugins() {
log.debug("Starting plugins");
// tell all lifecycle listeners to start
@@ -161,23 +162,10 @@ public class ServerPluginManager {
}
}
- // if there are any global schedules defined, schedule them now.
- // note that we know if there is no lifecycle listener, then there can't be a schedule
- for (String pluginName : this.pluginLifecycleListenerCache.keySet()) {
- Schedule schedule = getServerPluginContext(this.loadedPlugins.get(pluginName)).getSchedule();
- if (schedule != null) {
- try {
- this.parentPluginContainer.scheduleJob(schedule, pluginName, "__globalScheduleJob", null, null);
- } catch (Throwable t) {
- log.warn("Failed to schedule the global plugin job for plugin [" + pluginName + "]", t);
- }
- }
- }
-
return;
}
- public synchronized void stopPlugins() {
+ public void stopPlugins() {
log.debug("Stopping plugins");
// tell all lifecycle listeners to stop
@@ -208,7 +196,7 @@ public class ServerPluginManager {
*
* @throws Exception if the plugin manager cannot unload the plugin
*/
- public synchronized void unloadPlugin(ServerPluginEnvironment env) throws Exception {
+ public void unloadPlugin(ServerPluginEnvironment env) throws Exception {
String pluginName = env.getPluginName();
log.debug("Unloading server plugin [" + pluginName + "]");
@@ -241,7 +229,7 @@ public class ServerPluginManager {
*
* @return environments for all the plugins
*/
- public synchronized Collection<ServerPluginEnvironment> getPluginEnvironments() {
+ public Collection<ServerPluginEnvironment> getPluginEnvironments() {
return new ArrayList<ServerPluginEnvironment>(this.loadedPlugins.values());
}
@@ -254,7 +242,7 @@ public class ServerPluginManager {
* @param pluginName the plugin whose environment is to be returned
* @return given plugin's environment
*/
- public synchronized ServerPluginEnvironment getPluginEnvironment(String pluginName) {
+ public ServerPluginEnvironment getPluginEnvironment(String pluginName) {
return this.loadedPlugins.get(pluginName);
}
@@ -268,7 +256,7 @@ public class ServerPluginManager {
* return <code>null</code> if the plugin has not defined a lifecycle listener.
* <code>null</code> is also returned if the plugin is not initialized yet.
*/
- public synchronized ServerPluginLifecycleListener getServerPluginLifecycleListener(String pluginName) {
+ public ServerPluginLifecycleListener getServerPluginLifecycleListener(String pluginName) {
return this.pluginLifecycleListenerCache.get(pluginName);
}
@@ -280,7 +268,7 @@ public class ServerPluginManager {
return this.log;
}
- protected synchronized ServerPluginContext getServerPluginContext(ServerPluginEnvironment env) {
+ protected ServerPluginContext getServerPluginContext(ServerPluginEnvironment env) {
String pluginName = env.getPluginName();
ServerPluginContext context = this.pluginContextCache.get(pluginName);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
index d6bae90..0c80dcb 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
@@ -60,6 +60,7 @@ public class ServerPluginService implements ServerPluginServiceManagement {
if (this.masterPluginContainer == null) {
log.debug("The server plugin service is now starting the master server plugin container");
this.masterPluginContainer = createMasterPluginContainer();
+ this.masterPluginContainer.scheduleAllPluginJobs();
}
return;
@@ -90,6 +91,21 @@ public class ServerPluginService implements ServerPluginServiceManagement {
startMasterPluginContainer();
}
+ public synchronized void startMasterPluginContainerWithoutSchedulingJobs() {
+ if (!this.started) {
+ throw new IllegalStateException(
+ "The server plugin service is not started - cannot start the master plugin container!");
+ }
+
+ // only initialize if not already started; if already started/initialized, just ignore
+ if (this.masterPluginContainer == null) {
+ log.debug("The server plugin service is now starting the master server plugin container!");
+ this.masterPluginContainer = createMasterPluginContainer();
+ }
+
+ return;
+ }
+
public MasterServerPluginContainer getMasterPluginContainer() {
return this.masterPluginContainer;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java
index 8db19a8..490c9fd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginServiceManagement.java
@@ -45,9 +45,12 @@ public interface ServerPluginServiceManagement {
void stop();
/**
- * Starts the {@link #getMasterPluginContainer() master plugin container} which will load in all plugins and start them. You
- * cannot start the plugin container unless this service has {@link #start() been started}. If the master plugin container
- * {@link #isMasterPluginContainerStarted() is already started}, this does nothing and returns.
+ * Starts the {@link #getMasterPluginContainer() master plugin container} which will load in all plugins, start them and then
+ * schedule all jobs for all plugins. You cannot start the plugin container unless this service has
+ * {@link #start() been started}. If the master plugin container {@link #isMasterPluginContainerStarted() is already started},
+ * this does nothing and returns. You must ensure the job scheduler is started prior to calling this method.
+ *
+ * @see #startMasterPluginContainerWithoutSchedulingJobs()
*/
void startMasterPluginContainer();
@@ -63,6 +66,17 @@ public interface ServerPluginServiceManagement {
void restartMasterPluginContainer();
/**
+ * Similar to {@link #startMasterPluginContainer()}, but this will not tell the master plugin container
+ * to {@link MasterServerPluginContainer#scheduleAllPluginJobs() schedule any jobs} yet. Usually this is only
+ * called when the server itself is starting up and it wants to start the master PC but it has not yet
+ * started the scheduler. In this case, after this method is called, the caller must ensure the scheduler is
+ * started and then tell the master PC to schedule all its plugin jobs.
+ *
+ * @see #startMasterPluginContainer()
+ */
+ void startMasterPluginContainerWithoutSchedulingJobs();
+
+ /**
* Returns the master server plugin container that will be responsible for managing all plugins of all types and their classloaders.
*
* @return the master plugin container, if started. Will be <code>null</code> if not started
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
index 3edba4d..e32e858 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
@@ -73,6 +73,13 @@ public class ContentServerPluginContainer extends AbstractTypeServerPluginContai
}
@Override
+ public void schedulePluginJobs() throws Exception {
+ super.schedulePluginJobs();
+ scheduleSyncJobs();
+ return;
+ }
+
+ @Override
public ServerPluginType getSupportedServerPluginType() {
return new ServerPluginType(ContentPluginDescriptorType.class);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerService.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerService.java
index 1398a03..1856fdd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerService.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/SchedulerService.java
@@ -45,7 +45,7 @@ import org.quartz.impl.StdSchedulerFactory;
import org.quartz.spi.JobFactory;
/**
- * Scheduler MBean service that simply wraps the Quartz scheduler. This expects to wrap Quartz 1.5.2.
+ * Scheduler MBean service that simply wraps the Quartz scheduler.
*/
public class SchedulerService implements SchedulerServiceMBean, MBeanRegistration {
private Log log = LogFactory.getLog(SchedulerService.class);
commit 01aba910e8cf123f8b1c94f27ad6d8d520a50860
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Thu Nov 12 13:12:14 2009 -0800
807 - removing uneeded configs
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/resources/META-INF/rhq-serverplugin.xml b/modules/enterprise/server/plugins/rhnhosted/src/main/resources/META-INF/rhq-serverplugin.xml
index 06f2649..3862097 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -30,20 +30,6 @@
<!--<c:group name="repos" displayName="repo list">
<c:simple-property name="repos" type="string" default="rhn-tools-rhel-i386-server-5"/>
</c:group>-->
-
- <c:simple-property name="SyncableChannels" required="true" default="rhel-i386-server-vt-5"
- description="list of syncable channels.">
- <c:property-options>
- <c:option name="rhel-i386-server-5" value="rhel-i386-server-5"/>
- <c:option name="rhn-tools-rhel-i386-server-5" value="rhn-tools-rhel-i386-server-5"/>
- <c:option name="rhel-i386-server-vt-5" value="rhel-i386-server-vt-5"/>
- <c:option name="rhel-x86_64-server-5" value="rhel-x86_64-server-5"/>
- <c:option name="rhn-tools-rhel-x86_64-server-5" value="rhn-tools-rhel-x86_64-server-5"/>
- <c:option name="rhel-x86_64-server-vt-5" value="rhel-x86_64-server-vt-5"/>
- </c:property-options>
- </c:simple-property>
-
-
</configuration>
</contentSourceType>
commit 71ab7a94943035153fea104830e23792b40b49f3
Author: Pradeep Kilambi <pkilambi(a)redhat.com>
Date: Thu Nov 12 15:59:13 2009 -0500
helper calls to access distribution files by distro
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java
index f2d51ab..e07ca48 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java
@@ -36,6 +36,7 @@ import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.content.Distribution;
import org.rhq.core.domain.content.DistributionType;
import org.rhq.core.domain.content.RepoDistribution;
+import org.rhq.core.domain.content.DistributionFile;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.authz.AuthorizationManagerLocal;
import org.rhq.enterprise.server.authz.RequiredPermission;
@@ -162,6 +163,51 @@ public class DistributionManagerBean implements DistributionManagerLocal, Distri
}
/**
+ * Returns a list of available distribution files for requested distribution
+ * @param distId
+ * @return A list of Distributionfile objects associated to a given distribution
+ */
+ @SuppressWarnings("unchecked")
+ public List<DistributionFile> getDistributionFilesByDistId(int distId) {
+ Query query = entityManager.createNamedQuery(DistributionFile.SELECT_BY_DIST_ID);
+
+ query.setParameter("distId", distId);
+ List<DistributionFile> results = query.getResultList();
+
+ if (results.size() > 0) {
+ return results;
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * deletes list of available distribution files for requested distribution
+ * @param distId
+ */
+ @SuppressWarnings("unchecked")
+ public void deleteDistributionFilesByDistId(Subject user, int distId) {
+ log.debug("User [" + user + "] is deleting distribution file from distribution [" + distId + "]");
+
+ entityManager.flush();
+ entityManager.clear();
+
+ Query querydel = entityManager.createNamedQuery(DistributionFile.SELECT_BY_DIST_ID);
+
+ querydel.setParameter("distId", distId);
+
+ querydel.executeUpdate();
+
+ DistributionFile distFile = entityManager.find(DistributionFile.class, distId);
+ if (distFile != null) {
+ entityManager.remove(distFile);
+ log.debug("User [" + user + "] deleted distribution file [" + distFile + "]");
+ } else {
+ log.debug("Distribution file [" + distFile + "] doesn't exist - nothing to delete");
+ }
+ }
+
+ /**
* validates a given kickstart tree object and throws a KickstartTreeException
* @param kstree kickstart tree object
* @throws DistributionException
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerLocal.java
index 3867085..10b0fd8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerLocal.java
@@ -24,6 +24,9 @@ import javax.ejb.Local;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.content.Distribution;
import org.rhq.core.domain.content.DistributionType;
+import org.rhq.core.domain.content.DistributionFile;
+
+import java.util.List;
/**
* @author Pradeep Kilambi
@@ -78,4 +81,18 @@ public interface DistributionManagerLocal {
*/
Distribution getDistributionByPath(String basepath);
+ /**
+ * get list of distribution files
+ * @param distid
+ * @return list of distro file by dist id
+ */
+ List<DistributionFile> getDistributionFilesByDistId(int distid);
+
+ /**
+ * delete list of distribution files
+ * @param subject
+ * @param distid
+ *
+ */
+ void deleteDistributionFilesByDistId(Subject subject, int distid);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerRemote.java
index 6787017..6707075 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerRemote.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerRemote.java
@@ -27,8 +27,11 @@ import javax.jws.soap.SOAPBinding;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.content.Distribution;
import org.rhq.core.domain.content.DistributionType;
+import org.rhq.core.domain.content.DistributionFile;
import org.rhq.enterprise.server.system.ServerVersion;
+import java.util.List;
+
/**
* @author Pradeep Kilambi
*/
@@ -99,4 +102,22 @@ public interface DistributionManagerRemote {
*/
@WebMethod
Distribution getDistributionByPath(@WebParam(name = "basepath") String basepath);
+
+ /**
+ * get distribution file based on distro id
+ * @param distid
+ * @return
+ */
+ @WebMethod
+ List<DistributionFile> getDistributionFilesByDistId(@WebParam(name = "distid") int distid);
+
+ /**
+ * delete distribution file based on distro id
+ * @param distid
+ */
+ @WebMethod
+ void deleteDistributionFilesByDistId(@WebParam(name = "subject") Subject subject, //
+ @WebParam(name = "distid") int distid);
+
+
}
commit 143993ccb56e4e7909802c12bbce00a15d7ad87c
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Thu Nov 12 12:25:36 2009 -0800
800 - missing nav for the import button
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/content-navigation.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/content-navigation.xml
index 861683c..0910c04 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/content-navigation.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/content-navigation.xml
@@ -200,6 +200,12 @@
<to-view-id>/rhq/content/createRepo.xhtml</to-view-id>
<redirect/>
</navigation-case>
+
+ <navigation-case>
+ <from-outcome>importRepos</from-outcome>
+ <to-view-id>/rhq/content/importRepos.xhtml</to-view-id>
+ <redirect/>
+ </navigation-case>
<navigation-case>
<!-- sorting rule -->
commit 7c73c85e13abb9f0d092e2eeb40a56d12ef374ac
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Thu Nov 12 10:54:54 2009 -0800
fixing jar building phase so we get the deps every time
diff --git a/modules/enterprise/server/plugins/rhnhosted/pom.xml b/modules/enterprise/server/plugins/rhnhosted/pom.xml
index 738269f..8ff4be6 100644
--- a/modules/enterprise/server/plugins/rhnhosted/pom.xml
+++ b/modules/enterprise/server/plugins/rhnhosted/pom.xml
@@ -207,7 +207,7 @@
<execution>
<id>deploy</id>
- <phase>compile</phase>
+ <phase>package</phase>
<configuration>
<tasks>
<mkdir dir="${rhq.deploymentDir}" />
commit 1fa605eee3aa3a00c6bca12712bcb67973879182
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Wed Nov 11 14:27:21 2009 -0800
removing uneeded path
diff --git a/.classpath b/.classpath
index 7e33945..0b53527 100644
--- a/.classpath
+++ b/.classpath
@@ -91,7 +91,6 @@
<classpathentry kind="src" path="modules/plugins/sudoers/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/postfix/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/postfix/src/main/java"/>
- <classpathentry kind="src" path="modules/plugins/cron/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/cron/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/hudson/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/platform/src/test/java"/>
commit 7c13c5ad3725fa53a2bde180031f7e22cbe513ab
Author: Sayli Karmarkar <skarmark(a)redhat.com>
Date: Thu Nov 12 12:55:28 2009 -0500
bug 536811 - fixed db errors when deleting repo
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoTag.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoTag.java
new file mode 100644
index 0000000..6c65cc4
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoTag.java
@@ -0,0 +1,129 @@
+/*
+ * 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.content;
+
+import java.io.Serializable;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+import org.rhq.core.domain.common.Tag;
+
+/**
+ * This is the many-to-many entity that correlates a repo with a tag.
+ * It is an explicit relationship mapping entity between {@link Repo}
+ * and {@link Tag}.
+ *
+ * @author Sayli Karmarkar
+ */
+
+@Entity
+(a)IdClass(RepoTagPK.class)
+@Table(name = "RHQ_REPO_TAG_MAP")
+public class RepoTag implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /*
+ * http://opensource.atlassian.com/projects/hibernate/browse/EJB-286 Hibernate seems to want these mappings in the
+ * @IdClass and ignore these here, even though the mappings should be here and no mappings should be needed in the
+ * @IdClass.
+ */
+ @Id
+ @ManyToOne
+ @JoinColumn(name = "REPO_ID", referencedColumnName = "ID", nullable = false, insertable = false, updatable = false)
+ private Repo repo;
+
+ @Id
+ @ManyToOne
+ @JoinColumn(name = "TAG_ID", referencedColumnName = "ID", nullable = false, insertable = false, updatable = false)
+ private Tag tag;
+
+ protected RepoTag() {
+ }
+
+ public RepoTag(Repo repo, Tag tag) {
+ this.repo = repo;
+ this.tag = tag;
+ }
+
+ public RepoTagPK getRepoTagPK() {
+ return new RepoTagPK(repo, tag);
+ }
+
+ public void setRepoTagPK(RepoTagPK pk) {
+ this.repo = pk.getRepo();
+ this.tag = pk.getTag();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder("RepoTag: ");
+ str.append(", rp=[").append(this.repo).append("]");
+ str.append(", tg=[").append(this.tag).append("]");
+ return str.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = (31 * result) + ((repo == null) ? 0 : repo.hashCode());
+ result = (31 * result) + ((tag == null) ? 0 : tag.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if ((obj == null) || (!(obj instanceof RepoTag))) {
+ return false;
+ }
+
+ final RepoTag other = (RepoTag) obj;
+
+ if (repo == null) {
+ if (repo != null) {
+ return false;
+ }
+ } else if (!repo.equals(other.repo)) {
+ return false;
+ }
+
+ if (tag == null) {
+ if (tag != null) {
+ return false;
+ }
+ } else if (!tag.equals(other.tag)) {
+ return false;
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoTagPK.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoTagPK.java
new file mode 100644
index 0000000..7ac8dad
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoTagPK.java
@@ -0,0 +1,122 @@
+/*
+ * 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.content;
+
+import java.io.Serializable;
+
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+import org.rhq.core.domain.common.Tag;
+
+/**
+ * This is the composite primary key for the {@link RepoTag} entity. That entity is an explicit
+ * many-to-many mapping table, so this composite key is simply the foreign keys to both ends of that relationship.
+ *
+ * @author Sayli Karmarkar
+ */
+public class RepoTagPK implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /*
+ * http://opensource.atlassian.com/projects/hibernate/browse/EJB-286 Hibernate seems to want these mappings here,
+ * even though this class is an @IdClass and it should not need the mappings here. The mappings belong in the
+ * entity itself.
+ */
+
+ @JoinColumn(name = "REPO_ID", referencedColumnName = "ID", nullable = false)
+ @ManyToOne
+ private Repo repo;
+
+ @JoinColumn(name = "TAG_ID", referencedColumnName = "ID", nullable = false)
+ @ManyToOne
+ private Tag tag;
+
+ public RepoTagPK() {
+ }
+
+ public RepoTagPK(Repo repo, Tag tag) {
+ this.repo = repo;
+ this.tag = tag;
+ }
+
+ public Repo getRepo() {
+ return repo;
+ }
+
+ public void setRepo(Repo repo) {
+ this.repo = repo;
+ }
+
+ public Tag getTag() {
+ return tag;
+ }
+
+ public void setTag(Tag tag) {
+ this.tag = tag;
+ }
+
+ @Override
+ public String toString() {
+ return "RepoTagPK: repo=[" + repo + "]; tag=[" + tag + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = (31 * result) + ((repo == null) ? 0 : repo.hashCode());
+ result = (31 * result) + ((tag == null) ? 0 : tag.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if ((obj == null) || (!(obj instanceof RepoTagPK))) {
+ return false;
+ }
+
+ final RepoTagPK other = (RepoTagPK) obj;
+
+ if (repo == null) {
+ if (other.repo != null) {
+ return false;
+ }
+ } else if (!repo.equals(other.repo)) {
+ return false;
+ }
+
+ if (tag == null) {
+ if (other.tag != null) {
+ return false;
+ }
+ } else if (!tag.equals(other.tag)) {
+ return false;
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
commit 23f8a9850dae8105a48b8f30da01dd63cf0bf3a1
Author: Sayli Karmarkar <skarmark(a)redhat.com>
Date: Thu Nov 12 12:52:50 2009 -0500
bug 536811 - content source and package associations not needed for this sprint - once we have tagging feature and repo - resource tag model approved, we can just replicate it with other domain objects
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
index fe4d6e7..9a57ba8 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
@@ -49,8 +49,6 @@ import javax.persistence.PreUpdate;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
-import org.rhq.core.domain.common.Tag;
-import org.rhq.core.domain.common.Taggable;
import org.rhq.core.domain.configuration.Configuration;
/**
@@ -80,7 +78,7 @@ import org.rhq.core.domain.configuration.Configuration;
+ " WHERE ccs.repo.id = :repoId ) ") })
@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_CONTENT_SOURCE_ID_SEQ")
@Table(name = "RHQ_CONTENT_SOURCE")
-public class ContentSource implements Serializable, Taggable {
+public class ContentSource implements Serializable {
public static final String QUERY_FIND_ALL = "ContentSource.findAll";
public static final String QUERY_FIND_ALL_WITH_CONFIG = "ContentSource.findAllWithConfig";
public static final String QUERY_FIND_BY_NAME_AND_TYPENAME = "ContentSource.findByNameAndTypeName";
@@ -140,9 +138,6 @@ public class ContentSource implements Serializable, Taggable {
@OneToMany(mappedBy = "contentSource", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private Set<RepoContentSource> repoContentSources;
- @OneToMany()
- private Set<Tag> tags;
-
// Constructor
public ContentSource() {
@@ -448,46 +443,4 @@ public class ContentSource implements Serializable, Taggable {
return true;
}
- public Set<Tag> getTags() {
- return tags;
- }
-
- public void setTags(Set<Tag> tags) {
- this.tags = tags;
- }
-
- public boolean hasTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
- return false;
- }
-
- if (name == null) {
- if (tag.getName() != null) {
- return false;
- }
- } else if (!name.equals(tag.getName())) {
- return false;
- }
-
- return true;
-
- }
-
- public void addTag(Tag tag) {
- if (this.tags == null) {
- this.tags = new HashSet<Tag>();
- }
-
- this.tags.add(tag);
- }
-
- public void removeTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
- return;
- }
-
- if (tags.contains(tag)) {
- tags.remove(tag);
- }
- }
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
index 20e6d7d..1ac8126 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
@@ -24,9 +24,7 @@ package org.rhq.core.domain.content;
import java.io.Serializable;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
@@ -44,9 +42,6 @@ import javax.persistence.Table;
import org.hibernate.annotations.NamedQueries;
import org.hibernate.annotations.NamedQuery;
-import org.rhq.core.domain.common.Tag;
-import org.rhq.core.domain.common.Taggable;
-
/**
* Represents a package inventoried in the system. A package can be created by either a {@link ContentSource} (on the
* server side) or via a plugin discovery (on the agent side). A package has no knowledge of how it was created (i.e. it
@@ -69,7 +64,7 @@ import org.rhq.core.domain.common.Taggable;
+ "AND p.packageType.resourceType.id = :resourceTypeId") })
@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_PACKAGE_ID_SEQ")
@Table(name = "RHQ_PACKAGE")
-public class Package implements Serializable, Taggable {
+public class Package implements Serializable {
// Constants --------------------------------------------
private static final long serialVersionUID = 1L;
@@ -98,9 +93,6 @@ public class Package implements Serializable, Taggable {
@OneToMany(mappedBy = "generalPackage", fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
private List<PackageVersion> versions;
- @OneToMany()
- private Set<Tag> tags;
-
// Constructor ----------------------------------------
public Package() {
@@ -221,46 +213,4 @@ public class Package implements Serializable, Taggable {
return result;
}
- public Set<Tag> getTags() {
- return tags;
- }
-
- public void setTags(Set<Tag> tags) {
- this.tags = tags;
- }
-
- public boolean hasTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
- return false;
- }
-
- if (name == null) {
- if (tag.getName() != null) {
- return false;
- }
- } else if (!name.equals(tag.getName())) {
- return false;
- }
-
- return true;
-
- }
-
- public void addTag(Tag tag) {
- if (this.tags == null) {
- this.tags = new HashSet<Tag>();
- }
-
- this.tags.add(tag);
- }
-
- public void removeTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
- return;
- }
-
- if (tags.contains(tag)) {
- tags.remove(tag);
- }
- }
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
index 5dfd421..0c4b284 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
@@ -66,8 +66,6 @@ import org.jetbrains.annotations.Nullable;
import org.rhq.core.domain.alert.AlertDefinition;
import org.rhq.core.domain.auth.Subject;
-import org.rhq.core.domain.common.Tag;
-import org.rhq.core.domain.common.Taggable;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PluginConfigurationUpdate;
import org.rhq.core.domain.configuration.ResourceConfigurationUpdate;
@@ -731,7 +729,7 @@ import org.rhq.core.domain.util.serial.ExternalizableStrategy;
@Table(name = "RHQ_RESOURCE")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
-public class Resource implements Comparable<Resource>, Externalizable, Taggable {
+public class Resource implements Comparable<Resource>, Externalizable {
public static final String QUERY_FIND_PROBLEM_RESOURCES_ALERT = "Resource.findProblemResourcesAlert";
public static final String QUERY_FIND_PROBLEM_RESOURCES_ALERT_ADMIN = "Resource.findProblemResourcesAlert_admin";
public static final String QUERY_FIND_PROBLEM_RESOURCES_ALERT_COUNT = "Resource.findProblemResourcesAlertCount";
@@ -1019,9 +1017,6 @@ public class Resource implements Comparable<Resource>, Externalizable, Taggable
@ManyToOne(fetch = FetchType.LAZY)
private ProductVersion productVersion;
- @OneToMany()
- private Set<Tag> tags;
-
public Resource() {
this.uuid = UUID.randomUUID().toString();
}
@@ -1812,48 +1807,4 @@ public class Resource implements Comparable<Resource>, Externalizable, Taggable
public void initCurrentAvailability() {
this.currentAvailability = new ResourceAvailability(this, null);
}
-
- public Set<Tag> getTags() {
- return tags;
- }
-
- public void setTags(Set<Tag> tags) {
- this.tags = tags;
- }
-
- public boolean hasTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
- return false;
- }
-
- if (name == null) {
- if (tag.getName() != null) {
- return false;
- }
- } else if (!name.equals(tag.getName())) {
- return false;
- }
-
- return true;
-
- }
-
- public void addTag(Tag tag) {
- if (this.tags == null) {
- this.tags = new HashSet<Tag>();
- }
-
- this.tags.add(tag);
- }
-
- public void removeTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
- return;
- }
-
- if (tags.contains(tag)) {
- tags.remove(tag);
- }
- }
-
}
commit c32f832f78fe4461105491c68a6aff6320da8f21
Merge: b71712f... 86f71d8...
Author: Sayli Karmarkar <skarmark(a)redhat.com>
Date: Thu Nov 12 12:44:50 2009 -0500
Merge branch 'content' of git+ssh://git.fedorahosted.org/git/rhq/rhq into mycontent
commit b71712fcb18bb7a783b36cb17f4607d9f264252d
Author: Sayli Karmarkar <skarmark(a)redhat.com>
Date: Thu Nov 12 12:42:44 2009 -0500
bug 536811 - fixed db errors when deleting repo
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index a35452d..9ac94d7 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -22,7 +22,7 @@
<properties>
<scm.module.path>modules/core/dbutils/</scm.module.path>
- <db.schema.version>2.65</db.schema.version>
+ <db.schema.version>2.66</db.schema.version>
</properties>
<dependencies>
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml
index 8b2d89f..d7c510b 100644
--- a/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml
+++ b/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml
@@ -366,7 +366,19 @@
<field ref="RELATIVE_FILENAME"/>
</index>
</table>
-
+
+
+ <table name="RHQ_REPO_TAG_MAP">
+ <column name="REPO_ID" type="INTEGER" required="true" references="RHQ_REPO"/>
+ <column name="TAG_ID" type="INTEGER" required="true" references="RHQ_TAG"/>
+
+ <constraint name="RHQ_REPO_TAG_MAP_KEY">
+ <primaryKey>
+ <field ref="REPO_ID"/>
+ <field ref="TAG_ID"/>
+ </primaryKey>
+ </constraint>
+ </table>
</dbsetup>
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 2c8f5f2..ad4fe56 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -2079,6 +2079,49 @@
</schema-directSQL>
</schemaSpec>
+
+
+ <!-- RHQ_REPO_TAG_MAP -->
+ <schemaSpec version="2.66">
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_REPO_TAG_MAP ( REPO_ID INTEGER )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_REPO_TAG_MAP" column="REPO_ID" nullable="false" />
+ <schema-addColumn table="RHQ_REPO_TAG_MAP" column="TAG_ID" columnType="INTEGER" />
+ <schema-alterColumn table="RHQ_REPO_TAG_MAP" column="TAG_ID" nullable="false" />
+ <schema-directSQL>
+ <statement>
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD CONSTRAINT RHQ_REPO_TAG_MAP_KEY
+ PRIMARY KEY ( REPO_ID, TAG_ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD CONSTRAINT RHQ_REPO_TAG_MAP_REPO_ID_FKEY
+ FOREIGN KEY ( REPO_ID )
+ REFERENCES RHQ_REPO ( ID )
+ </statement>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD FOREIGN KEY ( REPO_ID )
+ REFERENCES RHQ_REPO ( ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD CONSTRAINT RHQ_REPO_TAG_MAP_TAG_ID_FKEY
+ FOREIGN KEY ( TAG_ID )
+ REFERENCES RHQ_TAG ( ID )
+ </statement>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_REPO_TAG_MAP
+ ADD FOREIGN KEY ( TAG_ID )
+ REFERENCES RHQ_TAG ( ID )
+ </statement>
+ </schema-directSQL>
+ </schemaSpec>
+
</dbupgrade>
</target>
</project>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/common/Taggable.java b/modules/core/domain/src/main/java/org/rhq/core/domain/common/Taggable.java
index fce4f88..3c831dd 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/common/Taggable.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/common/Taggable.java
@@ -28,7 +28,7 @@ public interface Taggable {
public Set<Tag> getTags();
- void setTags(Set<Tag> tags);
+ public void setTags(Set<Tag> tags);
public boolean hasTag(Tag tag);
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
index f041a93..8fe6b63 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
@@ -143,8 +143,8 @@ public class Repo implements Serializable, Taggable {
@OneToMany(mappedBy = "repo", fetch = FetchType.LAZY)
private Set<RepoRepoRelationship> repoRepoRelationships;
- @OneToMany()
- private Set<Tag> tags;
+ @OneToMany(mappedBy = "repo", fetch = FetchType.LAZY)
+ private Set<RepoTag> repoTags;
@Transient
private String syncStatus;
@@ -680,46 +680,95 @@ public class Repo implements Serializable, Taggable {
this.lastModifiedDate = System.currentTimeMillis();
}
- public Set<Tag> getTags() {
- return tags;
+ public Set<RepoTag> getRepoTags() {
+ return repoTags;
}
- public void setTags(Set<Tag> tags) {
- this.tags = tags;
+ public void setRepoTags(Set<RepoTag> tags) {
+ this.repoTags = repoTags;
}
public boolean hasTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
+ if ((this.repoTags == null) || (tag == null)) {
return false;
}
- if (name == null) {
- if (tag.getName() != null) {
- return false;
+ for (RepoTag rt : this.repoTags) {
+ if (tag.equals(rt.getRepoTagPK().getTag())) {
+ return true;
}
- } else if (!name.equals(tag.getName())) {
- return false;
}
+ return false;
- return true;
+ }
+ /**
+ * The tags associated with this repo.
+ */
+ public Set<Tag> getTags() {
+ HashSet<Tag> tags = new HashSet<Tag>();
+
+ if (repoTags != null) {
+ for (RepoTag rt : repoTags) {
+ tags.add(rt.getRepoTagPK().getTag());
+ }
+ }
+
+ return tags;
}
+ /**
+ * Add a tag association with this repo.
+ *
+ * @param tag
+ */
public void addTag(Tag tag) {
- if (this.tags == null) {
- this.tags = new HashSet<Tag>();
+ if (this.repoTags == null) {
+ this.repoTags = new HashSet<RepoTag>();
}
- this.tags.add(tag);
+ RepoTag mapping = new RepoTag(this, tag);
+ this.repoTags.add(mapping);
}
+ /**
+ * Set tag associations with this repo.
+ *
+ * @param tag
+ */
+ public void setTags(Set<Tag> tags) {
+ if (this.repoTags == null) {
+ this.repoTags = new HashSet<RepoTag>();
+ } else {
+ this.repoTags.clear();
+ }
+
+ for (Tag t : tags) {
+ RepoTag mapping = new RepoTag(this, t);
+ this.repoTags.add(mapping);
+ }
+
+ }
+
+ /**
+ * Removes association with a tag, if it exists.
+ */
public void removeTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
+ if ((this.repoTags == null) || (tag == null)) {
return;
}
- if (tags.contains(tag)) {
- tags.remove(tag);
+ RepoTag doomed = null;
+
+ for (RepoTag rt : this.repoTags) {
+ if (tag.equals(rt.getRepoTagPK().getTag())) {
+ doomed = rt;
+ break;
+ }
+ }
+
+ if (doomed != null) {
+ this.repoTags.remove(doomed);
}
}
commit 86f71d89cb6a2a9a5ac7c35e6ac02583952980ba
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Thu Nov 12 12:29:19 2009 -0500
Migrated existing calls to add repos directly through EJB calls to use the RepoSource and scheduled sync functionality.
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
index c9cb853..2554b30 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
@@ -199,7 +199,7 @@ public class RHNHelper {
* @throws IOException on systemid reads
* @throws XmlRpcException on xmlrpc faults
*/
- public ArrayList getSyncableChannels() throws IOException, XmlRpcException {
+ public List<String> getSyncableChannels() throws IOException, XmlRpcException {
ArrayList<String> allchannels = new ArrayList();
List<RhnChannelFamilyType> cfts = rhndata.getChannelFamilies(this.systemid);
for (RhnChannelFamilyType cf : cfts) {
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
index 1bf47aa..7cbc0b9 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
@@ -46,6 +46,9 @@ import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
import org.rhq.enterprise.server.plugin.pc.content.DistributionSource;
import org.rhq.enterprise.server.plugin.pc.content.DistributionSyncReport;
import org.rhq.enterprise.server.plugin.pc.content.DistributionDetails;
+import org.rhq.enterprise.server.plugin.pc.content.RepoSource;
+import org.rhq.enterprise.server.plugin.pc.content.RepoImportReport;
+import org.rhq.enterprise.server.plugin.pc.content.RepoDetails;
import org.rhq.enterprise.server.plugins.rhnhosted.certificate.Certificate;
import org.rhq.enterprise.server.plugins.rhnhosted.certificate.CertificateFactory;
import org.rhq.enterprise.server.plugins.rhnhosted.certificate.PublicKeyRing;
@@ -55,7 +58,7 @@ import org.rhq.enterprise.server.plugins.rhnhosted.certificate.PublicKeyRing;
* @author pkilambi
*
*/
-public class RHNProvider implements ContentProvider, PackageSource, DistributionSource
+public class RHNProvider implements ContentProvider, PackageSource, RepoSource, DistributionSource
{
private final Log log = LogFactory.getLog(RHNProvider.class);
@@ -136,34 +139,17 @@ public class RHNProvider implements ContentProvider, PackageSource, Distribution
// RHQ Server is now active, initialize the handler for the bits.
helper = new RHNHelper(locationIn, repos, rhnObject.getSystemid());
log.info("RHNProvider initialized RHNHelper with repos: " + repos);
-
- // Now that the server is activated, spawn all syncable channels
- ArrayList<String> channels = helper.getSyncableChannels();
-
-
- // when running under a test we are restricting behavior to not setup up Repos through RHQ
- if (!testMode) {
- // Eventually we should pass in a subset of selected channels to spawn
- initializeRepos(channels);
- }
}
/**
- * Shutdown the adapter.
+ * @inheritDoc
*/
public void shutdown() {
log.debug("shutdown");
}
-
/**
- * Get an input stream for the specified package (bits).
- *
- * @param location The location relative to the baseurl.
- *
- * @return An open stream that <b>must</b> be closed by the caller.
- *
- * @throws Exception On all errors.
+ * @inheritDoc
*/
public InputStream getInputStream(String location) throws Exception {
log.debug("opening: " + location);
@@ -171,7 +157,7 @@ public class RHNProvider implements ContentProvider, PackageSource, Distribution
}
/**
- * Synchronize package content for selected channel labels
+ * @inheritDoc
*/
public void synchronizePackages(String repoName, PackageSyncReport report,
Collection<ContentProviderPackageDetails> existingPackages)
@@ -210,6 +196,9 @@ public class RHNProvider implements ContentProvider, PackageSource, Distribution
}
}
+ /**
+ * @inheritDoc
+ */
public void synchronizeDistribution(DistributionSyncReport report, Collection<DistributionDetails> existingDistros) throws Exception {
// Goal:
@@ -250,16 +239,30 @@ public class RHNProvider implements ContentProvider, PackageSource, Distribution
}
/**
- * Test's the adapter's connection.
- *
- * @throws Exception When connection is not functional for any reason.
- */
+ * @inheritDoc
+ */
public void testConnection() throws Exception {
rhnObject.processDeActivation();
rhnObject.processActivation();
}
/**
+ * @inheritDoc
+ */
+ public RepoImportReport importRepos() throws Exception {
+ RepoImportReport report = new RepoImportReport();
+
+ List<String> channels = helper.getSyncableChannels();
+ for (String clabel : channels) {
+ log.info("Importing repo: " + clabel);
+ RepoDetails repo = new RepoDetails(clabel);
+ report.addRepo(repo);
+ }
+
+ return report;
+ }
+
+ /**
* Reads the public keyring on filesystem into memory
*
* @return A PublicKeyRing object.
@@ -272,26 +275,6 @@ public class RHNProvider implements ContentProvider, PackageSource, Distribution
}
/**
- * Spawns a list of repos for all available channels from RHN hosted.
- * @param channels The list of channels to be initialized as repos
- * @throws RepoException
- */
- public void initializeRepos(ArrayList<String> channels) throws RepoException {
- log.info("list of channels: " + channels);
- if (channels.size() == 0) {
- // No repos to create
- return;
- }
- RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
- Subject subject = LookupUtil.getSubjectManager().getOverlord();
- for (String clabel : channels) {
- Repo newRepo = new Repo(clabel.toString());
- newRepo = repoManager.createCandidateRepo(subject, newRepo);
- log.info("New " + newRepo + " repo created");
- }
- }
-
- /**
* Trim white space and trailing (/) characters.
*
* @param path A url/directory path string.
commit a1c36f7c4efb5fd4e78c246c9e270bb55901e883
Merge: ccb085f... d3dfc1a...
Author: Partha Aji <paji(a)redhat.com>
Date: Thu Nov 12 12:26:11 2009 -0500
Merge branch 'master' into linux-config
commit f4d516a44f2026551b616314c17b901eded4a9f0
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Thu Nov 12 12:12:11 2009 -0500
Until this gets yanked out, changing to have it create candidate repos.
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
index 89702f4..1bf47aa 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
@@ -286,7 +286,7 @@ public class RHNProvider implements ContentProvider, PackageSource, Distribution
Subject subject = LookupUtil.getSubjectManager().getOverlord();
for (String clabel : channels) {
Repo newRepo = new Repo(clabel.toString());
- newRepo = repoManager.createRepo(subject, newRepo);
+ newRepo = repoManager.createCandidateRepo(subject, newRepo);
log.info("New " + newRepo + " repo created");
}
}
commit 08644de029a313e09673870395bf0a5f8607098b
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 11:47:39 2009 -0500
fix the operation names in the rhq server plugin
diff --git a/modules/plugins/rhq-server/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/rhq-server/src/main/resources/META-INF/rhq-plugin.xml
index 0700d83..3b0b5da 100644
--- a/modules/plugins/rhq-server/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/rhq-server/src/main/resources/META-INF/rhq-plugin.xml
@@ -313,15 +313,15 @@
<c:simple-property name="descriptionTemplate" default="Details on the server-side plugin container subsystem"/>
</plugin-configuration>
- <operation name="startMasterPluginContainer" displayName="Start Master Plugin Container"
+ <operation name="startMasterPluginContainer"
description="Starts the master plugin container which will load and initialize all server-side plugins.">
</operation>
- <operation name="stopMasterPluginContainer" displayName="Stop Master Plugin Container"
+ <operation name="stopMasterPluginContainer"
description="Stops the master plugin container which will shutdown all server-side plugins.">
</operation>
- <operation name="restartMasterPluginContainer" displayName="Restart Plugin Container"
+ <operation name="restartMasterPluginContainer"
description="Convienence operation that first stops and then immediately restarts the master plugin container.">
</operation>
commit ccb085f89d6a36787da1c570fbb7006672de68f9
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Thu Nov 12 11:45:14 2009 -0500
remove experimental hosts-augeas plugin, which is no longer needed
diff --git a/modules/plugins/hosts-augeas/pom.xml b/modules/plugins/hosts-augeas/pom.xml
deleted file mode 100644
index 0927981..0000000
--- a/modules/plugins/hosts-augeas/pom.xml
+++ /dev/null
@@ -1,218 +0,0 @@
-<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-plugins-parent</artifactId>
- <version>1.4.0-SNAPSHOT</version>
- </parent>
-
- <groupId>org.rhq</groupId>
- <artifactId>rhq-hosts-augeas-plugin</artifactId>
- <packaging>jar</packaging>
-
- <name>RHQ Augeas-based Hosts Plugin</name>
- <description>A plugin for managing the *nix hosts service</description>
-
- <scm>
- <connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/plugins/hosts-augeas</connection>
- <developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/plugins/hosts-augeas</developerConnection>
- </scm>
-
- <properties>
- <scm.module.path>modules/plugins/hosts/</scm.module.path>
- </properties>
-
- <dependencies>
-
- <dependency>
- <groupId>net.augeas</groupId>
- <artifactId>augeas</artifactId>
- <version>0.0.1</version>
- </dependency>
-
- <dependency>
- <groupId>com.sun.jna</groupId>
- <artifactId>jna</artifactId>
- <version>3.0.9</version>
- </dependency>
-
- </dependencies>
-
- <profiles>
- <profile>
- <id>integration-tests</id>
- <activation>
- <property>
- <name>maven.test.skip</name>
- <value>!true</value>
- </property>
- </activation>
-
- <build>
- <plugins>
- <plugin>
- <artifactId>maven-antrun-plugin</artifactId>
- <executions>
- <execution>
- <phase>pre-integration-test</phase>
- <configuration>
- <tasks>
- <echo>Setting up plugin dependencies for ${project.artifactId}-${project.version}.jar...
- </echo>
- <property name="settings.localRepository" location="${user.home}/.m2/repository" />
- <mkdir dir="target/itest" />
- <mkdir dir="target/itest/plugins" />
- <mkdir dir="target/itest/lib" />
- <copy toDir="target/itest/plugins" flatten="true">
- <fileset dir="${settings.localRepository}/">
- <include name="org/rhq/rhq-platform-plugin/${project.version}/rhq-platform-plugin-${project.version}.jar" />
- </fileset>
- <fileset dir="${project.build.directory}">
- <include name="${project.artifactId}-${project.version}.jar" />
- </fileset>
- </copy>
- <unzip dest="target/itest/lib">
- <fileset dir="${settings.localRepository}/org/hyperic/sigar-dist/${sigar.version}" includes="*.zip" />
- <patternset>
- <include name="**/lib/sigar.jar" />
- <include name="**/lib/bcel*.jar" />
- <include name="**/lib/*.so" />
- <include name="**/lib/*.sl" />
- <include name="**/lib/*.dll" />
- <include name="**/lib/*.dylib" />
- </patternset>
- </unzip>
- <move todir="target/itest/lib" flatten="true">
- <fileset dir="target/itest/lib">
- <include name="**/lib/*" />
- </fileset>
- </move>
- <delete dir="target/itest/lib/hyperic-sigar-${sigar.version}" />
- </tasks>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
-
- <!-- Integration testing voodoo to load and test this plugin with its plugin dependencies -->
- <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>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
- <!--<argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
- <systemProperties>
- <property>
- <name>project.artifactId</name>
- <value>${project.artifactId}</value>
- </property>
- <property>
- <name>project.version</name>
- <value>${project.version}</value>
- </property>
- </systemProperties>
- </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.deploymentDir>
- ${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/rhq-downloads/rhq-plugins
- </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>deploy-jar-meta-inf</id>
- <phase>package</phase>
- <configuration>
- <tasks>
- <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>
- </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>
-
- </profiles>
-
-</project>
diff --git a/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/HostsAugeasComponent.java b/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/HostsAugeasComponent.java
deleted file mode 100644
index 4f81218..0000000
--- a/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/HostsAugeasComponent.java
+++ /dev/null
@@ -1,260 +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.plugins.hosts;
-
-import java.io.File;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Date;
-import java.util.Set;
-
-import net.augeas.Augeas;
-
-import org.rhq.core.domain.configuration.ConfigurationUpdateStatus;
-import org.rhq.core.domain.configuration.Property;
-import org.rhq.core.pluginapi.inventory.ResourceComponent;
-import org.rhq.core.pluginapi.inventory.ResourceContext;
-import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
-import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
-import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
-import org.rhq.core.domain.measurement.AvailabilityType;
-import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.configuration.PropertySimple;
-import org.rhq.core.domain.configuration.PropertyList;
-import org.rhq.core.domain.configuration.PropertyMap;
-import org.rhq.plugins.hosts.util.AugeasUtility;
-
-/**
- * @author Jason Dobies, Ian Springer
- */
-public class HostsAugeasComponent implements ResourceComponent, ConfigurationFacet {
-
- private ResourceContext resourceContext;
- private File hostsFile;
-
- public void start(ResourceContext resourceContext) throws InvalidPluginConfigurationException, Exception {
- this.resourceContext = resourceContext;
-
- Configuration pluginConfiguration = resourceContext.getPluginConfiguration();
-
- PropertySimple hostsPathProperty = pluginConfiguration.getSimple("hosts-path");
-
- if (hostsPathProperty == null) {
- throw new InvalidPluginConfigurationException("Hosts path not found in the plugin configuration, cannot start resource component");
- }
-
- String hostsPath = hostsPathProperty.getStringValue();
-
- hostsFile = new File(hostsPath);
-
- if (!hostsFile.exists()) {
- throw new InvalidPluginConfigurationException("Hosts file not found at specified location: " + hostsPath);
- }
- }
-
- public void stop() {
- }
-
- public AvailabilityType getAvailability() {
- if (hostsFile == null) {
- return AvailabilityType.DOWN;
- }
-
- return hostsFile.exists() ? AvailabilityType.UP : AvailabilityType.DOWN;
- }
-
- public Configuration loadResourceConfiguration() throws Exception {
- Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
- return loadResourceConfiguration(pluginConfig);
- }
-
- Configuration loadResourceConfiguration(Configuration pluginConfig) throws Exception {
- Augeas augeas = createAugeas(pluginConfig);
- List<String> entryPaths = getEntryPaths(pluginConfig, augeas);
-
- Configuration resourceConfig = new Configuration();
- resourceConfig.setNotes("Loaded from Augeas at " + new Date());
-
- PropertyList entriesList = new PropertyList("entries");
- resourceConfig.put(entriesList);
-
- for (String entryPath : entryPaths) {
- String ip = augeas.get(entryPath + "/ipaddr");
- String canonical = augeas.get(entryPath + "/canonical");
- List<String> aliasPaths = augeas.match(entryPath + "/alias[*]");
-
- PropertyMap entry = new PropertyMap("entry");
- entry.put(new PropertySimple("ipAddress", ip));
- entry.put(new PropertySimple("canonicalName", canonical));
- if (!aliasPaths.isEmpty()) {
- StringBuilder aliasesPropValue = new StringBuilder();
- for (String aliasPath : aliasPaths) {
- String alias = augeas.get(aliasPath);
- aliasesPropValue.append(alias).append("\n");
- }
- // Chop the final newline char.
- aliasesPropValue.deleteCharAt(aliasesPropValue.length() - 1);
- entry.put(new PropertySimple("aliases", aliasesPropValue));
- }
- entriesList.add(entry);
- }
-
- return resourceConfig;
- }
-
- public void updateResourceConfiguration(ConfigurationUpdateReport report) {
- Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
- Augeas augeas;
- try {
- augeas = createAugeas(pluginConfig);
- }
- catch (Exception e) {
- throw new RuntimeException("Failed to create Augeas object.", e);
- }
-
- PropertySimple augeasTreeNodeProperty = pluginConfig.getSimple("augeas-hosts-path");
- if (augeasTreeNodeProperty == null) {
- throw new IllegalStateException("Augeas tree node not specified for hosts, cannot retrieve configuration");
- }
- String hostsPath = augeasTreeNodeProperty.getStringValue();
-
- Set<String> originalEntryPaths = new HashSet<String>(augeas.match("/files/etc/hosts/*"));
- Set<String> updatedEntryPaths = new HashSet<String>();
-
- Configuration resourceConfig = report.getConfiguration();
- PropertyList entriesList = resourceConfig.getList("entries");
- for (Property entryProp : entriesList.getList()) {
- PropertyMap entry = (PropertyMap)entryProp;
- String ipAddress = entry.getSimple("ipAddress").getStringValue();
- String canonicalName = entry.getSimple("canonicalName").getStringValue();
- String aliases = entry.getSimpleValue("aliases", null);
- Set<String> aliasSet;
- if (aliases == null) {
- aliasSet = null;
- } else {
- String[] aliasArray = aliases.trim().split("\\s+");
- aliasSet = new LinkedHashSet<String>(aliasArray.length);
- for (String alias : aliasArray) {
- aliasSet.add(alias);
- }
- }
-
- int newEntryIndex = 0;
- String newEntryPathPattern = hostsPath + "/0%d";
-
- String nameFilter = "/files/etc/hosts/*/canonical";
- List<String> namePaths = AugeasUtility.matchFilter(augeas, nameFilter, canonicalName);
- if (!namePaths.isEmpty()) {
- // overwrite existing entry
-
- // name
- String namePath = namePaths.get(0);
- augeas.set(namePath, canonicalName);
-
- String entryPath = AugeasUtility.getParentPath(namePath);
- updatedEntryPaths.add(entryPath);
-
- // IP
- String ipPath = entryPath + "/ipaddr";
- augeas.set(ipPath, canonicalName);
-
- // aliases
- // remove existing alias nodes first
- String aliasExpression = entryPath + "/alias[*]";
- List<String> aliasPaths = augeas.match(aliasExpression);
- for (String aliasPath : aliasPaths) {
- augeas.remove(aliasPath);
- }
- // then add the new ones
- String aliasPathPattern = entryPath + "/alias[%d]";
- int i = 1;
- for (String alias : aliasSet) {
- String aliasPath = String.format(aliasPathPattern, i++);
- augeas.set(aliasPath, alias);
- }
- } else {
- // no existing entry w/ this canonical name - add a new entry
- String newEntryPath = String.format(newEntryPathPattern, newEntryIndex++);
- augeas.set(newEntryPath + "/ipaddr", ipAddress);
- augeas.set(newEntryPath + "/canonical", canonicalName);
- String aliasPathPattern = newEntryPath + "/alias[%d]";
- int i = 1;
- for (String alias : aliasSet) {
- String aliasPath = String.format(aliasPathPattern, i++);
- augeas.set(aliasPath, alias);
- }
- }
-
- }
-
- // Remove any entries from the Augeas tree that are not present in the updated Configuration.
- for (String originalEntryPath : originalEntryPaths) {
- if (!updatedEntryPaths.contains(originalEntryPath)) {
- augeas.remove(originalEntryPath);
- }
- }
-
- // TODO: Backup the original file.
-
- // Write the updated Augeas tree out to the /etc/hosts file.
- augeas.save();
-
- // If we got this far, we've succeeded in out mission.
- report.setStatus(ConfigurationUpdateStatus.SUCCESS);
-
- return;
- }
-
- private Augeas createAugeas(Configuration pluginConfiguration) throws Exception {
- PropertySimple lensesPathProperty = pluginConfiguration.getSimple("lenses-path");
-
- if (lensesPathProperty == null) {
- throw new Exception("Lenses path not found in plugin configuration, cannot retrieve configuration");
- }
-
- PropertySimple rootPathProperty = pluginConfiguration.getSimple("root-path");
-
- if (rootPathProperty == null) {
- throw new Exception("Root path not found in plugin configuration, cannot retrieve configuration");
- }
-
- String lensesPath = lensesPathProperty.getStringValue();
- String rootPath = rootPathProperty.getStringValue();
-
- Augeas augeas = new Augeas(rootPath, lensesPath, Augeas.NONE);
- return augeas;
- }
-
- private List<String> getEntryPaths(Configuration pluginConfiguration, Augeas augeas) throws Exception {
- // Find out where to look for the hosts tree
- PropertySimple augeasTreeNodeProperty = pluginConfiguration.getSimple("augeas-hosts-path");
- if (augeasTreeNodeProperty == null) {
- throw new Exception("Augeas tree node not specified for hosts, cannot retrieve configuration");
- }
- String hostsTreeNode = augeasTreeNodeProperty.getStringValue();
-
- // Request data from augeas
- List<String> matches = augeas.match(hostsTreeNode);
- if (matches.size() == 0) {
- throw new Exception("Unable to load hosts data from augeas");
- }
- return matches;
- }
-}
diff --git a/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/HostsAugeasDiscoveryComponent.java b/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/HostsAugeasDiscoveryComponent.java
deleted file mode 100644
index 4b7ac66..0000000
--- a/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/HostsAugeasDiscoveryComponent.java
+++ /dev/null
@@ -1,50 +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.plugins.hosts;
-
-import java.io.File;
-import java.util.HashSet;
-import java.util.Set;
-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;
-
-/**
- * @author Jason Dobies
- */
-public class HostsAugeasDiscoveryComponent implements ResourceDiscoveryComponent {
-
- public Set discoverResources(ResourceDiscoveryContext discoveryContext)
- throws InvalidPluginConfigurationException, Exception {
-
- Set<DiscoveredResourceDetails> details = new HashSet<DiscoveredResourceDetails>();
-
- File hostsFile = new File("/etc/hosts");
- if (hostsFile.exists()) {
- DiscoveredResourceDetails resource =
- new DiscoveredResourceDetails(discoveryContext.getResourceType(), hostsFile.getPath(),
- "Hosts File", null, "Hosts File", discoveryContext.getDefaultPluginConfiguration(), null);
-
- details.add(resource);
- }
-
- return details;
- }
-}
diff --git a/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/util/AugeasUtility.java b/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/util/AugeasUtility.java
deleted file mode 100644
index 44daf86..0000000
--- a/modules/plugins/hosts-augeas/src/main/java/org/rhq/plugins/hosts/util/AugeasUtility.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Jopr Management Platform
- * Copyright (C) 2005-2009 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.hosts.util;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import net.augeas.Augeas;
-
-/**
- * @author Ian Springer
- */
-public class AugeasUtility {
- public static String getParentPath(String path) {
- String trimmedPath = trimTrailingSlashes(path);
- if (trimmedPath.equals("/")) {
- return "/";
- }
- int lastSlashIndex = trimmedPath.lastIndexOf("/");
- String parentPath = trimmedPath.substring(0, lastSlashIndex);
- return parentPath;
- }
-
- public static List<String> matchFilter(Augeas augeas, String expression, String value) {
- List<String> matches = new ArrayList<String>();
- List<String> paths = augeas.match(expression);
- for (String path : paths) {
- String pathValue = augeas.get(path);
- if (pathValue.equals(value)) {
- matches.add(path);
- }
- }
- return matches;
- }
-
- private static String trimTrailingSlashes(String path) {
- int trailingSlashCount = 0;
- for (int i = path.length() - 1; i > 0; i--) {
- if (path.charAt(i) == '/') {
- trailingSlashCount++;
- }
- }
- String trimmedPath;
- if (trailingSlashCount > 0) {
- trimmedPath = path.substring(0, path.length() - trailingSlashCount);
- } else {
- trimmedPath = path;
- }
- return trimmedPath;
- }
-
- // prevent instantiation
- private AugeasUtility() {
- }
-}
diff --git a/modules/plugins/hosts-augeas/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/hosts-augeas/src/main/resources/META-INF/rhq-plugin.xml
deleted file mode 100644
index c98d62f..0000000
--- a/modules/plugins/hosts-augeas/src/main/resources/META-INF/rhq-plugin.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<plugin name="HostsAugeas"
- displayName="Hosts Server"
- description="Support for *nix hosts service"
- package="org.rhq.plugins.hosts"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns="urn:xmlns:rhq-plugin"
- xmlns:c="urn:xmlns:rhq-configuration">
-
- <depends plugin="Augeas"/>
-
- <service name="Hosts"
- description="The static table lookup for host names"
- discovery="HostsAugeasDiscoveryComponent"
- class="HostsAugeasComponent">
-
- <runs-inside>
- <parent-resource-type name="Linux" plugin="Platforms"/>
- <parent-resource-type name="Windows" plugin="Platforms"/>
- <parent-resource-type name="Solaris" plugin="Platforms"/>
- <parent-resource-type name="HP-UX" plugin="Platforms"/>
- <parent-resource-type name="AIX" plugin="Platforms"/>
- <parent-resource-type name="FreeBSD" plugin="Platforms"/>
- <parent-resource-type name="Mac OS X" plugin="Platforms"/>
- <parent-resource-type name="Java" plugin="Platforms"/>
- </runs-inside>
-
- <plugin-configuration>
- <c:group name="augeas" displayName="Augeas Settings">
- <c:simple-property name="lenses-path" displayName="Augeas Lenses Path"
- default="/usr/local/share/augeas/lenses" required="true"
- description="Full path to the augeas lenses directory. Example: /usr/local/share/augeas/lenses"/>
- <c:simple-property name="root-path" displayName="Augeas Root Path" default="/" required="true"
- description="Path from which augeas should begin to search for configuration files. Example: /"/>
- </c:group>
- <c:group name="hosts" displayName="Hosts Settings">
- <c:simple-property name="hosts-path" displayName="Hosts File Path" required="true"
- default="/etc/hosts" description="Location of the hosts file."/>
- <c:simple-property name="augeas-hosts-path" displayName="Augeas Hosts Tree Path" required="true"
- default="/files/etc/hosts/*" description="Augeas tree location of the hosts configuration values."/>
- </c:group>
- </plugin-configuration>
-
- <resource-configuration>
- <c:list-property name="entries">
- <c:map-property name="entry">
- <c:simple-property name="ipAddress" displayName="IP Address" type="string" required="true" activationPolicy="immediate"
- description="The IP address of the host entry. The address may be an IPv4 address (e.g., 192.168.1.10) or an IPv6 address (e.g., fec0:0:0:bebe::2)."/>
- <c:simple-property name="canonicalName" displayName="Canonical Host Name" type="string" required="true" activationPolicy="immediate"
- description="The canonical host name to refer to the IP address. Host names may contain only alphanumeric characters, minus signs ('-'), and periods ('.'). They must begin with an alphabetic character and end with an alphanumeric character. (e.g., foo.mydomain.org)"/>
- <c:simple-property name="aliases" displayName="Aliases" type="longString" required="false" activationPolicy="immediate"
- description="Optional aliases provide for name changes, alternate spellings, shorter host names, or generic host names (e.g., localhost); aliases should be newline or space separated)."/>
- </c:map-property>
- </c:list-property>
- </resource-configuration>
-
- </service>
-
-</plugin>
\ No newline at end of file
diff --git a/modules/plugins/hosts-augeas/src/test/java/org/rhq/plugins/hosts/HostsAugeasComponentTest.java b/modules/plugins/hosts-augeas/src/test/java/org/rhq/plugins/hosts/HostsAugeasComponentTest.java
deleted file mode 100644
index 17edecc..0000000
--- a/modules/plugins/hosts-augeas/src/test/java/org/rhq/plugins/hosts/HostsAugeasComponentTest.java
+++ /dev/null
@@ -1,86 +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.plugins.hosts;
-
-import java.util.Collection;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.testng.annotations.BeforeSuite;
-import org.testng.annotations.Test;
-
-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;
-
-/**
- * @author Jason Dobies
- */
-public class HostsAugeasComponentTest {
-
- private HostsAugeasComponent component = new HostsAugeasComponent();
-
- private Configuration pluginConfiguration = new Configuration();
-
- private final Log log = LogFactory.getLog(this.getClass());
-
- @BeforeSuite
- public void initPluginConfiguration() throws Exception {
- pluginConfiguration.put(new PropertySimple("lenses-path", "/usr/local/share/augeas/lenses"));
- pluginConfiguration.put(new PropertySimple("root-path", "/"));
- pluginConfiguration.put(new PropertySimple("hosts-path", "/etc/hosts"));
- pluginConfiguration.put(new PropertySimple("augeas-hosts-path", "/files/etc/hosts/*"));
- }
-
- @Test
- public void loadResourceConfiguration() throws Exception {
- Configuration configuration;
- try {
- configuration = component.loadResourceConfiguration(pluginConfiguration);
- } catch (UnsatisfiedLinkError ule) {
- // Skip tests if augeas not available
- return;
- }
-
- assert configuration != null : "Null configuration returned from load call";
-
- Collection<Property> allProperties = configuration.getProperties();
-
- assert allProperties.size() == 1 : "Incorrect number of properties found. Expected: 1, Found: "
- + allProperties.size();
-
- PropertyList entryList = (PropertyList) allProperties.iterator().next();
-
- for (Property property : entryList.getList()) {
- PropertyMap entry = (PropertyMap) property;
-
- Property ipProperty = entry.get("ip");
- Property canonicalProperty = entry.get("canonical");
-
- assert ipProperty != null : "IP was null in entry";
- assert canonicalProperty != null : "Canonical was null in entry";
-
- log.info("IP: " + ((PropertySimple) ipProperty).getStringValue());
- log.info("Canonical: " + ((PropertySimple) canonicalProperty).getStringValue());
- }
-
- }
-}
diff --git a/modules/plugins/hosts-augeas/src/test/resources/log4j.xml b/modules/plugins/hosts-augeas/src/test/resources/log4j.xml
deleted file mode 100644
index ef41b92..0000000
--- a/modules/plugins/hosts-augeas/src/test/resources/log4j.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
-
- <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
- <param name="Target" value="System.out"/>
- <param name="Threshold" value="DEBUG"/>
-
- <layout class="org.apache.log4j.PatternLayout">
- <!-- The default pattern: Date Priority [Category] Messagen -->
-
- <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
- </layout>
- </appender>
-
- <appender name="FILE" class="org.apache.log4j.RollingFileAppender">
- <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>
-
- <root>
- <appender-ref ref="CONSOLE"/>
- <appender-ref ref="FILE"/>
- </root>
-
-</log4j:configuration>
commit 6a676af5fd6af0c2fafd3faf5fc24a119bbceb72
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Thu Nov 12 11:18:13 2009 -0500
get hosts plugin integration tests passing on Windows
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
index b652f71..a47423e 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
@@ -83,16 +83,23 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
private final Log log = LogFactory.getLog(this.getClass());
private ResourceContext<T> resourceContext;
+ private String resourceDescription;
private List<String> includeGlobs;
private List<String> excludeGlobs;
private Augeas augeas;
private AugeasNode resourceConfigRootNode;
private String augeasRootPath;
-
+
public void start(ResourceContext<T> resourceContext) throws InvalidPluginConfigurationException, Exception {
this.resourceContext = resourceContext;
+ this.resourceDescription = this.resourceContext.getResourceType() + " Resource with key ["
+ + this.resourceContext.getResourceKey() + "]";
initGlobs();
+ Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
+ this.augeasRootPath = pluginConfig.getSimpleValue(AUGEAS_ROOT_PATH_PROP, DEFAULT_AUGEAS_ROOT_PATH);
+ log.debug("Augeas Root Path = \"" + this.augeasRootPath + "\"");
+
if (isAugeasAvailable()) {
initAugeas();
} else {
@@ -132,33 +139,11 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
loadProperty(propDef, resourceConfig, this.augeas, this.resourceConfigRootNode);
}
+ // This will add error messages to any PropertySimples with invalid values, so they can be displayed by the GUI.
+ validateResourceConfiguration(new ConfigurationUpdateReport(resourceConfig));
return resourceConfig;
}
- private void abortIfAugeasNotAvailable()
- throws Exception
- {
- if (getAugeas() == null) {
- if (isAugeasAvailable()) {
- initAugeas();
- if (getAugeas() == null) {
- throw new Exception("Failed to initialize Augeas Java API.");
- }
- } else {
- String message;
- if (IS_WINDOWS) {
- message = "Configuration of " + getResourceContext().getResourceType().getName()
- + " Resources is not supported on Windows.";
- } else {
- message = "Configuration of " + getResourceContext().getResourceType().getName()
- + " Resources requires that the Augeas shared library be installed on the Agent system."
- + " If on Fedora or RHEL, `yum install augeas`.";
- }
- throw new Exception(message);
- }
- }
- }
-
public void updateResourceConfiguration(ConfigurationUpdateReport report) {
try
{
@@ -171,9 +156,8 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
}
if (!validateResourceConfiguration(report)) {
- log.debug("Validation of updated Resource configuration for " + this.getResourceContext().getResourceType()
- + " Resource with key '" + this.getResourceContext().getResourceKey()
- + "' failed with the following errors: " + report.getErrorMessage());
+ log.debug("Validation of updated Resource configuration for " + this.resourceDescription
+ + " failed with the following errors: " + report.getErrorMessage());
report.setStatus(ConfigurationUpdateStatus.FAILURE);
return;
}
@@ -300,7 +284,12 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
}
public ResourceContext<T> getResourceContext() {
- return resourceContext;
+ return this.resourceContext;
+ }
+
+ public String getResourceDescription()
+ {
+ return this.resourceDescription;
}
public List<File> getConfigurationFiles() {
@@ -674,11 +663,7 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
return summary.toString();
}
- protected void initAugeas()
- {
- Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
- this.augeasRootPath = pluginConfig.getSimpleValue(AUGEAS_ROOT_PATH_PROP, DEFAULT_AUGEAS_ROOT_PATH);
- log.debug("Augeas Root Path = \"" + this.augeasRootPath + "\"");
+ protected void initAugeas() {
this.augeas = createAugeas();
String resourceConfigRootPath = getResourceConfigurationRootPath();
if (resourceConfigRootPath.indexOf(AugeasNode.SEPARATOR_CHAR) != 0) {
@@ -690,4 +675,28 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
}
log.debug("Resource Config Root Node = \"" + this.resourceConfigRootNode + "\"");
}
+
+ private void abortIfAugeasNotAvailable()
+ throws Exception
+ {
+ if (getAugeas() == null) {
+ if (isAugeasAvailable()) {
+ initAugeas();
+ if (getAugeas() == null) {
+ throw new Exception("Failed to initialize Augeas Java API.");
+ }
+ } else {
+ String message;
+ if (IS_WINDOWS) {
+ message = "Configuration of " + getResourceContext().getResourceType().getName()
+ + " Resources is not supported on Windows.";
+ } else {
+ message = "Configuration of " + getResourceContext().getResourceType().getName()
+ + " Resources requires that the Augeas shared library be installed on the Agent system."
+ + " If on Fedora or RHEL, `yum install augeas`.";
+ }
+ throw new Exception(message);
+ }
+ }
+ }
}
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java
index 00cc4f9..5fa0ebf 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java
@@ -24,7 +24,6 @@
package org.rhq.plugins.augeas.helper;
import java.io.File;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
@@ -97,6 +96,7 @@ public class Glob {
globPattern = parentPath.getAbsolutePath() + globPattern;
}
+ globPattern = new File(globPattern).getAbsolutePath();
File[] files = parentPath.listFiles(new GlobFilter(globPattern));
if (files == null) {
throw new IllegalStateException("Could not list files in " + parentPath);
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
index 8ffcfa7..4084023 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
@@ -28,22 +28,21 @@ import java.util.Arrays;
import java.util.List;
import java.util.Set;
-import net.augeas.jna.Aug;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.rhq.core.clientapi.agent.PluginContainerException;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
+import org.rhq.core.pluginapi.util.FileUtils;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
-import org.rhq.core.clientapi.agent.PluginContainerException;
import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
import org.rhq.core.domain.configuration.Configuration;
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.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pc.PluginContainer;
@@ -52,10 +51,11 @@ import org.rhq.core.pc.configuration.ConfigurationManager;
import org.rhq.core.pc.inventory.InventoryManager;
import org.rhq.core.pc.plugin.FileSystemPluginFinder;
import org.rhq.core.pc.plugin.PluginManager;
-import org.rhq.core.pluginapi.util.FileUtils;
import org.rhq.core.util.file.FileUtil;
import org.rhq.plugins.augeas.AugeasConfigurationComponent;
+import net.augeas.jna.Aug;
+
/**
* A base class for integration tests for instances of {@link AugeasConfigurationComponent}.
*
@@ -65,9 +65,9 @@ public abstract class AbstractAugeasConfigurationComponentTest {
public static final String TEST_GROUP = "linux-config";
private static final File ITEST_DIR = new File("target/itest");
private static final long ONE_WEEK_IN_SECONDS = 60L * 60 * 24;
- private static final boolean IS_WINDOWS = (File.separatorChar == '\\');
+ protected static final boolean IS_WINDOWS = (File.separatorChar == '\\');
- private static final File AUGEAS_ROOT;
+ protected static final File AUGEAS_ROOT;
static {
String tmpDirPath = System.getProperty("java.io.tmpdir");
File tmpDir = new File(tmpDirPath);
@@ -83,7 +83,7 @@ public abstract class AbstractAugeasConfigurationComponentTest {
if (IS_WINDOWS) {
message = "Augeas is not available on Windows. Augeas-based configuration functionality will *not* be tested.";
} else {
- message = "Augeas not found. If on Fedora or RHEL, `yum install augeas`. Augeas-based configuration functionality will *not* be tested.";
+ message = "Augeas not found. If on Fedora or RHEL, `yum install augeas`. Augeas-based configuration functionality will *not* be tested.";
}
System.out.println(message);
}
@@ -96,16 +96,14 @@ public abstract class AbstractAugeasConfigurationComponentTest {
pluginContainer.initialize();
Set<String> pluginNames = pluginContainer.getPluginManager().getMetadataManager().getPluginNames();
System.out.println("Plugin container started with the following plugins: " + pluginNames);
-
+
System.out.println("Updating Augeas root in default plugin config...");
ResourceType resourceType = getResourceType();
ConfigurationDefinition pluginConfigDef = resourceType.getPluginConfigurationDefinition();
ConfigurationTemplate defaultPluginConfigTemplate = pluginConfigDef.getDefaultTemplate();
Configuration defaultPluginConfig = defaultPluginConfigTemplate.getConfiguration();
+ tweakDefaultPluginConfig(defaultPluginConfig);
resetConfigFiles(defaultPluginConfig);
- PropertySimple rootPathProp = new PropertySimple(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP,
- AUGEAS_ROOT);
- defaultPluginConfig.put(rootPathProp);
InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
System.out.println("Executing server discovery scan...");
@@ -127,13 +125,16 @@ public abstract class AbstractAugeasConfigurationComponentTest {
public void testResourceConfigLoad() throws Exception {
ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
Resource resource = getResource();
- Configuration resourceConfig = null;
- try {
+ Configuration resourceConfig;
+ try
+ {
resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
Configuration expectedResourceConfig = getExpectedResourceConfig();
assert resourceConfig.equals(expectedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
+ expectedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
- } catch (PluginContainerException e) {
+ }
+ catch (PluginContainerException e)
+ {
if (isResourceConfigSupported()) {
throw e;
}
@@ -145,8 +146,8 @@ public abstract class AbstractAugeasConfigurationComponentTest {
ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
Resource resource = getResource();
Configuration updatedResourceConfig = getUpdatedResourceConfig();
- ConfigurationUpdateRequest updateRequest = new ConfigurationUpdateRequest(0, updatedResourceConfig, resource
- .getId());
+ ConfigurationUpdateRequest updateRequest = new ConfigurationUpdateRequest(0, updatedResourceConfig,
+ resource.getId());
configurationManager.updateResourceConfiguration(updateRequest);
if (isResourceConfigSupported()) {
@@ -175,7 +176,9 @@ public abstract class AbstractAugeasConfigurationComponentTest {
protected abstract Configuration getUpdatedResourceConfig();
- protected PluginContainerConfiguration createPluginContainerConfiguration() throws IOException {
+ protected PluginContainerConfiguration createPluginContainerConfiguration()
+ throws IOException
+ {
PluginContainerConfiguration pcConfig = new PluginContainerConfiguration();
File pluginsDir = new File(ITEST_DIR, "plugins");
pcConfig.setPluginFinder(new FileSystemPluginFinder(pluginsDir));
@@ -231,9 +234,19 @@ public abstract class AbstractAugeasConfigurationComponentTest {
List<String> includeGlobs = new ArrayList<String>();
includeGlobs.addAll(Arrays.asList(includes.split("\\s*\\|\\s*")));
for (String includeGlob : includeGlobs) {
- InputStream inputStream = this.getClass().getResourceAsStream(includeGlob);
+ String resourcePath;
+ if (IS_WINDOWS) {
+ resourcePath = includeGlob.replace('\\', '/');
+ int colonIndex = resourcePath.indexOf(':');
+ if (colonIndex != -1) {
+ resourcePath = resourcePath.substring(colonIndex + 1);
+ }
+ } else {
+ resourcePath = includeGlob;
+ }
+ InputStream inputStream = this.getClass().getResourceAsStream(resourcePath);
if (inputStream != null) {
- File outputFile = new File(AUGEAS_ROOT, includeGlob);
+ File outputFile = new File(AUGEAS_ROOT, resourcePath);
outputFile.getParentFile().mkdirs();
FileUtil.writeFile(inputStream, outputFile);
}
@@ -245,6 +258,13 @@ public abstract class AbstractAugeasConfigurationComponentTest {
return isAugeasAvailable();
}
+ protected void tweakDefaultPluginConfig(Configuration defaultPluginConfig)
+ {
+ PropertySimple rootPathProp = new PropertySimple(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP,
+ AUGEAS_ROOT);
+ defaultPluginConfig.put(rootPathProp);
+ }
+
private boolean isAugeasAvailable() {
try {
Aug aug = Aug.INSTANCE;
@@ -255,9 +275,12 @@ public abstract class AbstractAugeasConfigurationComponentTest {
}
private void deleteAugeasRootDir() {
- try {
+ try
+ {
FileUtils.purge(AUGEAS_ROOT, true);
- } catch (IOException e) {
+ }
+ catch (IOException e)
+ {
log.warn("Failed to delete Augeas root dir (" + AUGEAS_ROOT + ").");
}
}
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
index 366747b..dd29e6e 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
@@ -82,6 +82,8 @@ public class HostsComponent extends AugeasConfigurationComponent {
resourceConfig = super.loadResourceConfiguration();
} else {
resourceConfig = new NonAugeasHostsConfigurationDelegate(this).loadResourceConfiguration();
+ // This will add error messages to any PropertySimples with invalid values, so they can be displayed by the GUI.
+ validateResourceConfiguration(new ConfigurationUpdateReport(resourceConfig));
}
return resourceConfig;
}
@@ -92,10 +94,8 @@ public class HostsComponent extends AugeasConfigurationComponent {
super.updateResourceConfiguration(report);
} else {
if (!validateResourceConfiguration(report)) {
- log.debug("Validation of updated Resource configuration for "
- + this.getResourceContext().getResourceType() + " Resource with key '"
- + this.getResourceContext().getResourceKey() + "' failed with the following errors: "
- + report.getErrorMessage());
+ log.debug("Validation of updated Resource configuration for " + getResourceDescription()
+ + " failed with the following errors: " + report.getErrorMessage());
report.setStatus(ConfigurationUpdateStatus.FAILURE);
return;
}
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java
index cd64c12..a0908b4 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java
@@ -26,9 +26,11 @@ 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.ResourceDiscoveryContext;
+import org.rhq.plugins.augeas.AugeasConfigurationComponent;
import org.rhq.plugins.augeas.AugeasConfigurationDiscoveryComponent;
import org.rhq.plugins.platform.PlatformComponent;
@@ -59,16 +61,23 @@ public class HostsDiscoveryComponent extends AugeasConfigurationDiscoveryCompone
@Override
protected List<String> determineIncludeGlobs(ResourceDiscoveryContext<PlatformComponent> discoveryContext)
{
- if (IS_WINDOWS) {
- File windowsDir = getWindowsDir();
- File hostsFile = new File(windowsDir, "system32/drivers/etc/hosts");
- return Collections.singletonList(hostsFile.getPath());
- } else {
+ Configuration defaultPluginConfig = discoveryContext.getDefaultPluginConfiguration();
+ String includeGlobs = defaultPluginConfig.getSimpleValue(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP, null);
+ if (includeGlobs != null) {
return super.determineIncludeGlobs(discoveryContext);
- }
+ } else {
+ File hostsFile;
+ if (IS_WINDOWS) {
+ File windowsDir = getWindowsDir(discoveryContext);
+ hostsFile = new File(windowsDir, "system32/drivers/etc/hosts");
+ } else {
+ hostsFile = new File("/etc/hosts");
+ }
+ return Collections.singletonList(hostsFile.getPath());
+ }
}
- private File getWindowsDir() {
+ private File getWindowsDir(ResourceDiscoveryContext<PlatformComponent> discoveryContext) {
File windowsDir = null;
String windowsDirPath = System.getenv().get("SystemRoot");
if (windowsDirPath != null) {
@@ -92,6 +101,7 @@ public class HostsDiscoveryComponent extends AugeasConfigurationDiscoveryCompone
if (windowsDir == null) {
throw new IllegalStateException("Failed to determine Windows directory.");
}
+
log.debug("Windows directory: " + windowsDir);
return windowsDir;
}
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/Hosts.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/Hosts.java
index 85f3255..8b3c61f 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/Hosts.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/Hosts.java
@@ -37,12 +37,10 @@ import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
- * A set of hosts file entries. The set may contain duplicate entries (i.e. entries for different IP addresses
- * containing the same name, either as the canonical name or as an alias).
+ * A set of hosts file entries.
*
* @author Ian Springer
*/
@@ -50,39 +48,25 @@ public class Hosts {
private static final Log LOG = LogFactory.getLog(Hosts.class);
private Set<HostsEntry> entries = new LinkedHashSet<HostsEntry>();
- private Map<String, Set<HostsEntry>> ipAddressToEntriesMap = new HashMap<String, Set<HostsEntry>>();
- private Map<String, Set<HostsEntry>> nameToEntriesMap = new HashMap<String, Set<HostsEntry>>();
- private Set<String> namesWithDuplicateEntries = new HashSet<String>();
- private Set<String> ipAddressesWithDuplicateEntries = new HashSet<String>();
+ private Map<String, Set<HostsEntry>> nameToIpv4EntriesMap = new HashMap<String, Set<HostsEntry>>();
+ private Map<String, Set<HostsEntry>> nameToIpv6EntriesMap = new HashMap<String, Set<HostsEntry>>();
public Hosts() {
}
public void addEntry(HostsEntry entry) {
this.entries.add(entry);
- String ipAddress = entry.getIpAddress();
- Set<HostsEntry> entriesForIpAddress = this.ipAddressToEntriesMap.get(ipAddress);
- if (entriesForIpAddress == null) {
- entriesForIpAddress = new LinkedHashSet(1);
- this.ipAddressToEntriesMap.put(ipAddress, entriesForIpAddress);
- } else {
- this.ipAddressesWithDuplicateEntries.add(ipAddress);
- }
- entriesForIpAddress.add(entry);
String canonicalName = entry.getCanonicalName();
- updateNameToEntriesMap(entry, canonicalName);
- for (String alias : entry.getAliases()) {
- updateNameToEntriesMap(entry, alias);
- }
+ updateNameToEntriesMaps(entry, canonicalName);
}
- private void updateNameToEntriesMap(HostsEntry entry, String canonicalName) {
- Set<HostsEntry> entriesForCanonicalName = this.nameToEntriesMap.get(canonicalName);
+ private void updateNameToEntriesMaps(HostsEntry entry, String canonicalName) {
+ Map<String, Set<HostsEntry>> nameToEntriesMap = (entry.getIpVersion() == 4) ?
+ this.nameToIpv4EntriesMap : this.nameToIpv6EntriesMap;
+ Set<HostsEntry> entriesForCanonicalName = nameToEntriesMap.get(canonicalName);
if (entriesForCanonicalName == null) {
entriesForCanonicalName = new LinkedHashSet(1);
- this.nameToEntriesMap.put(canonicalName, entriesForCanonicalName);
- } else {
- this.namesWithDuplicateEntries.add(canonicalName);
+ nameToEntriesMap.put(canonicalName, entriesForCanonicalName);
}
entriesForCanonicalName.add(entry);
}
@@ -91,25 +75,16 @@ public class Hosts {
return this.entries;
}
- @NotNull
- public Set<HostsEntry> getEntriesByIpAddress(String ipAddress) {
- Set<HostsEntry> entries = this.ipAddressToEntriesMap.get(ipAddress);
+ public Set<HostsEntry> getIpv4EntriesByName(String canonicalName) {
+ Set<HostsEntry> entries = this.nameToIpv4EntriesMap.get(canonicalName);
return (entries != null) ? entries : Collections.<HostsEntry> emptySet();
}
- public Set<HostsEntry> getEntriesByName(String canonicalName) {
- Set<HostsEntry> entries = this.nameToEntriesMap.get(canonicalName);
+ public Set<HostsEntry> getIpv6EntriesByName(String canonicalName) {
+ Set<HostsEntry> entries = this.nameToIpv6EntriesMap.get(canonicalName);
return (entries != null) ? entries : Collections.<HostsEntry> emptySet();
}
- public Set<String> getIpAddressesWithDuplicateEntries() {
- return this.ipAddressesWithDuplicateEntries;
- }
-
- public Set<String> getNamesWithDuplicateEntries() {
- return this.namesWithDuplicateEntries;
- }
-
public static Hosts load(File hostsFile) throws IOException {
Hosts hosts = new Hosts();
SimpleUnixConfigFileReader reader = new SimpleUnixConfigFileReader(new FileReader(hostsFile));
@@ -130,19 +105,14 @@ public class Hosts {
}
public static void store(Hosts hosts, File hostsFile) throws IOException {
- // Set<String> namesWithDuplicateEntries = hosts.getNamesWithDuplicateEntries();
- // if (!namesWithDuplicateEntries.isEmpty()) {
- // throw new IllegalArgumentException("Hosts contains duplicate entries for the following names: "
- // + namesWithDuplicateEntries);
- // }
-
if (!hostsFile.exists()) {
// If a hosts file doesn't already exist, create an empty one.
FileOutputStream hostsFileWriter = new FileOutputStream(hostsFile);
hostsFileWriter.close();
}
- Set<String> storedCanonicalNames = new HashSet<String>();
+ Set<String> storedIpv4CanonicalNames = new HashSet<String>();
+ Set<String> storedIpv6CanonicalNames = new HashSet<String>();
File newHostsFile = new File(hostsFile.getPath() + "-" + System.currentTimeMillis());
PrintWriter newHostsFileWriter = new PrintWriter(new FileWriter(newHostsFile));
try {
@@ -150,7 +120,8 @@ public class Hosts {
SimpleUnixConfigFileReader hostsFileReader = new SimpleUnixConfigFileReader(new FileReader(hostsFile));
try {
while ((line = hostsFileReader.readLine()) != null) {
- StringBuilder newLine = createNewLine(hosts, hostsFile, line, storedCanonicalNames);
+ StringBuilder newLine = createNewLine(hosts, hostsFile, line, storedIpv4CanonicalNames,
+ storedIpv6CanonicalNames);
if (newLine != null) {
newHostsFileWriter.println(newLine);
}
@@ -161,6 +132,8 @@ public class Hosts {
// Write out any entries for IP addresses that did not have entries in the original file.
for (HostsEntry newEntry : hosts.getEntries()) {
+ Set<String> storedCanonicalNames = (newEntry.getIpVersion() == 4) ? storedIpv4CanonicalNames :
+ storedIpv6CanonicalNames;
if (!storedCanonicalNames.contains(newEntry.getCanonicalName())) {
StringBuilder newLine = new StringBuilder(newEntry.getIpAddress()).append("\t").append(
newEntry.getCanonicalName());
@@ -240,13 +213,16 @@ public class Hosts {
@Nullable
private static StringBuilder createNewLine(Hosts hosts, File hostsFile, SimpleUnixConfigFileLine existingLine,
- Set<String> storedCanonicalNames) {
+ Set<String> storedIpv4CanonicalNames,
+ Set<String> storedIpv6CanonicalNames) {
StringBuilder newLine;
String nonComment = existingLine.getNonComment();
String comment = existingLine.getComment();
HostsEntry existingEntry = parseEntry(nonComment, hostsFile);
if (existingEntry != null) {
- Set<HostsEntry> newEntries = hosts.getEntriesByName(existingEntry.getCanonicalName());
+ Set<HostsEntry> newEntries = (existingEntry.getIpVersion() == 4) ?
+ hosts.getIpv4EntriesByName(existingEntry.getCanonicalName()) :
+ hosts.getIpv6EntriesByName(existingEntry.getCanonicalName());
// TODO: Look up entries for existing entry's aliases too?
if (!newEntries.isEmpty()) {
// replace the existing entry
@@ -261,6 +237,8 @@ public class Hosts {
if (comment != null) {
newLine.append(" #").append(comment);
}
+ Set<String> storedCanonicalNames = (newEntry.getIpVersion() == 4) ? storedIpv4CanonicalNames :
+ storedIpv6CanonicalNames;
storedCanonicalNames.add(newEntry.getCanonicalName());
} else {
LOG.debug("Removing entry [" + existingEntry + "] from hosts file...");
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/HostsEntry.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/HostsEntry.java
index e37b3d2..6c6ad92 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/HostsEntry.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/HostsEntry.java
@@ -30,6 +30,7 @@ import java.util.Set;
*/
public class HostsEntry {
private String ipAddress;
+ private int ipVersion;
private String canonicalName;
private Set<String> aliases;
@@ -38,6 +39,7 @@ public class HostsEntry {
throw new IllegalArgumentException("ipAddress parameter is null.");
}
this.ipAddress = ipAddress;
+ this.ipVersion = (this.ipAddress.indexOf(':') == -1) ? 4 : 6;
if (canonicalName == null) {
throw new IllegalArgumentException("canonicalName parameter is null.");
}
@@ -49,6 +51,11 @@ public class HostsEntry {
return ipAddress;
}
+ public int getIpVersion()
+ {
+ return ipVersion;
+ }
+
public String getCanonicalName() {
return canonicalName;
}
@@ -56,4 +63,10 @@ public class HostsEntry {
public Set<String> getAliases() {
return aliases;
}
+
+ @Override
+ public String toString()
+ {
+ return this.ipAddress + " " + this.getCanonicalName() + " " + this.aliases;
+ }
}
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java
index 99204b8..731e532 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java
@@ -24,8 +24,6 @@ import java.util.Date;
import java.util.LinkedHashSet;
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.ConfigurationUpdateStatus;
import org.rhq.core.domain.configuration.Property;
@@ -41,8 +39,6 @@ import org.rhq.plugins.hosts.HostsComponent;
*/
public class NonAugeasHostsConfigurationDelegate implements ConfigurationFacet
{
- private final Log log = LogFactory.getLog(this.getClass());
-
private HostsComponent hostsComponent;
public NonAugeasHostsConfigurationDelegate(HostsComponent hostsComponent) {
@@ -58,47 +54,21 @@ public class NonAugeasHostsConfigurationDelegate implements ConfigurationFacet
PropertyList entriesProp = new PropertyList(".");
resourceConfig.put(entriesProp);
- Set<String> ipAddressesWithDuplicateEntries = hosts.getIpAddressesWithDuplicateEntries();
- if (!ipAddressesWithDuplicateEntries.isEmpty()) {
- log.debug("Hosts file [" + hostsFile + "] contains duplicate entries for the following IP addresses: "
- + ipAddressesWithDuplicateEntries);
- }
- Set<String> namesWithDuplicateEntries = hosts.getNamesWithDuplicateEntries();
- if (!namesWithDuplicateEntries.isEmpty()) {
- log.error("Hosts file [" + hostsFile + "] contains duplicate entries for the following names: "
- + namesWithDuplicateEntries);
- }
-
for (HostsEntry entry : hosts.getEntries()) {
- PropertyMap entryProp = new PropertyMap("entry");
+ PropertyMap entryProp = new PropertyMap("*[canonical]");
entriesProp.add(entryProp);
- PropertySimple ipAddressProp = new PropertySimple("ipaddr", entry.getIpAddress());
- entryProp.put(ipAddressProp);
-
- PropertySimple canonicalNameProp = new PropertySimple("canonical", entry.getCanonicalName());
- if (namesWithDuplicateEntries.contains(entry.getCanonicalName())) {
- canonicalNameProp.setErrorMessage("At the time of loading, there was more than one entry containing this name - please remove or fix duplicate entries before saving.");
- }
- entryProp.put(canonicalNameProp);
-
- StringBuilder aliasesPropValue = new StringBuilder();
- boolean foundDuplicateName = false;
+ entryProp.put(new PropertySimple("ipaddr", entry.getIpAddress()));
+ entryProp.put(new PropertySimple("canonical", entry.getCanonicalName()));
+ StringBuilder aliasPropValue = new StringBuilder();
for (String alias : entry.getAliases()) {
- if (namesWithDuplicateEntries.contains(alias)) {
- foundDuplicateName = true;
- }
- aliasesPropValue.append(alias).append("\n");
+ aliasPropValue.append(alias).append("\n");
}
if (!entry.getAliases().isEmpty()) {
// Chop the final newline char.
- aliasesPropValue.deleteCharAt(aliasesPropValue.length() - 1);
- }
- PropertySimple aliasesProp = new PropertySimple("alias", aliasesPropValue);
- if (foundDuplicateName) {
- aliasesProp.setErrorMessage("At the time of loading, there was more than one entry containing this name - please remove or fix duplicate entries before saving.");
+ aliasPropValue.deleteCharAt(aliasPropValue.length() - 1);
}
- entryProp.put(aliasesProp);
+ entryProp.put(new PropertySimple("alias", aliasPropValue));
}
return resourceConfig;
@@ -128,13 +98,6 @@ public class NonAugeasHostsConfigurationDelegate implements ConfigurationFacet
newHosts.addEntry(entry);
}
- Set<String> namesWithDuplicateEntries = newHosts.getNamesWithDuplicateEntries();
- if (!namesWithDuplicateEntries.isEmpty()) {
- report.setErrorMessage("There are duplicate entries for the following names: "
- + namesWithDuplicateEntries);
- return;
- }
-
File hostsFile = (File)this.hostsComponent.getConfigurationFiles().get(0);
try {
Hosts.store(newHosts, hostsFile);
diff --git a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
index 2227c4a..6ac7011 100644
--- a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
+++ b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2009 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -18,11 +18,16 @@
*/
package org.rhq.plugins.hosts;
+import java.io.File;
+import java.io.IOException;
+
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.plugins.augeas.AugeasConfigurationComponent;
import org.rhq.plugins.augeas.test.AbstractAugeasConfigurationComponentTest;
+import org.testng.annotations.BeforeTest;
/**
* An integration test for {@link HostsComponent}.
@@ -30,14 +35,17 @@ import org.rhq.plugins.augeas.test.AbstractAugeasConfigurationComponentTest;
* @author Ian Springer
*/
public class HostsComponentTest extends AbstractAugeasConfigurationComponentTest {
+ private static final String PLUGIN_NAME = "Hosts";
+ private static final String RESOURCE_TYPE_NAME = "Hosts File";
+
@Override
protected String getPluginName() {
- return "Hosts";
+ return PLUGIN_NAME;
}
@Override
protected String getResourceTypeName() {
- return "Hosts File";
+ return RESOURCE_TYPE_NAME;
}
@Override
@@ -47,6 +55,21 @@ public class HostsComponentTest extends AbstractAugeasConfigurationComponentTest
}
@Override
+ protected void tweakDefaultPluginConfig(Configuration defaultPluginConfig)
+ {
+ super.tweakDefaultPluginConfig(defaultPluginConfig);
+ String hostsFilePath = new File("/etc/hosts").getAbsolutePath();
+ defaultPluginConfig.put(new PropertySimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP, hostsFilePath));
+ }
+
+ @BeforeTest
+ @Override
+ public void resetConfigFiles() throws IOException
+ {
+ super.resetConfigFiles();
+ }
+
+ @Override
protected Configuration getExpectedResourceConfig() {
Configuration config = new Configuration();
PropertyList entries = new PropertyList(".");
commit 5d0f843738caa30f2afa7cf3ee3ccd0415dbc850
Author: Pradeep Kilambi <pkilambi(a)redhat.com>
Date: Thu Nov 12 10:49:51 2009 -0500
fixing the query to return repodistro as intended instaed of distro
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
index 7c4778a..9dcd6e2 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
@@ -48,10 +48,7 @@ import javax.persistence.Table;
@NamedQuery(name = RepoDistribution.DELETE_BY_KICKSTART_TREE_ID, query = "DELETE RepoDistribution rkt WHERE rkt.dist.id = :distId"),
@NamedQuery(name = RepoDistribution.DELETE_BY_REPO_ID, query = "DELETE RepoDistribution rkt WHERE rkt.repo.id = :repoId"),
@NamedQuery(name = RepoDistribution.QUERY_FIND_BY_REPO_ID,
- query = "SELECT kt FROM "
- + "Distribution kt, RepoDistribution as rkt "
- + "where rkt.repo.id = :repoId "
- + "and kt.id = rkt.distibution.id") })
+ query = "SELECT rkt FROM RepoDistribution rkt where rkt.repo.id = :repoId ") })
@Table(name = "RHQ_REPO_DISTRIBUTION")
public class RepoDistribution implements Serializable {
commit cb288a8321d659c8839328066f5c50f4e548a4ba
Author: Partha Aji <paji(a)redhat.com>
Date: Thu Nov 12 10:09:55 2009 -0500
Removed the augeas test jar dep from aliases pom since its going to be built as part of core
diff --git a/modules/plugins/aliases/pom.xml b/modules/plugins/aliases/pom.xml
index e2f5ee4..f04f6ae 100644
--- a/modules/plugins/aliases/pom.xml
+++ b/modules/plugins/aliases/pom.xml
@@ -35,15 +35,6 @@
<artifactId>rhq-augeas-plugin</artifactId>
<version>${project.version}</version>
</dependency>
-
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-augeas-plugin</artifactId>
- <version>${project.version}</version>
- <type>test-jar</type>
- <scope>test</scope>
- </dependency>
-
</dependencies>
<build>
commit bfadc10d2ada9896e8c9be16ef693a4875fee4fa
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 03:23:42 2009 -0500
Squashed commit of the following:
commit 8075b0b26d1c2514ff7a1c831491a51d8a2909c8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 03:22:06 2009 -0500
Squashed commit of the following:
commit d3dfc1a52b0414bd67f50ed9c881c8c3e33e9a1e
Merge: 2cd6ba1 ad45fe5
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 22:38:00 2009 -0500
Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq
commit 2cd6ba182ee07849e2ccd06be6c962b879f45112
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 16:33:18 2009 -0500
Allow clean install to still copy over the license file.
This patch moves the license file from the server container module to the ear module. It is copied over in the dev profile only.
commit 9d93844a860e54c2a012644975ccee198c76f9a6
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 02:53:23 2009 -0500
actually schedule the jobs in quartz
commit 25c0a3e27d9969368230277cb5a33633dbbdb897
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 02:06:54 2009 -0500
add plugin context to the job interface
commit c14822a979ab9e130dfc08279ae6ca342bd591bf
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 01:45:23 2009 -0500
provide an API to schedule jobs
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
new file mode 100644
index 0000000..6c39277
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -0,0 +1,173 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.quartz.Job;
+import org.quartz.JobDataMap;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+import org.rhq.core.util.exception.ThrowableUtil;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * The superclass to the concurrent and stateful job wrappers.
+ * See the subclasses for more information.
+ *
+ * @author John Mazzitelli
+ */
+abstract class AbstractJobWrapper implements Job {
+ private final Log log = LogFactory.getLog(this.getClass());
+
+ /**
+ * All keys prefixed with this leader identify the data map values as our internal values.
+ * Any data map key without this prefix is assumed to be part of the plugin callback data.
+ */
+ private static final String DATAMAP_LEADER = "__";
+
+ /**
+ * Key to the job data map that indicates the plugin that scheduled the job.
+ */
+ public static final String DATAMAP_PLUGIN_NAME = DATAMAP_LEADER + "pluginName";
+
+ /**
+ * Key to the job data map that indicates the type of plugin that scheduled the job.
+ */
+ public static final String DATAMAP_PLUGIN_TYPE = DATAMAP_LEADER + "pluginType";
+
+ /**
+ * Key to the job data map that indicates the ID of the job.
+ * This ID is passed to the plugin container when the job was scheduled, see:
+ * {@link AbstractTypeServerPluginContainer#scheduleJob(Schedule, String, String, ScheduledJob, java.util.Properties)}
+ */
+ public static final String DATAMAP_JOB_ID = DATAMAP_LEADER + "jobId";
+
+ /**
+ * Key to the job data map that indicates which plugin component class should be instantiated
+ * in order to process the job. This must implement {@link ScheduledJob}.
+ */
+ public static final String DATAMAP_SCHEDULED_JOB_CLASS = DATAMAP_LEADER + "scheduledJobClass";
+
+ /**
+ * This is the method that quartz calls when the schedule has triggered. This method will
+ * delegate to the plugin component that is responsible to do work for the plugin.
+ *
+ * @see ScheduledJob#execute(String, Properties)
+ */
+ public void execute(JobExecutionContext context) throws JobExecutionException {
+ log.debug("scheduled server plugin job triggered");
+
+ JobDataMap dataMap = context.getJobDetail().getJobDataMap();
+
+ // obtain our internal values that we need from the datamap
+ String pluginName = dataMap.getString(DATAMAP_PLUGIN_NAME);
+ String pluginTypeString = dataMap.getString(DATAMAP_PLUGIN_TYPE);
+ String jobId = dataMap.getString(DATAMAP_JOB_ID);
+ String scheduledJobClass = dataMap.getString(DATAMAP_SCHEDULED_JOB_CLASS);
+
+ // obtain the plugin's own callback data from the datamap
+ Properties callbackData = new Properties();
+ for (String key : dataMap.getKeys()) {
+ if (!key.startsWith(DATAMAP_LEADER)) {
+ callbackData.setProperty(key, dataMap.getString(key));
+ }
+ }
+
+ // determine what type of plugin is being triggered
+ ServerPluginType pluginType;
+ try {
+ pluginType = new ServerPluginType(pluginTypeString);
+ } catch (Throwable t) {
+ // datamap has an invalid plugin type string - we need to unschedule this, do not refire
+ log.error(logMsg(pluginName, pluginTypeString, jobId, "Datamap had invalid plugin type string", t));
+ JobExecutionException jobException = new JobExecutionException(t, false);
+ jobException.setUnscheduleFiringTrigger(true);
+ throw jobException;
+ }
+
+ // determine which plugin component class will be invoked to perform the work of the job
+ MasterServerPluginContainer mpc = LookupUtil.getServerPluginService().getMasterPluginContainer();
+ AbstractTypeServerPluginContainer pc = mpc.getPluginContainerByPluginType(pluginType);
+
+ ScheduledJob pluginJob;
+ ServerPluginManager pluginManager = pc.getPluginManager();
+ ServerPluginEnvironment pluginEnv = pluginManager.getPluginEnvironment(pluginName);
+ ServerPluginLifecycleListener lifecycleListener = pluginManager.getServerPluginLifecycleListener(pluginName);
+
+ if (scheduledJobClass == null) {
+ try {
+ pluginJob = (ScheduledJob) lifecycleListener;
+ if (pluginJob == null) {
+ log.error(logMsg(pluginName, pluginType, jobId, "no lifecycle listener to process job", null));
+ throw new UnsupportedOperationException("no lifecycle listener available to process the job");
+ }
+ } catch (Throwable t) {
+ // no valid lifecycle listener that implements job interface - we need to unschedule this, do not refire
+ log.error(logMsg(pluginName, pluginType, jobId, "invaild lifecycle listener", t));
+ JobExecutionException jobException = new JobExecutionException(t, false);
+ jobException.setUnscheduleFiringTrigger(true);
+ throw jobException;
+ }
+ } else {
+ try {
+ pluginJob = (ScheduledJob) pluginManager.instantiatePluginClass(pluginEnv, scheduledJobClass);
+ } catch (Throwable t) {
+ // invalid class - we need to unschedule this, do not refire since it will never work
+ log.error(logMsg(pluginName, pluginType, jobId, "invalid schedule job class", t));
+ JobExecutionException jobException = new JobExecutionException(t, false);
+ jobException.setUnscheduleFiringTrigger(true);
+ throw jobException;
+ }
+ }
+
+ // now actually tell the plugin its time to do the scheduled job
+
+ try {
+ ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(pluginEnv.getPluginClassLoader());
+ pluginJob.execute(jobId, lifecycleListener, callbackData);
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalContextClassLoader);
+ }
+ log.info(logMsg(pluginName, pluginType, jobId, "scheduled job executed", null));
+ } catch (Throwable t) {
+ // any exception thrown out of the job will mean the job is to be unscheduled
+ log.error(logMsg(pluginName, pluginType, jobId, "job threw exception, unscheduling it", t));
+ JobExecutionException jobException = new JobExecutionException(t, false);
+ jobException.setUnscheduleFiringTrigger(true);
+ throw jobException;
+ }
+
+ return;
+ }
+
+ protected String logMsg(String pluginName, Object pluginType, String jobId, String msg, Throwable t) {
+ String s = "Plugin [" + pluginName + "], type=[" + pluginType + "], jobId=[" + jobId + "]: " + msg;
+ if (t != null) {
+ s = s + ". Cause: " + ThrowableUtil.getAllMessages(t);
+ }
+ return s;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index 0d94174..ea0b5a6 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -20,9 +20,15 @@
package org.rhq.enterprise.server.plugin.pc;
import java.util.Collection;
+import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.quartz.Job;
+import org.quartz.JobDataMap;
+
+import org.rhq.enterprise.server.scheduler.SchedulerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
/**
* The abstract superclass for all plugin containers of the different {@link ServerPluginType plugin types}.
@@ -186,4 +192,70 @@ public abstract class AbstractTypeServerPluginContainer {
protected Log getLog() {
return this.log;
}
+
+ /**
+ * Schedules a job for periodic execution.
+ *
+ * @param schedule instructs how the job should be scheduled
+ * @param pluginName the name of the plugin scheduling the job
+ * @param jobId a unique ID that identifies the job within the plugin (jobIds across plugins need not be unique)
+ * @param scheduledJobClass the plugin component class name that implements {@link ScheduledJob} that will perform
+ * the work for the job. If <code>null</code>, the lifecycle listener instance will be
+ * used (note: if <code>null</code>, it means whatever listener instance was used to initialize
+ * the plugin is the same instance that will handle the job; a new instance of the listener
+ * class is not created. This allows a plugin to have a stateful object be periodically
+ * invoked for each job invocation, as opposed to having a new object instantiated for
+ * each job invocation).
+ * @param callbackData if not <code>null</code>, this is a map of properties that will be passed to the scheduled
+ * job - it is Properties to force both the keys and values to be strings, since that is how
+ * we tell quartz to store the data
+ *
+ * @throws Exception if failed to schedule the job
+ */
+ protected void scheduleJob(Schedule schedule, String pluginName, String jobId,
+ Class<? extends ScheduledJob> scheduledJobClass, Properties callbackData) throws Exception {
+
+ String groupName = pluginName;
+ boolean rescheduleIfExists = true; // just in case the parameters change, we'll always want to reschedule it if it exists
+ boolean isVolatile = true; // if plugin is removed, this allows for the schedule to go away upon restart automatically
+
+ // determine which quartz job class we should be using, based on the concurrency needs of the schedule
+ Class<? extends Job> jobClass;
+ if (schedule.isConcurrent()) {
+ jobClass = ConcurrentJobWrapper.class;
+ } else {
+ jobClass = StatefulJobWrapper.class;
+ }
+
+ // build the data map for the job, setting some values we need, plus adding the callback data for the plugin itself
+ JobDataMap jobData = new JobDataMap();
+ jobData.put(AbstractJobWrapper.DATAMAP_PLUGIN_NAME, pluginName);
+ jobData.put(AbstractJobWrapper.DATAMAP_PLUGIN_TYPE, getSupportedServerPluginType().stringify());
+ jobData.put(AbstractJobWrapper.DATAMAP_JOB_ID, jobId);
+ if (scheduledJobClass != null) {
+ jobData.put(AbstractJobWrapper.DATAMAP_SCHEDULED_JOB_CLASS, scheduledJobClass.getName());
+ }
+ if (callbackData != null) {
+ jobData.putAll(callbackData);
+ }
+
+ // schedule the job now
+ SchedulerLocal scheduler = LookupUtil.getSchedulerBean();
+ if (schedule instanceof CronSchedule) {
+ String cronExpression = ((CronSchedule) scheduler).getCronExpression();
+ log.info("Scheduling server plugin cron job: jobName=" + jobId + ", groupName=" + groupName + ", jobClass="
+ + jobClass + ", cron=" + cronExpression);
+ scheduler.scheduleCronJob(jobId, groupName, jobData, jobClass, rescheduleIfExists, isVolatile,
+ cronExpression);
+ } else {
+ long initialDelay = 10000L; // arbitrary - wait a small bit of time before triggering the job
+ long interval = ((PeriodicSchedule) schedule).getPeriod();
+ log.info("Scheduling server plugin periodic job: jobName=" + jobId + ", groupName=" + groupName
+ + ", jobClass=" + jobClass + ", interval=" + interval);
+ scheduler.scheduleRepeatingJob(jobId, groupName, jobData, jobClass, rescheduleIfExists, isVolatile,
+ initialDelay, interval);
+ }
+
+ return;
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java
new file mode 100644
index 0000000..e38d780
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java
@@ -0,0 +1,33 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+/**
+ * The actual quartz job that the plugin container will submit when it needs to invoke
+ * a concurrent scheduled job on behalf of a plugin. This is a normal non-stateful "job"
+ * which tells quartz that it can run multiple jobs concurrently.
+ *
+ * Note that server plugin developers do not extend this class. Instead, developers
+ * need to have their plugin components implement {@link ScheduledJob}.
+ *
+ * @author John Mazzitelli
+ */
+public class ConcurrentJobWrapper extends AbstractJobWrapper {
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index a8696dd..878b149 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -220,6 +220,7 @@ public class MasterServerPluginContainer {
* @param clazz the class name of the plugin container that the caller wants
* @return the plugin container of the given class (<code>null</code> if none found)
*/
+ @SuppressWarnings("unchecked")
public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainer(Class<T> clazz) {
for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
if (clazz.isInstance(pc)) {
@@ -235,11 +236,22 @@ public class MasterServerPluginContainer {
* @param descriptor descriptor to identify a plugin whose container is to be returned
* @return a plugin container that can handle the plugin with the given descriptor
*/
+ protected synchronized AbstractTypeServerPluginContainer getPluginContainerByPluginType(ServerPluginType pluginType) {
+ AbstractTypeServerPluginContainer pc = this.pluginContainers.get(pluginType);
+ return pc;
+ }
+
+ /**
+ * Given a plugin's descriptor, this will return the plugin container that can manage the plugin.
+ *
+ * @param descriptor descriptor to identify a plugin whose container is to be returned
+ * @return a plugin container that can handle the plugin with the given descriptor
+ */
protected synchronized AbstractTypeServerPluginContainer getPluginContainerByDescriptor(
ServerPluginDescriptorType descriptor) {
ServerPluginType pluginType = new ServerPluginType(descriptor.getClass());
- AbstractTypeServerPluginContainer pc = this.pluginContainers.get(pluginType);
+ AbstractTypeServerPluginContainer pc = getPluginContainerByPluginType(pluginType);
return pc;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java
new file mode 100644
index 0000000..b71ff23
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java
@@ -0,0 +1,47 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import java.util.Properties;
+
+/**
+ * An interface to be implemented by any server plugin component that needs to be scheduled.
+ *
+ * @author John Mazzitelli
+ */
+public interface ScheduledJob {
+ /**
+ * Called when the job triggers.
+ *
+ * @param jobId the job identifier that was used when creating the job
+ * @param lifecycleListener if the plugin has a lifecycle listener, this will be it.
+ * Use this object to obtain the plugin context and any other
+ * stateful plugin data specific to the plugin being invoked.
+ * This may be <code>null</code> if the plugin did not define
+ * a global lifecycle listener.
+ * @param callbackData a map of data that was used when creating the job whose values are
+ * passed back to this method as they were when the job was created.
+ *
+ * @throws Exception on any error that should cause the schedule to not fire. If an exception
+ * is thrown, the schedule will not trigger again until the plugin is restarted
+ */
+ void execute(String jobId, ServerPluginLifecycleListener lifecycleListener, Properties callbackData)
+ throws Exception;
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
index b28c14f..f0c8488 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
@@ -25,6 +25,8 @@ import org.rhq.core.domain.configuration.Configuration;
/**
* A global context containing information about a server-side plugin.
+ *
+ * This is an immutable object, plugins are not allowed to alter these values.
*
* @author John Mazzitelli
*/
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index 4226b12..70cd665 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -24,7 +24,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
-import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -54,6 +53,12 @@ public class ServerPluginManager {
private final Map<String, ServerPluginEnvironment> loadedPlugins;
/**
+ * To avoid having to create contexts multiple times for the same plugin,
+ * contexts are cached here, keyed on plugin name.
+ */
+ private final Map<String, ServerPluginContext> pluginContextCache;
+
+ /**
* Cached instances of objects used to initialize and shutdown individual plugins.
* Only plugins that declare their own lifecycle listener will have objects in this cache.
* This is keyed on plugin name.
@@ -68,6 +73,7 @@ public class ServerPluginManager {
public ServerPluginManager(AbstractTypeServerPluginContainer pc) {
this.parentPluginContainer = pc;
this.loadedPlugins = new HashMap<String, ServerPluginEnvironment>();
+ this.pluginContextCache = new HashMap<String, ServerPluginContext>();
this.pluginLifecycleListenerCache = new HashMap<String, ServerPluginLifecycleListener>();
}
@@ -91,9 +97,10 @@ public class ServerPluginManager {
if (this.loadedPlugins.size() > 0) {
log.warn("Server plugin manager is being shutdown while some plugins are still loaded: "
+ this.loadedPlugins);
- this.loadedPlugins.clear();
}
+ this.loadedPlugins.clear();
+ this.pluginContextCache.clear();
this.pluginLifecycleListenerCache.clear();
return;
@@ -114,7 +121,7 @@ public class ServerPluginManager {
// tell the plugin we are loading it
ServerPluginLifecycleListener listener = createServerPluginLifecycleListener(env);
if (listener != null) {
- ServerPluginContext context = createServerPluginContext(env);
+ ServerPluginContext context = getServerPluginContext(env);
log.debug("Initializing lifecycle listener for server plugin [" + pluginName + "]");
ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
@@ -138,7 +145,7 @@ public class ServerPluginManager {
log.debug("Starting plugins");
// tell all lifecycle listeners to start
- for (Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
+ for (Map.Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
String pluginName = entry.getKey();
ServerPluginLifecycleListener listener = entry.getValue();
ServerPluginEnvironment env = this.loadedPlugins.get(pluginName);
@@ -154,6 +161,19 @@ public class ServerPluginManager {
}
}
+ // if there are any global schedules defined, schedule them now.
+ // note that we know if there is no lifecycle listener, then there can't be a schedule
+ for (String pluginName : this.pluginLifecycleListenerCache.keySet()) {
+ Schedule schedule = getServerPluginContext(this.loadedPlugins.get(pluginName)).getSchedule();
+ if (schedule != null) {
+ try {
+ this.parentPluginContainer.scheduleJob(schedule, pluginName, "__globalScheduleJob", null, null);
+ } catch (Throwable t) {
+ log.warn("Failed to schedule the global plugin job for plugin [" + pluginName + "]", t);
+ }
+ }
+ }
+
return;
}
@@ -161,7 +181,7 @@ public class ServerPluginManager {
log.debug("Stopping plugins");
// tell all lifecycle listeners to stop
- for (Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
+ for (Map.Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
String pluginName = entry.getKey();
ServerPluginLifecycleListener listener = entry.getValue();
ServerPluginEnvironment env = this.loadedPlugins.get(pluginName);
@@ -238,6 +258,20 @@ public class ServerPluginManager {
return this.loadedPlugins.get(pluginName);
}
+ /**
+ * Returns the lifecycle listener instance that is responsible for initializing and managing
+ * the plugin. This will return <code>null</code> if a plugin has not defined a lifecycle listener.
+ *
+ * @param pluginName the name of the plugin whose lifecycle listener is to be returned
+ *
+ * @return the lifecycle listener instance that initialized and is managing a plugin. Will
+ * return <code>null</code> if the plugin has not defined a lifecycle listener.
+ * <code>null</code> is also returned if the plugin is not initialized yet.
+ */
+ public synchronized ServerPluginLifecycleListener getServerPluginLifecycleListener(String pluginName) {
+ return this.pluginLifecycleListenerCache.get(pluginName);
+ }
+
public AbstractTypeServerPluginContainer getParentPluginContainer() {
return this.parentPluginContainer;
}
@@ -246,8 +280,16 @@ public class ServerPluginManager {
return this.log;
}
- protected ServerPluginContext createServerPluginContext(ServerPluginEnvironment env) {
+ protected synchronized ServerPluginContext getServerPluginContext(ServerPluginEnvironment env) {
+
String pluginName = env.getPluginName();
+ ServerPluginContext context = this.pluginContextCache.get(pluginName);
+
+ // if we already created it, return it immediately and don't create another
+ if (context != null) {
+ return context;
+ }
+
ServerPluginDescriptorType pluginDescriptor = env.getPluginDescriptor();
MasterServerPluginContainer masterPC = this.parentPluginContainer.getMasterServerPluginContainer();
@@ -280,7 +322,8 @@ public class ServerPluginManager {
}
}
- ServerPluginContext context = new ServerPluginContext(env, dataDir, tmpDir, config, schedule);
+ context = new ServerPluginContext(env, dataDir, tmpDir, config, schedule);
+ this.pluginContextCache.put(pluginName, context);
return context;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
index f9fe313..feba2fc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
@@ -22,6 +22,7 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
/**
* Defines the types of server-side plugins that are currently supported.
+ * Server side plugin types are identified uniquely by their plugin descriptor types.
*
* @author John Mazzitelli
*/
@@ -35,8 +36,33 @@ public class ServerPluginType {
this.descriptorType = descriptorType;
}
+ /**
+ * Given a string that was returned by a call to {@link #stringify()}, this
+ * will create its server plugin type.
+ *
+ * @param stringifiedType string representation of a server plugin type.
+ *
+ * @throws Exception if the string was invalid
+ */
+ @SuppressWarnings("unchecked")
+ public ServerPluginType(String stringifiedType) throws Exception {
+ this((Class<? extends ServerPluginDescriptorType>) Class.forName(stringifiedType));
+ }
+
public Class<? extends ServerPluginDescriptorType> getDescriptorType() {
- return descriptorType;
+ return this.descriptorType;
+ }
+
+ /**
+ * Returns a "serialized" form of this instance by returning a string
+ * representation of the type. This is not the same as {@link #toString()}.
+ * The returned string can be used to reconstitute the type via
+ * the constructor {@link ServerPluginType#ServerPluginType(String)}.
+ *
+ * @return string representation of this type
+ */
+ public String stringify() {
+ return this.descriptorType.getName();
}
@Override
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java
new file mode 100644
index 0000000..0c6495e
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java
@@ -0,0 +1,35 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import org.quartz.StatefulJob;
+
+/**
+ * The actual quartz job that the plugin container will submit when it needs to invoke
+ * a scheduled job on behalf of a plugin. This is a "stateful job" which tells quartz
+ * that only one job should be invoked at any one time on any server.
+ *
+ * Note that server plugin developers do not extend this class. Instead, developers
+ * need to have their plugin components implement {@link ScheduledJob}.
+ *
+ * @author John Mazzitelli
+ */
+public class StatefulJobWrapper extends AbstractJobWrapper implements StatefulJob {
+}
commit 8075b0b26d1c2514ff7a1c831491a51d8a2909c8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 03:22:06 2009 -0500
Squashed commit of the following:
commit d3dfc1a52b0414bd67f50ed9c881c8c3e33e9a1e
Merge: 2cd6ba1 ad45fe5
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 22:38:00 2009 -0500
Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq
commit 2cd6ba182ee07849e2ccd06be6c962b879f45112
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 16:33:18 2009 -0500
Allow clean install to still copy over the license file.
This patch moves the license file from the server container module to the ear module. It is copied over in the dev profile only.
diff --git a/modules/enterprise/server/container/src/main/license/license.xml b/modules/enterprise/server/container/src/main/license/license.xml
deleted file mode 100644
index 2b4d104..0000000
--- a/modules/enterprise/server/container/src/main/license/license.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0"?>
-
-<!--
- This license should be uploaded to your RHQ Server in the
- Manage License section of the Administration area. If you have
- not already installed a license, you will be directed to this
- page on your first login to the application.
-
- You must login as an administrator to update your license file.
--->
-
-<!-- License created: Feb-12-2008 17:35 -->
-<license key="f3e30ce3f40d3da5a1b1625f1d8bd253" version="2.0">
-
- <license-owner name="RHQ"
- email="nobody(a)rhq-project.org"
- phone="888-555-1212"
- key="f6a629735537a0ff90c002ada39db105"/>
-
- <license-expiration date="*" key="8a58f1b633e356a321251f2ffdf2c34e" />
- <platform-limit count="*" key="a6ccfd9f9d66f73cff44b5953971166b" />
- <server-ip count="1" address="*" key="945f33206407c7743d205f2b345e8a57" />
- <plugin-enable name="*" key="62fa3b11086463a41abf7daf7fc572ee" />
- <support-level level="3" key="8e820272b1aa2289eb284a47745ab401" />
-
-</license>
diff --git a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
index 1c04382..ad1e0f6 100644
--- a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
+++ b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
@@ -371,13 +371,6 @@
<!-- optionally package the connectors -->
<antcall target="package-connectors" />
- <!-- Let's deploy some developer-only stuff - we'll remove these later if this is a release build -->
- <echo>Deploying the license file ...</echo>
- <copy file="${basedir}/src/main/license/license.xml"
- todir="${jboss.deploy.dir}/${rhq.earName}/license"
- verbose="true"
- failonerror="false"/>
-
<echo>Enabling server to run on Java 6 ...</echo>
<move todir="${jboss.home}/lib/endorsed" verbose="true">
<fileset dir="${jboss.home}/client">
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index 6668703..7308abb 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -434,6 +434,8 @@
<phase>package</phase>
<configuration>
<tasks>
+ <mkdir dir="${earDirectory}/license" />
+ <copy todir="${earDirectory}/license" file="${basedir}/src/main/license/license.xml"/>
<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}">
diff --git a/modules/enterprise/server/ear/src/main/license/license.xml b/modules/enterprise/server/ear/src/main/license/license.xml
new file mode 100644
index 0000000..2b4d104
--- /dev/null
+++ b/modules/enterprise/server/ear/src/main/license/license.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+
+<!--
+ This license should be uploaded to your RHQ Server in the
+ Manage License section of the Administration area. If you have
+ not already installed a license, you will be directed to this
+ page on your first login to the application.
+
+ You must login as an administrator to update your license file.
+-->
+
+<!-- License created: Feb-12-2008 17:35 -->
+<license key="f3e30ce3f40d3da5a1b1625f1d8bd253" version="2.0">
+
+ <license-owner name="RHQ"
+ email="nobody(a)rhq-project.org"
+ phone="888-555-1212"
+ key="f6a629735537a0ff90c002ada39db105"/>
+
+ <license-expiration date="*" key="8a58f1b633e356a321251f2ffdf2c34e" />
+ <platform-limit count="*" key="a6ccfd9f9d66f73cff44b5953971166b" />
+ <server-ip count="1" address="*" key="945f33206407c7743d205f2b345e8a57" />
+ <plugin-enable name="*" key="62fa3b11086463a41abf7daf7fc572ee" />
+ <support-level level="3" key="8e820272b1aa2289eb284a47745ab401" />
+
+</license>
commit 0a875651ffaaa5911d178db1e82e5599d9b84b83
Merge: c43c87d... d3dfc1a...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 03:15:45 2009 -0500
Merge branch 'master' into pc
Conflicts:
modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
commit 9d93844a860e54c2a012644975ccee198c76f9a6
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 02:53:23 2009 -0500
actually schedule the jobs in quartz
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
index bf71867..6c39277 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -113,10 +113,11 @@ abstract class AbstractJobWrapper implements Job {
ScheduledJob pluginJob;
ServerPluginManager pluginManager = pc.getPluginManager();
ServerPluginEnvironment pluginEnv = pluginManager.getPluginEnvironment(pluginName);
+ ServerPluginLifecycleListener lifecycleListener = pluginManager.getServerPluginLifecycleListener(pluginName);
if (scheduledJobClass == null) {
try {
- pluginJob = (ScheduledJob) pluginManager.getServerPluginLifecycleListener(pluginName);
+ pluginJob = (ScheduledJob) lifecycleListener;
if (pluginJob == null) {
log.error(logMsg(pluginName, pluginType, jobId, "no lifecycle listener to process job", null));
throw new UnsupportedOperationException("no lifecycle listener available to process the job");
@@ -140,11 +141,16 @@ abstract class AbstractJobWrapper implements Job {
}
}
- ServerPluginContext pluginContext = pluginManager.createServerPluginContext(pluginEnv);
-
// now actually tell the plugin its time to do the scheduled job
+
try {
- pluginJob.execute(jobId, pluginContext, callbackData);
+ ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(pluginEnv.getPluginClassLoader());
+ pluginJob.execute(jobId, lifecycleListener, callbackData);
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalContextClassLoader);
+ }
log.info(logMsg(pluginName, pluginType, jobId, "scheduled job executed", null));
} catch (Throwable t) {
// any exception thrown out of the job will mean the job is to be unscheduled
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java
index 5221b18..b71ff23 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java
@@ -31,12 +31,17 @@ public interface ScheduledJob {
* Called when the job triggers.
*
* @param jobId the job identifier that was used when creating the job
- * @param pluginContext the global plugin context for the plugin whose job is being triggered
+ * @param lifecycleListener if the plugin has a lifecycle listener, this will be it.
+ * Use this object to obtain the plugin context and any other
+ * stateful plugin data specific to the plugin being invoked.
+ * This may be <code>null</code> if the plugin did not define
+ * a global lifecycle listener.
* @param callbackData a map of data that was used when creating the job whose values are
* passed back to this method as they were when the job was created.
*
* @throws Exception on any error that should cause the schedule to not fire. If an exception
* is thrown, the schedule will not trigger again until the plugin is restarted
*/
- void execute(String jobId, ServerPluginContext pluginContext, Properties callbackData) throws Exception;
+ void execute(String jobId, ServerPluginLifecycleListener lifecycleListener, Properties callbackData)
+ throws Exception;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
index b28c14f..f0c8488 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
@@ -25,6 +25,8 @@ import org.rhq.core.domain.configuration.Configuration;
/**
* A global context containing information about a server-side plugin.
+ *
+ * This is an immutable object, plugins are not allowed to alter these values.
*
* @author John Mazzitelli
*/
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index 089f502..70cd665 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -24,7 +24,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
-import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -54,6 +53,12 @@ public class ServerPluginManager {
private final Map<String, ServerPluginEnvironment> loadedPlugins;
/**
+ * To avoid having to create contexts multiple times for the same plugin,
+ * contexts are cached here, keyed on plugin name.
+ */
+ private final Map<String, ServerPluginContext> pluginContextCache;
+
+ /**
* Cached instances of objects used to initialize and shutdown individual plugins.
* Only plugins that declare their own lifecycle listener will have objects in this cache.
* This is keyed on plugin name.
@@ -68,6 +73,7 @@ public class ServerPluginManager {
public ServerPluginManager(AbstractTypeServerPluginContainer pc) {
this.parentPluginContainer = pc;
this.loadedPlugins = new HashMap<String, ServerPluginEnvironment>();
+ this.pluginContextCache = new HashMap<String, ServerPluginContext>();
this.pluginLifecycleListenerCache = new HashMap<String, ServerPluginLifecycleListener>();
}
@@ -91,9 +97,10 @@ public class ServerPluginManager {
if (this.loadedPlugins.size() > 0) {
log.warn("Server plugin manager is being shutdown while some plugins are still loaded: "
+ this.loadedPlugins);
- this.loadedPlugins.clear();
}
+ this.loadedPlugins.clear();
+ this.pluginContextCache.clear();
this.pluginLifecycleListenerCache.clear();
return;
@@ -114,7 +121,7 @@ public class ServerPluginManager {
// tell the plugin we are loading it
ServerPluginLifecycleListener listener = createServerPluginLifecycleListener(env);
if (listener != null) {
- ServerPluginContext context = createServerPluginContext(env);
+ ServerPluginContext context = getServerPluginContext(env);
log.debug("Initializing lifecycle listener for server plugin [" + pluginName + "]");
ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
try {
@@ -138,7 +145,7 @@ public class ServerPluginManager {
log.debug("Starting plugins");
// tell all lifecycle listeners to start
- for (Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
+ for (Map.Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
String pluginName = entry.getKey();
ServerPluginLifecycleListener listener = entry.getValue();
ServerPluginEnvironment env = this.loadedPlugins.get(pluginName);
@@ -154,6 +161,19 @@ public class ServerPluginManager {
}
}
+ // if there are any global schedules defined, schedule them now.
+ // note that we know if there is no lifecycle listener, then there can't be a schedule
+ for (String pluginName : this.pluginLifecycleListenerCache.keySet()) {
+ Schedule schedule = getServerPluginContext(this.loadedPlugins.get(pluginName)).getSchedule();
+ if (schedule != null) {
+ try {
+ this.parentPluginContainer.scheduleJob(schedule, pluginName, "__globalScheduleJob", null, null);
+ } catch (Throwable t) {
+ log.warn("Failed to schedule the global plugin job for plugin [" + pluginName + "]", t);
+ }
+ }
+ }
+
return;
}
@@ -161,7 +181,7 @@ public class ServerPluginManager {
log.debug("Stopping plugins");
// tell all lifecycle listeners to stop
- for (Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
+ for (Map.Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
String pluginName = entry.getKey();
ServerPluginLifecycleListener listener = entry.getValue();
ServerPluginEnvironment env = this.loadedPlugins.get(pluginName);
@@ -260,8 +280,16 @@ public class ServerPluginManager {
return this.log;
}
- protected ServerPluginContext createServerPluginContext(ServerPluginEnvironment env) {
+ protected synchronized ServerPluginContext getServerPluginContext(ServerPluginEnvironment env) {
+
String pluginName = env.getPluginName();
+ ServerPluginContext context = this.pluginContextCache.get(pluginName);
+
+ // if we already created it, return it immediately and don't create another
+ if (context != null) {
+ return context;
+ }
+
ServerPluginDescriptorType pluginDescriptor = env.getPluginDescriptor();
MasterServerPluginContainer masterPC = this.parentPluginContainer.getMasterServerPluginContainer();
@@ -294,7 +322,8 @@ public class ServerPluginManager {
}
}
- ServerPluginContext context = new ServerPluginContext(env, dataDir, tmpDir, config, schedule);
+ context = new ServerPluginContext(env, dataDir, tmpDir, config, schedule);
+ this.pluginContextCache.put(pluginName, context);
return context;
}
commit 25c0a3e27d9969368230277cb5a33633dbbdb897
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 02:06:54 2009 -0500
add plugin context to the job interface
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
index d781255..bf71867 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -112,6 +112,8 @@ abstract class AbstractJobWrapper implements Job {
ScheduledJob pluginJob;
ServerPluginManager pluginManager = pc.getPluginManager();
+ ServerPluginEnvironment pluginEnv = pluginManager.getPluginEnvironment(pluginName);
+
if (scheduledJobClass == null) {
try {
pluginJob = (ScheduledJob) pluginManager.getServerPluginLifecycleListener(pluginName);
@@ -127,7 +129,6 @@ abstract class AbstractJobWrapper implements Job {
throw jobException;
}
} else {
- ServerPluginEnvironment pluginEnv = pluginManager.getPluginEnvironment(pluginName);
try {
pluginJob = (ScheduledJob) pluginManager.instantiatePluginClass(pluginEnv, scheduledJobClass);
} catch (Throwable t) {
@@ -139,9 +140,11 @@ abstract class AbstractJobWrapper implements Job {
}
}
+ ServerPluginContext pluginContext = pluginManager.createServerPluginContext(pluginEnv);
+
// now actually tell the plugin its time to do the scheduled job
try {
- pluginJob.execute(jobId, callbackData);
+ pluginJob.execute(jobId, pluginContext, callbackData);
log.info(logMsg(pluginName, pluginType, jobId, "scheduled job executed", null));
} catch (Throwable t) {
// any exception thrown out of the job will mean the job is to be unscheduled
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java
index 138e718..5221b18 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java
@@ -31,11 +31,12 @@ public interface ScheduledJob {
* Called when the job triggers.
*
* @param jobId the job identifier that was used when creating the job
+ * @param pluginContext the global plugin context for the plugin whose job is being triggered
* @param callbackData a map of data that was used when creating the job whose values are
* passed back to this method as they were when the job was created.
*
* @throws Exception on any error that should cause the schedule to not fire. If an exception
* is thrown, the schedule will not trigger again until the plugin is restarted
*/
- void execute(String jobId, Properties callbackData) throws Exception;
+ void execute(String jobId, ServerPluginContext pluginContext, Properties callbackData) throws Exception;
}
commit c14822a979ab9e130dfc08279ae6ca342bd591bf
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 12 01:45:23 2009 -0500
provide an API to schedule jobs
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
new file mode 100644
index 0000000..d781255
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractJobWrapper.java
@@ -0,0 +1,164 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.quartz.Job;
+import org.quartz.JobDataMap;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+
+import org.rhq.core.util.exception.ThrowableUtil;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * The superclass to the concurrent and stateful job wrappers.
+ * See the subclasses for more information.
+ *
+ * @author John Mazzitelli
+ */
+abstract class AbstractJobWrapper implements Job {
+ private final Log log = LogFactory.getLog(this.getClass());
+
+ /**
+ * All keys prefixed with this leader identify the data map values as our internal values.
+ * Any data map key without this prefix is assumed to be part of the plugin callback data.
+ */
+ private static final String DATAMAP_LEADER = "__";
+
+ /**
+ * Key to the job data map that indicates the plugin that scheduled the job.
+ */
+ public static final String DATAMAP_PLUGIN_NAME = DATAMAP_LEADER + "pluginName";
+
+ /**
+ * Key to the job data map that indicates the type of plugin that scheduled the job.
+ */
+ public static final String DATAMAP_PLUGIN_TYPE = DATAMAP_LEADER + "pluginType";
+
+ /**
+ * Key to the job data map that indicates the ID of the job.
+ * This ID is passed to the plugin container when the job was scheduled, see:
+ * {@link AbstractTypeServerPluginContainer#scheduleJob(Schedule, String, String, ScheduledJob, java.util.Properties)}
+ */
+ public static final String DATAMAP_JOB_ID = DATAMAP_LEADER + "jobId";
+
+ /**
+ * Key to the job data map that indicates which plugin component class should be instantiated
+ * in order to process the job. This must implement {@link ScheduledJob}.
+ */
+ public static final String DATAMAP_SCHEDULED_JOB_CLASS = DATAMAP_LEADER + "scheduledJobClass";
+
+ /**
+ * This is the method that quartz calls when the schedule has triggered. This method will
+ * delegate to the plugin component that is responsible to do work for the plugin.
+ *
+ * @see ScheduledJob#execute(String, Properties)
+ */
+ public void execute(JobExecutionContext context) throws JobExecutionException {
+ log.debug("scheduled server plugin job triggered");
+
+ JobDataMap dataMap = context.getJobDetail().getJobDataMap();
+
+ // obtain our internal values that we need from the datamap
+ String pluginName = dataMap.getString(DATAMAP_PLUGIN_NAME);
+ String pluginTypeString = dataMap.getString(DATAMAP_PLUGIN_TYPE);
+ String jobId = dataMap.getString(DATAMAP_JOB_ID);
+ String scheduledJobClass = dataMap.getString(DATAMAP_SCHEDULED_JOB_CLASS);
+
+ // obtain the plugin's own callback data from the datamap
+ Properties callbackData = new Properties();
+ for (String key : dataMap.getKeys()) {
+ if (!key.startsWith(DATAMAP_LEADER)) {
+ callbackData.setProperty(key, dataMap.getString(key));
+ }
+ }
+
+ // determine what type of plugin is being triggered
+ ServerPluginType pluginType;
+ try {
+ pluginType = new ServerPluginType(pluginTypeString);
+ } catch (Throwable t) {
+ // datamap has an invalid plugin type string - we need to unschedule this, do not refire
+ log.error(logMsg(pluginName, pluginTypeString, jobId, "Datamap had invalid plugin type string", t));
+ JobExecutionException jobException = new JobExecutionException(t, false);
+ jobException.setUnscheduleFiringTrigger(true);
+ throw jobException;
+ }
+
+ // determine which plugin component class will be invoked to perform the work of the job
+ MasterServerPluginContainer mpc = LookupUtil.getServerPluginService().getMasterPluginContainer();
+ AbstractTypeServerPluginContainer pc = mpc.getPluginContainerByPluginType(pluginType);
+
+ ScheduledJob pluginJob;
+ ServerPluginManager pluginManager = pc.getPluginManager();
+ if (scheduledJobClass == null) {
+ try {
+ pluginJob = (ScheduledJob) pluginManager.getServerPluginLifecycleListener(pluginName);
+ if (pluginJob == null) {
+ log.error(logMsg(pluginName, pluginType, jobId, "no lifecycle listener to process job", null));
+ throw new UnsupportedOperationException("no lifecycle listener available to process the job");
+ }
+ } catch (Throwable t) {
+ // no valid lifecycle listener that implements job interface - we need to unschedule this, do not refire
+ log.error(logMsg(pluginName, pluginType, jobId, "invaild lifecycle listener", t));
+ JobExecutionException jobException = new JobExecutionException(t, false);
+ jobException.setUnscheduleFiringTrigger(true);
+ throw jobException;
+ }
+ } else {
+ ServerPluginEnvironment pluginEnv = pluginManager.getPluginEnvironment(pluginName);
+ try {
+ pluginJob = (ScheduledJob) pluginManager.instantiatePluginClass(pluginEnv, scheduledJobClass);
+ } catch (Throwable t) {
+ // invalid class - we need to unschedule this, do not refire since it will never work
+ log.error(logMsg(pluginName, pluginType, jobId, "invalid schedule job class", t));
+ JobExecutionException jobException = new JobExecutionException(t, false);
+ jobException.setUnscheduleFiringTrigger(true);
+ throw jobException;
+ }
+ }
+
+ // now actually tell the plugin its time to do the scheduled job
+ try {
+ pluginJob.execute(jobId, callbackData);
+ log.info(logMsg(pluginName, pluginType, jobId, "scheduled job executed", null));
+ } catch (Throwable t) {
+ // any exception thrown out of the job will mean the job is to be unscheduled
+ log.error(logMsg(pluginName, pluginType, jobId, "job threw exception, unscheduling it", t));
+ JobExecutionException jobException = new JobExecutionException(t, false);
+ jobException.setUnscheduleFiringTrigger(true);
+ throw jobException;
+ }
+
+ return;
+ }
+
+ protected String logMsg(String pluginName, Object pluginType, String jobId, String msg, Throwable t) {
+ String s = "Plugin [" + pluginName + "], type=[" + pluginType + "], jobId=[" + jobId + "]: " + msg;
+ if (t != null) {
+ s = s + ". Cause: " + ThrowableUtil.getAllMessages(t);
+ }
+ return s;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index 0d94174..ea0b5a6 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -20,9 +20,15 @@
package org.rhq.enterprise.server.plugin.pc;
import java.util.Collection;
+import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.quartz.Job;
+import org.quartz.JobDataMap;
+
+import org.rhq.enterprise.server.scheduler.SchedulerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
/**
* The abstract superclass for all plugin containers of the different {@link ServerPluginType plugin types}.
@@ -186,4 +192,70 @@ public abstract class AbstractTypeServerPluginContainer {
protected Log getLog() {
return this.log;
}
+
+ /**
+ * Schedules a job for periodic execution.
+ *
+ * @param schedule instructs how the job should be scheduled
+ * @param pluginName the name of the plugin scheduling the job
+ * @param jobId a unique ID that identifies the job within the plugin (jobIds across plugins need not be unique)
+ * @param scheduledJobClass the plugin component class name that implements {@link ScheduledJob} that will perform
+ * the work for the job. If <code>null</code>, the lifecycle listener instance will be
+ * used (note: if <code>null</code>, it means whatever listener instance was used to initialize
+ * the plugin is the same instance that will handle the job; a new instance of the listener
+ * class is not created. This allows a plugin to have a stateful object be periodically
+ * invoked for each job invocation, as opposed to having a new object instantiated for
+ * each job invocation).
+ * @param callbackData if not <code>null</code>, this is a map of properties that will be passed to the scheduled
+ * job - it is Properties to force both the keys and values to be strings, since that is how
+ * we tell quartz to store the data
+ *
+ * @throws Exception if failed to schedule the job
+ */
+ protected void scheduleJob(Schedule schedule, String pluginName, String jobId,
+ Class<? extends ScheduledJob> scheduledJobClass, Properties callbackData) throws Exception {
+
+ String groupName = pluginName;
+ boolean rescheduleIfExists = true; // just in case the parameters change, we'll always want to reschedule it if it exists
+ boolean isVolatile = true; // if plugin is removed, this allows for the schedule to go away upon restart automatically
+
+ // determine which quartz job class we should be using, based on the concurrency needs of the schedule
+ Class<? extends Job> jobClass;
+ if (schedule.isConcurrent()) {
+ jobClass = ConcurrentJobWrapper.class;
+ } else {
+ jobClass = StatefulJobWrapper.class;
+ }
+
+ // build the data map for the job, setting some values we need, plus adding the callback data for the plugin itself
+ JobDataMap jobData = new JobDataMap();
+ jobData.put(AbstractJobWrapper.DATAMAP_PLUGIN_NAME, pluginName);
+ jobData.put(AbstractJobWrapper.DATAMAP_PLUGIN_TYPE, getSupportedServerPluginType().stringify());
+ jobData.put(AbstractJobWrapper.DATAMAP_JOB_ID, jobId);
+ if (scheduledJobClass != null) {
+ jobData.put(AbstractJobWrapper.DATAMAP_SCHEDULED_JOB_CLASS, scheduledJobClass.getName());
+ }
+ if (callbackData != null) {
+ jobData.putAll(callbackData);
+ }
+
+ // schedule the job now
+ SchedulerLocal scheduler = LookupUtil.getSchedulerBean();
+ if (schedule instanceof CronSchedule) {
+ String cronExpression = ((CronSchedule) scheduler).getCronExpression();
+ log.info("Scheduling server plugin cron job: jobName=" + jobId + ", groupName=" + groupName + ", jobClass="
+ + jobClass + ", cron=" + cronExpression);
+ scheduler.scheduleCronJob(jobId, groupName, jobData, jobClass, rescheduleIfExists, isVolatile,
+ cronExpression);
+ } else {
+ long initialDelay = 10000L; // arbitrary - wait a small bit of time before triggering the job
+ long interval = ((PeriodicSchedule) schedule).getPeriod();
+ log.info("Scheduling server plugin periodic job: jobName=" + jobId + ", groupName=" + groupName
+ + ", jobClass=" + jobClass + ", interval=" + interval);
+ scheduler.scheduleRepeatingJob(jobId, groupName, jobData, jobClass, rescheduleIfExists, isVolatile,
+ initialDelay, interval);
+ }
+
+ return;
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java
new file mode 100644
index 0000000..e38d780
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ConcurrentJobWrapper.java
@@ -0,0 +1,33 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+/**
+ * The actual quartz job that the plugin container will submit when it needs to invoke
+ * a concurrent scheduled job on behalf of a plugin. This is a normal non-stateful "job"
+ * which tells quartz that it can run multiple jobs concurrently.
+ *
+ * Note that server plugin developers do not extend this class. Instead, developers
+ * need to have their plugin components implement {@link ScheduledJob}.
+ *
+ * @author John Mazzitelli
+ */
+public class ConcurrentJobWrapper extends AbstractJobWrapper {
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index a8696dd..878b149 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -220,6 +220,7 @@ public class MasterServerPluginContainer {
* @param clazz the class name of the plugin container that the caller wants
* @return the plugin container of the given class (<code>null</code> if none found)
*/
+ @SuppressWarnings("unchecked")
public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainer(Class<T> clazz) {
for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
if (clazz.isInstance(pc)) {
@@ -235,11 +236,22 @@ public class MasterServerPluginContainer {
* @param descriptor descriptor to identify a plugin whose container is to be returned
* @return a plugin container that can handle the plugin with the given descriptor
*/
+ protected synchronized AbstractTypeServerPluginContainer getPluginContainerByPluginType(ServerPluginType pluginType) {
+ AbstractTypeServerPluginContainer pc = this.pluginContainers.get(pluginType);
+ return pc;
+ }
+
+ /**
+ * Given a plugin's descriptor, this will return the plugin container that can manage the plugin.
+ *
+ * @param descriptor descriptor to identify a plugin whose container is to be returned
+ * @return a plugin container that can handle the plugin with the given descriptor
+ */
protected synchronized AbstractTypeServerPluginContainer getPluginContainerByDescriptor(
ServerPluginDescriptorType descriptor) {
ServerPluginType pluginType = new ServerPluginType(descriptor.getClass());
- AbstractTypeServerPluginContainer pc = this.pluginContainers.get(pluginType);
+ AbstractTypeServerPluginContainer pc = getPluginContainerByPluginType(pluginType);
return pc;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java
new file mode 100644
index 0000000..138e718
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ScheduledJob.java
@@ -0,0 +1,41 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import java.util.Properties;
+
+/**
+ * An interface to be implemented by any server plugin component that needs to be scheduled.
+ *
+ * @author John Mazzitelli
+ */
+public interface ScheduledJob {
+ /**
+ * Called when the job triggers.
+ *
+ * @param jobId the job identifier that was used when creating the job
+ * @param callbackData a map of data that was used when creating the job whose values are
+ * passed back to this method as they were when the job was created.
+ *
+ * @throws Exception on any error that should cause the schedule to not fire. If an exception
+ * is thrown, the schedule will not trigger again until the plugin is restarted
+ */
+ void execute(String jobId, Properties callbackData) throws Exception;
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index 4226b12..089f502 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -238,6 +238,20 @@ public class ServerPluginManager {
return this.loadedPlugins.get(pluginName);
}
+ /**
+ * Returns the lifecycle listener instance that is responsible for initializing and managing
+ * the plugin. This will return <code>null</code> if a plugin has not defined a lifecycle listener.
+ *
+ * @param pluginName the name of the plugin whose lifecycle listener is to be returned
+ *
+ * @return the lifecycle listener instance that initialized and is managing a plugin. Will
+ * return <code>null</code> if the plugin has not defined a lifecycle listener.
+ * <code>null</code> is also returned if the plugin is not initialized yet.
+ */
+ public synchronized ServerPluginLifecycleListener getServerPluginLifecycleListener(String pluginName) {
+ return this.pluginLifecycleListenerCache.get(pluginName);
+ }
+
public AbstractTypeServerPluginContainer getParentPluginContainer() {
return this.parentPluginContainer;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
index f9fe313..feba2fc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
@@ -22,6 +22,7 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
/**
* Defines the types of server-side plugins that are currently supported.
+ * Server side plugin types are identified uniquely by their plugin descriptor types.
*
* @author John Mazzitelli
*/
@@ -35,8 +36,33 @@ public class ServerPluginType {
this.descriptorType = descriptorType;
}
+ /**
+ * Given a string that was returned by a call to {@link #stringify()}, this
+ * will create its server plugin type.
+ *
+ * @param stringifiedType string representation of a server plugin type.
+ *
+ * @throws Exception if the string was invalid
+ */
+ @SuppressWarnings("unchecked")
+ public ServerPluginType(String stringifiedType) throws Exception {
+ this((Class<? extends ServerPluginDescriptorType>) Class.forName(stringifiedType));
+ }
+
public Class<? extends ServerPluginDescriptorType> getDescriptorType() {
- return descriptorType;
+ return this.descriptorType;
+ }
+
+ /**
+ * Returns a "serialized" form of this instance by returning a string
+ * representation of the type. This is not the same as {@link #toString()}.
+ * The returned string can be used to reconstitute the type via
+ * the constructor {@link ServerPluginType#ServerPluginType(String)}.
+ *
+ * @return string representation of this type
+ */
+ public String stringify() {
+ return this.descriptorType.getName();
}
@Override
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java
new file mode 100644
index 0000000..0c6495e
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/StatefulJobWrapper.java
@@ -0,0 +1,35 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import org.quartz.StatefulJob;
+
+/**
+ * The actual quartz job that the plugin container will submit when it needs to invoke
+ * a scheduled job on behalf of a plugin. This is a "stateful job" which tells quartz
+ * that only one job should be invoked at any one time on any server.
+ *
+ * Note that server plugin developers do not extend this class. Instead, developers
+ * need to have their plugin components implement {@link ScheduledJob}.
+ *
+ * @author John Mazzitelli
+ */
+public class StatefulJobWrapper extends AbstractJobWrapper implements StatefulJob {
+}
commit d3dfc1a52b0414bd67f50ed9c881c8c3e33e9a1e
Merge: 2cd6ba1... ad45fe5...
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 22:38:00 2009 -0500
Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq
commit 3b6e81de84ba5b3ec4af37fd7c1ba7afafe65d8a
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 20:38:51 2009 -0500
Added Load and Update tests for the alias component
diff --git a/modules/plugins/aliases/src/test/java/org/rhq/plugins/aliases/AliasesComponentTest.java b/modules/plugins/aliases/src/test/java/org/rhq/plugins/aliases/AliasesComponentTest.java
index 4071fb4..27d6f0c 100644
--- a/modules/plugins/aliases/src/test/java/org/rhq/plugins/aliases/AliasesComponentTest.java
+++ b/modules/plugins/aliases/src/test/java/org/rhq/plugins/aliases/AliasesComponentTest.java
@@ -18,13 +18,11 @@
*/
package org.rhq.plugins.aliases;
-import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
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.pc.PluginContainer;
-import org.rhq.plugins.augeas.AbstractAugeasConfigurationComponentTest;
+import org.rhq.plugins.augeas.test.AbstractAugeasConfigurationComponentTest;
/**
* An integration test for {@link AliasesComponent}.
@@ -32,12 +30,12 @@ import org.rhq.plugins.augeas.AbstractAugeasConfigurationComponentTest;
public class AliasesComponentTest extends AbstractAugeasConfigurationComponentTest {
@Override
protected String getPluginName() {
- return "Hosts";
+ return "Aliases";
}
@Override
protected String getResourceTypeName() {
- return "Hosts File";
+ return "Aliases File";
}
@Override
@@ -48,54 +46,52 @@ public class AliasesComponentTest extends AbstractAugeasConfigurationComponentTe
PropertyMap entry;
- entry = new PropertyMap("*[canonical]");
- entry.put(new PropertySimple("ipaddr", "127.0.0.1"));
- entry.put(new PropertySimple("canonical", "localhost"));
- entry.put(new PropertySimple("alias", "localhost.localdomain\nlocalhost4\nlocalhost4.localdomain4"));
+ entry = new PropertyMap("*[name]");
+ entry.put(new PropertySimple("name", "bin"));
+ entry.put(new PropertySimple("value", "root"));
entries.getList().add(entry);
- entry = new PropertyMap("*[canonical]");
- entry.put(new PropertySimple("ipaddr", "::1"));
- entry.put(new PropertySimple("canonical", "localhost"));
- entry.put(new PropertySimple("alias", "localhost.localdomain\nlocalhost6\nlocalhost6.localdomain6"));
+ entry = new PropertyMap("*[name]");
+ entry.put(new PropertySimple("name", "daemon"));
+ entry.put(new PropertySimple("value", "root"));
entries.getList().add(entry);
- entry = new PropertyMap("*[canonical]");
- entry.put(new PropertySimple("ipaddr", "1.1.1.1"));
- entry.put(new PropertySimple("canonical", "one-one-one-one.com"));
- entry.put(new PropertySimple("alias", null));
+ entry = new PropertyMap("*[name]");
+ entry.put(new PropertySimple("name", "adm"));
+ entry.put(new PropertySimple("value", "root"));
entries.getList().add(entry);
- entry = new PropertyMap("*[canonical]");
- entry.put(new PropertySimple("ipaddr", "2.2.2.2"));
- entry.put(new PropertySimple("canonical", "two-two-two-two.com"));
- entry.put(new PropertySimple("alias", "alias"));
+ entry = new PropertyMap("*[name]");
+ entry.put(new PropertySimple("name", "lp"));
+ entry.put(new PropertySimple("value", "root"));
entries.getList().add(entry);
- entry = new PropertyMap("*[canonical]");
- entry.put(new PropertySimple("ipaddr", "3.3.3.3"));
- entry.put(new PropertySimple("canonical", "three-three-three-three.com"));
- entry.put(new PropertySimple("alias", "alias1\nalias2"));
+ entry = new PropertyMap("*[name]");
+ entry.put(new PropertySimple("name", "sync"));
+ entry.put(new PropertySimple("value", "root"));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("*[name]");
+ entry.put(new PropertySimple("name", "shutdown"));
+ entry.put(new PropertySimple("value", "root"));
entries.getList().add(entry);
return config;
}
- private boolean supportsFacet(Class<?> facetInterface) {
- PluginMetadataManager manager = PluginContainer.getInstance().getPluginManager().getMetadataManager();
- String componentClass = manager.getComponentClass(getResourceType());
+ @Override
+ protected Configuration getUpdatedResourceConfig() {
+ Configuration config = new Configuration();
+ PropertyList entries = new PropertyList(".");
+ config.put(entries);
+
+ PropertyMap entry;
- try {
- return facetInterface.isAssignableFrom(Class.forName(componentClass));
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException("Could not find component class " + componentClass, e);
- }
- }
+ entry = new PropertyMap("*[name]");
+ entry.put(new PropertySimple("name", "shutdown"));
+ entry.put(new PropertySimple("value", "parthaa"));
+ entries.getList().add(entry);
- @Override
- protected Configuration getChangedResourceConfig() {
- // TODO Auto-generated method stub
- //TODO NEED TO FIX THIS
- return null;
+ return config;
}
}
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
index 13f35a2..8ffcfa7 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
@@ -28,21 +28,22 @@ import java.util.Arrays;
import java.util.List;
import java.util.Set;
+import net.augeas.jna.Aug;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.rhq.core.clientapi.agent.PluginContainerException;
-import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
-import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
-import org.rhq.core.pluginapi.util.FileUtils;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
+import org.rhq.core.clientapi.agent.PluginContainerException;
import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
import org.rhq.core.domain.configuration.Configuration;
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.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pc.PluginContainer;
@@ -51,11 +52,10 @@ import org.rhq.core.pc.configuration.ConfigurationManager;
import org.rhq.core.pc.inventory.InventoryManager;
import org.rhq.core.pc.plugin.FileSystemPluginFinder;
import org.rhq.core.pc.plugin.PluginManager;
+import org.rhq.core.pluginapi.util.FileUtils;
import org.rhq.core.util.file.FileUtil;
import org.rhq.plugins.augeas.AugeasConfigurationComponent;
-import net.augeas.jna.Aug;
-
/**
* A base class for integration tests for instances of {@link AugeasConfigurationComponent}.
*
@@ -96,7 +96,7 @@ public abstract class AbstractAugeasConfigurationComponentTest {
pluginContainer.initialize();
Set<String> pluginNames = pluginContainer.getPluginManager().getMetadataManager().getPluginNames();
System.out.println("Plugin container started with the following plugins: " + pluginNames);
-
+
System.out.println("Updating Augeas root in default plugin config...");
ResourceType resourceType = getResourceType();
ConfigurationDefinition pluginConfigDef = resourceType.getPluginConfigurationDefinition();
@@ -104,7 +104,7 @@ public abstract class AbstractAugeasConfigurationComponentTest {
Configuration defaultPluginConfig = defaultPluginConfigTemplate.getConfiguration();
resetConfigFiles(defaultPluginConfig);
PropertySimple rootPathProp = new PropertySimple(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP,
- AUGEAS_ROOT);
+ AUGEAS_ROOT);
defaultPluginConfig.put(rootPathProp);
InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
@@ -128,15 +128,12 @@ public abstract class AbstractAugeasConfigurationComponentTest {
ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
Resource resource = getResource();
Configuration resourceConfig = null;
- try
- {
+ try {
resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
Configuration expectedResourceConfig = getExpectedResourceConfig();
assert resourceConfig.equals(expectedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
+ expectedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
- }
- catch (PluginContainerException e)
- {
+ } catch (PluginContainerException e) {
if (isResourceConfigSupported()) {
throw e;
}
@@ -148,8 +145,8 @@ public abstract class AbstractAugeasConfigurationComponentTest {
ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
Resource resource = getResource();
Configuration updatedResourceConfig = getUpdatedResourceConfig();
- ConfigurationUpdateRequest updateRequest = new ConfigurationUpdateRequest(0, updatedResourceConfig,
- resource.getId());
+ ConfigurationUpdateRequest updateRequest = new ConfigurationUpdateRequest(0, updatedResourceConfig, resource
+ .getId());
configurationManager.updateResourceConfiguration(updateRequest);
if (isResourceConfigSupported()) {
@@ -178,9 +175,7 @@ public abstract class AbstractAugeasConfigurationComponentTest {
protected abstract Configuration getUpdatedResourceConfig();
- protected PluginContainerConfiguration createPluginContainerConfiguration()
- throws IOException
- {
+ protected PluginContainerConfiguration createPluginContainerConfiguration() throws IOException {
PluginContainerConfiguration pcConfig = new PluginContainerConfiguration();
File pluginsDir = new File(ITEST_DIR, "plugins");
pcConfig.setPluginFinder(new FileSystemPluginFinder(pluginsDir));
@@ -260,12 +255,9 @@ public abstract class AbstractAugeasConfigurationComponentTest {
}
private void deleteAugeasRootDir() {
- try
- {
+ try {
FileUtils.purge(AUGEAS_ROOT, true);
- }
- catch (IOException e)
- {
+ } catch (IOException e) {
log.warn("Failed to delete Augeas root dir (" + AUGEAS_ROOT + ").");
}
}
commit 771b96fc5e2213dc8bcba4bb0991aefe1556bd37
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 19:50:04 2009 -0500
added aliaseses to .classpath
diff --git a/.classpath b/.classpath
index f4a074e..1be8e0d 100644
--- a/.classpath
+++ b/.classpath
@@ -97,7 +97,9 @@
<classpathentry kind="src" path="modules/plugins/apt/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/hosts/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/hosts/src/test/java"/>
- <classpathentry kind="src" path="modules/plugins/virt/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/virt/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/aliases/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/aliases/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/snmptrapd/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/script/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/antlr-config/src/main/antlr3"/>
commit 7e8a1621b6990bd4d673c49dda47ad910d0eaab3
Merge: 15a3b45... ad45fe5...
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 19:42:58 2009 -0500
Merge branch 'master' into linux-config
commit 15a3b45d91942fdcccef99a20e422c857834ae0a
Author: Ian P. Springer <ips(a)jetengine.springer.net>
Date: Wed Nov 11 18:48:34 2009 -0500
fix several bugs in augeas and hosts plugins to get hosts+samba+sudoers integration tests passing on Linux; update test log4j.xml in all augeas-based plugins
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java
index 1cfa2de..00cc4f9 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java
@@ -63,6 +63,13 @@ public class Glob {
* @return the list of matches
*/
public static List<File> match(File parentPath, String globPattern) {
+ if (!parentPath.exists()) {
+ throw new IllegalArgumentException("Path '" + parentPath + "' does not exist.");
+ }
+ if (!parentPath.isDirectory()) {
+ throw new IllegalArgumentException("Path '" + parentPath + "' is not a directory.");
+ }
+
String rootPortion = rootPortion(globPattern);
globPattern = globPattern.substring(rootPortion.length());
@@ -76,7 +83,7 @@ public class Glob {
}
if (specialCharIdx > 0) {
- //now search for the first path separator preceeding the special char
+ //now search for the first path separator preceding the special char
int globParentIdx = globPattern.lastIndexOf(File.separatorChar, specialCharIdx);
if (globParentIdx > 0) {
//move the parent path down to the nearest parent of the wildcard part of the
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
index 9688aa8..13f35a2 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
@@ -28,6 +28,8 @@ import java.util.Arrays;
import java.util.List;
import java.util.Set;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.rhq.core.clientapi.agent.PluginContainerException;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
@@ -72,9 +74,11 @@ public abstract class AbstractAugeasConfigurationComponentTest {
AUGEAS_ROOT = new File(tmpDir, "rhq-itest-augeas-root-path");
}
+ private final Log log = LogFactory.getLog(this.getClass());
+
@BeforeSuite(groups = TEST_GROUP)
public void start() {
- if (!isAugeasAvailable()) {
+ if (!isResourceConfigSupported()) {
String message;
if (IS_WINDOWS) {
message = "Augeas is not available on Windows. Augeas-based configuration functionality will *not* be tested.";
@@ -92,14 +96,15 @@ public abstract class AbstractAugeasConfigurationComponentTest {
pluginContainer.initialize();
Set<String> pluginNames = pluginContainer.getPluginManager().getMetadataManager().getPluginNames();
System.out.println("Plugin container started with the following plugins: " + pluginNames);
-
+
System.out.println("Updating Augeas root in default plugin config...");
ResourceType resourceType = getResourceType();
ConfigurationDefinition pluginConfigDef = resourceType.getPluginConfigurationDefinition();
ConfigurationTemplate defaultPluginConfigTemplate = pluginConfigDef.getDefaultTemplate();
Configuration defaultPluginConfig = defaultPluginConfigTemplate.getConfiguration();
resetConfigFiles(defaultPluginConfig);
- PropertySimple rootPathProp = new PropertySimple(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP, null);
+ PropertySimple rootPathProp = new PropertySimple(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP,
+ AUGEAS_ROOT);
defaultPluginConfig.put(rootPathProp);
InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
@@ -132,7 +137,7 @@ public abstract class AbstractAugeasConfigurationComponentTest {
}
catch (PluginContainerException e)
{
- if (isAugeasAvailable()) {
+ if (isResourceConfigSupported()) {
throw e;
}
}
@@ -147,7 +152,7 @@ public abstract class AbstractAugeasConfigurationComponentTest {
resource.getId());
configurationManager.updateResourceConfiguration(updateRequest);
- if (isAugeasAvailable()) {
+ if (isResourceConfigSupported()) {
// Give the component and the managed resource some time to properly persist the update.
Thread.sleep(500);
@@ -159,14 +164,7 @@ public abstract class AbstractAugeasConfigurationComponentTest {
@AfterSuite(groups = TEST_GROUP)
public void stop() {
- try
- {
- FileUtils.purge(AUGEAS_ROOT, true);
- }
- catch (IOException e)
- {
- // ignore
- }
+ deleteAugeasRootDir();
System.out.println("Stopping plugin container...");
PluginContainer.getInstance().shutdown();
System.out.println("Plugin container stopped.");
@@ -231,6 +229,8 @@ public abstract class AbstractAugeasConfigurationComponentTest {
}
protected void resetConfigFiles(Configuration pluginConfig) throws IOException {
+ deleteAugeasRootDir();
+ AUGEAS_ROOT.mkdirs();
String includes = pluginConfig.getSimpleValue(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP, null);
if (includes != null) {
List<String> includeGlobs = new ArrayList<String>();
@@ -246,7 +246,11 @@ public abstract class AbstractAugeasConfigurationComponentTest {
}
}
- protected boolean isAugeasAvailable() {
+ protected boolean isResourceConfigSupported() {
+ return isAugeasAvailable();
+ }
+
+ private boolean isAugeasAvailable() {
try {
Aug aug = Aug.INSTANCE;
return true;
@@ -254,4 +258,15 @@ public abstract class AbstractAugeasConfigurationComponentTest {
return false;
}
}
+
+ private void deleteAugeasRootDir() {
+ try
+ {
+ FileUtils.purge(AUGEAS_ROOT, true);
+ }
+ catch (IOException e)
+ {
+ log.warn("Failed to delete Augeas root dir (" + AUGEAS_ROOT + ").");
+ }
+ }
}
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java
index bfd82a1..cd64c12 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java
@@ -30,19 +30,20 @@ import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
import org.rhq.plugins.augeas.AugeasConfigurationDiscoveryComponent;
+import org.rhq.plugins.platform.PlatformComponent;
/**
* The ResourceDiscoveryComponent for the "Hosts File" ResourceType.
*
* @author Ian Springer
*/
-public class HostsDiscoveryComponent extends AugeasConfigurationDiscoveryComponent {
+public class HostsDiscoveryComponent extends AugeasConfigurationDiscoveryComponent<PlatformComponent> {
private static final boolean IS_WINDOWS = (File.separatorChar == '\\');
private final Log log = LogFactory.getLog(this.getClass());
@Override
- public Set discoverResources(ResourceDiscoveryContext discoveryContext) throws InvalidPluginConfigurationException,
+ public Set discoverResources(ResourceDiscoveryContext<PlatformComponent> discoveryContext) throws InvalidPluginConfigurationException,
Exception
{
return super.discoverResources(discoveryContext);
@@ -56,21 +57,15 @@ public class HostsDiscoveryComponent extends AugeasConfigurationDiscoveryCompone
}
@Override
- protected List<String> determineIncludeGlobs(ResourceDiscoveryContext discoveryContext)
+ protected List<String> determineIncludeGlobs(ResourceDiscoveryContext<PlatformComponent> discoveryContext)
{
- File hostsFile;
if (IS_WINDOWS) {
File windowsDir = getWindowsDir();
- hostsFile = new File(windowsDir, "system32/drivers/etc/hosts");
+ File hostsFile = new File(windowsDir, "system32/drivers/etc/hosts");
+ return Collections.singletonList(hostsFile.getPath());
} else {
- hostsFile = new File("/etc/hosts");
+ return super.determineIncludeGlobs(discoveryContext);
}
- return Collections.singletonList(hostsFile.getAbsolutePath());
- }
-
- @Override
- protected List<String> determineExcludeGlobs(ResourceDiscoveryContext discoveryContext) {
- return null;
}
private File getWindowsDir() {
diff --git a/modules/plugins/hosts/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/hosts/src/main/resources/META-INF/rhq-plugin.xml
index eeeb667..a2aef3d 100644
--- a/modules/plugins/hosts/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/hosts/src/main/resources/META-INF/rhq-plugin.xml
@@ -29,10 +29,11 @@
<plugin-configuration>
<c:simple-property name="augeasModuleName" displayName="Augeas Module Name" default="Hosts" required="true" readOnly="true"
- description="the name of the Augeas module/lens to use for loading and updating this resource's configuration"/>
+ description="the name of the Augeas module/lens to use for loading and updating this Resource's configuration"/>
- <c:simple-property name="configurationFilesInclusionPatterns" displayName="Configuration File Paths" required="true" readOnly="true"
- description="the absolute paths of the configuration files, delimited with pipe characters"/>
+ <c:simple-property name="configurationFilesInclusionPatterns"
+ default="/etc/hosts" required="true" readOnly="true"
+ description="the absolute paths of the configuration files, delimited with pipe characters; wildcards are permitted in the last component of the path (e.g. /etc/cron.d/*)"/>
</plugin-configuration>
<resource-configuration>
diff --git a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
index 9c67cfc..2227c4a 100644
--- a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
+++ b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
@@ -41,6 +41,12 @@ public class HostsComponentTest extends AbstractAugeasConfigurationComponentTest
}
@Override
+ protected boolean isResourceConfigSupported() {
+ // The hosts plugin will use Augeas if it's available but will fall back to direct file parsing if it's not.
+ return true;
+ }
+
+ @Override
protected Configuration getExpectedResourceConfig() {
Configuration config = new Configuration();
PropertyList entries = new PropertyList(".");
diff --git a/modules/plugins/hosts/src/test/resources/log4j.xml b/modules/plugins/hosts/src/test/resources/log4j.xml
index 65b7562..8ec981a 100644
--- a/modules/plugins/hosts/src/test/resources/log4j.xml
+++ b/modules/plugins/hosts/src/test/resources/log4j.xml
@@ -25,7 +25,14 @@
</layout>
</appender>
+ <category name="org.rhq.plugins">
+ <priority value="DEBUG"/>
+ </category>
+
<root>
+ <!-- default log priority -->
+ <priority value="INFO"/>
+
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
diff --git a/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml
index 87ddf64..9fce0e1 100644
--- a/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml
@@ -37,7 +37,7 @@
<c:simple-property displayName="Banner" name="smtpd_banner" description="SMTP Banner (RFC requires hostname and ESMTP prompt)" default="$myhostname ESMTP" required="true"/>
</c:group>
<c:group name="Security">
- <c:simple-property displayName="Supress VRFY" name="disable_vrfy_command" type="boolean" default="true" required="false" description="Supress Response to SMTP VRFY requests by default"/>
+ <c:simple-property displayName="Suppress VRFY" name="disable_vrfy_command" type="boolean" default="true" required="false" description="Supress Response to SMTP VRFY requests by default"/>
<c:simple-property displayName="Force HELO" name="smtpd_helo_required" type="boolean" default="true" required="false" description="Force clients to start connection with HELO"/>
<c:simple-property displayName="Always send EHLO" name="smtp_always_send_ehlo" type="boolean" default="true" required="true" description="Always send a correct EHLO greeting"/>
<c:simple-property displayName="In Flow Delay" name="in_flow_delay" required="false" description="Number of seconds to delay before accepting messages if arriving faster than delivering"/>
@@ -45,7 +45,6 @@
</c:group>
</resource-configuration>
-
</server>
</plugin>
diff --git a/modules/plugins/postfix/src/test/resources/log4j.xml b/modules/plugins/postfix/src/test/resources/log4j.xml
index ef41b92..8ec981a 100644
--- a/modules/plugins/postfix/src/test/resources/log4j.xml
+++ b/modules/plugins/postfix/src/test/resources/log4j.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
+
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
- <param name="Threshold" value="DEBUG"/>
+ <param name="Threshold" value="ERROR"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Messagen -->
@@ -24,7 +25,14 @@
</layout>
</appender>
+ <category name="org.rhq.plugins">
+ <priority value="DEBUG"/>
+ </category>
+
<root>
+ <!-- default log priority -->
+ <priority value="INFO"/>
+
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
diff --git a/modules/plugins/samba/src/test/resources/log4j.xml b/modules/plugins/samba/src/test/resources/log4j.xml
index ef41b92..8ec981a 100644
--- a/modules/plugins/samba/src/test/resources/log4j.xml
+++ b/modules/plugins/samba/src/test/resources/log4j.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
+
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
- <param name="Threshold" value="DEBUG"/>
+ <param name="Threshold" value="ERROR"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Messagen -->
@@ -24,7 +25,14 @@
</layout>
</appender>
+ <category name="org.rhq.plugins">
+ <priority value="DEBUG"/>
+ </category>
+
<root>
+ <!-- default log priority -->
+ <priority value="INFO"/>
+
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
diff --git a/modules/plugins/sudoers/src/test/resources/log4j.xml b/modules/plugins/sudoers/src/test/resources/log4j.xml
index ef41b92..8ec981a 100644
--- a/modules/plugins/sudoers/src/test/resources/log4j.xml
+++ b/modules/plugins/sudoers/src/test/resources/log4j.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
+
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
- <param name="Threshold" value="DEBUG"/>
+ <param name="Threshold" value="ERROR"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Messagen -->
@@ -24,7 +25,14 @@
</layout>
</appender>
+ <category name="org.rhq.plugins">
+ <priority value="DEBUG"/>
+ </category>
+
<root>
+ <!-- default log priority -->
+ <priority value="INFO"/>
+
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
</root>
commit 1b6bb2314442d0946c152298015849a8b9baac5c
Author: Pradeep Kilambi <pkilambi(a)redhat.com>
Date: Wed Nov 11 18:37:36 2009 -0500
wrap up of UIBean layer and jsf for listing associated kickstart trees by repo
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
index 71df772..7c4778a 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
@@ -47,7 +47,12 @@ import javax.persistence.Table;
@NamedQueries( {
@NamedQuery(name = RepoDistribution.DELETE_BY_KICKSTART_TREE_ID, query = "DELETE RepoDistribution rkt WHERE rkt.dist.id = :distId"),
@NamedQuery(name = RepoDistribution.DELETE_BY_REPO_ID, query = "DELETE RepoDistribution rkt WHERE rkt.repo.id = :repoId"),
- @NamedQuery(name = RepoDistribution.QUERY_FIND_BY_REPO_ID, query = "SELECT rkt FROM RepoDistribution rkt where rkt.repo.id = :repoId") })
+ @NamedQuery(name = RepoDistribution.QUERY_FIND_BY_REPO_ID,
+ query = "SELECT kt FROM "
+ + "Distribution kt, RepoDistribution as rkt "
+ + "where rkt.repo.id = :repoId "
+ + "and kt.id = rkt.distibution.id") })
+
@Table(name = "RHQ_REPO_DISTRIBUTION")
public class RepoDistribution implements Serializable {
public static final String DELETE_BY_KICKSTART_TREE_ID = "RepoDistribution.deleteByKickstartTreeId";
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDistributionUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDistributionUIBean.java
index e56bce1..fed772b 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDistributionUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDistributionUIBean.java
@@ -31,10 +31,12 @@ import org.rhq.enterprise.gui.common.paging.PagedListDataModel;
import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.Log;
public class RepoDistributionUIBean extends PagedDataTableUIBean {
public static final String MANAGED_BEAN_NAME = "RepoDistributionUIBean";
-
+ private final Log log = LogFactory.getLog(RepoDistributionUIBean.class);
public RepoDistributionUIBean() {
}
@@ -58,7 +60,6 @@ public class RepoDistributionUIBean extends PagedDataTableUIBean {
Subject subject = EnterpriseFacesContextUtility.getSubject();
int id = Integer.valueOf(FacesContextUtility.getRequiredRequestParameter("id"));
RepoManagerLocal manager = LookupUtil.getRepoManagerLocal();
-
PageList<Distribution> results = manager.findAssociatedDistributions(subject, id, pc);
return results;
}
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/content-beans.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/content-beans.xml
index 8d58c87..6bce7d7 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/content-beans.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/content-beans.xml
@@ -149,6 +149,11 @@
<managed-bean-class>org.rhq.enterprise.gui.content.RepoResourcesUIBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
+ <managed-bean>
+ <managed-bean-name>RepoDistributionUIBean</managed-bean-name>
+ <managed-bean-class>org.rhq.enterprise.gui.content.RepoDistributionUIBean</managed-bean-class>
+ <managed-bean-scope>request</managed-bean-scope>
+ </managed-bean>
<!-- /rhq/resource/content/subscription*.xhtml -->
<managed-bean>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml
index 7b740cd..483fd6f 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml
@@ -513,9 +513,9 @@
<rich:dataTable id="repoDistributionDataTable"
rows="#{PageControl.RepoDistributionList.pageSize}"
value="#{repoDistributionDataModel}"
- var="pvitem"
+ var="dist"
width="100%"
- columnsWidth="5%,20%, 10%, 5%, 60%"
+ columnsWidth="20%,30%,50%"
headerClass="tableRowHeader"
footerClass="on-pager-footer"
onRowMouseOver="this.style.backgroundColor='#E7E7E7'"
@@ -528,31 +528,38 @@
<rich:column>
<f:facet name="header">
- <onc:sortableColumnHeader sort="pv.label">
- <h:outputText styleClass="headerText" value="Label" />
- </onc:sortableColumnHeader>
+ <h:outputText styleClass="headerText" value="Distribution Label" />
</f:facet>
+ <h:outputText value="#{dist.label}"/>
</rich:column>
+
<rich:column>
<f:facet name="header">
- <onc:sortableColumnHeader sort="pv.base_path">
- <h:outputText styleClass="headerText" value="Base Path" />
- </onc:sortableColumnHeader>
+ <h:outputText styleClass="headerText" value="Distribution Type" />
</f:facet>
+ <h:outputText value="#{dist.distributionType}"/>
</rich:column>
-
+
<rich:column>
<f:facet name="header">
- <onc:sortableColumnHeader sort="pv.last_modified">
- <h:outputText styleClass="headerText" value="Last Modified" />
- </onc:sortableColumnHeader>
+ <h:outputText styleClass="headerText" value="Base Path" />
</f:facet>
+ <h:outputText value="#{dist.basePath}"/>
</rich:column>
+ <rich:column>
+ <f:facet name="header">
+ <h:outputText styleClass="headerText" value="Last Modified" />
+ </f:facet>
+ <h:outputText value="#{dist.lastModifiedDate}"/>
+
+ </rich:column>
+
+
<f:facet name="footer">
<rich:columnGroup>
<!-- colspan 5:4 for the debug 'id' column -->
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 78d56f8..8788038 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
@@ -862,10 +862,16 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
query.setParameter("repoId", repoid);
- List<Distribution> results = query.getResultList();
+ List<RepoDistribution> results = query.getResultList();
+
+ ArrayList<Distribution> distros = new ArrayList();
+ for (RepoDistribution result : results) {
+ distros.add(result.getRepoDistributionPK().getDistribution());
+
+ }
long count = getDistributionCountFromRepo(subject, repoid);
- return new PageList<Distribution>(results, (int) count, pc);
+ return new PageList<Distribution>(distros, (int) count, pc);
}
commit ad45fe56e61978d2496e19ef18c340194c57d89e
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 11 17:05:49 2009 -0500
there are no tests for the cron and postfix plugin, removing from
classpath so eclipse doesn't give errors
diff --git a/.classpath b/.classpath
index 2555353..f4a074e 100644
--- a/.classpath
+++ b/.classpath
@@ -89,9 +89,7 @@
<classpathentry kind="src" path="modules/plugins/samba/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/sudoers/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/sudoers/src/test/java"/>
- <classpathentry kind="src" path="modules/plugins/postfix/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/postfix/src/main/java"/>
- <classpathentry kind="src" path="modules/plugins/cron/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/cron/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/hudson/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/platform/src/test/java"/>
commit 2cd6ba182ee07849e2ccd06be6c962b879f45112
Author: Bryan Kearney <bkearney(a)redhat.com>
Date: Wed Nov 11 16:33:18 2009 -0500
Allow clean install to still copy over the license file.
This patch moves the license file from the server container module to the ear module. It is copied over in the dev profile only.
diff --git a/modules/enterprise/server/container/src/main/license/license.xml b/modules/enterprise/server/container/src/main/license/license.xml
deleted file mode 100644
index 2b4d104..0000000
--- a/modules/enterprise/server/container/src/main/license/license.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0"?>
-
-<!--
- This license should be uploaded to your RHQ Server in the
- Manage License section of the Administration area. If you have
- not already installed a license, you will be directed to this
- page on your first login to the application.
-
- You must login as an administrator to update your license file.
--->
-
-<!-- License created: Feb-12-2008 17:35 -->
-<license key="f3e30ce3f40d3da5a1b1625f1d8bd253" version="2.0">
-
- <license-owner name="RHQ"
- email="nobody(a)rhq-project.org"
- phone="888-555-1212"
- key="f6a629735537a0ff90c002ada39db105"/>
-
- <license-expiration date="*" key="8a58f1b633e356a321251f2ffdf2c34e" />
- <platform-limit count="*" key="a6ccfd9f9d66f73cff44b5953971166b" />
- <server-ip count="1" address="*" key="945f33206407c7743d205f2b345e8a57" />
- <plugin-enable name="*" key="62fa3b11086463a41abf7daf7fc572ee" />
- <support-level level="3" key="8e820272b1aa2289eb284a47745ab401" />
-
-</license>
diff --git a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
index 1c04382..ad1e0f6 100644
--- a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
+++ b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
@@ -371,13 +371,6 @@
<!-- optionally package the connectors -->
<antcall target="package-connectors" />
- <!-- Let's deploy some developer-only stuff - we'll remove these later if this is a release build -->
- <echo>Deploying the license file ...</echo>
- <copy file="${basedir}/src/main/license/license.xml"
- todir="${jboss.deploy.dir}/${rhq.earName}/license"
- verbose="true"
- failonerror="false"/>
-
<echo>Enabling server to run on Java 6 ...</echo>
<move todir="${jboss.home}/lib/endorsed" verbose="true">
<fileset dir="${jboss.home}/client">
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index 6668703..7308abb 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -434,6 +434,8 @@
<phase>package</phase>
<configuration>
<tasks>
+ <mkdir dir="${earDirectory}/license" />
+ <copy todir="${earDirectory}/license" file="${basedir}/src/main/license/license.xml"/>
<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}">
diff --git a/modules/enterprise/server/ear/src/main/license/license.xml b/modules/enterprise/server/ear/src/main/license/license.xml
new file mode 100644
index 0000000..2b4d104
--- /dev/null
+++ b/modules/enterprise/server/ear/src/main/license/license.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+
+<!--
+ This license should be uploaded to your RHQ Server in the
+ Manage License section of the Administration area. If you have
+ not already installed a license, you will be directed to this
+ page on your first login to the application.
+
+ You must login as an administrator to update your license file.
+-->
+
+<!-- License created: Feb-12-2008 17:35 -->
+<license key="f3e30ce3f40d3da5a1b1625f1d8bd253" version="2.0">
+
+ <license-owner name="RHQ"
+ email="nobody(a)rhq-project.org"
+ phone="888-555-1212"
+ key="f6a629735537a0ff90c002ada39db105"/>
+
+ <license-expiration date="*" key="8a58f1b633e356a321251f2ffdf2c34e" />
+ <platform-limit count="*" key="a6ccfd9f9d66f73cff44b5953971166b" />
+ <server-ip count="1" address="*" key="945f33206407c7743d205f2b345e8a57" />
+ <plugin-enable name="*" key="62fa3b11086463a41abf7daf7fc572ee" />
+ <support-level level="3" key="8e820272b1aa2289eb284a47745ab401" />
+
+</license>
commit 55c018ca53853c70413c906b4ea6c329838e719e
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Wed Nov 11 16:22:13 2009 -0500
Removed unnecessary @Overrides
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 f8c0d64..78d56f8 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
@@ -869,7 +869,6 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
}
- @Override
public String calculateSyncStatus(Subject subject, int repoId) {
Repo found = this.getRepo(subject, repoId);
Set<ContentSourceSyncStatus> stati = new HashSet<ContentSourceSyncStatus>();
commit cefb3d3fc0992ccdd7a88fc2241adfcfc22211f9
Author: John Matthews <jmatthew(a)redhat.com>
Date: Wed Nov 11 14:41:18 2009 -0500
Update test for synchronizePackages method signature
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java
index 3bd360e..8d93636 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java
@@ -148,7 +148,7 @@ public class RHNProviderTest
List<ContentProviderPackageDetails> existingPackages = new ArrayList<ContentProviderPackageDetails>();
try {
provider.initializeForTest(config);
- provider.synchronizePackages(report, existingPackages);
+ provider.synchronizePackages("testRepo", report, existingPackages);
}
catch (Exception e) {
e.printStackTrace();
commit 9c89925e0a9c2da104da5a4dd11d3b93886e491f
Merge: 66eeae1... 46d0de1...
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Wed Nov 11 11:35:39 2009 -0800
Merge branch 'master' into content
Conflicts:
modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
diff --cc modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index a2512a6,e317d58..2c8f5f2
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@@ -2026,79 -2005,25 +2005,80 @@@
-
</schema-directSQL>
</schemaSpec>
- <schemaSpec version="2.62">
- <schema-alterColumn
- table="RHQ_CONFIG_PROP_DEF"
- column="NAME"
- columnType="VARCHAR2"
- precision="255" />
- <schema-alterColumn
- table="RHQ_CONFIG_PROPERTY"
- column="NAME"
- columnType="VARCHAR2"
- precision="255" />
- </schemaSpec>
+ <schemaSpec version="2.62">
+ <schema-alterColumn
+ table="RHQ_CONFIG_PROP_DEF"
+ column="NAME"
+ columnType="VARCHAR2"
+ precision="255" />
+
+ <schema-alterColumn
+ table="RHQ_CONFIG_PROPERTY"
+ column="NAME"
+ columnType="VARCHAR2"
+ precision="255" />
+ </schemaSpec>
+
- <schemaSpec version="2.62.1">
- <schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
- <schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
- </schemaSpec>
+ <schemaSpec version="2.63">
+ <schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
+ <schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
+ </schemaSpec>
+
+ <!-- Generic tagging support -->
+ <schemaSpec version="2.64">
+ <schema-createSequence name="RHQ_TAG_ID_SEQ" initial="10001" />
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_TAG ( ID INTEGER PRIMARY KEY )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_TAG" column="ID" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="NAME" precision="200" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_TAG" column="NAME" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="DESCRIPTION" precision="500" columnType="VARCHAR2" />
+ </schemaSpec>
+
+ <!-- Distribution Files -->
+ <schemaSpec version="2.65">
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID INTEGER )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="DISTRIBUTION_ID" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" precision="256" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" precision="64" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" columnType="LONG" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" nullable="false" />
+ <schema-directSQL>
+ <statement targetDBVendor="postgresql">
+ CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
+ ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
+ </statement>
+ <statement targetDBVendor="oracle">
+ CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
+ ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
+ </statement>
+ </schema-directSQL>
+ <schema-directSQL>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_DISTRIBUTION_FILE
+ ADD CONSTRAINT RHQ_DIST_FILE_FKEY
+ FOREIGN KEY ( DISTRIBUTION_ID)
+ REFERENCES RHQ_DISTRIBUTION ( ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_DISTRIBUTION_FILE
+ ADD CONSTRAINT RHQ_DIST_FILE_FKEY
+ FOREIGN KEY ( DISTRIBUTION_ID)
+ REFERENCES RHQ_DISTRIBUTION ( ID )
+ </statement>
+ </schema-directSQL>
+
+ </schemaSpec>
</dbupgrade>
</target>
</project>
diff --cc modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginService.java
index 0000000,cfc59b7..0f728cc
mode 000000,100644..100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginService.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginService.java
@@@ -1,0 -1,187 +1,187 @@@
+ /*
+ * 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.plugin.pc.content;
+
+ import java.io.ByteArrayInputStream;
+ import java.io.File;
+ import java.io.InputStream;
+ import java.net.URL;
+ import java.util.ArrayList;
+ import java.util.Collection;
+ import java.util.HashMap;
+ import java.util.HashSet;
+ import java.util.List;
+ import java.util.Map;
+ import java.util.Set;
+
+ import org.rhq.core.domain.content.ContentSource;
+ import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
+ import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+ import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
+ import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+ 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.ContentProviderPackageDetails;
+ import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
+ import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginManager;
+ import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
+ import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
+ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
+
+ /**
+ * Used as a mock service for the content source plugin container.
+ */
+ public class TestContentServerPluginService extends ServerPluginService implements TestContentServerPluginServiceMBean {
+ // public so tests can directly set these
+ public Map<ContentSource, ContentProvider> testAdapters;
+ public PackageSyncReport testLastSyncReport;
+ public Map<ContentSource, Collection<ContentProviderPackageDetails>> testExistingPackages;
+ public TestMasterServerPluginContainer master;
+
+ @Override
+ protected MasterServerPluginContainer createMasterPluginContainer() {
+ this.master = new TestMasterServerPluginContainer();
+ File dir = new File(System.getProperty("java.io.tmpdir"), "test-server-plugins");
+ MasterServerPluginContainerConfiguration config = new MasterServerPluginContainerConfiguration(dir, dir, dir,
+ null);
+ this.master.initialize(config);
+ return this.master;
+ }
+
+ /**
+ * The test master PC
+ */
+ class TestMasterServerPluginContainer extends MasterServerPluginContainer {
+ @Override
+ protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
+ ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(1);
+ pcs.add(new TestContentServerPluginContainer(this));
+ return pcs;
+ }
+
+ @Override
+ protected ClassLoader createRootServerPluginClassLoader() {
+ return this.getClass().getClassLoader();
+ }
+
+ @Override
+ protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
+ return new HashMap<URL, ServerPluginDescriptorType>();
+ }
+ }
+
+ /**
+ * The test content PC.
+ */
+ class TestContentServerPluginContainer extends ContentServerPluginContainer {
+ public TestContentServerPluginContainer(MasterServerPluginContainer master) {
+ super(master);
+ }
+
+ @Override
+ protected ContentProviderManager createAdapterManager() {
+ TestContentProviderManager am = new TestContentProviderManager();
+ return am;
+ }
+
+ @Override
+ protected ContentServerPluginManager createPluginManager() {
+ TestContentProviderPluginManager pm = new TestContentProviderPluginManager(this);
+ return pm;
+ }
+ }
+
+ /**
+ * The test plugin manager.
+ */
+ class TestContentProviderPluginManager extends ContentServerPluginManager {
+ public TestContentProviderPluginManager(ContentServerPluginContainer pc) {
+ super(pc);
+ }
+ }
+
+ /**
+ * The test adapter manager.
+ */
+ class TestContentProviderManager extends ContentProviderManager {
+ @Override
+ public Set<ContentSource> getAllContentSources() {
+ return (testAdapters != null) ? testAdapters.keySet() : new HashSet<ContentSource>();
+ }
+
+ @Override
+ protected void initialize(ContentServerPluginManager pluginManager) {
+ createInitialAdaptersMap();
+ }
+
+ @Override
+ public void shutdown() {
+ }
+
+ @Override
+ public InputStream loadPackageBits(int contentSourceId, String location) throws Exception {
+ if (testAdapters != null) {
+ for (ContentSource cs : testAdapters.keySet()) {
+ if (cs.getId() == contentSourceId) {
+ PackageSource packageSource = (PackageSource) testAdapters.get(cs);
+ return packageSource.getInputStream(location);
+ }
+ }
+ }
+
+ System.out.println("!!!!!!!!!!");
+ System.out.println("STREAM: TEST DID NOT SETUP ADAPTER - EMPTY STREAM FOR [" + contentSourceId + "]");
+ return new ByteArrayInputStream(new byte[0]);
+ }
+
+ @Override
+ public boolean synchronizeContentSource(int contentSourceId) throws Exception {
+ if (testAdapters != null) {
+ for (ContentSource cs : testAdapters.keySet()) {
+ if (cs.getId() == contentSourceId) {
+ testLastSyncReport = new PackageSyncReport();
+ PackageSource packageSource = (PackageSource) testAdapters.get(cs);
- packageSource.synchronizePackages(testLastSyncReport, testExistingPackages.get(cs));
++ packageSource.synchronizePackages(null, testLastSyncReport, testExistingPackages.get(cs));
+ return true;
+ }
+ }
+ }
+
+ System.out.println("!!!!!!!!!!");
+ System.out.println("SYNC: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
+ return true;
+ }
+
+ @Override
+ public boolean testConnection(int contentSourceId) throws Exception {
+ if (testAdapters != null) {
+ for (ContentSource cs : testAdapters.keySet()) {
+ if (cs.getId() == contentSourceId) {
+ testAdapters.get(cs).testConnection();
+ return true;
+ }
+ }
+ }
+
+ System.out.println("!!!!!!!!!!");
+ System.out.println("CONN: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
+ return true;
+ }
+ }
+ }
commit 66eeae1566ed52eab107c489406fd96854802182
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Wed Nov 11 11:31:00 2009 -0800
582 - removing commented out code
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/listRepos.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/listRepos.xhtml
index ce733a2..5e05070 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/listRepos.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/listRepos.xhtml
@@ -165,16 +165,6 @@
</rich:panel>
</h:form>
- <!--
- <a4j:region>
- <h:form>
- <a4j:poll id="poll" interval="1000" enabled="#{ListReposUIBean.pollEnabled}"
- reRender="serverDate" />
- <h:outputText id="serverDate" style="font-size:16px"
- value="Server Date2: #{ListReposUIBean.randomString}" />
- </h:form>
- </a4j:region>
- -->
<p align="center">
<h:outputLink value="listContentProviders.xhtml">
<h:outputText value="Go To All Content Providers View" />
commit 4b3ea19c95ea689f674cd103a4425d72fce80f40
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Wed Nov 11 10:59:53 2009 -0800
582 - sync status per repository.
Need to get better at calculating sync status for the different phases:
* metadata
* packages
* ks trees
* errata
right now we just track progress for metadata.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
index 975199d..f041a93 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
@@ -40,6 +40,7 @@ import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
+import javax.persistence.Transient;
import org.rhq.core.domain.common.Tag;
import org.rhq.core.domain.common.Taggable;
@@ -88,6 +89,7 @@ import org.rhq.core.domain.resource.Resource;
@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_REPO_ID_SEQ")
@Table(name = "RHQ_REPO")
public class Repo implements Serializable, Taggable {
+
// Constants --------------------------------------------
public static final String QUERY_FIND_ALL_IMPORTED_REPOS = "Repo.findAll";
@@ -144,6 +146,9 @@ public class Repo implements Serializable, Taggable {
@OneToMany()
private Set<Tag> tags;
+ @Transient
+ private String syncStatus;
+
// Constructor ----------------------------------------
public Repo() {
@@ -309,6 +314,22 @@ public class Repo implements Serializable, Taggable {
}
/**
+ * Get the overall sync status of this Repository. This is a summation of all the syncs.
+ *
+ * There is a weight to the status since this returns the most 'relevant' status:
+ *
+ * 1) ContentSourceSyncStatus.FAILURE
+ * 2) ContentSourceSyncStatus.INPROGRESS
+ * 3) ContentSourceSyncStatus.SUCCESS
+ *
+ * @return String summary of the status of this Repository
+ */
+ @Transient
+ public String getSyncStatus() {
+ return this.syncStatus;
+ }
+
+ /**
* The content sources that this repo serves up. These are the content sources that provide or provided packages
* for this repo. This relationship is weak; a content source may not be in this set but the packages it loaded
* into this repo may still exist.
@@ -702,4 +723,12 @@ public class Repo implements Serializable, Taggable {
}
}
+ /**
+ * Set the sync status for this repo.
+ * @param syncStatusIn
+ */
+ @Transient
+ public void setSyncStatus(String syncStatusIn) {
+ this.syncStatus = syncStatusIn;
+ }
}
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/content/test/ContentSourceSyncResultsTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/content/test/ContentSourceSyncResultsTest.java
index 688f462..151e8c0 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/content/test/ContentSourceSyncResultsTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/content/test/ContentSourceSyncResultsTest.java
@@ -1,30 +1,33 @@
- /*
- * 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.
- */
+/*
+ * 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.content.test;
import java.util.List;
+
import javax.persistence.EntityManager;
+
import org.testng.annotations.Test;
+
import org.rhq.core.domain.content.Architecture;
import org.rhq.core.domain.content.ContentSource;
import org.rhq.core.domain.content.ContentSourceSyncResults;
@@ -33,6 +36,7 @@ import org.rhq.core.domain.content.ContentSourceType;
import org.rhq.core.domain.content.Package;
import org.rhq.core.domain.content.PackageType;
import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceCategory;
import org.rhq.core.domain.resource.ResourceType;
@@ -54,6 +58,8 @@ public class ContentSourceSyncResultsTest extends AbstractEJB3Test {
ContentSourceType cst = new ContentSourceType("testPVCSContentSourceType");
ContentSource cs = new ContentSource("testPVCSContentSource", cst);
ContentSourceSyncResults results = new ContentSourceSyncResults(cs);
+ Repo repo = new Repo("testPVCSRepo");
+ repo.addContentSource(cs);
em.persist(rt);
em.persist(resource);
@@ -63,6 +69,7 @@ public class ContentSourceSyncResultsTest extends AbstractEJB3Test {
em.persist(pv);
em.persist(cst);
em.persist(cs);
+ em.persist(repo);
em.persist(results);
cs.addSyncResult(results);
em.flush();
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java
index b99b18b..c392eac 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java
@@ -18,10 +18,17 @@
*/
package org.rhq.enterprise.gui.content;
+import java.util.Iterator;
+import java.util.Set;
+
import javax.faces.application.FacesMessage;
import javax.faces.model.DataModel;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.content.ContentSource;
import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
@@ -30,13 +37,18 @@ import org.rhq.enterprise.gui.common.framework.PagedDataTableUIBean;
import org.rhq.enterprise.gui.common.paging.PageControlView;
import org.rhq.enterprise.gui.common.paging.PagedListDataModel;
import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
+import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.util.LookupUtil;
public class ListReposUIBean extends PagedDataTableUIBean {
+
+ private final Log log = LogFactory.getLog(ListReposUIBean.class);
+
public static final String MANAGED_BEAN_NAME = "ListReposUIBean";
private RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
+ private ContentSourceManagerLocal contentSourceManager = LookupUtil.getContentSourceManager();
public ListReposUIBean() {
}
@@ -49,6 +61,40 @@ public class ListReposUIBean extends PagedDataTableUIBean {
return "importRepos";
}
+ public String syncSelectedContentSources() {
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
+ String[] selected = getSelectedRepos();
+ Integer[] ids = getIntegerArray(selected);
+ int syncCount = 0;
+ if (ids.length > 0) {
+ try {
+ for (Integer id : ids) {
+ Repo r = repoManager.getRepo(subject, id);
+ Set<ContentSource> sources = r.getContentSources();
+ Iterator<ContentSource> i = sources.iterator();
+ while (i.hasNext()) {
+ ContentSource source = i.next();
+ contentSourceManager.synchronizeAndLoadContentSource(subject, source.getId());
+ syncCount++;
+ log.debug("Initiating sync: " + source.getId());
+ }
+ }
+ if (syncCount > 0) {
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Synchronizing [" + syncCount
+ + "] content sources.");
+ } else {
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO,
+ "Selected Repositories have no content to sync.");
+ }
+ } catch (Exception e) {
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, "Failed to synchronized content sources.",
+ e);
+ }
+ }
+
+ return "success";
+ }
+
public String deleteSelectedRepos() {
Subject subject = EnterpriseFacesContextUtility.getSubject();
String[] selected = getSelectedRepos();
@@ -91,6 +137,9 @@ public class ListReposUIBean extends PagedDataTableUIBean {
RepoManagerLocal manager = LookupUtil.getRepoManagerLocal();
PageList<Repo> results = manager.findRepos(subject, pc);
+ for (Repo repo : results) {
+ repo.setSyncStatus(manager.calculateSyncStatus(subject, repo.getId()));
+ }
return results;
}
}
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/listRepos.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/listRepos.xhtml
index 67f91db..ce733a2 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/listRepos.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/listRepos.xhtml
@@ -10,6 +10,7 @@
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:onc="http://jboss.org/on/component"
+ xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.ajax4jsf.org/rich">
<ui:composition template="/rhq/layout/main.xhtml">
@@ -105,16 +106,19 @@
</h:outputText>
</rich:column>
- <rich:column>
+ <rich:column id="statusid">
<f:facet name="header">
<onc:sortableColumnHeader sort="c.lastModifiedDate">
- <h:outputText styleClass="headerText" value="Date Modified" />
+ <h:outputText styleClass="headerText" value="Sync Status" />
</onc:sortableColumnHeader>
</f:facet>
-
- <h:outputText value="#{item.lastModifiedDate}">
- <f:convertDateTime pattern="M/d/yy, h:mm:ss aa, zzz" timeZone="#{ServerInfoUIBean.timeZone}"/>
- </h:outputText>
+
+ <a4j:region>
+ <a4j:poll id="poll" interval="5000"
+ reRender="statusid" />
+ <h:outputText style="font-size:16px"
+ value="#{item.syncStatus}" />
+ </a4j:region>
</rich:column>
<rich:column>
@@ -143,6 +147,8 @@
<onc:selectCommandButton action="#{ListReposUIBean.deleteSelectedRepos}"
value="DELETE SELECTED" target="selectedRepos" styleClass="on-pager-button buttonsmall"/>
+ <onc:selectCommandButton action="#{ListReposUIBean.syncSelectedContentSources}"
+ value="SYNC SELECTED" target="selectedRepos" styleClass="on-pager-button buttonsmall"/>
<ui:param name="paginationDataTableName" value="reposDataTable"/>
<ui:param name="paginationDataModel" value="#{reposDataModel}"/>
@@ -157,8 +163,18 @@
</h:panelGrid>
</rich:panel>
+
</h:form>
-
+ <!--
+ <a4j:region>
+ <h:form>
+ <a4j:poll id="poll" interval="1000" enabled="#{ListReposUIBean.pollEnabled}"
+ reRender="serverDate" />
+ <h:outputText id="serverDate" style="font-size:16px"
+ value="Server Date2: #{ListReposUIBean.randomString}" />
+ </h:form>
+ </a4j:region>
+ -->
<p align="center">
<h:outputLink value="listContentProviders.xhtml">
<h:outputText value="Go To All Content Providers View" />
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 4712584..f8c0d64 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,6 +20,7 @@ package org.rhq.enterprise.server.content;
import java.util.ArrayList;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -39,6 +40,8 @@ import org.jboss.annotation.IgnoreDependency;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.content.ContentSource;
+import org.rhq.core.domain.content.ContentSourceSyncResults;
+import org.rhq.core.domain.content.ContentSourceSyncStatus;
import org.rhq.core.domain.content.Distribution;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.core.domain.content.PackageVersionContentSource;
@@ -865,4 +868,30 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
return new PageList<Distribution>(results, (int) count, pc);
}
+
+ @Override
+ public String calculateSyncStatus(Subject subject, int repoId) {
+ Repo found = this.getRepo(subject, repoId);
+ Set<ContentSourceSyncStatus> stati = new HashSet<ContentSourceSyncStatus>();
+ Set<ContentSource> contentSources = found.getContentSources();
+ Iterator<ContentSource> i = contentSources.iterator();
+ while (i.hasNext()) {
+ ContentSource cs = i.next();
+ List<ContentSourceSyncResults> results = cs.getSyncResults();
+ for (ContentSourceSyncResults result : results) {
+ stati.add(result.getStatus());
+ }
+ }
+ if (stati.contains(ContentSourceSyncStatus.FAILURE)) {
+ return ContentSourceSyncStatus.FAILURE.toString();
+ }
+ if (stati.contains(ContentSourceSyncStatus.INPROGRESS)) {
+ return ContentSourceSyncStatus.INPROGRESS.toString();
+ }
+ if (stati.contains(ContentSourceSyncStatus.SUCCESS)) {
+ return ContentSourceSyncStatus.SUCCESS.toString();
+ }
+ return null;
+ }
+
}
\ No newline at end of file
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 c5227fe..d2f5c80 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
@@ -106,6 +106,22 @@ public interface RepoManagerLocal {
PageList<PackageVersion> findPackageVersionsInRepo(Subject subject, int repoId, String filter, PageControl pc);
/**
+ * Get the overall sync status of this Repository. This is a summation of all the syncs.
+ *
+ * There is a weight to the status since this returns the most 'relevant' status:
+ *
+ * 1) ContentSourceSyncStatus.FAILURE
+ * 2) ContentSourceSyncStatus.INPROGRESS
+ * 3) ContentSourceSyncStatus.SUCCESS
+ *
+
+ * @param subject caller
+ * @param repoId to calc status for
+ * @return String summary of the status of this Repository
+ */
+ String calculateSyncStatus(Subject subject, int repoId);
+
+ /**
*/
void addContentSourcesToRepo(Subject subject, int repoId, int[] contentSourceIds) throws Exception;
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
index 4cd6378..755c2b6 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
@@ -18,36 +18,39 @@
*/
package org.rhq.enterprise.server.content.test;
-import javax.transaction.TransactionManager;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Set;
+
import javax.persistence.EntityManager;
+import javax.transaction.TransactionManager;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.content.ContentSource;
+import org.rhq.core.domain.content.ContentSourceSyncResults;
+import org.rhq.core.domain.content.ContentSourceSyncStatus;
+import org.rhq.core.domain.content.ContentSourceType;
import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.content.RepoGroup;
import org.rhq.core.domain.content.RepoGroupType;
import org.rhq.core.domain.content.RepoRelationshipType;
import org.rhq.core.domain.content.RepoRepoRelationship;
-import org.rhq.core.domain.content.ContentSourceType;
-import org.rhq.core.domain.content.ContentSource;
import org.rhq.core.domain.criteria.RepoCriteria;
-import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.PageControl;
-import org.rhq.enterprise.server.content.RepoManagerLocal;
-import org.rhq.enterprise.server.content.RepoException;
+import org.rhq.core.domain.util.PageList;
import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
+import org.rhq.enterprise.server.content.RepoException;
+import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.content.metadata.ContentSourceMetadataManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.util.LookupUtil;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.List;
-import java.util.ArrayList;
-
public class RepoManagerBeanTest extends AbstractEJB3Test {
private final static boolean ENABLED = true;
@@ -79,6 +82,48 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
}
@Test(enabled = ENABLED)
+ public void createABunchOfRepos() throws Exception {
+ PageList<Repo> repos = repoManager.findRepos(overlord, new PageControl());
+ int origsize = 0;
+ if (repos != null) {
+ origsize = repos.size();
+ }
+ for (int i = 0; i < 10; i++) {
+ Random r = new Random(System.currentTimeMillis());
+ Repo repo = new Repo(r.nextLong() + "");
+ repoManager.createRepo(overlord, repo).getId();
+ }
+ repos = repoManager.findRepos(overlord, new PageControl());
+
+ assert repos.size() == (origsize + 10);
+
+ }
+
+ @Test(enabled = ENABLED)
+ public void testSyncStatus() throws Exception {
+ Repo repo = new Repo("testSyncStatus");
+ repoManager.createRepo(overlord, repo).getId();
+
+ ContentSourceType cst = new ContentSourceType("testSyncStatus");
+ ContentSource cs = new ContentSource("testSyncStatus", cst);
+ ContentSourceSyncResults results = new ContentSourceSyncResults(cs);
+ repo.addContentSource(cs);
+
+ EntityManager em = getEntityManager();
+ em.persist(cst);
+ em.persist(cs);
+ em.persist(results);
+ cs.addSyncResult(results);
+ em.flush();
+ em.close();
+
+ // Check sync status
+ String status = repoManager.calculateSyncStatus(overlord, repo.getId());
+ assert status.equals(ContentSourceSyncStatus.INPROGRESS.toString());
+
+ }
+
+ @Test(enabled = ENABLED)
public void createDeleteRepo() throws Exception {
Repo repo = new Repo("testCreateDeleteRepo");
int id = repoManager.createRepo(overlord, repo).getId();
@@ -131,6 +176,12 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
// Setup
Repo repo = new Repo("test candidate repo");
+ PageList<Repo> importedRepos = repoManager.findRepos(overlord, new PageControl());
+ int origSize = 0;
+ if (importedRepos != null) {
+ origSize = importedRepos.size();
+ }
+
// Test
repo = repoManager.createCandidateRepo(overlord, repo);
@@ -139,12 +190,10 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
assert repo.isCandidate();
// Should not be returned from this call since its a candidate repo
- PageList<Repo> importedRepos = repoManager.findRepos(overlord, new PageControl());
- assert importedRepos.size() == 0;
-
+ importedRepos = repoManager.findRepos(overlord, new PageControl());
+ assert importedRepos.size() == origSize;
assert repoManager.getRepo(overlord, repo.getId()) != null;
- }
- finally {
+ } finally {
repoManager.deleteRepo(overlord, repo.getId());
}
}
@@ -174,8 +223,7 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
try {
repoManager.createRepoGroup(overlord, existing);
assert false;
- }
- catch (RepoException e) {
+ } catch (RepoException e) {
// Expected
}
@@ -183,7 +231,7 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
repoManager.deleteRepoGroup(overlord, existing.getId());
existing = repoManager.getRepoGroup(overlord, existing.getId());
assert existing == null;
-
+
entityManager.remove(groupType);
}
@@ -249,8 +297,10 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
RepoRepoRelationship relationship = relationships.iterator().next();
assert relationship.getRepoRepoRelationshipPK().getRepo().getName().equals("repo1");
- assert relationship.getRepoRepoRelationshipPK().getRepoRelationship().getRelatedRepo().getName().equals("repo2");
- assert relationship.getRepoRepoRelationshipPK().getRepoRelationship().getRepoRelationshipType().getName().equals(relationshipTypeName);
+ assert relationship.getRepoRepoRelationshipPK().getRepoRelationship().getRelatedRepo().getName()
+ .equals("repo2");
+ assert relationship.getRepoRepoRelationshipPK().getRepoRelationship().getRepoRelationshipType().getName()
+ .equals(relationshipTypeName);
// Cleanup handled by rollback in tear down method
}
@@ -272,7 +322,7 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
Repo importedRepo = new Repo("imported repo");
importedRepo.addContentSource(contentSource);
importedRepo = repoManager.createRepo(overlord, importedRepo);
-
+
// Create a candidate repo associated with that source
Repo candidateRepo = new Repo(candidateRepoName);
candidateRepo.addContentSource(contentSource);
@@ -329,8 +379,7 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
repoIds.add(12345);
repoManager.importCandidateRepo(overlord, repoIds);
assert false;
- }
- catch (RepoException e) {
+ } catch (RepoException e) {
// Expected
}
}
@@ -347,8 +396,7 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
repoIds.add(created.getId());
repoManager.importCandidateRepo(overlord, repoIds);
assert false;
- }
- catch (RepoException e) {
+ } catch (RepoException e) {
// Expected
}
commit 4f886eff89e4a8549ff6f5751a90c3708cfe6098
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Wed Nov 11 10:55:15 2009 -0800
adding src reference
diff --git a/.classpath b/.classpath
index 478e351..399e441 100644
--- a/.classpath
+++ b/.classpath
@@ -160,7 +160,7 @@
<classpathentry exported="true" kind="var" path="M2_REPO/ant/ant-launcher/1.6.5/ant-launcher-1.6.5.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/commons-logging/commons-logging/1.1/commons-logging-1.1.jar"/>
- <classpathentry exported="true" kind="var" path="M2_REPO/commons-lang/commons-lang/2.4/commons-lang-2.4.jar"/>
+ <classpathentry exported="true" kind="var" path="M2_REPO/commons-lang/commons-lang/2.4/commons-lang-2.4.jar" sourcepath="/M2_REPO/commons-lang/commons-lang/2.4/commons-lang-2.4-sources.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/javax/faces/jsf-api/1.2_12/jsf-api-1.2_12.jar" sourcepath="/M2_REPO/javax/faces/jsf-api/1.2_06/jsf-api-1.2_06-sources.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/javax/faces/jsf-impl/1.2_12/jsf-impl-1.2_12.jar" sourcepath="/M2_REPO/javax/faces/jsf-impl/1.2_06/jsf-impl-1.2_06-sources.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/javax/el/el-api/1.0/el-api-1.0.jar"/>
commit 066da530b822938691704fd29cf8e77a6856074d
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Wed Nov 11 11:00:51 2009 -0500
808 - Added repo name to the package sync call out to a content provider.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersionContentSource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersionContentSource.java
index 37fc62e..6ae6c39 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersionContentSource.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/PackageVersionContentSource.java
@@ -44,10 +44,24 @@ import javax.persistence.Table;
@NamedQuery(name = PackageVersionContentSource.QUERY_FIND_BY_CONTENT_SOURCE_ID_NO_FETCH, query = "SELECT pvcs "
+ " FROM PackageVersionContentSource pvcs " + " WHERE pvcs.contentSource.id = :id "),
@NamedQuery(name = PackageVersionContentSource.QUERY_FIND_BY_CONTENT_SOURCE_ID, query = "SELECT pvcs "
- + " FROM PackageVersionContentSource pvcs " + " LEFT JOIN FETCH pvcs.packageVersion pv "
- + " LEFT JOIN FETCH pv.generalPackage gp " + " LEFT JOIN FETCH gp.packageType pt "
- + " LEFT JOIN FETCH pv.architecture arch " + " LEFT JOIN FETCH pv.extraProperties extra "
+ + " FROM PackageVersionContentSource pvcs " //
+ + " LEFT JOIN FETCH pvcs.packageVersion pv " //
+ + " LEFT JOIN FETCH pv.generalPackage gp " //
+ + " LEFT JOIN FETCH gp.packageType pt " //
+ + " LEFT JOIN FETCH pv.architecture arch " //
+ + " LEFT JOIN FETCH pv.extraProperties extra " //
+ " WHERE pvcs.contentSource.id = :id "),
+ @NamedQuery(name = PackageVersionContentSource.QUERY_FIND_BY_CONTENT_SOURCE_ID_AND_REPO_ID, query = "SELECT pvcs "
+ + " FROM PackageVersionContentSource pvcs " //
+ + " LEFT JOIN FETCH pvcs.packageVersion pv " //
+ + " LEFT JOIN FETCH pv.generalPackage gp " //
+ + " LEFT JOIN FETCH gp.packageType pt " //
+ + " LEFT JOIN FETCH pv.architecture arch " //
+ + " LEFT JOIN FETCH pv.extraProperties extra " //
+ + " WHERE pvcs.contentSource.id = :content_source_id " //
+ + " AND pvcs.packageVersion.id IN " //
+ + " ( SELECT rpv.packageVersion.id FROM RepoPackageVersion rpv " //
+ + " WHERE rpv.repo.id = :repo_id )"),
@NamedQuery(name = PackageVersionContentSource.QUERY_FIND_BY_CONTENT_SOURCE_ID_COUNT, query = "SELECT COUNT(pvcs.contentSource.id) "
+ " FROM PackageVersionContentSource pvcs " + " WHERE pvcs.contentSource.id = :id "),
@@ -84,6 +98,7 @@ import javax.persistence.Table;
public class PackageVersionContentSource implements Serializable {
public static final String QUERY_FIND_BY_CONTENT_SOURCE_ID_NO_FETCH = "PackageVersionContentSource.findByContentSourceIdNoFetch";
public static final String QUERY_FIND_BY_CONTENT_SOURCE_ID = "PackageVersionContentSource.findByContentSourceId";
+ public static final String QUERY_FIND_BY_CONTENT_SOURCE_ID_AND_REPO_ID = "PackageVersionContentSource.findByContentSourceIdAndRepoId";
public static final String QUERY_FIND_BY_CONTENT_SOURCE_ID_COUNT = "PackageVersionContentSource.findByContentSourceIdCount";
public static final String QUERY_FIND_BY_ALL_CONTENT_SOURCE_IDS = "PackageVersionContentSource.findByAllContentSourceIds";
public static final String QUERY_FIND_BY_ALL_CONTENT_SOURCE_IDS_COUNT = "PackageVersionContentSource.findByAllContentSourceIdsCount";
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
index 058e87d..fc2e1f3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerBean.java
@@ -538,6 +538,22 @@ public class ContentSourceManagerBean implements ContentSourceManagerLocal {
return new PageList<PackageVersionContentSource>(results, (int) count, pc);
}
+ @SuppressWarnings("unchecked")
+ @RequiredPermission(Permission.MANAGE_INVENTORY)
+ public List<PackageVersionContentSource> getPackageVersionsFromContentSourceForRepo(Subject subject,
+ int contentSourceId,
+ int repoId) {
+
+ Query query =
+ entityManager.createNamedQuery(PackageVersionContentSource.QUERY_FIND_BY_CONTENT_SOURCE_ID_AND_REPO_ID);
+ query.setParameter("content_source_id", contentSourceId);
+ query.setParameter("repo_id", repoId);
+
+ List<PackageVersionContentSource> results = query.getResultList();
+
+ return results;
+ }
+
@RequiredPermission(Permission.MANAGE_INVENTORY)
public long getPackageVersionCountFromContentSource(Subject subject, int contentSourceId) {
Query countQuery = PersistenceUtility.createCountQuery(entityManager,
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java
index ebd5f6d..bf5312d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentSourceManagerLocal.java
@@ -221,6 +221,21 @@ public interface ContentSourceManagerLocal {
PageControl pc);
/**
+ * Returns all packages from the given repo. This call takes into account the content source to provide any
+ * extra data on the package versions that exist for the particular mapping of content source and package,
+ * such as the location attribute.
+ *
+ * @param subject user retrieving the data
+ * @param contentSourceId content source from which the packages are retrieved
+ * @param repoId repo from which the packages are retrieved
+ *
+ * @return all package versions that the content source will be providing content for. The object returned also
+ * contains the location where those package versions are located in the content source
+ */
+ List<PackageVersionContentSource> getPackageVersionsFromContentSourceForRepo(Subject subject, int contentSourceId,
+ int repoId);
+
+ /**
* Returns count of PackageVersions associated with the given content source.
*
* @param subject caller requesting count
@@ -257,6 +272,8 @@ public interface ContentSourceManagerLocal {
PageList<PackageVersionContentSource> getPackageVersionsFromContentSources(Subject subject, int[] contentSourceIds,
PageControl pc);
+
+
/**
* Returns all the package versions that are served by the content source identified by the given ID but whose
* {@link PackageVersion#getPackageBits() package bits} have not been loaded yet.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
index cbd28b8..30f9277 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
@@ -44,13 +44,12 @@ import org.rhq.core.domain.content.Package;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.core.domain.content.PackageVersionContentSource;
import org.rhq.core.domain.content.Repo;
-import org.rhq.core.domain.content.RepoGroup;
-import org.rhq.core.domain.content.RepoGroupType;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.criteria.RepoCriteria;
import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
-import org.rhq.enterprise.server.content.RepoException;
import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.content.metadata.ContentSourceMetadataManagerLocal;
import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
@@ -67,7 +66,6 @@ public class ContentProviderManager {
private static final Log log = LogFactory.getLog(ContentProviderManager.class);
private ContentServerPluginManager pluginManager;
- private static final String PARENT_RELATIONSHIP_NAME = "parent";
private Map<ContentSource, ContentProvider> adapters;
// This is used as a monitor lock to the synchronizeContentSource method;
@@ -115,16 +113,18 @@ public class ContentProviderManager {
*/
public boolean synchronizeContentSource(int contentSourceId) throws Exception {
- ContentSourceManagerLocal manager = LookupUtil.getContentSourceManager();
+ ContentSourceManagerLocal contentSourceManager = LookupUtil.getContentSourceManager();
+ RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
+
ContentProvider provider = getIsolatedContentProvider(contentSourceId);
ContentSourceSyncResults results = null;
SubjectManagerLocal subjMgr = LookupUtil.getSubjectManager();
Subject overlord = subjMgr.getOverlord();
StringBuilder progress = new StringBuilder(); // append to this as we go along, building a status report
- long start;
+ long start = System.currentTimeMillis();
try {
- ContentSource contentSource = manager.getContentSource(overlord, contentSourceId);
+ ContentSource contentSource = contentSourceManager.getContentSource(overlord, contentSourceId);
if (contentSource == null) {
throw new Exception("Cannot sync a non-existing content source [" + contentSourceId + "]");
}
@@ -143,7 +143,7 @@ public class ContentProviderManager {
progress.append("Getting currently known list of content source packages...");
results = new ContentSourceSyncResults(contentSource);
results.setResults(progress.toString());
- results = manager.persistContentSourceSyncResults(results);
+ results = contentSourceManager.persistContentSourceSyncResults(results);
}
if (results == null) {
@@ -162,7 +162,6 @@ public class ContentProviderManager {
progress.append(new Date()).append(": ");
progress.append("Asking content provider for repositories to import...");
- RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
RepoSource repoSource = (RepoSource) provider;
start = System.currentTimeMillis();
@@ -177,90 +176,71 @@ public class ContentProviderManager {
}
// ------------------
- // NOTE: This is being moved to the repo synchronization as part of Core Team A - Sprint 2
+ // NOTE: Ultimately, this will be moved out as repos get their own schedules. For now, simply
+ // synchronize *all* repos for this provider.
// ------------------
// If the provider is capable of handling packages, perform the package synchronization portion of the sync
if (provider instanceof PackageSource) {
PackageSource packageSource = (PackageSource) provider;
- PackageSyncReport report; // the plugin will fill this in for us
- List<PackageVersionContentSource> existingPVCS; // what we already know about this content source
+ RepoCriteria reposForContentSource = new RepoCriteria();
+ reposForContentSource.addFilterContentSourceIds(contentSourceId);
- Set<ContentProviderPackageDetails> allDetails; // what we tell the plugin about what we know
- Map<ContentProviderPackageDetailsKey, PackageVersionContentSource> keyPVCSMap;
+ List<Repo> repos = repoManager.findReposByCriteria(overlord, reposForContentSource);
- start = System.currentTimeMillis();
- report = new PackageSyncReport();
- PageControl pc = PageControl.getUnlimitedInstance(); // gulp - I assume we can fit all package versions in mem
- existingPVCS = manager.getPackageVersionsFromContentSource(subjMgr.getOverlord(),
- contentSource.getId(), pc);
- int existingCount = existingPVCS.size();
- keyPVCSMap = new HashMap<ContentProviderPackageDetailsKey, PackageVersionContentSource>(existingCount);
- allDetails = new HashSet<ContentProviderPackageDetails>(existingCount);
-
- for (PackageVersionContentSource pvcs : existingPVCS) {
- PackageVersion pv = pvcs.getPackageVersionContentSourcePK().getPackageVersion();
- Package p = pv.getGeneralPackage();
- ResourceType rt = p.getPackageType().getResourceType();
-
- ContentProviderPackageDetailsKey key;
- key = new ContentProviderPackageDetailsKey(p.getName(), pv.getVersion(), p.getPackageType()
- .getName(), pv.getArchitecture().getName(), rt.getName(), rt.getPlugin());
-
- ContentProviderPackageDetails details = new ContentProviderPackageDetails(key);
- details.setClassification(pv.getGeneralPackage().getClassification());
- details.setDisplayName(pv.getDisplayName());
- details.setDisplayVersion(pv.getDisplayVersion());
- details.setExtraProperties(pv.getExtraProperties());
- details.setFileCreatedDate(pv.getFileCreatedDate());
- details.setFileName(pv.getFileName());
- details.setFileSize(pv.getFileSize());
- details.setLicenseName(pv.getLicenseName());
- details.setLicenseVersion(pv.getLicenseVersion());
- details.setLocation(pvcs.getLocation());
- details.setLongDescription(pv.getLongDescription());
- details.setMD5(pv.getMD5());
- details.setMetadata(pv.getMetadata());
- details.setSHA256(pv.getSHA256());
- details.setShortDescription(pv.getShortDescription());
-
- allDetails.add(details);
- keyPVCSMap.put(key, pvcs);
- }
+ // Temporary functionality: loop for all repos that use this content source
+ for (Repo repo : repos) {
- log.info("synchronizePackages: [" + contentSource.getName() + "]: loaded existing list of size=["
- + existingCount + "] (" + (System.currentTimeMillis() - start) + ")ms");
+ // Convert the existing package list for this repo into DTOs for the API
+ // --------------------------------------------
+ List<PackageVersionContentSource> existingPVCS; // what we already know about this content source
+ Set<ContentProviderPackageDetails> allDetails; // what we tell the plugin about what we know
+ Map<ContentProviderPackageDetailsKey, PackageVersionContentSource> keyPVCSMap;
- progress.append(existingCount).append('\n');
- progress.append(new Date()).append(": ");
- progress.append("Asking content source to update the list of packages...");
- results.setResults(progress.toString());
- results = manager.mergeContentSourceSyncResults(results);
- start = System.currentTimeMillis();
+ start = System.currentTimeMillis();
- packageSource.synchronizePackages(report, allDetails);
+ existingPVCS = contentSourceManager.getPackageVersionsFromContentSourceForRepo(subjMgr.getOverlord(),
+ contentSource.getId(), repo.getId());
- log.info("synchronizePackages: [" + contentSource.getName() + "]: got sync report from adapter=["
- + report + "] (" + (System.currentTimeMillis() - start) + ")ms");
+ int existingCount = existingPVCS.size();
+ keyPVCSMap = new HashMap<ContentProviderPackageDetailsKey, PackageVersionContentSource>(existingCount);
+ allDetails = new HashSet<ContentProviderPackageDetails>(existingCount);
- progress.append("new=").append(report.getNewPackages().size());
- progress.append(", updated=").append(report.getUpdatedPackages().size());
- progress.append(", deleted=").append(report.getDeletedPackages().size());
- progress.append('\n');
- progress.append(new Date()).append(": ");
- progress.append("FULL SUMMARY FOLLOWS:");
- progress.append('\n');
- progress.append(report.getSummary());
- progress.append('\n');
- progress.append(new Date()).append(": ");
- progress.append("Merging the updated list of packages to database");
- progress.append('\n');
- results.setResults(progress.toString());
- results = manager.mergeContentSourceSyncResults(results);
- start = System.currentTimeMillis();
+ translateDomainToDto(existingPVCS, allDetails, keyPVCSMap);
+
+ log.info("synchronizePackages: [" + contentSource.getName() + "]: loaded existing list of size=["
+ + existingCount + "] (" + (System.currentTimeMillis() - start) + ")ms");
- results = manager.mergeContentSourceSyncReport(contentSource, report, keyPVCSMap, results);
+ progress.append(existingCount).append('\n');
+ progress.append(new Date()).append(": ");
+ progress.append("Asking content source to update the list of packages...");
+ results.setResults(progress.toString());
+ results = contentSourceManager.mergeContentSourceSyncResults(results);
+ start = System.currentTimeMillis();
+
+ PackageSyncReport report; // the plugin will fill this in for us
+ report = new PackageSyncReport();
+
+ packageSource.synchronizePackages(repo.getName(), report, allDetails);
+
+ log.info("synchronizePackages: [" + contentSource.getName() + "]: got sync report from adapter=["
+ + report + "] (" + (System.currentTimeMillis() - start) + ")ms");
+
+ progress.append("new=").append(report.getNewPackages().size());
+ progress.append(", updated=").append(report.getUpdatedPackages().size());
+ progress.append(", deleted=").append(report.getDeletedPackages().size()).append('\n');
+ progress.append(new Date()).append(": ");
+ progress.append("FULL SUMMARY FOLLOWS:").append('\n');
+ progress.append(report.getSummary()).append('\n');
+ progress.append(new Date()).append(": ");
+ progress.append("Merging the updated list of packages to database").append('\n');
+ results.setResults(progress.toString());
+ results = contentSourceManager.mergeContentSourceSyncResults(results);
+ start = System.currentTimeMillis();
+
+ results = contentSourceManager.mergeContentSourceSyncReport(contentSource, report, keyPVCSMap, results);
+ }
// let's reset our progress string to the full results including the text added by the merge
progress.setLength(0);
@@ -272,12 +252,12 @@ public class ContentProviderManager {
progress.append(new Date()).append(": ").append("DONE.");
results.setResults(progress.toString());
results.setStatus(ContentSourceSyncStatus.SUCCESS);
- results = manager.mergeContentSourceSyncResults(results);
+ results = contentSourceManager.mergeContentSourceSyncResults(results);
}
} catch (Throwable t) {
if (results != null) {
// try to reload the results in case it was updated by the SLSB before the exception happened
- ContentSourceSyncResults reloadedResults = manager.getContentSourceSyncResults(results.getId());
+ ContentSourceSyncResults reloadedResults = contentSourceManager.getContentSourceSyncResults(results.getId());
if (reloadedResults != null) {
results = reloadedResults;
if (results.getResults() != null) {
@@ -299,7 +279,7 @@ public class ContentProviderManager {
} finally {
if (results != null) {
results.setEndTime(System.currentTimeMillis());
- manager.mergeContentSourceSyncResults(results);
+ contentSourceManager.mergeContentSourceSyncResults(results);
}
}
@@ -346,8 +326,7 @@ public class ContentProviderManager {
* <p>If there is already an adapter currently started for the given content source, this returns silently.</p>
*
* @param contentSource the new content source that was added
- *
- * @throws InitializationException failed to initialize the adapter that processes the content source
+ * @throws InitializationException if the provider throws an error on its startup
*/
public void startAdapter(ContentSource contentSource) throws InitializationException {
synchronized (this.adapters) {
@@ -406,6 +385,7 @@ public class ContentProviderManager {
* {@link ContentSource#getConfiguration() configuration} has changed.
*
* @param contentSource the content source whose adapter is to be restarted
+ * @throws Exception if there is an error asking the provider to shutdown or start
*/
public void restartAdapter(ContentSource contentSource) throws Exception {
shutdownAdapter(contentSource);
@@ -418,6 +398,7 @@ public class ContentProviderManager {
* <p>This is protected so only the plugin container and subclasses can use it.</p>
*
* @param pluginManager the plugin manager this object can use to obtain information from (like classloaders)
+ * @throws InitializationException if any of the providers throw an error on startup
*/
protected void initialize(ContentServerPluginManager pluginManager) {
this.pluginManager = pluginManager;
@@ -482,54 +463,6 @@ public class ContentProviderManager {
}
/**
- * Creates a provider instance that will service the give {@link ContentSource}.
- *
- * @param contentSource the source that the adapter will connect to
- *
- * @return an adapter instance; will be <code>null</code> if failed to create adapter
- */
- private ContentProvider instantiateAdapter(ContentSource contentSource) {
- ContentProvider adapter = null;
- String apiClassName = "?";
- String pluginName = "?";
-
- try {
- ContentSourceType type = contentSource.getContentSourceType();
- apiClassName = type.getContentSourceApiClass();
- pluginName = this.pluginManager.getMetadataManager().getPluginNameFromContentSourceType(type);
-
- ServerPluginEnvironment pluginEnv = this.pluginManager.getPluginEnvironment(pluginName);
- ClassLoader pluginClassloader = pluginEnv.getPluginClassLoader();
-
- ClassLoader startingClassLoader = Thread.currentThread().getContextClassLoader();
- try {
- Thread.currentThread().setContextClassLoader(pluginClassloader);
-
- Class<?> apiClass = Class.forName(apiClassName, true, pluginClassloader);
-
- if (ContentProvider.class.isAssignableFrom(apiClass)) {
- adapter = (ContentProvider) apiClass.newInstance();
- } else {
- log.warn("The API class [" + apiClassName + "] does not implement ["
- + ContentProvider.class.getName() + "] in plugin [" + pluginName + "]");
- }
- } finally {
- Thread.currentThread().setContextClassLoader(startingClassLoader);
- }
- } catch (Throwable t) {
- log.warn("Failed to create the API class [" + apiClassName + "] for plugin [" + pluginName + "]", t);
- }
-
- if (adapter != null) {
- synchronized (this.adapters) {
- this.adapters.put(contentSource, adapter);
- }
- }
-
- return adapter;
- }
-
- /**
* Given a ID to a content source, this returns the adapter that is responsible for communicating with that content
* source where that adapter object will ensure invocations on it are isolated to its plugin classloader.
*
@@ -596,6 +529,98 @@ public class ContentProviderManager {
}
/**
+ * Creates a provider instance that will service the give {@link ContentSource}.
+ *
+ * @param contentSource the source that the adapter will connect to
+ *
+ * @return an adapter instance; will be <code>null</code> if failed to create adapter
+ */
+ private ContentProvider instantiateAdapter(ContentSource contentSource) {
+ ContentProvider adapter = null;
+ String apiClassName = "?";
+ String pluginName = "?";
+
+ try {
+ ContentSourceType type = contentSource.getContentSourceType();
+ apiClassName = type.getContentSourceApiClass();
+ pluginName = this.pluginManager.getMetadataManager().getPluginNameFromContentSourceType(type);
+
+ ServerPluginEnvironment pluginEnv = this.pluginManager.getPluginEnvironment(pluginName);
+ ClassLoader pluginClassloader = pluginEnv.getPluginClassLoader();
+
+ ClassLoader startingClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(pluginClassloader);
+
+ Class<?> apiClass = Class.forName(apiClassName, true, pluginClassloader);
+
+ if (ContentProvider.class.isAssignableFrom(apiClass)) {
+ adapter = (ContentProvider) apiClass.newInstance();
+ } else {
+ log.warn("The API class [" + apiClassName + "] does not implement ["
+ + ContentProvider.class.getName() + "] in plugin [" + pluginName + "]");
+ }
+ } finally {
+ Thread.currentThread().setContextClassLoader(startingClassLoader);
+ }
+ } catch (Throwable t) {
+ log.warn("Failed to create the API class [" + apiClassName + "] for plugin [" + pluginName + "]", t);
+ }
+
+ if (adapter != null) {
+ synchronized (this.adapters) {
+ this.adapters.put(contentSource, adapter);
+ }
+ }
+
+ return adapter;
+ }
+
+ /**
+ * Translates the domain representation of a list of packages into DTOs used in the plugin APIs. During the
+ * translation the two collections (allDetails and keyPVCSMap) will be populated with different
+ * views into the data.
+ *
+ * @param existingPVCS list of packages in the form of the wrapper object linking them to the content source
+ * @param allDetails set of all translated package DTOs
+ * @param keyPVCSMap mapping of package version key to package domain object
+ */
+ private void translateDomainToDto(List<PackageVersionContentSource> existingPVCS,
+ Set<ContentProviderPackageDetails> allDetails,
+ Map<ContentProviderPackageDetailsKey, PackageVersionContentSource> keyPVCSMap) {
+
+ for (PackageVersionContentSource pvcs : existingPVCS) {
+ PackageVersion pv = pvcs.getPackageVersionContentSourcePK().getPackageVersion();
+ Package p = pv.getGeneralPackage();
+ ResourceType rt = p.getPackageType().getResourceType();
+
+ ContentProviderPackageDetailsKey key;
+ key = new ContentProviderPackageDetailsKey(p.getName(), pv.getVersion(), p.getPackageType()
+ .getName(), pv.getArchitecture().getName(), rt.getName(), rt.getPlugin());
+
+ ContentProviderPackageDetails details = new ContentProviderPackageDetails(key);
+ details.setClassification(pv.getGeneralPackage().getClassification());
+ details.setDisplayName(pv.getDisplayName());
+ details.setDisplayVersion(pv.getDisplayVersion());
+ details.setExtraProperties(pv.getExtraProperties());
+ details.setFileCreatedDate(pv.getFileCreatedDate());
+ details.setFileName(pv.getFileName());
+ details.setFileSize(pv.getFileSize());
+ details.setLicenseName(pv.getLicenseName());
+ details.setLicenseVersion(pv.getLicenseVersion());
+ details.setLocation(pvcs.getLocation());
+ details.setLongDescription(pv.getLongDescription());
+ details.setMD5(pv.getMD5());
+ details.setMetadata(pv.getMetadata());
+ details.setSHA256(pv.getSHA256());
+ details.setShortDescription(pv.getShortDescription());
+
+ allDetails.add(details);
+ keyPVCSMap.put(key, pvcs);
+ }
+ }
+
+ /**
* This will handle invocations to an object ensuring that the call is isolated to within the appropriate
* classloader.
*/
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/PackageSource.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/PackageSource.java
index c4c4d6a..459d78f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/PackageSource.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/PackageSource.java
@@ -37,6 +37,8 @@ public interface PackageSource {
/**
* Requests that this package source perform a synchronization with its external package source.
*
+ * @param repoName indicates the repo from which packages should be retrieved; may be ignored
+ * if the package source does not support the concept of repos
* @param report used to populate the packages diff information necessary to
* bring the server up to date
* with the current state of the external package source.
@@ -45,7 +47,8 @@ public interface PackageSource {
* @throws Exception if the package source is unable to perform the synchronization, for instance if the external
* source cannot be connected to.
*/
- void synchronizePackages(PackageSyncReport report, Collection<ContentProviderPackageDetails> existingPackages)
+ void synchronizePackages(String repoName, PackageSyncReport report,
+ Collection<ContentProviderPackageDetails> existingPackages)
throws Exception;
/**
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
index b307161..2c1ce23 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
@@ -368,8 +368,8 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
return report;
}
- public void synchronizePackages(PackageSyncReport report,
- Collection<ContentProviderPackageDetails> existingPackages) throws Exception {
+ public void synchronizePackages(String repoName, PackageSyncReport report,
+ Collection<ContentProviderPackageDetails> existingPackages) throws Exception {
ContentProviderPackageDetailsKey key1 = new ContentProviderPackageDetailsKey(PACKAGE_NAME, PACKAGE_VERSION,
PACKAGE_TYPE_NAME, PACKAGE_ARCH, RESOURCE_TYPE_NAME, PLUGIN_NAME);
ContentProviderPackageDetails pkg1 = new ContentProviderPackageDetails(key1);
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java
index 1d68798..b45c50b 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java
@@ -157,7 +157,7 @@ public class TestContentServerPluginService extends ServerPluginService implemen
if (cs.getId() == contentSourceId) {
testLastSyncReport = new PackageSyncReport();
PackageSource packageSource = (PackageSource) testAdapters.get(cs);
- packageSource.synchronizePackages(testLastSyncReport, testExistingPackages.get(cs));
+ packageSource.synchronizePackages(null, testLastSyncReport, testExistingPackages.get(cs));
return true;
}
}
diff --git a/modules/enterprise/server/plugins/disk/src/main/java/org/rhq/enterprise/server/plugins/disk/DiskSource.java b/modules/enterprise/server/plugins/disk/src/main/java/org/rhq/enterprise/server/plugins/disk/DiskSource.java
index 2628999..f70bb69 100644
--- a/modules/enterprise/server/plugins/disk/src/main/java/org/rhq/enterprise/server/plugins/disk/DiskSource.java
+++ b/modules/enterprise/server/plugins/disk/src/main/java/org/rhq/enterprise/server/plugins/disk/DiskSource.java
@@ -95,7 +95,8 @@ public class DiskSource implements ContentProvider, PackageSource {
this.supportedPackageTypes = null;
}
- public void synchronizePackages(PackageSyncReport report, Collection<ContentProviderPackageDetails> existingPackages)
+ public void synchronizePackages(String repoName, PackageSyncReport report,
+ Collection<ContentProviderPackageDetails> existingPackages)
throws Exception {
// put all existing packages in a "to be deleted" list. As we sync, we will remove
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
index a398672..89702f4 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
@@ -173,7 +173,8 @@ public class RHNProvider implements ContentProvider, PackageSource, Distribution
/**
* Synchronize package content for selected channel labels
*/
- public void synchronizePackages(PackageSyncReport report, Collection<ContentProviderPackageDetails> existingPackages)
+ public void synchronizePackages(String repoName, PackageSyncReport report,
+ Collection<ContentProviderPackageDetails> existingPackages)
throws Exception {
RHNSummary summary = new RHNSummary(helper);
List<ContentProviderPackageDetails> deletedPackages = new ArrayList<ContentProviderPackageDetails>();
diff --git a/modules/enterprise/server/plugins/url/src/main/java/org/rhq/enterprise/server/plugins/url/UrlProvider.java b/modules/enterprise/server/plugins/url/src/main/java/org/rhq/enterprise/server/plugins/url/UrlProvider.java
index 0b90813..492f35a 100644
--- a/modules/enterprise/server/plugins/url/src/main/java/org/rhq/enterprise/server/plugins/url/UrlProvider.java
+++ b/modules/enterprise/server/plugins/url/src/main/java/org/rhq/enterprise/server/plugins/url/UrlProvider.java
@@ -174,7 +174,8 @@ public class UrlProvider implements ContentProvider, PackageSource {
this.supportedPackageTypes = null;
}
- public void synchronizePackages(PackageSyncReport report, Collection<ContentProviderPackageDetails> existingPackages)
+ public void synchronizePackages(String repoName, PackageSyncReport report,
+ Collection<ContentProviderPackageDetails> existingPackages)
throws Exception {
// put all existing packages in a "to be deleted" list. As we sync, we will remove
diff --git a/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/RepoProvider.java b/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/RepoProvider.java
index 6a96adf..7f1a143 100644
--- a/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/RepoProvider.java
+++ b/modules/enterprise/server/plugins/yum/src/main/java/org/rhq/enterprise/server/plugins/yum/RepoProvider.java
@@ -124,12 +124,13 @@ public class RepoProvider implements ContentProvider, PackageSource {
* indicate packages that need to be added and deleted. The notion of updated packages does not make sense in the
* rpm works since an update generates a new package version.
*
- * @param report A report to fill in.
+ * @param repoName
+ *@param report A report to fill in.
* @param existingPackages A collection of package specifications already in inventory.
- *
- * @throws Exception On all errors.
+ * @throws Exception On all errors.
*/
- public void synchronizePackages(PackageSyncReport report, Collection<ContentProviderPackageDetails> existingPackages)
+ public void synchronizePackages(String repoName, PackageSyncReport report,
+ Collection<ContentProviderPackageDetails> existingPackages)
throws Exception {
Summary summary = new Summary(reader);
log.info("synchronizing with repo: " + reader + " started");
commit 47984778f2bb79a0d57fa9c737e084f233ce8de0
Author: Pradeep Kilambi <pkilambi(a)redhat.com>
Date: Wed Nov 11 12:06:04 2009 -0500
implementing dist tree lookups in webservicesManager
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 f9cff70..6728210 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
@@ -29,8 +29,6 @@ import java.util.Set;
import javax.ejb.Stateless;
import javax.jws.WebService;
-import javax.jws.WebMethod;
-import javax.jws.WebParam;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@@ -49,15 +47,15 @@ import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
import org.rhq.core.domain.configuration.group.GroupPluginConfigurationUpdate;
import org.rhq.core.domain.configuration.group.GroupResourceConfigurationUpdate;
import org.rhq.core.domain.content.Architecture;
-import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.content.Distribution;
import org.rhq.core.domain.content.InstalledPackage;
import org.rhq.core.domain.content.PackageType;
import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.content.RepoGroup;
import org.rhq.core.domain.content.RepoGroupType;
import org.rhq.core.domain.criteria.AlertCriteria;
import org.rhq.core.domain.criteria.AlertDefinitionCriteria;
-import org.rhq.core.domain.criteria.RepoCriteria;
import org.rhq.core.domain.criteria.Criteria;
import org.rhq.core.domain.criteria.EventCriteria;
import org.rhq.core.domain.criteria.GroupOperationHistoryCriteria;
@@ -66,6 +64,7 @@ import org.rhq.core.domain.criteria.MeasurementDefinitionCriteria;
import org.rhq.core.domain.criteria.MeasurementScheduleCriteria;
import org.rhq.core.domain.criteria.OperationDefinitionCriteria;
import org.rhq.core.domain.criteria.PackageVersionCriteria;
+import org.rhq.core.domain.criteria.RepoCriteria;
import org.rhq.core.domain.criteria.ResourceCriteria;
import org.rhq.core.domain.criteria.ResourceGroupCriteria;
import org.rhq.core.domain.criteria.ResourceOperationHistoryCriteria;
@@ -102,9 +101,9 @@ import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.authz.RoleManagerLocal;
import org.rhq.enterprise.server.configuration.ConfigurationManagerLocal;
import org.rhq.enterprise.server.configuration.ConfigurationUpdateStillInProgressException;
+import org.rhq.enterprise.server.content.ContentManagerLocal;
import org.rhq.enterprise.server.content.RepoException;
import org.rhq.enterprise.server.content.RepoManagerLocal;
-import org.rhq.enterprise.server.content.ContentManagerLocal;
import org.rhq.enterprise.server.discovery.DiscoveryBossLocal;
import org.rhq.enterprise.server.event.EventManagerLocal;
import org.rhq.enterprise.server.exception.LoginException;
@@ -238,13 +237,11 @@ public class WebservicesManagerBean implements WebservicesRemote {
return repoManager.findReposByCriteria(subject, criteria);
}
- public PageList<PackageVersion> findPackageVersionsInRepo(Subject subject, int repoId, String filter,
- PageControl pc) {
+ public PageList<PackageVersion> findPackageVersionsInRepo(Subject subject, int repoId, String filter, PageControl pc) {
return repoManager.findPackageVersionsInRepo(subject, repoId, filter, pc);
}
- public PageList<PackageVersion> findPackageVersionsInRepoByCriteria(Subject subject,
- PackageVersionCriteria criteria) {
+ public PageList<PackageVersion> findPackageVersionsInRepoByCriteria(Subject subject, PackageVersionCriteria criteria) {
return repoManager.findPackageVersionsInRepoByCriteria(subject, criteria);
}
@@ -256,8 +253,7 @@ public class WebservicesManagerBean implements WebservicesRemote {
return repoManager.getRepo(subject, repoId);
}
- public RepoGroup createRepoGroup(Subject subject, RepoGroup repoGroup)
- throws RepoException {
+ public RepoGroup createRepoGroup(Subject subject, RepoGroup repoGroup) throws RepoException {
return repoManager.createRepoGroup(subject, repoGroup);
}
@@ -881,4 +877,8 @@ public class WebservicesManagerBean implements WebservicesRemote {
}
}
+ public PageList<Distribution> findAssociatedDistributions(Subject subject, int repoId, PageControl pc) {
+ return repoManager.findAssociatedDistributions(subject, repoId, pc);
+ }
+
}
commit 06eb2ee352c198385e2797d4e3c9816a59ba0c02
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Nov 11 11:31:46 2009 -0500
Augeas-based ResourceComponents now handle it as gracefully as possible when Augeas is not installed on the Agent system
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
index 5649b4b..b652f71 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
@@ -91,22 +91,15 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
public void start(ResourceContext<T> resourceContext) throws InvalidPluginConfigurationException, Exception {
this.resourceContext = resourceContext;
- Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
-
- this.augeasRootPath = pluginConfig.getSimpleValue(AUGEAS_ROOT_PATH_PROP, DEFAULT_AUGEAS_ROOT_PATH);
- log.debug("Augeas Root Path = \"" + this.augeasRootPath + "\"");
-
- initGlobs(pluginConfig);
+ initGlobs();
- this.augeas = createAugeas();
- if (this.augeas != null) {
- String resourceConfigRootPath = getResourceConfigurationRootPath();
- if (resourceConfigRootPath.indexOf(AugeasNode.SEPARATOR_CHAR) != 0) {
- // root path is relative - make it absolute
- this.resourceConfigRootNode = new AugeasNode("/files/", resourceConfigRootPath);
+ if (isAugeasAvailable()) {
+ initAugeas();
+ } else {
+ if (IS_WINDOWS) {
+ log.debug("Augeas not found - this is expected, since Augeas is not currently available for Windows.");
} else {
- // root path is already absolute
- this.resourceConfigRootNode = new AugeasNode(resourceConfigRootPath);
+ log.warn("Augeas not found - if on Fedora or RHEL, `yum install augeas`.");
}
}
}
@@ -123,6 +116,8 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
}
public Configuration loadResourceConfiguration() throws Exception {
+ abortIfAugeasNotAvailable();
+
// Load the config file from disk and build a tree representation of it.
loadConfigurationFiles(this.augeas);
@@ -140,7 +135,41 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
return resourceConfig;
}
+ private void abortIfAugeasNotAvailable()
+ throws Exception
+ {
+ if (getAugeas() == null) {
+ if (isAugeasAvailable()) {
+ initAugeas();
+ if (getAugeas() == null) {
+ throw new Exception("Failed to initialize Augeas Java API.");
+ }
+ } else {
+ String message;
+ if (IS_WINDOWS) {
+ message = "Configuration of " + getResourceContext().getResourceType().getName()
+ + " Resources is not supported on Windows.";
+ } else {
+ message = "Configuration of " + getResourceContext().getResourceType().getName()
+ + " Resources requires that the Augeas shared library be installed on the Agent system."
+ + " If on Fedora or RHEL, `yum install augeas`.";
+ }
+ throw new Exception(message);
+ }
+ }
+ }
+
public void updateResourceConfiguration(ConfigurationUpdateReport report) {
+ try
+ {
+ abortIfAugeasNotAvailable();
+ }
+ catch (Exception e)
+ {
+ report.setErrorMessage(e.getLocalizedMessage());
+ return;
+ }
+
if (!validateResourceConfiguration(report)) {
log.debug("Validation of updated Resource configuration for " + this.getResourceContext().getResourceType()
+ " Resource with key '" + this.getResourceContext().getResourceKey()
@@ -288,11 +317,7 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
String augeasModuleName = pluginConfig.getSimpleValue(AUGEAS_MODULE_NAME_PROP, null);
if (augeasModuleName == null) {
- return null;
- }
-
- if (!initAugeasJnaProxy()) {
- return null;
+ throw new IllegalStateException("Plugin config property '" + AUGEAS_MODULE_NAME_PROP + "' is required.");
}
Augeas augeas;
@@ -311,19 +336,16 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
loadConfigurationFiles(augeas);
} catch (RuntimeException e) {
augeas = null;
- log.warn("Failed to initialize Augeas Java API.", e);
+ log.error("Failed to initialize Augeas Java API.", e);
}
return augeas;
}
- private boolean initAugeasJnaProxy() {
+ protected boolean isAugeasAvailable() {
Aug aug;
try {
aug = Aug.INSTANCE;
} catch (Error e) {
- if (!IS_WINDOWS) {
- log.warn("Augeas shared library not found. If on Fedora or RHEL, yum install augeas.");
- }
return false;
}
if (log.isTraceEnabled()) {
@@ -604,9 +626,11 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
}
}
- private void initGlobs(Configuration pluginConfiguration) {
- PropertySimple includes = pluginConfiguration.getSimple(INCLUDE_GLOBS_PROP);
- PropertySimple excludes = pluginConfiguration.getSimple(EXCLUDE_GLOBS_PROP);
+ private void initGlobs() {
+ Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
+
+ PropertySimple includes = pluginConfig.getSimple(INCLUDE_GLOBS_PROP);
+ PropertySimple excludes = pluginConfig.getSimple(EXCLUDE_GLOBS_PROP);
includeGlobs = new ArrayList<String>();
excludeGlobs = new ArrayList<String>();
@@ -649,4 +673,21 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
return summary.toString();
}
+
+ protected void initAugeas()
+ {
+ Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
+ this.augeasRootPath = pluginConfig.getSimpleValue(AUGEAS_ROOT_PATH_PROP, DEFAULT_AUGEAS_ROOT_PATH);
+ log.debug("Augeas Root Path = \"" + this.augeasRootPath + "\"");
+ this.augeas = createAugeas();
+ String resourceConfigRootPath = getResourceConfigurationRootPath();
+ if (resourceConfigRootPath.indexOf(AugeasNode.SEPARATOR_CHAR) != 0) {
+ // root path is relative - make it absolute
+ this.resourceConfigRootNode = new AugeasNode("/files/", resourceConfigRootPath);
+ } else {
+ // root path is already absolute
+ this.resourceConfigRootNode = new AugeasNode(resourceConfigRootPath);
+ }
+ log.debug("Resource Config Root Node = \"" + this.resourceConfigRootNode + "\"");
+ }
}
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
index 2706cee..9688aa8 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
@@ -28,10 +28,10 @@ import java.util.Arrays;
import java.util.List;
import java.util.Set;
+import org.rhq.core.clientapi.agent.PluginContainerException;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
import org.rhq.core.pluginapi.util.FileUtils;
-import org.testng.SkipException;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.BeforeTest;
@@ -72,16 +72,14 @@ public abstract class AbstractAugeasConfigurationComponentTest {
AUGEAS_ROOT = new File(tmpDir, "rhq-itest-augeas-root-path");
}
- private boolean augeasAvailable;
-
@BeforeSuite(groups = TEST_GROUP)
public void start() {
if (!isAugeasAvailable()) {
String message;
if (IS_WINDOWS) {
- message = "Augeas is not available on Windows. Skipping tests that rely on it...";
+ message = "Augeas is not available on Windows. Augeas-based configuration functionality will *not* be tested.";
} else {
- message = "Augeas not found. If on Fedora or RHEL, `yum install augeas`. Skipping tests that rely on it...";
+ message = "Augeas not found. If on Fedora or RHEL, `yum install augeas`. Augeas-based configuration functionality will *not* be tested.";
}
System.out.println(message);
}
@@ -122,37 +120,41 @@ public abstract class AbstractAugeasConfigurationComponentTest {
@Test(groups = TEST_GROUP)
public void testResourceConfigLoad() throws Exception {
- skipTestIfAugeasNotAvailable();
ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
Resource resource = getResource();
- Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
- Configuration expectedResourceConfig = getExpectedResourceConfig();
- assert resourceConfig.equals(expectedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
- + expectedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
- }
-
- private void skipTestIfAugeasNotAvailable()
- {
- if (!isAugeasAvailable()) {
- throw new SkipException("Skipping test since Augeas is not available.");
+ Configuration resourceConfig = null;
+ try
+ {
+ resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
+ Configuration expectedResourceConfig = getExpectedResourceConfig();
+ assert resourceConfig.equals(expectedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
+ + expectedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
+ }
+ catch (PluginContainerException e)
+ {
+ if (isAugeasAvailable()) {
+ throw e;
+ }
}
}
@Test(groups = TEST_GROUP)
public void testResourceConfigUpdate() throws Exception {
- skipTestIfAugeasNotAvailable();
ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
Resource resource = getResource();
Configuration updatedResourceConfig = getUpdatedResourceConfig();
- configurationManager.updateResourceConfiguration(new ConfigurationUpdateRequest(0,
- updatedResourceConfig, resource.getId()));
+ ConfigurationUpdateRequest updateRequest = new ConfigurationUpdateRequest(0, updatedResourceConfig,
+ resource.getId());
+ configurationManager.updateResourceConfiguration(updateRequest);
- // Give the component and the managed resource some time to properly persist the update.
- Thread.sleep(500);
+ if (isAugeasAvailable()) {
+ // Give the component and the managed resource some time to properly persist the update.
+ Thread.sleep(500);
- Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
- assert resourceConfig.equals(updatedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
- + updatedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
+ Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
+ assert resourceConfig.equals(updatedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
+ + updatedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
+ }
}
@AfterSuite(groups = TEST_GROUP)
@@ -163,7 +165,7 @@ public abstract class AbstractAugeasConfigurationComponentTest {
}
catch (IOException e)
{
- System.err.println("Failed to purge Augeas root dir '" + AUGEAS_ROOT + "' - cause: " + e);
+ // ignore
}
System.out.println("Stopping plugin container...");
PluginContainer.getInstance().shutdown();
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
index 15374f4..366747b 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
@@ -26,7 +26,10 @@ import java.util.regex.Pattern;
import net.augeas.Augeas;
+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.ConfigurationUpdateStatus;
import org.rhq.core.domain.configuration.Property;
import org.rhq.core.domain.configuration.PropertyList;
import org.rhq.core.domain.configuration.PropertyMap;
@@ -58,6 +61,8 @@ public class HostsComponent extends AugeasConfigurationComponent {
private static final String DOMAIN_NAME_REGEX = "(([a-zA-Z\\d]|[a-zA-Z\\d][a-zA-Z\\d\\-]*[a-zA-Z\\d])\\.)*([A-Za-z]|[A-Za-z][A-Za-z\\d\\-]*[A-Za-z\\d])";
private static final Pattern DOMAIN_NAME_PATTERN = Pattern.compile(DOMAIN_NAME_REGEX);
+ private final Log log = LogFactory.getLog(this.getClass());
+
public void start(ResourceContext resourceContext) throws InvalidPluginConfigurationException, Exception {
super.start(resourceContext);
}
@@ -86,6 +91,14 @@ public class HostsComponent extends AugeasConfigurationComponent {
if (getAugeas() != null) {
super.updateResourceConfiguration(report);
} else {
+ if (!validateResourceConfiguration(report)) {
+ log.debug("Validation of updated Resource configuration for "
+ + this.getResourceContext().getResourceType() + " Resource with key '"
+ + this.getResourceContext().getResourceKey() + "' failed with the following errors: "
+ + report.getErrorMessage());
+ report.setStatus(ConfigurationUpdateStatus.FAILURE);
+ return;
+ }
new NonAugeasHostsConfigurationDelegate(this).updateResourceConfiguration(report);
}
}
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java
index 8856938..99204b8 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java
@@ -105,7 +105,7 @@ public class NonAugeasHostsConfigurationDelegate implements ConfigurationFacet
}
public void updateResourceConfiguration(ConfigurationUpdateReport report) {
- Configuration resourceConfig = report.getConfiguration();
+ Configuration resourceConfig = report.getConfiguration();
Hosts newHosts = new Hosts();
PropertyList entriesProp = resourceConfig.getList(".");
commit 48237156ef871371daef72f02e3956f7ea95c11a
Author: John Matthews <jmatthew(a)redhat.com>
Date: Wed Nov 11 10:44:53 2009 -0500
555 - Add syncing Kickstart trees to rhnhosted plugin
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionDetails.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionDetails.java
index e58895f..80ed9b9 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionDetails.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionDetails.java
@@ -23,6 +23,9 @@
package org.rhq.enterprise.server.plugin.pc.content;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* @author Pradeep Kilambi
*/
@@ -32,6 +35,7 @@ public class DistributionDetails {
private String distType;
private String distpath;
+ private List<DistributionFileDetails> files;
public DistributionDetails(String labelIn, String disttypeIn) {
setLabel(labelIn);
@@ -44,6 +48,25 @@ public class DistributionDetails {
setDistributionType(disttypeIn);
}
+ public void addFile(DistributionFileDetails file) {
+ if (files == null) {
+ files = new ArrayList<DistributionFileDetails>();
+ }
+ files.add(file);
+ }
+
+ public void addFiles(List<DistributionFileDetails> filesIn) {
+ files.addAll(filesIn);
+ }
+
+ public List<DistributionFileDetails> getFiles() {
+ return files;
+ }
+
+ public void setFiles(List<DistributionFileDetails> filesIn) {
+ files = filesIn;
+ }
+
/**
* Returns the identifying name of the distribution.
*
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionFileDetails.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionFileDetails.java
new file mode 100644
index 0000000..02e3816
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionFileDetails.java
@@ -0,0 +1,78 @@
+/*
+ * 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.plugin.pc.content;
+
+/**
+ * @author jmatthews
+ */
+public class DistributionFileDetails
+{
+ private String relativeFilename;
+ private long lastModified;
+ private String md5sum;
+ private long fileSize;
+
+ public long getFileSize()
+ {
+ return fileSize;
+ }
+
+ public void setFileSize(long fileSizeIn)
+ {
+ this.fileSize = fileSizeIn;
+ }
+
+ public DistributionFileDetails(String filenameIn, long lastModifiedIn, String md5sumIn) {
+ relativeFilename = filenameIn;
+ lastModified = lastModifiedIn;
+ md5sum = md5sumIn;
+ this.fileSize = 0;
+
+ }
+
+ public String getRelativeFilename()
+ {
+ return relativeFilename;
+ }
+
+ public void setRelativeFilename(String relativeFilenameIn)
+ {
+ this.relativeFilename = relativeFilenameIn;
+ }
+
+ public long getLastModified()
+ {
+ return lastModified;
+ }
+
+ public void setLastModified(long lastModifiedIn)
+ {
+ this.lastModified = lastModifiedIn;
+ }
+
+ public String getMd5sum()
+ {
+ return md5sum;
+ }
+
+ public void setMd5sum(String md5sumIn)
+ {
+ this.md5sum = md5sumIn;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java
index b702645..0ae61f7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java
@@ -23,6 +23,7 @@
package org.rhq.enterprise.server.plugin.pc.content;
import java.io.InputStream;
+import java.util.Collection;
/**
* Indicates a content provider has the capability to provide distributions into the server.
@@ -39,7 +40,7 @@ public interface DistributionSource {
* @throws Exception if the source is unable to perform the synchronization, for instance if the external
* source cannot be connected to.
*/
- void synchronizeDistribution(DistributionSyncReport report)
+ void synchronizeDistribution(DistributionSyncReport report, Collection<DistributionDetails> existingDistros)
throws Exception;
/**
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSyncReport.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSyncReport.java
index 0b68c1b..c59b1f8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSyncReport.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSyncReport.java
@@ -33,7 +33,7 @@ import java.util.Collection;
*/
public class DistributionSyncReport {
private List<DistributionDetails> distros = new ArrayList<DistributionDetails>();
-
+ private List<DistributionDetails> deletedDistros = new ArrayList<DistributionDetails>();
public DistributionSyncReport() {
}
@@ -42,12 +42,23 @@ public class DistributionSyncReport {
return distros;
}
- public void addRepo(DistributionDetails distro) {
- distros.add(distro);
+ public void addDistro(DistributionDetails distroIn) {
+ distros.add(distroIn);
+ }
+
+ public void addDistros(Collection<DistributionDetails> distrosIn) {
+ distros.addAll(distrosIn);
}
- public void addDistros(Collection<DistributionDetails> distros) {
- distros.addAll(distros);
+ public List<DistributionDetails> getDeletedDistributions() {
+ return deletedDistros;
}
+ public void addDeletedDistro(DistributionDetails distroIn) {
+ deletedDistros.add(distroIn);
+ }
+
+ public void addDeletedDistros(Collection<DistributionDetails> distrosIn) {
+ deletedDistros.addAll(distrosIn);
+ }
}
diff --git a/modules/enterprise/server/plugins/rhnhosted/pom.xml b/modules/enterprise/server/plugins/rhnhosted/pom.xml
index c76bfc2..738269f 100644
--- a/modules/enterprise/server/plugins/rhnhosted/pom.xml
+++ b/modules/enterprise/server/plugins/rhnhosted/pom.xml
@@ -135,6 +135,17 @@
<!--
<argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
-->
+ <systemProperties>
+ <property>
+ <!--
+ set this to true if you want to run a test with RHNProvider
+ against RHN Hosted. It will sync packages & kickstart trees
+ This should be set to false by default
+ -->
+ <name>RunRHNProviderTest</name>
+ <value>false</value>
+ </property>
+ </systemProperties>
</configuration>
</plugin>
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
index 4f0d4c5..c9cb853 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
@@ -39,6 +39,8 @@ import org.rhq.enterprise.server.plugins.rhnhosted.xmlrpc.RhnDownloader;
import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails;
import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetailsKey;
import org.rhq.enterprise.server.plugin.pc.content.DistributionDetails;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionFileDetails;
+
/**
* @author pkilambi
@@ -51,6 +53,7 @@ public class RHNHelper {
private final RhnComm rhndata;
private final RhnDownloader rhndownload;
private final String systemid;
+ private final String distributionType;
//TODO: Need to determine what the ksTreeType should be for RHN Kickstarts
private final String ksTreeType = "CHANGE_ME";
@@ -71,23 +74,35 @@ public class RHNHelper {
this.rhndata = new RhnComm(baseurl);
this.rhndownload = new RhnDownloader(baseurl);
this.systemid = systemIdIn;
+ this.distributionType = "Kickstart";
}
- public List<DistributionDetails> getDistributionDetails(List<String> ksLabels)
+ public List<DistributionDetails> getDistributionMetaData(List<String> labels)
throws IOException, XmlRpcException {
- List<DistributionDetails> ddList = new ArrayList<DistributionDetails>();
- List<RhnKickstartableTreeType> ksTreeTypes = rhndata.getKickstartTreeMetadata(this.systemid, ksLabels);
+ List<DistributionDetails> distros = new ArrayList<DistributionDetails>();
+ List<RhnKickstartableTreeType> ksTreeTypes = rhndata.getKickstartTreeMetadata(this.systemid, labels);
for (RhnKickstartableTreeType ksTree: ksTreeTypes) {
+ DistributionDetails details =
+ new DistributionDetails(ksTree.getLabel(), ksTree.getBasePath(), distributionType);
+ distros.add(details);
+
List<RhnKickstartFileType> ksFiles = ksTree.getRhnKickstartFiles().getRhnKickstartFile();
for (RhnKickstartFileType ksFile: ksFiles) {
- String path = ksTree.getBasePath() + "/" + ksFile.getRelativePath();
- //TODO: Should add fileSize and md5sum to DistributionDetails
- ddList.add(new DistributionDetails(ksTree.getLabel(), path, ksTreeType));
+ if (log.isDebugEnabled()) {
+ log.debug("RHNHelper::getDistributionMetaData<ksLabel=" + ksTree.getLabel() +
+ "> current file = " + ksFile.getRelativePath() + ", md5sum = " + ksFile.getMd5Sum() +
+ ", lastModified = " + ksFile.getLastModified() + ", fileSize = " + ksFile.getFileSize());
+ }
+ Long lastMod = Long.parseLong(ksFile.getLastModified());
+ DistributionFileDetails dFile = new DistributionFileDetails(ksFile.getRelativePath(), lastMod, ksFile.getMd5Sum());
+ Long fileSize = Long.parseLong(ksFile.getFileSize());
+ dFile.setFileSize(fileSize);
+ details.addFile(dFile);
}
}
- return ddList;
+ return distros;
}
/**
@@ -97,10 +112,8 @@ public class RHNHelper {
* @throws Exception On all errors
*/
public List<ContentProviderPackageDetails> getPackageDetails(List packageIds) throws Exception {
-
List<ContentProviderPackageDetails> pdlist = new ArrayList<ContentProviderPackageDetails>();
List<RhnPackageType> pkgs = rhndata.getPackageMetadata(this.systemid, packageIds);
-
for (RhnPackageType pkg : pkgs) {
try {
pdlist.add(getDetails(pkg));
@@ -146,6 +159,16 @@ public class RHNHelper {
}
/**
+ * Get List of kickstart labels for the channel associated to this instance.
+ * @return List of all kickstart labels associate to the channel
+ * @throws IOException on io errors on systemid reads
+ * @throws XmlRpcException on xmlrpc faults
+ */
+ public List<String> getChannelKickstartLabels() throws IOException, XmlRpcException {
+ return getSyncableKickstartLabels(Arrays.asList(this.repolabel));
+ }
+
+ /**
* Get List of packagesIds for Given Channels
* @return List of all package ids associated to the channel
* @throws IOException on io errors on systemid reads
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
index c06826e..a398672 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
@@ -49,9 +49,6 @@ import org.rhq.enterprise.server.plugin.pc.content.DistributionDetails;
import org.rhq.enterprise.server.plugins.rhnhosted.certificate.Certificate;
import org.rhq.enterprise.server.plugins.rhnhosted.certificate.CertificateFactory;
import org.rhq.enterprise.server.plugins.rhnhosted.certificate.PublicKeyRing;
-import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartableTreeType;
-import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartFilesType;
-import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartFileType;
/**
@@ -64,6 +61,13 @@ public class RHNProvider implements ContentProvider, PackageSource, Distribution
private final Log log = LogFactory.getLog(RHNProvider.class);
private RHNActivator rhnObject;
private RHNHelper helper;
+ private boolean testMode = false;
+
+ public void initializeForTest(Configuration configuration) throws Exception {
+ log.info("**TEST MODE RHNProvider is running in a test configuration**");
+ testMode = true;
+ initialize(configuration);
+ }
/**
* Initializes the adapter with the specified configuration.
@@ -131,12 +135,17 @@ public class RHNProvider implements ContentProvider, PackageSource, Distribution
// RHQ Server is now active, initialize the handler for the bits.
helper = new RHNHelper(locationIn, repos, rhnObject.getSystemid());
+ log.info("RHNProvider initialized RHNHelper with repos: " + repos);
// Now that the server is activated, spawn all syncable channels
ArrayList<String> channels = helper.getSyncableChannels();
- // Eventually we should pass in a subset of selected channels to spawn
- initializeRepos(channels);
+
+ // when running under a test we are restricting behavior to not setup up Repos through RHQ
+ if (!testMode) {
+ // Eventually we should pass in a subset of selected channels to spawn
+ initializeRepos(channels);
+ }
}
/**
@@ -170,11 +179,11 @@ public class RHNProvider implements ContentProvider, PackageSource, Distribution
List<ContentProviderPackageDetails> deletedPackages = new ArrayList<ContentProviderPackageDetails>();
deletedPackages.addAll(existingPackages);
log.info("Report" + report);
-
// sync now
try {
summary.markStarted();
ArrayList pkgIds = helper.getChannelPackages();
+ log.info("RHNProvider:: helper.getChannelPackages returned " + pkgIds.size() + " packages");
for (ContentProviderPackageDetails p : helper.getPackageDetails(pkgIds)) {
log.debug("Processing package at (" + p.getLocation());
deletedPackages.remove(p);
@@ -184,7 +193,6 @@ public class RHNProvider implements ContentProvider, PackageSource, Distribution
summary.added++;
}
}
-
for (ContentProviderPackageDetails p : deletedPackages) {
log.debug("Package at (" + p.getDisplayName() + ") marked as deleted");
report.addDeletePackage(p);
@@ -199,25 +207,44 @@ public class RHNProvider implements ContentProvider, PackageSource, Distribution
report.setSummary(summary.toString());
log.info("synchronizing with repo: " + helper + " finished\n" + summary);
}
-
- }
-
- public void synchronizeDistribution(DistributionSyncReport report) throws Exception {
- // hard coding a kickstart label for testing.
- List<String> distLabels = new ArrayList<String>();
- distLabels.add("ks-rhel-i386-server-5");
- synchronizeDistribution(report, distLabels);
}
- public void synchronizeDistribution(DistributionSyncReport report, List<String> distLabels) throws Exception {
+ public void synchronizeDistribution(DistributionSyncReport report, Collection<DistributionDetails> existingDistros) throws Exception {
// Goal:
// This method will create the metadata representing what kickstart tree files need to be downloaded.
// the metadata will be returned through the DistributionSyncReport object.
// NOTE: This method DOES not do the actual downloading of data.
- List<DistributionDetails> ddList = helper.getDistributionDetails(distLabels);
- //TODO: Need to add logic to determine what has already been synced, what needs to be synced.
+ List<String> existingLabels = new ArrayList<String>();
+ for (DistributionDetails d: existingDistros) {
+ existingLabels.add(d.getLabel());
+ }
+ List<String> toSyncDistros = new ArrayList<String>();
+ List<String> deletedDistros = new ArrayList<String>(); //Existing distros we want to remove.
+ deletedDistros.addAll(existingLabels);
+
+ List<String> availableLabels = helper.getChannelKickstartLabels();
+ log.debug("Found " + availableLabels.size() + " available kickstart trees");
+ for (String label: availableLabels) {
+ log.debug("Processing kickstart: " + label);
+ deletedDistros.remove(label);
+ if (!existingLabels.contains(label)) {
+ log.debug("New kickstart to sync: " + label);
+ toSyncDistros.add(label);
+ }
+ }
+
+ // Determine what distros are to be removed, i.e. they are synced by RHQ but no longer exist from RHN
+ for (String label: deletedDistros) {
+ for (DistributionDetails dd: existingDistros) {
+ if (dd.getLabel().compareToIgnoreCase(label) == 0) {
+ report.addDeletedDistro(dd);
+ }
+ }
+ }
+
+ List<DistributionDetails> ddList = helper.getDistributionMetaData(toSyncDistros);
report.addDistros(ddList);
}
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnDownloader.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnDownloader.java
index 0414f6a..8fa9375 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnDownloader.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnDownloader.java
@@ -109,7 +109,7 @@ public class RhnDownloader {
public InputStream getKickstartTreeFile(String systemId, String channelName, String ksTreeLabel, String ksFilePath)
throws IOException, XmlRpcException {
- String extra = "/SAT/$RHN/" + channelName + "/getKickstartFile/" + ksTreeLabel + "/" + ksFilePath;
+ String extra = getURLForKickstartFile(channelName, ksTreeLabel, ksFilePath);
HttpURLConnection conn = getNewConnection(serverUrl + extra);
Map props = login(systemId);
for (Object key : props.keySet()) {
@@ -121,4 +121,8 @@ public class RhnDownloader {
return in;
}
+ public static String getURLForKickstartFile(String channelName, String ksTreeLabel, String ksFilePath) {
+ return "/SAT/$RHN/" + channelName + "/getKickstartFile/" + ksTreeLabel + "/" + ksFilePath;
+ }
+
}
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java
new file mode 100644
index 0000000..3bd360e
--- /dev/null
+++ b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProviderTest.java
@@ -0,0 +1,207 @@
+/*
+ * 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.plugins.rhnhosted;
+
+
+import java.util.List;
+import java.util.ArrayList;
+import java.io.InputStream;
+import java.io.File;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails;
+import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionSyncReport;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionDetails;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionFileDetails;
+import org.rhq.enterprise.server.plugins.rhnhosted.xmlrpc.RhnDownloader;
+
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.Test;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * @author John Matthews
+ */
+public class RHNProviderTest
+{
+ // By Default the tests in this class will be skipped. This class is intended as a simple integration test
+ // desire is for it to only run against RHN Hosted, other tests in this package will execute against a mocked RHN
+ // connection. This test is a means for us to manually check that Plugin->RHN Hosted communication is behaving as
+ // we expect.
+ //
+ // If you want to run these tests, then set the java property "RunRHNProviderTest"
+ //
+ String PROP_NAME_TO_TRIGGER_TEST = "RunRHNProviderTest";
+ String rhnURL = "http://satellite.rhn.redhat.com";
+ String certLoc = "./entitlement-cert.xml";
+ boolean isTesting = false;
+
+ RHNProvider provider = new RHNProvider();
+
+ @BeforeTest
+ public void setUp() throws Exception
+ {
+ String value = System.getProperty(PROP_NAME_TO_TRIGGER_TEST);
+ if (!StringUtils.isBlank(value)) {
+ isTesting = Boolean.parseBoolean(value);
+ }
+ }
+
+ @AfterTest
+ public void tearDown()
+ {
+ }
+
+ public Configuration getConfiguration(String channelName) {
+ String certData = "";
+ try {
+ certData = FileUtils.readFileToString(new File(certLoc));
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ assert false;
+ }
+ return getConfiguration(channelName, rhnURL, certData);
+ }
+
+ public Configuration getConfiguration(String channelName, String location, String certData) {
+ Configuration config = new Configuration();
+ PropertySimple locProp = new PropertySimple();
+ locProp.setName("location");
+ locProp.setStringValue(location);
+ config.put(locProp);
+ PropertySimple certProp = new PropertySimple();
+ certProp.setName("certificate");
+ certProp.setStringValue(certData);
+ config.put(certProp);
+ PropertySimple channelsProp = new PropertySimple();
+ channelsProp.setName("SyncableChannels");
+ channelsProp.setStringValue(channelName);
+ config.put(channelsProp);
+ return config;
+ }
+
+ @Test
+ public void testGetInputStream()
+ {
+ if (!isTesting) {
+ System.out.println("Intentionally skipping test, since property is missing: -D" + PROP_NAME_TO_TRIGGER_TEST);
+ return;
+ }
+
+ System.out.println("testGetInputStream invoked");
+ //
+ // systemid used for this test needs to be entitled so the channel/package selected
+ //
+ String cName = "rhel-x86_64-server-5";
+ String rName = "openhpi-2.4.1-6.el5.1.x86_64.rpm";
+ RHNProvider provider = new RHNProvider();
+ Configuration config = getConfiguration(cName);
+ try {
+ provider.initializeForTest(config);
+ String loc = rhnURL + "/SAT/$RHN/" + cName + "/getPackage/" + rName;
+ InputStream in = provider.getInputStream(loc);
+ assert (in != null);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ assert false;
+ }
+ System.out.println("testGetInputStream finished.");
+ provider.shutdown();
+ }
+
+ @Test
+ public void testSynchronizePackages()
+ {
+ if (!isTesting) {
+ System.out.println("Intentionally skipping test, since property is missing: -D" + PROP_NAME_TO_TRIGGER_TEST);
+ return;
+ }
+
+ String channelName = "rhn-tools-rhel-i386-server-5";
+ Configuration config = getConfiguration(channelName);
+ RHNProvider provider = new RHNProvider();
+
+ System.out.println("testSynchronizePackages invoked");
+ PackageSyncReport report = new PackageSyncReport();
+ List<ContentProviderPackageDetails> existingPackages = new ArrayList<ContentProviderPackageDetails>();
+ try {
+ provider.initializeForTest(config);
+ provider.synchronizePackages(report, existingPackages);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ assert false;
+ }
+ System.out.println("testSynchronizePackages finished.");
+ }
+
+ @Test
+ public void testSynchronizeDistribution()
+ {
+ if (!isTesting) {
+ System.out.println("Intentionally skipping test, since property is missing: -D" + PROP_NAME_TO_TRIGGER_TEST);
+ return;
+ }
+ System.out.println("testSynchronizeDistribution invoked");
+ String channelName = "rhel-x86_64-server-5";
+ DistributionSyncReport report = new DistributionSyncReport();
+ List<DistributionDetails> existingDistro = new ArrayList<DistributionDetails>();
+ RHNProvider provider = new RHNProvider();
+ Configuration config = getConfiguration(channelName);
+ try {
+ provider.initializeForTest(config);
+ provider.synchronizeDistribution(report, existingDistro);
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ assert false;
+ }
+ List<DistributionDetails> details = report.getDistributions();
+ System.out.println("RHNProviderTest details.size() = " + details.size());
+ for (DistributionDetails d: details) {
+ System.out.println("Label = " + d.getLabel());
+ System.out.println("Path = " + d.getDistributionPath());
+ List<DistributionFileDetails> files = d.getFiles();
+ for (DistributionFileDetails f: files) {
+ System.out.println(d.getLabel() + ", " + d.getDistributionPath() + ", " +
+ f.getRelativeFilename() + " , " + f.getMd5sum() + ", lastModified = " + f.getLastModified() +
+ ", fileSize = " + f.getFileSize());
+ try {
+ String url = rhnURL +
+ RhnDownloader.getURLForKickstartFile(channelName, d.getLabel(), f.getRelativeFilename());
+ InputStream in = provider.getInputStream(url);
+ assert(in != null);
+ //TODO: Consider mplementing read from inputStream, compare against fileSize & md5sum
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ assert false;
+ }
+
+ }
+ }
+ System.out.println("testSynchronizeDistribution finished.");
+ }
+}
commit d391bb6be98bfeabfaa06f25fbf33cf67ea85f06
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Nov 11 10:19:44 2009 -0500
refactor so that config tests are skipped if Augeas is not available, so tests will pass on systems without Augeas (e.g. Windows boxes)
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
index aa0223e..5649b4b 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
@@ -69,15 +69,15 @@ import org.rhq.plugins.augeas.helper.Glob;
*/
public class AugeasConfigurationComponent<T extends ResourceComponent> implements ResourceComponent<T>,
ConfigurationFacet, CreateChildResourceFacet, DeleteResourceFacet {
+ /* Plugin config prop names */
public static final String INCLUDE_GLOBS_PROP = "configurationFilesInclusionPatterns";
public static final String EXCLUDE_GLOBS_PROP = "configurationFilesExclusionPatterns";
public static final String RESOURCE_CONFIGURATION_ROOT_NODE_PROP = "resourceConfigurationRootNode";
public static final String AUGEAS_MODULE_NAME_PROP = "augeasModuleName";
public static final String AUGEAS_ROOT_PATH_PROP = "augeasRootPath";
- public static final String DEFAULT_AUGEAS_ROOT_PATH = File.listRoots()[0].getPath();
-
private static final boolean IS_WINDOWS = (File.separatorChar == '\\');
+ public static final String DEFAULT_AUGEAS_ROOT_PATH = (IS_WINDOWS) ? "C:/" : "/";
private static final String AUGEAS_LOAD_PATH = "/usr/share/augeas/lenses";
private final Log log = LogFactory.getLog(this.getClass());
@@ -89,24 +89,16 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
private AugeasNode resourceConfigRootNode;
private String augeasRootPath;
- public static String getAugeasRootPath() {
- if (System.getProperty(AUGEAS_ROOT_PATH_PROP) != null) {
- return System.getProperty(AUGEAS_ROOT_PATH_PROP);
- }
- return DEFAULT_AUGEAS_ROOT_PATH;
- }
-
public void start(ResourceContext<T> resourceContext) throws InvalidPluginConfigurationException, Exception {
this.resourceContext = resourceContext;
Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
- this.augeasRootPath = getAugeasRootPath();
+ this.augeasRootPath = pluginConfig.getSimpleValue(AUGEAS_ROOT_PATH_PROP, DEFAULT_AUGEAS_ROOT_PATH);
log.debug("Augeas Root Path = \"" + this.augeasRootPath + "\"");
initGlobs(pluginConfig);
this.augeas = createAugeas();
-
if (this.augeas != null) {
String resourceConfigRootPath = getResourceConfigurationRootPath();
if (resourceConfigRootPath.indexOf(AugeasNode.SEPARATOR_CHAR) != 0) {
@@ -116,7 +108,6 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
// root path is already absolute
this.resourceConfigRootNode = new AugeasNode(resourceConfigRootPath);
}
-
}
}
@@ -329,7 +320,7 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
Aug aug;
try {
aug = Aug.INSTANCE;
- } catch (NoClassDefFoundError e) {
+ } catch (Error e) {
if (!IS_WINDOWS) {
log.warn("Augeas shared library not found. If on Fedora or RHEL, yum install augeas.");
}
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
index cea1974..8d533a4 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
@@ -117,7 +117,8 @@ public class AugeasConfigurationDiscoveryComponent<T extends ResourceComponent>
PropertySimple excludeGlobsProp = pluginConfiguration
.getSimple(AugeasConfigurationComponent.EXCLUDE_GLOBS_PROP);
- String augeasRootPath = AugeasConfigurationComponent.getAugeasRootPath();
+ String augeasRootPath = pluginConfiguration.getSimpleValue(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP,
+ AugeasConfigurationComponent.DEFAULT_AUGEAS_ROOT_PATH);
File root = new File(augeasRootPath);
List<String> includeGlobs = getGlobList(includeGlobsProp);
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java
index 0a2fc52..1cfa2de 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java
@@ -24,6 +24,7 @@
package org.rhq.plugins.augeas.helper;
import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
@@ -88,8 +89,12 @@ public class Glob {
} else {
globPattern = parentPath.getAbsolutePath() + globPattern;
}
-
- return Arrays.asList(parentPath.listFiles(new GlobFilter(globPattern)));
+
+ File[] files = parentPath.listFiles(new GlobFilter(globPattern));
+ if (files == null) {
+ throw new IllegalStateException("Could not list files in " + parentPath);
+ }
+ return Arrays.asList(files);
}
public static List<File> matchAll(File parentPath, String... globPattern) {
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
index 3631261..2706cee 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
@@ -28,8 +28,13 @@ import java.util.Arrays;
import java.util.List;
import java.util.Set;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.ConfigurationTemplate;
+import org.rhq.core.pluginapi.util.FileUtils;
+import org.testng.SkipException;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
@@ -47,8 +52,10 @@ import org.rhq.core.pc.plugin.PluginManager;
import org.rhq.core.util.file.FileUtil;
import org.rhq.plugins.augeas.AugeasConfigurationComponent;
+import net.augeas.jna.Aug;
+
/**
- * An base class for integration tests for instances of {@link AugeasConfigurationComponent}.
+ * A base class for integration tests for instances of {@link AugeasConfigurationComponent}.
*
* @author Ian Springer
*/
@@ -56,121 +63,146 @@ public abstract class AbstractAugeasConfigurationComponentTest {
public static final String TEST_GROUP = "linux-config";
private static final File ITEST_DIR = new File("target/itest");
private static final long ONE_WEEK_IN_SECONDS = 60L * 60 * 24;
+ private static final boolean IS_WINDOWS = (File.separatorChar == '\\');
+
+ private static final File AUGEAS_ROOT;
+ static {
+ String tmpDirPath = System.getProperty("java.io.tmpdir");
+ File tmpDir = new File(tmpDirPath);
+ AUGEAS_ROOT = new File(tmpDir, "rhq-itest-augeas-root-path");
+ }
+
+ private boolean augeasAvailable;
@BeforeSuite(groups = TEST_GROUP)
public void start() {
- try {
- PluginContainerConfiguration pcConfig = new PluginContainerConfiguration();
- File pluginsDir = new File(ITEST_DIR, "plugins");
- pcConfig.setPluginFinder(new FileSystemPluginFinder(pluginsDir));
- pcConfig.setPluginDirectory(pluginsDir);
- pcConfig.setInsideAgent(false);
- pcConfig.setCreateResourceClassloaders(true);
-
- // Set initial delays for all scheduled scans to one week to effectively disable them.
- pcConfig.setServerDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
- pcConfig.setServiceDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
- pcConfig.setAvailabilityScanInitialDelay(ONE_WEEK_IN_SECONDS);
- pcConfig.setConfigurationDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
- pcConfig.setContentDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
-
- File tmpDir = new File(ITEST_DIR, "tmp");
- tmpDir.mkdirs();
- if (!tmpDir.isDirectory() || !tmpDir.canWrite()) {
- throw new IOException("Failed to create temporary directory (" + tmpDir + ").");
+ if (!isAugeasAvailable()) {
+ String message;
+ if (IS_WINDOWS) {
+ message = "Augeas is not available on Windows. Skipping tests that rely on it...";
+ } else {
+ message = "Augeas not found. If on Fedora or RHEL, `yum install augeas`. Skipping tests that rely on it...";
}
- pcConfig.setTemporaryDirectory(tmpDir);
+ System.out.println(message);
+ }
+ try {
+ PluginContainerConfiguration pcConfig = createPluginContainerConfiguration();
PluginContainer.getInstance().setConfiguration(pcConfig);
- System.out.println("Starting PC...");
- PluginContainer.getInstance().initialize();
- Set<String> pluginNames = PluginContainer.getInstance().getPluginManager().getMetadataManager()
- .getPluginNames();
- System.out.println("PC started with the following plugins: " + pluginNames);
+
+ System.out.println("Starting plugin container...");
+ PluginContainer pluginContainer = PluginContainer.getInstance();
+ pluginContainer.initialize();
+ Set<String> pluginNames = pluginContainer.getPluginManager().getMetadataManager().getPluginNames();
+ System.out.println("Plugin container started with the following plugins: " + pluginNames);
+
+ System.out.println("Updating Augeas root in default plugin config...");
+ ResourceType resourceType = getResourceType();
+ ConfigurationDefinition pluginConfigDef = resourceType.getPluginConfigurationDefinition();
+ ConfigurationTemplate defaultPluginConfigTemplate = pluginConfigDef.getDefaultTemplate();
+ Configuration defaultPluginConfig = defaultPluginConfigTemplate.getConfiguration();
+ resetConfigFiles(defaultPluginConfig);
+ PropertySimple rootPathProp = new PropertySimple(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP, null);
+ defaultPluginConfig.put(rootPathProp);
+
+ InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
+ System.out.println("Executing server discovery scan...");
+ inventoryManager.executeServerScanImmediately();
+ System.out.println("Executing service discovery scan...");
+ inventoryManager.executeServiceScanImmediately();
} catch (Exception e) {
e.printStackTrace();
- fail("Failed to start the plugin container.", e);
+ fail("Failed to initialize the plugin container.", e);
}
}
- @BeforeSuite(dependsOnMethods = "start", groups = TEST_GROUP)
- public void updatePluginConfiguration() {
- try {
- System.out.println("Updating Augeas root in plugin configuration...");
+ @BeforeTest(groups = TEST_GROUP)
+ public void resetConfigFiles() throws IOException {
+ resetConfigFiles(getResource().getPluginConfiguration());
+ }
- // We need to have the Resource inventoried in order to update its plugin config.
- InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
- ResourceType resourceType = getResourceType();
- switch (resourceType.getCategory()) {
- case SERVICE:
- System.out.println("Executing platform service scan to discover " + resourceType + " Resource...");
- inventoryManager.performServiceScan(inventoryManager.getPlatform().getId());
- break;
- case SERVER:
- System.out.println("Executing server scan to discover " + resourceType + " Resource...");
- inventoryManager.executeServerScanImmediately();
- break;
- case PLATFORM:
- throw new IllegalStateException("Huh? Using Augeas to configure a platform?");
- }
- resetAugeasConfigs();
- Resource resource = getResource();
- Configuration pluginConfig = resource.getPluginConfiguration();
- inventoryManager.updatePluginConfiguration(resource.getId(), pluginConfig);
- } catch (Exception e) {
- fail("Failed to update Augeas root in plugin configuration.", e);
- }
+ @Test(groups = TEST_GROUP)
+ public void testResourceConfigLoad() throws Exception {
+ skipTestIfAugeasNotAvailable();
+ ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
+ Resource resource = getResource();
+ Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
+ Configuration expectedResourceConfig = getExpectedResourceConfig();
+ assert resourceConfig.equals(expectedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
+ + expectedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
}
- public void resetAugeasConfigs() throws IOException {
- String tmpDirPath = System.getProperty("java.io.tmpdir");
- File tmpDir = new File(tmpDirPath);
- File augeasRootPath = new File(tmpDir, "rhq-itest-augeas-root-path");
- if (!augeasRootPath.exists()) {
- if (!augeasRootPath.mkdirs()) {
- throw new IOException("Could not create the augeasRootPath " + augeasRootPath);
- }
+ private void skipTestIfAugeasNotAvailable()
+ {
+ if (!isAugeasAvailable()) {
+ throw new SkipException("Skipping test since Augeas is not available.");
}
- System.setProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP, augeasRootPath.getAbsolutePath());
+ }
+
+ @Test(groups = TEST_GROUP)
+ public void testResourceConfigUpdate() throws Exception {
+ skipTestIfAugeasNotAvailable();
+ ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
Resource resource = getResource();
- Configuration pluginConfig = resource.getPluginConfiguration();
- PropertySimple includes = pluginConfig.getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP);
- List<String> includeGlobs = new ArrayList<String>();
- includeGlobs.addAll(Arrays.asList(includes.getStringValue().split("\\s*\\|\\s*")));
- for (String includeGlob : includeGlobs) {
- InputStream inputStream = this.getClass().getResourceAsStream(includeGlob);
- if (inputStream != null) {
- File outputFile = new File(augeasRootPath, includeGlob);
- if (!outputFile.getParentFile().exists() && !outputFile.getParentFile().mkdirs()) {
- throw new IOException("Could not create the component base path " + outputFile.getParentFile());
- }
- FileUtil.writeFile(inputStream, outputFile);
- }
- }
+ Configuration updatedResourceConfig = getUpdatedResourceConfig();
+ configurationManager.updateResourceConfiguration(new ConfigurationUpdateRequest(0,
+ updatedResourceConfig, resource.getId()));
+
+ // Give the component and the managed resource some time to properly persist the update.
+ Thread.sleep(500);
+
+ Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
+ assert resourceConfig.equals(updatedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
+ + updatedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
}
@AfterSuite(groups = TEST_GROUP)
public void stop() {
- System.clearProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP);
- System.out.println("Stopping PC...");
+ try
+ {
+ FileUtils.purge(AUGEAS_ROOT, true);
+ }
+ catch (IOException e)
+ {
+ System.err.println("Failed to purge Augeas root dir '" + AUGEAS_ROOT + "' - cause: " + e);
+ }
+ System.out.println("Stopping plugin container...");
PluginContainer.getInstance().shutdown();
- System.out.println("PC stopped.");
+ System.out.println("Plugin container stopped.");
}
- @Test(groups = TEST_GROUP)
- public void testResourceConfigLoad() throws Exception {
- if (getResourceType().getResourceConfigurationDefinition() != null) {
- ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
- Resource resource = getResource();
- Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
- Configuration expectedResourceConfig = getExpectedResourceConfig();
- assert resourceConfig.equals(expectedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
- + expectedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
- }
- }
+ protected abstract String getPluginName();
+
+ protected abstract String getResourceTypeName();
protected abstract Configuration getExpectedResourceConfig();
- protected abstract Configuration getChangedResourceConfig();
+ protected abstract Configuration getUpdatedResourceConfig();
+
+ protected PluginContainerConfiguration createPluginContainerConfiguration()
+ throws IOException
+ {
+ PluginContainerConfiguration pcConfig = new PluginContainerConfiguration();
+ File pluginsDir = new File(ITEST_DIR, "plugins");
+ pcConfig.setPluginFinder(new FileSystemPluginFinder(pluginsDir));
+ pcConfig.setPluginDirectory(pluginsDir);
+ pcConfig.setInsideAgent(false);
+ pcConfig.setCreateResourceClassloaders(true);
+
+ // Set initial delays for all scheduled scans to one week to effectively disable them.
+ pcConfig.setServerDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setServiceDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setAvailabilityScanInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setConfigurationDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setContentDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+
+ File tmpDir = new File(ITEST_DIR, "tmp");
+ tmpDir.mkdirs();
+ if (!tmpDir.isDirectory() || !tmpDir.canWrite()) {
+ throw new IOException("Failed to create temporary directory (" + tmpDir + ").");
+ }
+ pcConfig.setTemporaryDirectory(tmpDir);
+ return pcConfig;
+ }
protected static ResourceType getResourceType(String resourceTypeName, String pluginName) {
PluginManager pluginManager = PluginContainer.getInstance().getPluginManager();
@@ -182,10 +214,6 @@ public abstract class AbstractAugeasConfigurationComponentTest {
return getResourceType(getResourceTypeName(), getPluginName());
}
- protected abstract String getPluginName();
-
- protected abstract String getResourceTypeName();
-
protected Resource getResource() {
InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
ResourceType resourceType = getResourceType();
@@ -200,25 +228,28 @@ public abstract class AbstractAugeasConfigurationComponentTest {
return resources.iterator().next();
}
- @Test(groups = TEST_GROUP)
- public void testResourceConfigUpdate() throws Exception {
- if (getResourceType().getResourceConfigurationDefinition() != null) {
- try {
- ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
- Resource resource = getResource();
- Configuration updatedResourceConfig = getChangedResourceConfig();
- configurationManager.updateResourceConfiguration(new ConfigurationUpdateRequest(0,
- updatedResourceConfig, resource.getId()));
-
- //give the component and the managed resource some time to properly persist the update
- Thread.sleep(500);
-
- Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
- assert resourceConfig.equals(updatedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
- + updatedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
- } finally {
- resetAugeasConfigs();
+ protected void resetConfigFiles(Configuration pluginConfig) throws IOException {
+ String includes = pluginConfig.getSimpleValue(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP, null);
+ if (includes != null) {
+ List<String> includeGlobs = new ArrayList<String>();
+ includeGlobs.addAll(Arrays.asList(includes.split("\\s*\\|\\s*")));
+ for (String includeGlob : includeGlobs) {
+ InputStream inputStream = this.getClass().getResourceAsStream(includeGlob);
+ if (inputStream != null) {
+ File outputFile = new File(AUGEAS_ROOT, includeGlob);
+ outputFile.getParentFile().mkdirs();
+ FileUtil.writeFile(inputStream, outputFile);
+ }
}
}
}
+
+ protected boolean isAugeasAvailable() {
+ try {
+ Aug aug = Aug.INSTANCE;
+ return true;
+ } catch (Error e) {
+ return false;
+ }
+ }
}
diff --git a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
index af8de77..9c67cfc 100644
--- a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
+++ b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
@@ -82,7 +82,7 @@ public class HostsComponentTest extends AbstractAugeasConfigurationComponentTest
}
@Override
- protected Configuration getChangedResourceConfig() {
+ protected Configuration getUpdatedResourceConfig() {
Configuration config = new Configuration();
PropertyList entries = new PropertyList(".");
config.put(entries);
diff --git a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
index 93afd70..d5836ef 100644
--- a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
+++ b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
@@ -48,7 +48,7 @@ public class SambaComponentTest extends AbstractAugeasConfigurationComponentTest
}
@Override
- protected Configuration getChangedResourceConfig() {
+ protected Configuration getUpdatedResourceConfig() {
Configuration config = new Configuration();
config.put(new PropertySimple("workgroup", "DUMBCHANGE"));
diff --git a/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java b/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
index 63bed0f..109e118 100644
--- a/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
+++ b/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
@@ -70,7 +70,7 @@ public class SudoersComponentTest extends AbstractAugeasConfigurationComponentTe
}
@Override
- protected Configuration getChangedResourceConfig() {
+ protected Configuration getUpdatedResourceConfig() {
Configuration config = new Configuration();
PropertyList entries = new PropertyList(".");
config.put(entries);
commit 65ded009295ab0742cba8e7568d287ecbec2437a
Author: Pradeep Kilambi <pkilambi(a)redhat.com>
Date: Wed Nov 11 10:21:23 2009 -0500
UI representation for the distribution tree logic. This is a read only widget displaying the list of available distros per repo
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
index 078fc84..71df772 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
@@ -46,11 +46,13 @@ import javax.persistence.Table;
@IdClass(RepoDistributionPK.class)
@NamedQueries( {
@NamedQuery(name = RepoDistribution.DELETE_BY_KICKSTART_TREE_ID, query = "DELETE RepoDistribution rkt WHERE rkt.dist.id = :distId"),
- @NamedQuery(name = RepoDistribution.DELETE_BY_REPO_ID, query = "DELETE RepoDistribution rkt WHERE rkt.repo.id = :repoId") })
+ @NamedQuery(name = RepoDistribution.DELETE_BY_REPO_ID, query = "DELETE RepoDistribution rkt WHERE rkt.repo.id = :repoId"),
+ @NamedQuery(name = RepoDistribution.QUERY_FIND_BY_REPO_ID, query = "SELECT rkt FROM RepoDistribution rkt where rkt.repo.id = :repoId") })
@Table(name = "RHQ_REPO_DISTRIBUTION")
public class RepoDistribution implements Serializable {
public static final String DELETE_BY_KICKSTART_TREE_ID = "RepoDistribution.deleteByKickstartTreeId";
public static final String DELETE_BY_REPO_ID = "RepoDistribution.deleteByRepoId";
+ public static final String QUERY_FIND_BY_REPO_ID = "RepoDistribution.queryFindByRepoId";
private static final long serialVersionUID = 1L;
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PageControlView.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PageControlView.java
index 8d5549f..d993d0e 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PageControlView.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PageControlView.java
@@ -45,6 +45,7 @@ import org.rhq.enterprise.gui.content.RepoAssociationsUIBean;
import org.rhq.enterprise.gui.content.RepoContentSourcesUIBean;
import org.rhq.enterprise.gui.content.RepoDisassociationsUIBean;
import org.rhq.enterprise.gui.content.RepoImportUIBean;
+import org.rhq.enterprise.gui.content.RepoDistributionUIBean;
import org.rhq.enterprise.gui.content.RepoPackageVersionsUIBean;
import org.rhq.enterprise.gui.content.RepoResourcesUIBean;
import org.rhq.enterprise.gui.content.RepoSubscriptionsUIBean;
@@ -140,6 +141,8 @@ public enum PageControlView {
/** */
RepoPackageVersionsList(RepoPackageVersionsUIBean.class),
/** */
+ RepoDistributionList(RepoDistributionUIBean.class),
+ /** */
RepoAssociationsList(RepoAssociationsUIBean.class),
/** */
RepoDisassociationsList(RepoDisassociationsUIBean.class),
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDistributionUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDistributionUIBean.java
new file mode 100644
index 0000000..e56bce1
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoDistributionUIBean.java
@@ -0,0 +1,67 @@
+/*
+ * 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.content;
+
+import javax.faces.model.DataModel;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.content.Distribution;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.core.gui.util.FacesContextUtility;
+import org.rhq.enterprise.gui.common.framework.PagedDataTableUIBean;
+import org.rhq.enterprise.gui.common.paging.PageControlView;
+import org.rhq.enterprise.gui.common.paging.PagedListDataModel;
+import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
+import org.rhq.enterprise.server.content.RepoManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+public class RepoDistributionUIBean extends PagedDataTableUIBean {
+ public static final String MANAGED_BEAN_NAME = "RepoDistributionUIBean";
+
+ public RepoDistributionUIBean() {
+ }
+
+ @Override
+ public DataModel getDataModel() {
+ if (dataModel == null) {
+ dataModel = new RepoDistributionDataModel(PageControlView.RepoDistributionList, MANAGED_BEAN_NAME);
+ }
+ return dataModel;
+
+ }
+
+ private class RepoDistributionDataModel extends PagedListDataModel<Distribution> {
+ public RepoDistributionDataModel(PageControlView view, String beanName) {
+ super(view, beanName);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public PageList<Distribution> fetchPage(PageControl pc) {
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
+ int id = Integer.valueOf(FacesContextUtility.getRequiredRequestParameter("id"));
+ RepoManagerLocal manager = LookupUtil.getRepoManagerLocal();
+
+ PageList<Distribution> results = manager.findAssociatedDistributions(subject, id, pc);
+ return results;
+ }
+ }
+
+}
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml
index 34611bd..7b740cd 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml
@@ -495,6 +495,84 @@
</rich:panel>
</a4j:region>
</h:form>
+
+ <h:form id="repoDistributionListForm">
+ <a4j:region id="distributionList">
+ <input type="hidden" name="id" value="${param.id}"/>
+ <input type="hidden" name="mode" value="${param.mode}"/>
+
+ <rich:panel>
+ <f:facet name="header">
+ <h:outputText value="Distribution Trees Associated To This Repository"/>
+ </f:facet>
+
+ <h:panelGrid columns="1" width="100%">
+
+
+ <ui:param name="repoDistributionDataModel" value="#{RepoDistributionUIBean.dataModel}"/>
+ <rich:dataTable id="repoDistributionDataTable"
+ rows="#{PageControl.RepoDistributionList.pageSize}"
+ value="#{repoDistributionDataModel}"
+ var="pvitem"
+ width="100%"
+ columnsWidth="5%,20%, 10%, 5%, 60%"
+ headerClass="tableRowHeader"
+ footerClass="on-pager-footer"
+ onRowMouseOver="this.style.backgroundColor='#E7E7E7'"
+ onRowMouseOut="this.style.backgroundColor='#{a4jSkin.tableBackgroundColor}'">
+
+
+ <f:facet name="PageControlView">
+ <onc:paginationControl id="RepoDistributionList" />
+ </f:facet>
+
+ <rich:column>
+ <f:facet name="header">
+ <onc:sortableColumnHeader sort="pv.label">
+ <h:outputText styleClass="headerText" value="Label" />
+ </onc:sortableColumnHeader>
+ </f:facet>
+
+ </rich:column>
+
+ <rich:column>
+ <f:facet name="header">
+ <onc:sortableColumnHeader sort="pv.base_path">
+ <h:outputText styleClass="headerText" value="Base Path" />
+ </onc:sortableColumnHeader>
+ </f:facet>
+
+ </rich:column>
+
+ <rich:column>
+ <f:facet name="header">
+ <onc:sortableColumnHeader sort="pv.last_modified">
+ <h:outputText styleClass="headerText" value="Last Modified" />
+ </onc:sortableColumnHeader>
+ </f:facet>
+
+ </rich:column>
+
+ <f:facet name="footer">
+ <rich:columnGroup>
+ <!-- colspan 5:4 for the debug 'id' column -->
+ <rich:column colspan="#{param.debug ? 6 : 5}" width="100%">
+
+ <ui:param name="paginationDataTableName" value="repoDistributionDataTable"/>
+ <ui:param name="paginationDataModel" value="#{repoDistributionDataModel}"/>
+ <ui:param name="paginationPageControl" value="#{PageControl.RepoDistributionList}"/>
+ <ui:include src="../resource/include/pagination.xhtml"/>
+ </rich:column>
+ </rich:columnGroup>
+ </f:facet>
+
+ </rich:dataTable>
+
+ </h:panelGrid>
+
+ </rich:panel>
+ </a4j:region>
+ </h:form>
</ui:define>
</ui:composition>
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 df0933a..4712584 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
@@ -39,10 +39,12 @@ import org.jboss.annotation.IgnoreDependency;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.content.ContentSource;
+import org.rhq.core.domain.content.Distribution;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.core.domain.content.PackageVersionContentSource;
import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.content.RepoContentSource;
+import org.rhq.core.domain.content.RepoDistribution;
import org.rhq.core.domain.content.RepoGroup;
import org.rhq.core.domain.content.RepoGroupType;
import org.rhq.core.domain.content.RepoPackageVersion;
@@ -63,9 +65,9 @@ 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.ContentServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.content.RepoImportReport;
-import org.rhq.enterprise.server.plugin.pc.content.RepoGroupDetails;
import org.rhq.enterprise.server.plugin.pc.content.RepoDetails;
+import org.rhq.enterprise.server.plugin.pc.content.RepoGroupDetails;
+import org.rhq.enterprise.server.plugin.pc.content.RepoImportReport;
import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
import org.rhq.enterprise.server.util.CriteriaQueryRunner;
@@ -328,8 +330,8 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
}
@RequiredPermission(Permission.MANAGE_INVENTORY)
- public void processRepoImportReport(Subject subject, RepoImportReport report,
- int contentSourceId, StringBuilder result) {
+ public void processRepoImportReport(Subject subject, RepoImportReport report, int contentSourceId,
+ StringBuilder result) {
// Import groups first
List<RepoGroupDetails> repoGroups = report.getRepoGroups();
@@ -351,15 +353,14 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
try {
createRepoGroup(subject, existingGroup);
repoGroupCounter++;
- }
- catch (RepoException e) {
+ } catch (RepoException e) {
if (e.getType() == RepoException.RepoExceptionType.NAME_ALREADY_EXISTS) {
result.append("Skipping existing repo group [").append(name).append("]").append('\n');
- }
- else {
+ } else {
log.error("Error adding repo group [" + name + "]", e);
- result.append("Could not add repo group [").append(name).append("]. See log for more information.").append('\n');
+ result.append("Could not add repo group [").append(name).append(
+ "]. See log for more information.").append('\n');
}
}
}
@@ -388,16 +389,16 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
addCandidateRepo(contentSourceId, createMe);
removeRepoFromList(createMe.getName(), candidatesForThisProvider);
repoCounter++;
- }
- catch (Exception e) {
+ } catch (Exception e) {
- if (e instanceof RepoException &&
- ((RepoException) e).getType() == RepoException.RepoExceptionType.NAME_ALREADY_EXISTS) {
- result.append("Skipping addition of existing repo [").append(createMe.getName()).append("]").append('\n');
- }
- else {
+ if (e instanceof RepoException
+ && ((RepoException) e).getType() == RepoException.RepoExceptionType.NAME_ALREADY_EXISTS) {
+ result.append("Skipping addition of existing repo [").append(createMe.getName()).append("]")
+ .append('\n');
+ } else {
log.error("Error processing repo [" + createMe + "]", e);
- result.append("Could not add repo [").append(createMe.getName()).append("]. See log for more information.").append('\n');
+ result.append("Could not add repo [").append(createMe.getName()).append(
+ "]. See log for more information.").append('\n');
}
}
}
@@ -412,10 +413,10 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
addCandidateRepo(contentSourceId, createMe);
removeRepoFromList(createMe.getName(), candidatesForThisProvider);
repoCounter++;
- }
- catch (Exception e) {
+ } catch (Exception e) {
log.error("Error processing repo [" + createMe + "]", e);
- result.append("Could not add repo [").append(createMe.getName()).append("]. See log for more information.").append('\n');
+ result.append("Could not add repo [").append(createMe.getName()).append(
+ "]. See log for more information.").append('\n');
}
}
}
@@ -742,8 +743,7 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
List<Repo> repos = getRepoByName(c.getName());
if (repos.size() != 0) {
- RepoException e =
- new RepoException("There is already a repo with the name of [" + c.getName() + "]");
+ RepoException e = new RepoException("There is already a repo with the name of [" + c.getName() + "]");
e.setType(RepoException.RepoExceptionType.NAME_ALREADY_EXISTS);
throw e;
}
@@ -763,8 +763,8 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
RepoGroup existingRepoGroup = getRepoGroupByName(repoGroup.getName());
if (existingRepoGroup != null) {
- RepoException e =
- new RepoException("There is already a repo group with the name [" + repoGroup.getName() + "]");
+ RepoException e = new RepoException("There is already a repo group with the name [" + repoGroup.getName()
+ + "]");
e.setType(RepoException.RepoExceptionType.NAME_ALREADY_EXISTS);
throw e;
}
@@ -840,4 +840,29 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
repoList.remove(deleteMe);
}
}
+
+ @RequiredPermission(Permission.MANAGE_INVENTORY)
+ public long getDistributionCountFromRepo(Subject subject, int repoId) {
+ Query countQuery = PersistenceUtility.createCountQuery(entityManager, RepoDistribution.QUERY_FIND_BY_REPO_ID);
+
+ countQuery.setParameter("repoId", repoId);
+
+ return ((Long) countQuery.getSingleResult()).longValue();
+ }
+
+ @RequiredPermission(Permission.MANAGE_INVENTORY)
+ @SuppressWarnings("unchecked")
+ public PageList<Distribution> findAssociatedDistributions(Subject subject, int repoid, PageControl pc) {
+
+ Query query = PersistenceUtility.createQueryWithOrderBy(entityManager, RepoDistribution.QUERY_FIND_BY_REPO_ID,
+ pc);
+
+ query.setParameter("repoId", repoid);
+
+ List<Distribution> results = query.getResultList();
+ long count = getDistributionCountFromRepo(subject, repoid);
+
+ return new PageList<Distribution>(results, (int) count, pc);
+
+ }
}
\ No newline at end of file
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 b0a2dca..c5227fe 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
@@ -23,14 +23,15 @@ import java.util.List;
import javax.ejb.Local;
import org.rhq.core.domain.auth.Subject;
-import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.content.ContentSource;
+import org.rhq.core.domain.content.Distribution;
import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.content.RepoGroup;
import org.rhq.core.domain.content.RepoGroupType;
import org.rhq.core.domain.content.composite.RepoComposite;
-import org.rhq.core.domain.criteria.RepoCriteria;
import org.rhq.core.domain.criteria.PackageVersionCriteria;
+import org.rhq.core.domain.criteria.RepoCriteria;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
@@ -110,8 +111,7 @@ public interface RepoManagerLocal {
/**
*/
- void removeContentSourcesFromRepo(Subject subject, int repoId, int[] contentSourceIds)
- throws RepoException;
+ void removeContentSourcesFromRepo(Subject subject, int repoId, int[] contentSourceIds) throws RepoException;
/**
*/
@@ -254,4 +254,9 @@ public interface RepoManagerLocal {
*/
Repo updateRepo(Subject subject, Repo repo) throws RepoException;
+ /**
+ * @see RepoManagerRemote#findAssociatedDistributions(Subject, int, PageControl)
+ */
+ PageList<Distribution> findAssociatedDistributions(Subject subject, int repoid, PageControl pc);
+
}
\ 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 c85bcd7..0b31bed 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
@@ -25,12 +25,13 @@ import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import org.rhq.core.domain.auth.Subject;
-import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.content.Distribution;
import org.rhq.core.domain.content.PackageVersion;
+import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.content.RepoGroup;
import org.rhq.core.domain.content.RepoGroupType;
-import org.rhq.core.domain.criteria.RepoCriteria;
import org.rhq.core.domain.criteria.PackageVersionCriteria;
+import org.rhq.core.domain.criteria.RepoCriteria;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
@@ -127,8 +128,7 @@ public interface RepoManagerRemote {
* @return details describing the repo group
*/
@WebMethod
- RepoGroup getRepoGroup(
- @WebParam(name = "subject") Subject subject, //
+ RepoGroup getRepoGroup(@WebParam(name = "subject") Subject subject, //
@WebParam(name = "repoGroupId") int repoGroupId);
/**
@@ -139,8 +139,7 @@ public interface RepoManagerRemote {
* @return details of the group type; <code>null</code> if no group is found with the name
*/
@WebMethod
- RepoGroupType getRepoGroupTypeByName(
- @WebParam(name = "subject") Subject subject, //
+ RepoGroupType getRepoGroupTypeByName(@WebParam(name = "subject") Subject subject, //
@WebParam(name = "name") String name);
/**
@@ -253,4 +252,17 @@ public interface RepoManagerRemote {
@WebParam(name = "resourceId") int resourceId, //
@WebParam(name = "repoIds") int[] repoIds);
+ /**
+ * gets a list of all associated distributions
+ * @param subject
+ * @param resourceId
+ * @param pc
+ * @return
+ */
+ @WebMethod
+ PageList<Distribution> findAssociatedDistributions( //
+ @WebParam(name = "subject") Subject subject, //
+ @WebParam(name = "repoId") int repoId, //
+ @WebParam(name = "pageControl") PageControl pc);
+
}
\ No newline at end of file
commit 62f8c89cd2fcc882f6783c8530ac4cf46f7cec34
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 10:06:08 2009 -0500
Revert "Fixed test cases related to samba and sudoer plugins"
Looks like there is a better way to achieve the same.. Waiing for ips'
commit
This reverts commit 6d666b6987f1c58732851a57560ec93ba21c4cc5.
diff --git a/.classpath b/.classpath
index 0d36a1d..2555353 100644
--- a/.classpath
+++ b/.classpath
@@ -17,7 +17,7 @@
<classpathentry kind="var" path="M2_REPO/org/jboss/integration/jboss-profileservice-spi/5.1.0.SP1/jboss-profileservice-spi-5.1.0.SP1.jar"/>
<classpathentry kind="var" path="M2_REPO/org/jboss/man/jboss-managed/2.1.1.GA/jboss-managed-2.1.1.GA.jar"/>
<classpathentry kind="var" path="M2_REPO/org/jboss/man/jboss-metatype/2.1.1.GA/jboss-metatype-2.1.1.GA.jar"/>
- <classpathentry kind="var" path="M2_REPO/commons-io/commons-io/1.4/commons-io-1.4.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/apache/commons/commons-io/1.3.2/commons-io-1.3.2.jar"/>
<classpathentry kind="var" path="M2_REPO/com/sun/xml/bind/jaxb-impl/2.1.6/jaxb-impl-2.1.6.jar"/>
<classpathentry kind="src" path="modules/core/util/src/main/java"/>
<classpathentry kind="src" path="modules/core/util/src/test/java"/>
diff --git a/modules/plugins/augeas/pom.xml b/modules/plugins/augeas/pom.xml
index 7ad9339..657766c 100644
--- a/modules/plugins/augeas/pom.xml
+++ b/modules/plugins/augeas/pom.xml
@@ -51,11 +51,6 @@
<artifactId>jna</artifactId>
<version>3.2.2</version>
</dependency>
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>1.4</version>
- </dependency>
</dependencies>
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
index ee2e192..3631261 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
@@ -23,9 +23,11 @@ import static org.testng.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import java.util.Set;
-import org.apache.commons.io.FileUtils;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
@@ -33,6 +35,7 @@ import org.testng.annotations.Test;
import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pc.PluginContainer;
@@ -43,6 +46,7 @@ import org.rhq.core.pc.plugin.FileSystemPluginFinder;
import org.rhq.core.pc.plugin.PluginManager;
import org.rhq.core.util.file.FileUtil;
import org.rhq.plugins.augeas.AugeasConfigurationComponent;
+
/**
* An base class for integration tests for instances of {@link AugeasConfigurationComponent}.
*
@@ -56,7 +60,6 @@ public abstract class AbstractAugeasConfigurationComponentTest {
@BeforeSuite(groups = TEST_GROUP)
public void start() {
try {
- resetAugeasConfigs();
PluginContainerConfiguration pcConfig = new PluginContainerConfiguration();
File pluginsDir = new File(ITEST_DIR, "plugins");
pcConfig.setPluginFinder(new FileSystemPluginFinder(pluginsDir));
@@ -93,6 +96,7 @@ public abstract class AbstractAugeasConfigurationComponentTest {
public void updatePluginConfiguration() {
try {
System.out.println("Updating Augeas root in plugin configuration...");
+
// We need to have the Resource inventoried in order to update its plugin config.
InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
ResourceType resourceType = getResourceType();
@@ -108,6 +112,7 @@ public abstract class AbstractAugeasConfigurationComponentTest {
case PLATFORM:
throw new IllegalStateException("Huh? Using Augeas to configure a platform?");
}
+ resetAugeasConfigs();
Resource resource = getResource();
Configuration pluginConfig = resource.getPluginConfiguration();
inventoryManager.updatePluginConfiguration(resource.getId(), pluginConfig);
@@ -116,38 +121,38 @@ public abstract class AbstractAugeasConfigurationComponentTest {
}
}
- private File makeRootDir() throws IOException {
+ public void resetAugeasConfigs() throws IOException {
String tmpDirPath = System.getProperty("java.io.tmpdir");
File tmpDir = new File(tmpDirPath);
File augeasRootPath = new File(tmpDir, "rhq-itest-augeas-root-path");
- if (!augeasRootPath.exists() && !augeasRootPath.mkdirs()) {
- throw new IOException("Could not create the augeasRootPath " + augeasRootPath);
+ if (!augeasRootPath.exists()) {
+ if (!augeasRootPath.mkdirs()) {
+ throw new IOException("Could not create the augeasRootPath " + augeasRootPath);
+ }
}
System.setProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP, augeasRootPath.getAbsolutePath());
- return augeasRootPath;
- }
-
- public void resetAugeasConfigs() throws IOException {
- File augeasRootPath = makeRootDir();
- for (String config : getAssociatedConfigs()) {
- InputStream inputStream = this.getClass().getResourceAsStream(config);
+ Resource resource = getResource();
+ Configuration pluginConfig = resource.getPluginConfiguration();
+ PropertySimple includes = pluginConfig.getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP);
+ List<String> includeGlobs = new ArrayList<String>();
+ includeGlobs.addAll(Arrays.asList(includes.getStringValue().split("\\s*\\|\\s*")));
+ for (String includeGlob : includeGlobs) {
+ InputStream inputStream = this.getClass().getResourceAsStream(includeGlob);
if (inputStream != null) {
- File outputFile = new File(augeasRootPath, config);
- outputFile.getParentFile().mkdirs();
+ File outputFile = new File(augeasRootPath, includeGlob);
+ if (!outputFile.getParentFile().exists() && !outputFile.getParentFile().mkdirs()) {
+ throw new IOException("Could not create the component base path " + outputFile.getParentFile());
+ }
FileUtil.writeFile(inputStream, outputFile);
}
}
}
@AfterSuite(groups = TEST_GROUP)
- public void stop() throws Exception {
- String path = System.getProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP);
- File root = new File(path);
- FileUtils.deleteQuietly(root);
+ public void stop() {
System.clearProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP);
System.out.println("Stopping PC...");
PluginContainer.getInstance().shutdown();
-
System.out.println("PC stopped.");
}
@@ -216,6 +221,4 @@ public abstract class AbstractAugeasConfigurationComponentTest {
}
}
}
-
- protected abstract String[] getAssociatedConfigs();
}
diff --git a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
index cb4cfde..af8de77 100644
--- a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
+++ b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
@@ -120,9 +120,4 @@ public class HostsComponentTest extends AbstractAugeasConfigurationComponentTest
entries.getList().add(entry);
return config;
}
-
- @Override
- protected String[] getAssociatedConfigs() {
- return new String[] { "/etc/hosts" };
- }
}
diff --git a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
index a8d5178..93afd70 100644
--- a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
+++ b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
@@ -37,7 +37,6 @@ public class SambaComponentTest extends AbstractAugeasConfigurationComponentTest
return config;
}
-
@Override
protected String getPluginName() {
return "Samba";
@@ -61,10 +60,4 @@ public class SambaComponentTest extends AbstractAugeasConfigurationComponentTest
return config;
}
-
- @Override
- protected String[] getAssociatedConfigs() {
- return new String[] { "/etc/samba/smb.conf" };
- }
-
}
diff --git a/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java b/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
index f497cb9..63bed0f 100644
--- a/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
+++ b/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
@@ -118,10 +118,4 @@ public class SudoersComponentTest extends AbstractAugeasConfigurationComponentTe
protected String getResourceTypeName() {
return "Sudoers";
}
-
- @Override
- protected String[] getAssociatedConfigs() {
- return new String[] { "/etc/sudoers" };
- }
-
}
commit 7d952067685d548fc7b26bf7a8a272cece448484
Merge: 6d666b6... 46d0de1...
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 00:53:22 2009 -0500
Merge branch 'master' into hope
commit 6d666b6987f1c58732851a57560ec93ba21c4cc5
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 11 00:51:04 2009 -0500
Fixed test cases related to samba and sudoer plugins
diff --git a/.classpath b/.classpath
index 478e351..0199455 100644
--- a/.classpath
+++ b/.classpath
@@ -17,7 +17,7 @@
<classpathentry kind="var" path="M2_REPO/org/jboss/integration/jboss-profileservice-spi/5.1.0.SP1/jboss-profileservice-spi-5.1.0.SP1.jar"/>
<classpathentry kind="var" path="M2_REPO/org/jboss/man/jboss-managed/2.1.1.GA/jboss-managed-2.1.1.GA.jar"/>
<classpathentry kind="var" path="M2_REPO/org/jboss/man/jboss-metatype/2.1.1.GA/jboss-metatype-2.1.1.GA.jar"/>
- <classpathentry kind="var" path="M2_REPO/org/apache/commons/commons-io/1.3.2/commons-io-1.3.2.jar"/>
+ <classpathentry kind="var" path="M2_REPO/commons-io/commons-io/1.4/commons-io-1.4.jar"/>
<classpathentry kind="var" path="M2_REPO/com/sun/xml/bind/jaxb-impl/2.1.6/jaxb-impl-2.1.6.jar"/>
<classpathentry kind="src" path="modules/core/util/src/main/java"/>
<classpathentry kind="src" path="modules/core/util/src/test/java"/>
diff --git a/modules/plugins/augeas/pom.xml b/modules/plugins/augeas/pom.xml
index 657766c..7ad9339 100644
--- a/modules/plugins/augeas/pom.xml
+++ b/modules/plugins/augeas/pom.xml
@@ -51,6 +51,11 @@
<artifactId>jna</artifactId>
<version>3.2.2</version>
</dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>1.4</version>
+ </dependency>
</dependencies>
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
index 3631261..ee2e192 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
@@ -23,11 +23,9 @@ import static org.testng.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
import java.util.Set;
+import org.apache.commons.io.FileUtils;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
@@ -35,7 +33,6 @@ import org.testng.annotations.Test;
import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pc.PluginContainer;
@@ -46,7 +43,6 @@ import org.rhq.core.pc.plugin.FileSystemPluginFinder;
import org.rhq.core.pc.plugin.PluginManager;
import org.rhq.core.util.file.FileUtil;
import org.rhq.plugins.augeas.AugeasConfigurationComponent;
-
/**
* An base class for integration tests for instances of {@link AugeasConfigurationComponent}.
*
@@ -60,6 +56,7 @@ public abstract class AbstractAugeasConfigurationComponentTest {
@BeforeSuite(groups = TEST_GROUP)
public void start() {
try {
+ resetAugeasConfigs();
PluginContainerConfiguration pcConfig = new PluginContainerConfiguration();
File pluginsDir = new File(ITEST_DIR, "plugins");
pcConfig.setPluginFinder(new FileSystemPluginFinder(pluginsDir));
@@ -96,7 +93,6 @@ public abstract class AbstractAugeasConfigurationComponentTest {
public void updatePluginConfiguration() {
try {
System.out.println("Updating Augeas root in plugin configuration...");
-
// We need to have the Resource inventoried in order to update its plugin config.
InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
ResourceType resourceType = getResourceType();
@@ -112,7 +108,6 @@ public abstract class AbstractAugeasConfigurationComponentTest {
case PLATFORM:
throw new IllegalStateException("Huh? Using Augeas to configure a platform?");
}
- resetAugeasConfigs();
Resource resource = getResource();
Configuration pluginConfig = resource.getPluginConfiguration();
inventoryManager.updatePluginConfiguration(resource.getId(), pluginConfig);
@@ -121,38 +116,38 @@ public abstract class AbstractAugeasConfigurationComponentTest {
}
}
- public void resetAugeasConfigs() throws IOException {
+ private File makeRootDir() throws IOException {
String tmpDirPath = System.getProperty("java.io.tmpdir");
File tmpDir = new File(tmpDirPath);
File augeasRootPath = new File(tmpDir, "rhq-itest-augeas-root-path");
- if (!augeasRootPath.exists()) {
- if (!augeasRootPath.mkdirs()) {
- throw new IOException("Could not create the augeasRootPath " + augeasRootPath);
- }
+ if (!augeasRootPath.exists() && !augeasRootPath.mkdirs()) {
+ throw new IOException("Could not create the augeasRootPath " + augeasRootPath);
}
System.setProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP, augeasRootPath.getAbsolutePath());
- Resource resource = getResource();
- Configuration pluginConfig = resource.getPluginConfiguration();
- PropertySimple includes = pluginConfig.getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP);
- List<String> includeGlobs = new ArrayList<String>();
- includeGlobs.addAll(Arrays.asList(includes.getStringValue().split("\\s*\\|\\s*")));
- for (String includeGlob : includeGlobs) {
- InputStream inputStream = this.getClass().getResourceAsStream(includeGlob);
+ return augeasRootPath;
+ }
+
+ public void resetAugeasConfigs() throws IOException {
+ File augeasRootPath = makeRootDir();
+ for (String config : getAssociatedConfigs()) {
+ InputStream inputStream = this.getClass().getResourceAsStream(config);
if (inputStream != null) {
- File outputFile = new File(augeasRootPath, includeGlob);
- if (!outputFile.getParentFile().exists() && !outputFile.getParentFile().mkdirs()) {
- throw new IOException("Could not create the component base path " + outputFile.getParentFile());
- }
+ File outputFile = new File(augeasRootPath, config);
+ outputFile.getParentFile().mkdirs();
FileUtil.writeFile(inputStream, outputFile);
}
}
}
@AfterSuite(groups = TEST_GROUP)
- public void stop() {
+ public void stop() throws Exception {
+ String path = System.getProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP);
+ File root = new File(path);
+ FileUtils.deleteQuietly(root);
System.clearProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP);
System.out.println("Stopping PC...");
PluginContainer.getInstance().shutdown();
+
System.out.println("PC stopped.");
}
@@ -221,4 +216,6 @@ public abstract class AbstractAugeasConfigurationComponentTest {
}
}
}
+
+ protected abstract String[] getAssociatedConfigs();
}
diff --git a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
index af8de77..cb4cfde 100644
--- a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
+++ b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
@@ -120,4 +120,9 @@ public class HostsComponentTest extends AbstractAugeasConfigurationComponentTest
entries.getList().add(entry);
return config;
}
+
+ @Override
+ protected String[] getAssociatedConfigs() {
+ return new String[] { "/etc/hosts" };
+ }
}
diff --git a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
index 93afd70..a8d5178 100644
--- a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
+++ b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
@@ -37,6 +37,7 @@ public class SambaComponentTest extends AbstractAugeasConfigurationComponentTest
return config;
}
+
@Override
protected String getPluginName() {
return "Samba";
@@ -60,4 +61,10 @@ public class SambaComponentTest extends AbstractAugeasConfigurationComponentTest
return config;
}
+
+ @Override
+ protected String[] getAssociatedConfigs() {
+ return new String[] { "/etc/samba/smb.conf" };
+ }
+
}
diff --git a/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java b/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
index 63bed0f..f497cb9 100644
--- a/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
+++ b/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
@@ -118,4 +118,10 @@ public class SudoersComponentTest extends AbstractAugeasConfigurationComponentTe
protected String getResourceTypeName() {
return "Sudoers";
}
+
+ @Override
+ protected String[] getAssociatedConfigs() {
+ return new String[] { "/etc/sudoers" };
+ }
+
}
commit 46d0de190343f6ac211d1d9eb8e807fa78ef90bd
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 10 23:46:48 2009 -0500
add a "concurrent" attribute to allow for us to use StatefulJob
when submitted the scheduled job to quartz. only the xml schema
is implemented, we don't yet to any real scheduling.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/CronSchedule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/CronSchedule.java
index ce2a96d..b5c7435 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/CronSchedule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/CronSchedule.java
@@ -27,7 +27,8 @@ package org.rhq.enterprise.server.plugin.pc;
public class CronSchedule extends Schedule {
private final String cronExpression;
- public CronSchedule(String cronExpression) {
+ public CronSchedule(boolean concurrent, String cronExpression) {
+ super(concurrent);
this.cronExpression = cronExpression;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PeriodicSchedule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PeriodicSchedule.java
index 32db896..2ff75ba 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PeriodicSchedule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PeriodicSchedule.java
@@ -27,7 +27,8 @@ package org.rhq.enterprise.server.plugin.pc;
public class PeriodicSchedule extends Schedule {
private final long period;
- public PeriodicSchedule(long period) {
+ public PeriodicSchedule(boolean concurrent, long period) {
+ super(concurrent);
this.period = period;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/Schedule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/Schedule.java
index 3cedbd6..c985f92 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/Schedule.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/Schedule.java
@@ -20,9 +20,32 @@
package org.rhq.enterprise.server.plugin.pc;
/**
- * Defines a schedule for a plugin component.
+ * Defines a schedule for a server plugin component.
*
* @author John Mazzitelli
*/
public abstract class Schedule {
+ private final boolean concurrent;
+
+ /**
+ * Builds the schedule object.
+ *
+ * @param concurrent if true, multiple jobs can run concurrently. If false, only one
+ * scheduled job will run at any one time across the RHQ Server cloud.
+ */
+ public Schedule(boolean concurrent) {
+ this.concurrent = concurrent;
+ }
+
+ /**
+ * If true, multiple jobs can execute at any one time. If false, only a single job will be allowed
+ * to run at any one time (across all servers in the RHQ server cloud). Even if the schedule
+ * is triggered multiple times, if a job is still running, any future jobs that are triggered will
+ * be delayed.
+ *
+ * @return concurrent flag
+ */
+ public boolean isConcurrent() {
+ return concurrent;
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index f9b4ede..4226b12 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -271,10 +271,11 @@ public class ServerPluginManager {
if (pluginDescriptor.getLifecycleListener() != null) {
ScheduleType scheduleType = pluginDescriptor.getLifecycleListener().getSchedule();
if (scheduleType != null) {
+ boolean concurrent = scheduleType.isConcurrent();
if (scheduleType.getPeriod() != null) {
- schedule = new PeriodicSchedule(scheduleType.getPeriod().longValue());
+ schedule = new PeriodicSchedule(concurrent, scheduleType.getPeriod().longValue());
} else {
- schedule = new CronSchedule(scheduleType.getCron());
+ schedule = new CronSchedule(concurrent, scheduleType.getCron());
}
}
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
index 78b1681..3a2067f 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
@@ -75,6 +75,7 @@ public class GenericServerPluginTest extends AbstractEJB3Test {
Schedule schedule = listener.context.getSchedule();
assert schedule != null;
+ assert schedule.isConcurrent() == false;
assert schedule instanceof PeriodicSchedule;
assert ((PeriodicSchedule) schedule).getPeriod() == 60000L;
diff --git a/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml b/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml
index ca40e8e..7904ed0 100644
--- a/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml
+++ b/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml
@@ -10,7 +10,7 @@
xmlns:c="urn:xmlns:rhq-configuration">
<serverplugin:lifecycle-listener class="org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener">
- <serverplugin:schedule>
+ <serverplugin:schedule concurrent="false">
<serverplugin:period>60000</serverplugin:period>
</serverplugin:schedule>
</serverplugin:lifecycle-listener>
diff --git a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
index 2ee2a5c..88c0022 100644
--- a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
+++ b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
@@ -157,6 +157,20 @@
</xs:element>
</xs:choice>
</xs:sequence>
+ <xs:attribute name="concurrent" type="xs:boolean" use="optional" default="true">
+ <xs:annotation>
+ <xs:documentation>
+ If true, multiple invocations of the scheduled job are allowed to
+ occur at the same time. If false, only one invocation will ever run at any
+ one time. This means that if a schedule triggers again while the previous
+ scheduled invocation is still running, the second invocation will be delayed
+ until after the previous invocation completes. If there is more than one
+ RHQ Server in the system, and this is false, you can be assured that only
+ a single server will handle the invocation at any one time (i.e. multiple servers
+ will not run invocations at the same time).
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
</xs:complexType>
<xs:simpleType name="classNameType">
commit 323bc8eb72d98132c0583fa38c23317c60dec091
Author: Jeff Ortel <jortel(a)redhat.com>
Date: Tue Nov 10 20:54:29 2009 -0600
800 - UI changes to import repos from content providers.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PageControlView.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PageControlView.java
index adf88f8..8d5549f 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PageControlView.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PageControlView.java
@@ -30,26 +30,27 @@ import org.rhq.enterprise.gui.configuration.group.GroupResourceConfigurationHist
import org.rhq.enterprise.gui.configuration.history.ListConfigurationUpdateUIBean;
import org.rhq.enterprise.gui.content.AuditTrailUIBean;
import org.rhq.enterprise.gui.content.AvailableResourceReposUIBean;
-import org.rhq.enterprise.gui.content.RepoAssociationsUIBean;
-import org.rhq.enterprise.gui.content.RepoContentSourcesUIBean;
-import org.rhq.enterprise.gui.content.RepoDisassociationsUIBean;
-import org.rhq.enterprise.gui.content.RepoPackageVersionsUIBean;
-import org.rhq.enterprise.gui.content.RepoResourcesUIBean;
-import org.rhq.enterprise.gui.content.RepoSubscriptionsUIBean;
-import org.rhq.enterprise.gui.content.RepoUnsubscriptionsUIBean;
-import org.rhq.enterprise.gui.content.ContentSourceReposUIBean;
import org.rhq.enterprise.gui.content.ContentSourcePackageVersionsUIBean;
+import org.rhq.enterprise.gui.content.ContentSourceReposUIBean;
import org.rhq.enterprise.gui.content.ContentSourceSyncResultsUIBean;
import org.rhq.enterprise.gui.content.DeployPackagesUIBean;
-import org.rhq.enterprise.gui.content.ListReposUIBean;
import org.rhq.enterprise.gui.content.ListCompletedContentRequestsUIBean;
import org.rhq.enterprise.gui.content.ListContentSourcesUIBean;
import org.rhq.enterprise.gui.content.ListInProgressContentRequestsUIBean;
import org.rhq.enterprise.gui.content.ListPackageHistoryUIBean;
import org.rhq.enterprise.gui.content.ListPackageTypesUIBean;
import org.rhq.enterprise.gui.content.ListPackagesUIBean;
-import org.rhq.enterprise.gui.content.ResourceReposUIBean;
+import org.rhq.enterprise.gui.content.ListReposUIBean;
+import org.rhq.enterprise.gui.content.RepoAssociationsUIBean;
+import org.rhq.enterprise.gui.content.RepoContentSourcesUIBean;
+import org.rhq.enterprise.gui.content.RepoDisassociationsUIBean;
+import org.rhq.enterprise.gui.content.RepoImportUIBean;
+import org.rhq.enterprise.gui.content.RepoPackageVersionsUIBean;
+import org.rhq.enterprise.gui.content.RepoResourcesUIBean;
+import org.rhq.enterprise.gui.content.RepoSubscriptionsUIBean;
+import org.rhq.enterprise.gui.content.RepoUnsubscriptionsUIBean;
import org.rhq.enterprise.gui.content.ResourcePackageVersionsUIBean;
+import org.rhq.enterprise.gui.content.ResourceReposUIBean;
import org.rhq.enterprise.gui.content.ShowContentServiceRequestUIBean;
import org.rhq.enterprise.gui.definition.group.GroupDefinitionUIBean;
import org.rhq.enterprise.gui.definition.group.ListGroupDefinitionsUIBean;
@@ -123,6 +124,8 @@ public enum PageControlView {
/** */
ContentSourcesList(ListContentSourcesUIBean.class),
/** */
+ ReposToImportList(RepoImportUIBean.class),
+ /** */
ReposList(ListReposUIBean.class),
/** */
ContentSourceSyncResultsList(ContentSourceSyncResultsUIBean.class),
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java
index 6ad77c0..b99b18b 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/ListReposUIBean.java
@@ -45,6 +45,10 @@ public class ListReposUIBean extends PagedDataTableUIBean {
return "createNewRepo";
}
+ public String importRepos() {
+ return "importRepos";
+ }
+
public String deleteSelectedRepos() {
Subject subject = EnterpriseFacesContextUtility.getSubject();
String[] selected = getSelectedRepos();
@@ -56,7 +60,8 @@ public class ListReposUIBean extends PagedDataTableUIBean {
repoManager.deleteRepo(subject, id);
}
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Deleted [" + ids.length + "] repositories.");
+ FacesContextUtility
+ .addMessage(FacesMessage.SEVERITY_INFO, "Deleted [" + ids.length + "] repositories.");
} catch (Exception e) {
FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, "Failed to delete repositories.", e);
}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
new file mode 100644
index 0000000..42edf8b
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoImportUIBean.java
@@ -0,0 +1,118 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.content;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.faces.model.DataModel;
+import javax.faces.model.SelectItem;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.common.composite.OptionItem;
+import org.rhq.core.domain.content.ContentSource;
+import org.rhq.core.domain.content.Repo;
+import org.rhq.core.domain.util.PageControl;
+import org.rhq.core.domain.util.PageList;
+import org.rhq.core.gui.util.FacesContextUtility;
+import org.rhq.enterprise.gui.common.converter.SelectItemUtils;
+import org.rhq.enterprise.gui.common.framework.PagedDataTableUIBean;
+import org.rhq.enterprise.gui.common.paging.PageControlView;
+import org.rhq.enterprise.gui.common.paging.PagedListDataModel;
+import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
+import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * @author jortel
+ *
+ */
+public class RepoImportUIBean extends PagedDataTableUIBean {
+
+ public static final String MANAGED_BEAN_NAME = "RepoImportUIBean";
+
+ private int selectedProvider = 10001;
+
+ public RepoImportUIBean() {
+ }
+
+ /**
+ * @return the selectedProvider
+ */
+ public String getSelectedProvider() {
+ return String.valueOf(selectedProvider);
+ }
+
+ /**
+ * @param selectedProvider the selectedProvider to set
+ */
+ public void setSelectedProvider(String selectedProvider) {
+ this.selectedProvider = Integer.valueOf(selectedProvider);
+ }
+
+ /* (non-Javadoc)
+ * @see org.rhq.enterprise.gui.common.framework.PagedDataTableUIBean#getDataModel()
+ */
+ @Override
+ public DataModel getDataModel() {
+ if (dataModel == null) {
+ dataModel = new ImportRepDataModel(PageControlView.ReposToImportList, MANAGED_BEAN_NAME);
+ }
+ return dataModel;
+ }
+
+ public SelectItem[] getProviderOptions() {
+ List<OptionItem<Integer>> list = new ArrayList<OptionItem<Integer>>();
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
+ ContentSourceManagerLocal manager = LookupUtil.getContentSourceManager();
+ PageControl pc = new PageControl();
+ PageList<ContentSource> results = manager.getAllContentSources(subject, pc);
+ for (ContentSource p : results) {
+ OptionItem<Integer> item = new OptionItem<Integer>(p.getId(), p.getName());
+ list.add(item);
+ }
+ return SelectItemUtils.convertFromListOptionItem(list, false);
+ }
+
+ public String[] getSelectedRepos() {
+ return FacesContextUtility.getRequest().getParameterValues("selectedRepos");
+ }
+
+ public String importSelected() {
+ String[] selected = getSelectedRepos();
+ // TODO: Actually import the repos using a manager bean.
+ return "success";
+ }
+
+ private class ImportRepDataModel extends PagedListDataModel<Repo> {
+ public ImportRepDataModel(PageControlView view, String beanName) {
+ super(view, beanName);
+ }
+
+ @Override
+ public PageList<Repo> fetchPage(PageControl pc) {
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
+ ContentSourceManagerLocal manager = LookupUtil.getContentSourceManager();
+ // TODO: Replace with call to get 'candidate' repos for provider.
+ PageList<Repo> results = manager.getAssociatedRepos(subject, selectedProvider, pc);
+ return results;
+ }
+ }
+}
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/content-beans.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/content-beans.xml
index 6f7b7d3..8d58c87 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/content-beans.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/content-beans.xml
@@ -90,6 +90,13 @@
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
+ <!-- /rhq/content/importRepos.xhtml -->
+ <managed-bean>
+ <managed-bean-name>RepoImportUIBean</managed-bean-name>
+ <managed-bean-class>org.rhq.enterprise.gui.content.RepoImportUIBean</managed-bean-class>
+ <managed-bean-scope>request</managed-bean-scope>
+ </managed-bean>
+
<!-- /rhq/content/createContentProvider.xhtml -->
<managed-bean>
<managed-bean-name>CreateContentSourceUIBean</managed-bean-name>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml
new file mode 100644
index 0000000..bcc0c8c
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/importRepos.xhtml
@@ -0,0 +1,122 @@
+<?xml version="1.0"?>
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jstl/core"
+ xmlns:onc="http://jboss.org/on/component"
+ xmlns:onf="http://jboss.org/on/function"
+ xmlns:a4j="http://richfaces.org/a4j"
+ xmlns:rich="http://richfaces.ajax4jsf.org/rich">
+<ui:composition template="/rhq/layout/main.xhtml">
+ <ui:param name="id" value="${param.id}" />
+ <ui:param name="pageTitle" value="Import Repositories"/>
+ <ui:define name="breadcrumbs">
+ <h:outputLink value="listRepos.xhtml">
+ ${msg["repo.list.breadcrumb"]}
+ </h:outputLink>
+ >
+ <h:outputLink value="importRepos.xhtml">
+ Import From Content Provider
+ </h:outputLink>
+ </ui:define>
+ <ui:define name="body">
+ <h:messages showSummary="true"
+ showDetail="true"
+ infoClass="InfoBlock"
+ warnClass="WarnBlock"
+ errorClass="ErrorBlock"
+ fatalClass="FatalBlock"
+ globalOnly="true"
+ layout="table"
+ width="100%"/>
+ <h:form id="importRepoForm">
+ <input type="hidden" name="id" value="${param.id}"/>
+ <!-- CONTENT PROVIDERS -->
+ <rich:panel>
+ <f:facet name="header">
+ <h:outputText value="Content Providers"/>
+ </f:facet>
+ <h:panelGrid columns="1" width="100%">
+ <h:selectOneRadio
+ id="providers"
+ value="#{RepoImportUIBean.selectedProvider}"
+ layout="pageDirection">
+ <f:selectItems value="#{RepoImportUIBean.providerOptions}"/>
+ <a4j:support event="onchange" reRender="repoTable"/>
+ </h:selectOneRadio>
+ </h:panelGrid>
+ </rich:panel>
+ <!-- REPOS -->
+ <rich:panel>
+ <f:facet name="header">
+ <h:outputText value="Available Repositories"/>
+ </f:facet>
+ <h:panelGrid columns="1" width="100%">
+ <ui:param name="repoModel" value="#{RepoImportUIBean.dataModel}"/>
+ <rich:dataTable id="repoTable"
+ rows="#{PageControl.ReposToImportList.pageSize}"
+ value="#{repoModel}"
+ var="item"
+ width="100%"
+ columnsWidth="1%, 99%"
+ headerClass="tableRowHeader"
+ footerClass="on-pager-footer"
+ onRowMouseOver="this.style.backgroundColor='#E7E7E7'"
+ onRowMouseOut="this.style.backgroundColor='#{a4jSkin.tableBackgroundColor}'">
+ <f:facet name="PageControlView">
+ <onc:paginationControl id="ReposToImportList" />
+ </f:facet>
+ <rich:column>
+ <f:facet name="header">
+ <onc:allSelect target="selectedRepos" />
+ </f:facet>
+ <onc:select rendered="#{RepoImportUIBean.selectedRepos[item.id] eq null}"
+ name="selectedRepos"
+ value="#{item.id}" />
+ </rich:column>
+ <rich:column rendered="#{param.debug}">
+ <f:facet name="header">
+ <onc:sortableColumnHeader sort="cs.id">
+ <h:outputText styleClass="headerText" value="ID" />
+ </onc:sortableColumnHeader>
+ </f:facet>
+ <h:outputText value="#{item.id}"/>
+ </rich:column>
+ <rich:column>
+ <f:facet name="header">
+ <onc:sortableColumnHeader sort="cs.name">
+ <h:outputText styleClass="headerText" value="Name" />
+ </onc:sortableColumnHeader>
+ </f:facet>
+ <h:outputLink value="repo.xhtml">
+ <f:param name="mode" value="view"/>
+ <f:param name="id" value="#{item.id}"/>
+ <h:outputText value="#{item.name}" />
+ </h:outputLink>
+ </rich:column>
+ <f:facet name="footer">
+ <rich:columnGroup>
+ <!-- colspan 6:5 for the debug 'id' column -->
+ <rich:column colspan="#{param.debug ? 6 : 5}" width="100%">
+ <onc:selectCommandButton action="#{RepoImportUIBean.importSelected}"
+ value="IMPORT SELECTED"
+ target="selectedReposa"
+ styleClass="on-pager-button buttonsmall"/>
+ <ui:param name="paginationDataTableName" value="repoTable"/>
+ <ui:param name="paginationDataModel" value="#{repoModel}"/>
+ <ui:param name="paginationPageControl" value="#{PageControl.ReposToImportList}"/>
+ <ui:include src="../resource/include/pagination.xhtml"/>
+ </rich:column>
+ </rich:columnGroup>
+ </f:facet>
+ </rich:dataTable>
+ </h:panelGrid>
+ </rich:panel>
+ </h:form>
+ </ui:define>
+</ui:composition>
+</html>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/listRepos.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/listRepos.xhtml
index 8e6475d..67f91db 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/listRepos.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/listRepos.xhtml
@@ -136,6 +136,11 @@
<f:param name="mode" value="new"/>
</h:commandButton>
+ <h:commandButton action="#{ListReposUIBean.importRepos}"
+ value="IMPORT" styleClass="on-pager-button buttonsmall">
+ <f:param name="mode" value="new"/>
+ </h:commandButton>
+
<onc:selectCommandButton action="#{ListReposUIBean.deleteSelectedRepos}"
value="DELETE SELECTED" target="selectedRepos" styleClass="on-pager-button buttonsmall"/>
commit 852806cc802e35b3ff9a61e92a13b5b1bd80c93e
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 10 20:36:34 2009 -0500
maven is barfing due to a java.net repo hosting change.
this sets the hostname to the new server name
diff --git a/modules/enterprise/server/container/pom.xml b/modules/enterprise/server/container/pom.xml
index 7eb6635..a56e6fe 100644
--- a/modules/enterprise/server/container/pom.xml
+++ b/modules/enterprise/server/container/pom.xml
@@ -278,7 +278,7 @@
<repository>
<id>java.net-m1-releases</id>
<name>Java.net Maven1 Repository</name>
- <url>https://maven-repository.dev.java.net/repository/</url>
+ <url>http://download.java.net/maven/1/</url>
<layout>legacy</layout>
</repository>
commit 1f373dfdcda1f21779ad28a4b479cb360ec9000c
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 10 18:44:52 2009 -0500
somehow the db upgrade script got reformatted - things aren't lined up
and some lines wrapped poorly. this fixes most of it, most of this is
just whitespace changes
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 1737386..e317d58 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -1,12 +1,10 @@
-
<project name="db-upgrade" default="upgrade" basedir=".">
- <!--
+<!--
This target upgrades a database schema. The parameters that it accepts are: jdbc.url = the jdbc url of the database
to upgrade jdbc.user = the user to connect to the database as jdbc.password = the database user's password
target.schema.version = the schema version to upgrade to. If this is omitted then the schema is upgraded to the
latest version. This target assumes that the taskdefs for the dbupgrade ant task have already been defined.
-
-->
<target name="upgrade">
@@ -16,10 +14,16 @@
JDBC URL: ${jdbc.url}
JDBC User: ${jdbc.user}
Update Version: ${target.schema.version}
-</echo>
+ </echo>
- <dbupgrade jdbcUrl="${jdbc.url}" jdbcUser="${jdbc.user}" jdbcPassword="${jdbc.password}" valueColumn="PROPERTY_VALUE"
- table="RHQ_SYSTEM_CONFIG" keyColumn="PROPERTY_KEY" keyMatch="DB_SCHEMA_VERSION" targetSchemaVersion="${target.schema.version}">
+ <dbupgrade jdbcUrl="${jdbc.url}"
+ jdbcUser="${jdbc.user}"
+ jdbcPassword="${jdbc.password}"
+ valueColumn="PROPERTY_VALUE"
+ table="RHQ_SYSTEM_CONFIG"
+ keyColumn="PROPERTY_KEY"
+ keyMatch="DB_SCHEMA_VERSION"
+ targetSchemaVersion="${target.schema.version}">
<schemaSpec version="2.0">
<!-- Empty initial schema to avoid install failure on default latest schema version -->
@@ -27,12 +31,9 @@
<schemaSpec version="2.1">
<!--
- Keep the columnType VARCHAR2, but increase size; (see note for RHQ_ALERT_CONDITION table in alert-schema.xml
- for more info)
-
+ Keep the columnType VARCHAR2, but increase size; (see note for RHQ_ALERT_CONDITION table in alert-schema.xml for more info)
-->
- <schema-alterColumn table="RHQ_ALERT_CONDITION" column="OPTION_STATUS" columnType="VARCHAR2"
- precision="256" />
+ <schema-alterColumn table="RHQ_ALERT_CONDITION" column="OPTION_STATUS" columnType="VARCHAR2" precision="256" />
</schemaSpec>
<schemaSpec version="2.2">
@@ -42,8 +43,7 @@
<schemaSpec version="2.3">
<!-- RHQ-666 - Don't require resource name at creation time -->
- <schema-alterColumn table="RHQ_CREATE_RES_HIST" column="CREATED_RESOURCE_NAME" columnType="VARCHAR2"
- precision="500" />
+ <schema-alterColumn table="RHQ_CREATE_RES_HIST" column="CREATED_RESOURCE_NAME" columnType="VARCHAR2" precision="500" />
</schemaSpec>
<!-- RHQ-669 - Add metadata to package type to indicate architecture support -->
@@ -51,18 +51,15 @@
<schema-addColumn table="RHQ_PACKAGE_TYPE" column="SUPPORTS_ARCHITECTURE" columnType="BOOLEAN" />
<schema-directSQL>
- <statement targetDBVendor="postgresql"
- desc="Updating existing package types with default for SUPPORTS_ARCHITECTURE flag">
+ <statement targetDBVendor="postgresql" desc="Updating existing package types with default for SUPPORTS_ARCHITECTURE flag">
UPDATE RHQ_PACKAGE_TYPE SET SUPPORTS_ARCHITECTURE = FALSE
</statement>
- <statement targetDBVendor="oracle"
- desc="Updating existing package types with default for SUPPORTS_ARCHITECTURE flag">
+ <statement targetDBVendor="oracle" desc="Updating existing package types with default for SUPPORTS_ARCHITECTURE flag">
UPDATE RHQ_PACKAGE_TYPE SET SUPPORTS_ARCHITECTURE = 0
</statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_PACKAGE_TYPE" column="SUPPORTS_ARCHITECTURE" nullable="FALSE" />
-
</schemaSpec>
<!-- RHQ-176 - Add notes column to content requests -->
@@ -77,14 +74,14 @@
<schema-directSQL>
<statement desc="Creating table RHQ_AFFINITY_GROUP">
CREATE TABLE RHQ_AFFINITY_GROUP ( ID INTEGER )
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_AFFINITY_GROUP" column="ID" nullable="FALSE" />
<schema-createSequence name="RHQ_AFFINITY_GROUP_ID_SEQ" initial="10001" />
<schema-directSQL>
<statement desc="Creating primary key for RHQ_AFFINITY_GROUP">
ALTER TABLE RHQ_AFFINITY_GROUP ADD PRIMARY KEY ( ID )
- </statement>
+ </statement>
</schema-directSQL>
<schema-addColumn table="RHQ_AFFINITY_GROUP" column="NAME" columnType="VARCHAR2" precision="255" />
<schema-alterColumn table="RHQ_AFFINITY_GROUP" column="NAME" nullable="FALSE" />
@@ -93,14 +90,14 @@
<schema-directSQL>
<statement desc="Creating table RHQ_SERVER">
CREATE TABLE RHQ_SERVER ( ID INTEGER )
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_SERVER" column="ID" nullable="FALSE" />
<schema-createSequence name="RHQ_SERVER_ID_SEQ" initial="10001" />
<schema-directSQL>
<statement desc="Creating primary key for RHQ_SERVER">
ALTER TABLE RHQ_SERVER ADD PRIMARY KEY ( ID )
- </statement>
+ </statement>
</schema-directSQL>
<schema-addColumn table="RHQ_SERVER" column="NAME" columnType="VARCHAR2" precision="255" />
<schema-alterColumn table="RHQ_SERVER" column="NAME" nullable="FALSE" />
@@ -119,7 +116,7 @@
ADD CONSTRAINT RHQ_SERVER_AG_ID_FK
FOREIGN KEY (AFFINITY_GROUP_ID)
REFERENCES RHQ_AFFINITY_GROUP (ID)
- </statement>
+ </statement>
</schema-directSQL>
<!-- RHQ_AGENT modifications -->
@@ -130,7 +127,7 @@
ADD CONSTRAINT RHQ_AGENT_AG_ID_FK
FOREIGN KEY (AFFINITY_GROUP_ID)
REFERENCES RHQ_AFFINITY_GROUP (ID)
- </statement>
+ </statement>
</schema-directSQL>
<schema-addColumn table="RHQ_AGENT" column="SERVER_ID" columnType="INTEGER" />
<schema-directSQL>
@@ -139,27 +136,25 @@
ADD CONSTRAINT RHQ_AGENT_SERVER_ID_FK
FOREIGN KEY (SERVER_ID)
REFERENCES RHQ_SERVER (ID)
- </statement>
+ </statement>
</schema-directSQL>
<!-- RHQ_PARTITION_EVENT -->
<schema-directSQL>
<statement desc="Creating table RHQ_PARTITION_EVENT">
CREATE TABLE RHQ_PARTITION_EVENT ( ID INTEGER )
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_PARTITION_EVENT" column="ID" nullable="FALSE" />
<schema-createSequence name="RHQ_PARTITION_EVENT_ID_SEQ" initial="10001" />
<schema-directSQL>
<statement desc="Creating primary key for RHQ_PARTITION_EVENT">
ALTER TABLE RHQ_PARTITION_EVENT ADD PRIMARY KEY ( ID )
- </statement>
+ </statement>
</schema-directSQL>
- <schema-addColumn table="RHQ_PARTITION_EVENT" column="SUBJECT_NAME" columnType="VARCHAR2"
- precision="255" />
+ <schema-addColumn table="RHQ_PARTITION_EVENT" column="SUBJECT_NAME" columnType="VARCHAR2" precision="255" />
<schema-alterColumn table="RHQ_PARTITION_EVENT" column="SUBJECT_NAME" nullable="FALSE" />
- <schema-addColumn table="RHQ_PARTITION_EVENT" column="EVENT_TYPE" columnType="VARCHAR2"
- precision="50" />
+ <schema-addColumn table="RHQ_PARTITION_EVENT" column="EVENT_TYPE" columnType="VARCHAR2" precision="50" />
<schema-alterColumn table="RHQ_PARTITION_EVENT" column="EVENT_TYPE" nullable="FALSE" />
<schema-addColumn table="RHQ_PARTITION_EVENT" column="CTIME" columnType="LONG" />
<schema-alterColumn table="RHQ_PARTITION_EVENT" column="CTIME" nullable="FALSE" />
@@ -168,14 +163,14 @@
<schema-directSQL>
<statement desc="Creating table RHQ_PARTITION_DETAILS">
CREATE TABLE RHQ_PARTITION_DETAILS ( ID INTEGER )
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_PARTITION_DETAILS" column="ID" nullable="FALSE" />
<schema-createSequence name="RHQ_PARTITION_DETAILS_ID_SEQ" initial="10001" />
<schema-directSQL>
<statement desc="Creating primary key for RHQ_PARTITION_DETAILS">
ALTER TABLE RHQ_PARTITION_DETAILS ADD PRIMARY KEY ( ID )
- </statement>
+ </statement>
</schema-directSQL>
<schema-addColumn table="RHQ_PARTITION_DETAILS" column="PARTITION_EVENT_ID" columnType="INTEGER" />
<schema-alterColumn table="RHQ_PARTITION_DETAILS" column="PARTITION_EVENT_ID" nullable="FALSE" />
@@ -185,7 +180,7 @@
ADD CONSTRAINT RHQ_PD_EVENT_ID_FK
FOREIGN KEY (PARTITION_EVENT_ID)
REFERENCES RHQ_PARTITION_EVENT (ID)
- </statement>
+ </statement>
</schema-directSQL>
<schema-addColumn table="RHQ_PARTITION_DETAILS" column="AGENT_ID" columnType="INTEGER" />
<schema-alterColumn table="RHQ_PARTITION_DETAILS" column="AGENT_ID" nullable="FALSE" />
@@ -195,7 +190,7 @@
ADD CONSTRAINT RHQ_PD_AGENT_ID_FK
FOREIGN KEY (AGENT_ID)
REFERENCES RHQ_AGENT (ID)
- </statement>
+ </statement>
</schema-directSQL>
<schema-addColumn table="RHQ_PARTITION_DETAILS" column="SERVER_ID" columnType="INTEGER" />
<schema-alterColumn table="RHQ_PARTITION_DETAILS" column="SERVER_ID" nullable="FALSE" />
@@ -205,21 +200,21 @@
ADD CONSTRAINT RHQ_PD_SERVER_ID_FK
FOREIGN KEY (SERVER_ID)
REFERENCES RHQ_SERVER (ID)
- </statement>
+ </statement>
</schema-directSQL>
<!-- RHQ_FAILOVER_LIST -->
<schema-directSQL>
<statement desc="Creating table RHQ_FAILOVER_LIST">
CREATE TABLE RHQ_FAILOVER_LIST ( ID INTEGER )
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_FAILOVER_LIST" column="ID" nullable="FALSE" />
<schema-createSequence name="RHQ_FAILOVER_LIST_ID_SEQ" initial="10001" />
<schema-directSQL>
<statement desc="Creating primary key for RHQ_FAILOVER_LIST">
ALTER TABLE RHQ_FAILOVER_LIST ADD PRIMARY KEY ( ID )
- </statement>
+ </statement>
</schema-directSQL>
<schema-addColumn table="RHQ_FAILOVER_LIST" column="PARTITION_EVENT_ID" columnType="INTEGER" />
<schema-alterColumn table="RHQ_FAILOVER_LIST" column="PARTITION_EVENT_ID" nullable="FALSE" />
@@ -229,7 +224,7 @@
ADD CONSTRAINT RHQ_FL_EVENT_ID_FK
FOREIGN KEY (PARTITION_EVENT_ID)
REFERENCES RHQ_PARTITION_EVENT (ID)
- </statement>
+ </statement>
</schema-directSQL>
<schema-addColumn table="RHQ_FAILOVER_LIST" column="AGENT_ID" columnType="INTEGER" />
<schema-alterColumn table="RHQ_FAILOVER_LIST" column="AGENT_ID" nullable="FALSE" />
@@ -239,7 +234,7 @@
ADD CONSTRAINT RHQ_FL_AGENT_ID_FK
FOREIGN KEY (AGENT_ID)
REFERENCES RHQ_AGENT (ID)
- </statement>
+ </statement>
</schema-directSQL>
<schema-addColumn table="RHQ_FAILOVER_LIST" column="CTIME" columnType="LONG" />
<schema-alterColumn table="RHQ_FAILOVER_LIST" column="CTIME" nullable="FALSE" />
@@ -248,14 +243,14 @@
<schema-directSQL>
<statement desc="Creating table RHQ_FAILOVER_DETAILS">
CREATE TABLE RHQ_FAILOVER_DETAILS ( ID INTEGER )
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_FAILOVER_DETAILS" column="ID" nullable="FALSE" />
<schema-createSequence name="RHQ_FAILOVER_DETAILS_ID_SEQ" initial="10001" />
<schema-directSQL>
<statement desc="Creating primary key for RHQ_FAILOVER_DETAILS">
ALTER TABLE RHQ_FAILOVER_DETAILS ADD PRIMARY KEY ( ID )
- </statement>
+ </statement>
</schema-directSQL>
<schema-addColumn table="RHQ_FAILOVER_DETAILS" column="FAILOVER_LIST_ID" columnType="INTEGER" />
<schema-alterColumn table="RHQ_FAILOVER_DETAILS" column="FAILOVER_LIST_ID" nullable="FALSE" />
@@ -265,7 +260,7 @@
ADD CONSTRAINT RHQ_FD_FAILOVER_LIST_ID_FK
FOREIGN KEY (FAILOVER_LIST_ID)
REFERENCES RHQ_FAILOVER_LIST (ID)
- </statement>
+ </statement>
</schema-directSQL>
<schema-addColumn table="RHQ_FAILOVER_DETAILS" column="SERVER_ID" columnType="INTEGER" />
<schema-alterColumn table="RHQ_FAILOVER_DETAILS" column="SERVER_ID" nullable="FALSE" />
@@ -275,7 +270,7 @@
ADD CONSTRAINT RHQ_FD_SERVER_ID_FK
FOREIGN KEY (SERVER_ID)
REFERENCES RHQ_SERVER (ID)
- </statement>
+ </statement>
</schema-directSQL>
<schema-addColumn table="RHQ_FAILOVER_DETAILS" column="CTIME" columnType="LONG" />
<schema-alterColumn table="RHQ_FAILOVER_DETAILS" column="CTIME" nullable="FALSE" />
@@ -287,7 +282,7 @@
<schema-directSQL>
<statement desc="Updating existing agents with default STATUS flag">
UPDATE RHQ_AGENT SET STATUS = 0
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_AGENT" column="STATUS" default="0" />
</schemaSpec>
@@ -297,14 +292,14 @@
<schema-directSQL>
<statement desc="Updating existing servers with default OPERATION_MODE flag">
UPDATE RHQ_SERVER SET OPERATION_MODE = 'NORMAL'
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_SERVER" column="OPERATION_MODE" nullable="FALSE" />
<schema-directSQL>
<statement desc="Creating RHQ_SERVER unique constraint on NAME">
CREATE UNIQUE INDEX rhq_server_name_unique ON rhq_server (name)
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -328,7 +323,7 @@
<schema-directSQL>
<statement desc="Updating existing servers with default BIND_PORT=7080">
UPDATE RHQ_SERVER SET BIND_PORT = 7080
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_SERVER" column="BIND_PORT" nullable="FALSE" />
@@ -336,7 +331,7 @@
<schema-directSQL>
<statement desc="Updating existing servers with default TRANSPORT=servlet">
UPDATE RHQ_SERVER SET TRANSPORT = 'servlet'
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_SERVER" column="TRANSPORT" nullable="FALSE" />
@@ -353,7 +348,7 @@
<schema-directSQL>
<statement desc="Updating existing servers with default COMPUTE_POWER=1">
UPDATE RHQ_SERVER SET COMPUTE_POWER = 1
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_SERVER" column="COMPUTE_POWER" nullable="FALSE" />
@@ -368,14 +363,14 @@
<schema-directSQL>
<statement desc="Updating existing servers with default PORT=7080">
UPDATE RHQ_SERVER SET PORT = 7080
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_SERVER" column="PORT" nullable="FALSE" />
<schema-addColumn table="RHQ_SERVER" column="SECURE_PORT" columnType="INTEGER" />
<schema-directSQL>
<statement desc="Updating existing servers with default SECURE_PORT=7443">
UPDATE RHQ_SERVER SET SECURE_PORT = 7443
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_SERVER" column="SECURE_PORT" nullable="FALSE" />
</schemaSpec>
@@ -406,48 +401,45 @@
</schemaSpec>
<schemaSpec version="2.15">
- <schema-addColumn table="RHQ_PARTITION_EVENT" column="EXECUTION_STATUS" columnType="VARCHAR2"
- precision="32" />
+ <schema-addColumn table="RHQ_PARTITION_EVENT" column="EXECUTION_STATUS" columnType="VARCHAR2" precision="32" />
<schema-directSQL>
<statement desc="Updating existing partition events with default EXECUTION_STATUS=COMPLETED">
UPDATE RHQ_PARTITION_EVENT SET EXECUTION_STATUS = 'COMPLETED'
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_PARTITION_EVENT" column="EXECUTION_STATUS" nullable="FALSE" />
</schemaSpec>
<schemaSpec version="2.16">
- <schema-addColumn table="RHQ_PARTITION_DETAILS" column="AGENT_NAME" columnType="VARCHAR2"
- precision="255" />
- <schema-addColumn table="RHQ_PARTITION_DETAILS" column="SERVER_NAME" columnType="VARCHAR2"
- precision="255" />
+ <schema-addColumn table="RHQ_PARTITION_DETAILS" column="AGENT_NAME" columnType="VARCHAR2" precision="255" />
+ <schema-addColumn table="RHQ_PARTITION_DETAILS" column="SERVER_NAME" columnType="VARCHAR2" precision="255" />
<schema-directSQL>
<statement desc="Updating existing partition events details with default AGENT_NAME">
UPDATE RHQ_PARTITION_DETAILS SET AGENT_NAME = 'UNKNOWN'
- </statement>
+ </statement>
</schema-directSQL>
<schema-directSQL>
<statement desc="Updating existing partition events details with known agents">
UPDATE RHQ_PARTITION_DETAILS
SET AGENT_NAME = ( SELECT RHQ_AGENT.NAME
- FROM RHQ_AGENT
- WHERE RHQ_AGENT.ID = RHQ_PARTITION_DETAILS.AGENT_ID )
- </statement>
+ FROM RHQ_AGENT
+ WHERE RHQ_AGENT.ID = RHQ_PARTITION_DETAILS.AGENT_ID )
+ </statement>
</schema-directSQL>
<schema-directSQL>
<statement desc="Updating existing partition events details with default SERVER_NAME">
UPDATE RHQ_PARTITION_DETAILS SET SERVER_NAME = 'UNKNOWN'
- </statement>
+ </statement>
</schema-directSQL>
<schema-directSQL>
<statement desc="Updating existing partition events details with known servers">
UPDATE RHQ_PARTITION_DETAILS
SET SERVER_NAME = ( SELECT RHQ_SERVER.NAME
- FROM RHQ_SERVER
- WHERE RHQ_SERVER.ID = RHQ_PARTITION_DETAILS.SERVER_ID )
- </statement>
+ FROM RHQ_SERVER
+ WHERE RHQ_SERVER.ID = RHQ_PARTITION_DETAILS.SERVER_ID )
+ </statement>
</schema-directSQL>
<schema-deleteColumn table="RHQ_PARTITION_DETAILS" column="AGENT_ID" />
@@ -490,14 +482,13 @@
</schemaSpec>
<schemaSpec version="2.18">
- <schema-addColumn table="RHQ_PARTITION_EVENT" column="EVENT_DETAIL" columnType="VARCHAR2"
- precision="512" />
+ <schema-addColumn table="RHQ_PARTITION_EVENT" column="EVENT_DETAIL" columnType="VARCHAR2" precision="512" />
<schema-addColumn table="RHQ_SERVER" column="MTIME" columnType="LONG" />
<schema-directSQL>
<statement desc="Updating existing servers with default MTIME=CTIME">
UPDATE RHQ_SERVER SET MTIME = CTIME
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_SERVER" column="MTIME" nullable="FALSE" />
</schemaSpec>
@@ -510,7 +501,7 @@
SET LAST_AVAILABILITY_REPORT_LONG =
EXTRACT ( EPOCH FROM LAST_AVAILABILITY_REPORT )
WHERE LAST_AVAILABILITY_REPORT IS NOT NULL
- </statement>
+ </statement>
<statement targetDBVendor="oracle" desc="Converting RHQ_AGENT.LAST_AVAILABILITY_REPORT timestamp to long">
UPDATE RHQ_AGENT
SET LAST_AVAILABILITY_REPORT_LONG = 1000 *
@@ -523,7 +514,7 @@
)
WHERE
LAST_AVAILABILITY_REPORT IS NOT NULL
- </statement>
+ </statement>
</schema-directSQL>
<schema-deleteColumn table="RHQ_AGENT" column="LAST_AVAILABILITY_REPORT" />
<schema-directSQL>
@@ -532,7 +523,7 @@
RENAME COLUMN LAST_AVAILABILITY_REPORT_LONG
TO
LAST_AVAILABILITY_REPORT
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -544,7 +535,7 @@
SET EVENT_TIMESTAMP_LONG =
EXTRACT ( EPOCH FROM EVENT_TIMESTAMP )
WHERE EVENT_TIMESTAMP IS NOT NULL
- </statement>
+ </statement>
<statement targetDBVendor="oracle" desc="Converting RHQ_ALERT_DAMPEN_EVENT.EVENT_TIMESTAMP timestamp to long">
UPDATE RHQ_ALERT_DAMPEN_EVENT
SET EVENT_TIMESTAMP_LONG = 1000
@@ -556,7 +547,7 @@
)
WHERE
EVENT_TIMESTAMP IS NOT NULL
- </statement>
+ </statement>
</schema-directSQL>
<schema-deleteColumn table="RHQ_ALERT_DAMPEN_EVENT" column="EVENT_TIMESTAMP" />
<schema-directSQL>
@@ -565,7 +556,7 @@
RENAME COLUMN EVENT_TIMESTAMP_LONG
TO
EVENT_TIMESTAMP
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -575,16 +566,14 @@
<schema-directSQL>
<statement targetDBVendor="postgresql" desc="Converting RHQ_EVENT.TIMESTAMP timestamp to long">
UPDATE RHQ_EVENT
- SET TIMESTAMP_LONG = EXTRACT ( EPOCH
- FROM TIMESTAMP )
+ SET TIMESTAMP_LONG = EXTRACT ( EPOCH FROM TIMESTAMP )
WHERE TIMESTAMP IS NOT NULL
- </statement>
+ </statement>
<statement targetDBVendor="postgresql" desc="Converting RHQ_EVENT.ACK_TIME timestamp to long">
UPDATE RHQ_EVENT
- SET ACK_TIME_LONG = EXTRACT ( EPOCH FROM
- ACK_TIME )
+ SET ACK_TIME_LONG = EXTRACT ( EPOCH FROM ACK_TIME )
WHERE ACK_TIME IS NOT NULL
- </statement>
+ </statement>
<statement targetDBVendor="oracle" desc="Converting RHQ_EVENT.TIMESTAMP timestamp to long">
UPDATE RHQ_EVENT
SET TIMESTAMP_LONG = 1000 *
@@ -615,12 +604,12 @@
ALTER TABLE RHQ_EVENT
RENAME COLUMN TIMESTAMP_LONG
TO TIMESTAMP
- </statement>
+ </statement>
<statement desc="Renaming new RHQ_EVENT.ACK_TIME column to match old schema expectations">
ALTER TABLE RHQ_EVENT
RENAME COLUMN ACK_TIME_LONG
TO ACK_TIME
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -634,13 +623,13 @@
SET CREATION_TIME_LONG =
EXTRACT ( EPOCH FROM CREATION_TIME )
WHERE CREATION_TIME IS NOT NULL
- </statement>
+ </statement>
<statement targetDBVendor="postgresql" desc="Converting RHQ_CONTENT_SOURCE.LAST_MODIFIED_TIME timestamp to long">
UPDATE RHQ_CONTENT_SOURCE
SET LAST_MODIFIED_TIME_LONG =
EXTRACT ( EPOCH FROM LAST_MODIFIED_TIME )
WHERE LAST_MODIFIED_TIME IS NOT NULL
- </statement>
+ </statement>
<statement targetDBVendor="oracle" desc="Converting RHQ_CONTENT_SOURCE.CREATION_TIME timestamp to long">
UPDATE RHQ_CONTENT_SOURCE
SET CREATION_TIME_LONG = 1000 *
@@ -652,7 +641,7 @@
)
WHERE
CREATION_TIME IS NOT NULL
- </statement>
+ </statement>
<statement targetDBVendor="oracle" desc="Converting RHQ_CONTENT_SOURCE.LAST_MODIFIED_TIME timestamp to long">
UPDATE RHQ_CONTENT_SOURCE
SET LAST_MODIFIED_TIME_LONG = 1000
@@ -664,7 +653,7 @@
)
WHERE
LAST_MODIFIED_TIME IS NOT NULL
- </statement>
+ </statement>
</schema-directSQL>
<schema-deleteColumn table="RHQ_CONTENT_SOURCE" column="CREATION_TIME" />
<schema-deleteColumn table="RHQ_CONTENT_SOURCE" column="LAST_MODIFIED_TIME" />
@@ -679,7 +668,7 @@
RENAME COLUMN LAST_MODIFIED_TIME_LONG
TO
LAST_MODIFIED_TIME
- </statement>
+ </statement>
</schema-directSQL>
<!-- RHQ_CHANNEL timestamp to long conversion -->
@@ -688,16 +677,15 @@
<schema-directSQL>
<statement targetDBVendor="postgresql" desc="Converting RHQ_CHANNEL.CREATION_TIME timestamp to long">
UPDATE RHQ_CHANNEL
- SET CREATION_TIME_LONG = EXTRACT (
- EPOCH FROM CREATION_TIME )
+ SET CREATION_TIME_LONG = EXTRACT ( EPOCH FROM CREATION_TIME )
WHERE CREATION_TIME IS NOT NULL
- </statement>
+ </statement>
<statement targetDBVendor="postgresql" desc="Converting RHQ_CHANNEL.LAST_MODIFIED_TIME timestamp to long">
UPDATE RHQ_CHANNEL
SET LAST_MODIFIED_TIME_LONG = EXTRACT
( EPOCH FROM LAST_MODIFIED_TIME )
WHERE LAST_MODIFIED_TIME IS NOT NULL
- </statement>
+ </statement>
<statement targetDBVendor="oracle" desc="Converting RHQ_CHANNEL.CREATION_TIME timestamp to long">
UPDATE RHQ_CHANNEL
SET CREATION_TIME_LONG = 1000 *
@@ -709,7 +697,7 @@
)
WHERE
CREATION_TIME IS NOT NULL
- </statement>
+ </statement>
<statement targetDBVendor="oracle" desc="Converting RHQ_CHANNEL.LAST_MODIFIED_TIME timestamp to long">
UPDATE RHQ_CHANNEL
SET LAST_MODIFIED_TIME_LONG = 1000 *
@@ -721,7 +709,7 @@
)
WHERE
LAST_MODIFIED_TIME IS NOT NULL
- </statement>
+ </statement>
</schema-directSQL>
<schema-deleteColumn table="RHQ_CHANNEL" column="CREATION_TIME" />
<schema-deleteColumn table="RHQ_CHANNEL" column="LAST_MODIFIED_TIME" />
@@ -730,7 +718,7 @@
ALTER TABLE RHQ_CHANNEL
RENAME COLUMN CREATION_TIME_LONG
TO CREATION_TIME
- </statement>
+ </statement>
<statement desc="Renaming new RHQ_CHANNEL.LAST_MODIFIED_TIME column to match old schema expectations">
ALTER TABLE RHQ_CHANNEL
RENAME COLUMN LAST_MODIFIED_TIME_LONG
@@ -746,7 +734,7 @@
SET FILE_CREATION_TIME_LONG =
EXTRACT ( EPOCH FROM FILE_CREATION_TIME )
WHERE FILE_CREATION_TIME IS NOT NULL
- </statement>
+ </statement>
<statement targetDBVendor="oracle" desc="Converting RHQ_PACKAGE_VERSION.FILE_CREATION_TIME timestamp to long">
UPDATE RHQ_PACKAGE_VERSION
SET FILE_CREATION_TIME_LONG = 1000
@@ -767,7 +755,7 @@
RENAME COLUMN FILE_CREATION_TIME_LONG
TO
FILE_CREATION_TIME
- </statement>
+ </statement>
</schema-directSQL>
<!-- RHQ_INSTALLED_PACKAGE timestamp to long conversion -->
@@ -775,10 +763,9 @@
<schema-directSQL>
<statement targetDBVendor="postgresql" desc="Converting RHQ_INSTALLED_PACKAGE.INSTALLATION_TIME timestamp to long">
UPDATE RHQ_INSTALLED_PACKAGE
- SET INSTALLATION_TIME_LONG =
- EXTRACT ( EPOCH FROM INSTALLATION_TIME )
+ SET INSTALLATION_TIME_LONG = EXTRACT ( EPOCH FROM INSTALLATION_TIME )
WHERE INSTALLATION_TIME IS NOT NULL
- </statement>
+ </statement>
<statement targetDBVendor="oracle" desc="Converting RHQ_INSTALLED_PACKAGE.INSTALLATION_TIME timestamp to long">
UPDATE RHQ_INSTALLED_PACKAGE
SET INSTALLATION_TIME_LONG =
@@ -791,7 +778,7 @@
)
WHERE INSTALLATION_TIME IS
NOT NULL
- </statement>
+ </statement>
</schema-directSQL>
<schema-deleteColumn table="RHQ_INSTALLED_PACKAGE" column="INSTALLATION_TIME" />
<schema-directSQL>
@@ -800,7 +787,7 @@
RENAME COLUMN INSTALLATION_TIME_LONG
TO
INSTALLATION_TIME
- </statement>
+ </statement>
</schema-directSQL>
<!-- RHQ_INSTALLED_PKG_HIST timestamp to long conversion -->
@@ -808,10 +795,9 @@
<schema-directSQL>
<statement targetDBVendor="postgresql" desc="Converting RHQ_INSTALLED_PKG_HIST.HISTORY_TIMESTAMP timestamp to long">
UPDATE RHQ_INSTALLED_PKG_HIST
- SET HISTORY_TIMESTAMP_LONG
- = EXTRACT ( EPOCH FROM HISTORY_TIMESTAMP )
+ SET HISTORY_TIMESTAMP_LONG = EXTRACT ( EPOCH FROM HISTORY_TIMESTAMP )
WHERE HISTORY_TIMESTAMP IS NOT NULL
- </statement>
+ </statement>
<statement targetDBVendor="oracle" desc="Converting RHQ_INSTALLED_PKG_HIST.HISTORY_TIMESTAMP timestamp to long">
UPDATE RHQ_INSTALLED_PKG_HIST
SET HISTORY_TIMESTAMP_LONG =
@@ -824,7 +810,7 @@
)
WHERE HISTORY_TIMESTAMP IS
NOT NULL
- </statement>
+ </statement>
</schema-directSQL>
<schema-deleteColumn table="RHQ_INSTALLED_PKG_HIST" column="HISTORY_TIMESTAMP" />
<schema-directSQL>
@@ -833,7 +819,7 @@
RENAME COLUMN HISTORY_TIMESTAMP_LONG
TO
HISTORY_TIMESTAMP
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -842,10 +828,9 @@
<schema-directSQL>
<statement targetDBVendor="postgresql" desc="Converting RHQ_MEASUREMENT_SCHED.MTIME timestamp to long">
UPDATE RHQ_MEASUREMENT_SCHED
- SET MTIME_LONG = EXTRACT (
- EPOCH FROM MTIME )
+ SET MTIME_LONG = EXTRACT ( EPOCH FROM MTIME )
WHERE MTIME IS NOT NULL
- </statement>
+ </statement>
<statement targetDBVendor="oracle" desc="Converting RHQ_MEASUREMENT_SCHED.MTIME timestamp to long">
UPDATE RHQ_MEASUREMENT_SCHED
SET MTIME_LONG = 1000 *
@@ -864,7 +849,7 @@
ALTER TABLE RHQ_MEASUREMENT_SCHED
RENAME COLUMN MTIME_LONG
TO MTIME
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -884,52 +869,48 @@
<schemaSpec version="2.26">
<schema-directSQL>
<statement desc="Unscheduling auto-baseline job from Quartz - removing trigger">
- DELETE FROM rhq_qrtz_triggers WHERE
- trigger_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
- </statement>
+ DELETE FROM rhq_qrtz_triggers
+ WHERE trigger_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
+ </statement>
<statement desc="Unscheduling auto-baseline job from Quartz - removing simple trigger">
- DELETE FROM rhq_qrtz_simple_triggers WHERE
- trigger_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
- </statement>
+ DELETE FROM rhq_qrtz_simple_triggers
+ WHERE trigger_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
+ </statement>
<statement desc="Unscheduling auto-baseline job from Quartz - removing job details">
- DELETE FROM rhq_qrtz_job_details WHERE
- job_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
- </statement>
+ DELETE FROM rhq_qrtz_job_details
+ WHERE job_name='org.rhq.enterprise.server.scheduler.jobs.AutoBaselineCalculationJob'
+ </statement>
</schema-directSQL>
</schemaSpec>
<schemaSpec version="2.27">
<schema-directSQL>
<statement desc="Adding Agent Max Quiet Time Allowed system configuration setting">
- INSERT INTO rhq_system_config (id, property_key, property_value,
- default_property_value)
+ INSERT INTO rhq_system_config (id, property_key, property_value, default_property_value)
VALUES (52, 'AGENT_MAX_QUIET_TIME_ALLOWED', '120000', '120000')
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
<schemaSpec version="2.28">
<schema-directSQL>
<statement desc="Adding Enable Agent Auto Update system configuration setting">
- INSERT INTO rhq_system_config (id, property_key, property_value,
- default_property_value)
+ INSERT INTO rhq_system_config (id, property_key, property_value, default_property_value)
VALUES (53, 'ENABLE_AGENT_AUTO_UPDATE', 'true', 'true')
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
<schemaSpec version="2.29">
<schema-directSQL>
<statement desc="Adding Trait Purge system configuration setting">
- INSERT INTO rhq_system_config (id, property_key, property_value,
- default_property_value)
+ INSERT INTO rhq_system_config (id, property_key, property_value, default_property_value)
VALUES (54, 'TRAIT_PURGE', '31536000000', '31536000000')
- </statement>
+ </statement>
<statement desc="Adding Avail Purge system configuration setting">
- INSERT INTO rhq_system_config (id, property_key, property_value,
- default_property_value)
+ INSERT INTO rhq_system_config (id, property_key, property_value, default_property_value)
VALUES (55, 'AVAILABILITY_PURGE', '31536000000', '31536000000')
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -938,7 +919,7 @@
<schema-directSQL>
<statement desc="Creating table RHQ_RESOURCE_AVAIL">
CREATE TABLE RHQ_RESOURCE_AVAIL ( ID INTEGER )
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_RESOURCE_AVAIL" column="ID" nullable="FALSE" />
<schema-createSequence name="RHQ_RESOURCE_AVAIL_ID_SEQ" initial="10001" />
@@ -957,7 +938,7 @@
RESOURCE_ID )
REFERENCES RHQ_RESOURCE ( ID )
ON DELETE CASCADE
- </statement>
+ </statement>
</schema-directSQL>
<schema-addColumn table="RHQ_RESOURCE_AVAIL" column="AVAILABILITY_TYPE" columnType="SMALLINT" />
<schema-directSQL>
@@ -972,7 +953,7 @@
SELECT MAX( A.START_TIME )
FROM RHQ_AVAILABILITY A
WHERE A.RESOURCE_ID = RES.ID )
- </statement>
+ </statement>
<statement targetDBVendor="postgresql" desc="Inserting known, current availability data into RHQ_RESOURCE_AVAIL">
INSERT INTO RHQ_RESOURCE_AVAIL ( ID, RESOURCE_ID,
AVAILABILITY_TYPE )
@@ -984,7 +965,7 @@
SELECT MAX( A.START_TIME )
FROM RHQ_AVAILABILITY A
WHERE A.RESOURCE_ID = RES.ID )
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -992,17 +973,15 @@
<!-- The following three columns support backing groups for resource clusters -->
<schema-addColumn table="RHQ_RESOURCE_GROUP" column="CLUSTER_RESOURCE_GROUP_ID" columnType="INTEGER" />
<schema-directSQL>
- <statement
- desc="Creating RHQ_RESOURCE_GROUP foreign key relation to RHQ_RESOURCE_GROUP for resource cluster groups">
+ <statement desc="Creating RHQ_RESOURCE_GROUP foreign key relation to RHQ_RESOURCE_GROUP for resource cluster groups">
ALTER TABLE RHQ_RESOURCE_GROUP
ADD CONSTRAINT RHQ_RESOURCE_GROUP_ID_FK
FOREIGN KEY (CLUSTER_RESOURCE_GROUP_ID)
REFERENCES RHQ_RESOURCE_GROUP (ID)
- </statement>
+ </statement>
</schema-directSQL>
- <schema-addColumn table="RHQ_RESOURCE_GROUP" column="CLUSTER_KEY" columnType="VARCHAR2"
- precision="4000" />
+ <schema-addColumn table="RHQ_RESOURCE_GROUP" column="CLUSTER_KEY" columnType="VARCHAR2" precision="4000" />
<schema-addColumn table="RHQ_RESOURCE_GROUP" column="VISIBLE" columnType="BOOLEAN" />
@@ -1018,9 +997,8 @@
<!-- The following constraint change forces cascade delete of config_update if the parent config is deleted -->
<schema-directSQL>
<statement targetDBVendor="postgresql" desc="Dropping RHQ_CONFIG_UPDATE foreign key relation to RHQ_CONFIG">
- ALTER TABLE rhq_config_update DROP CONSTRAINT
- rhq_config_update_configuration_id_fkey;
- </statement>
+ ALTER TABLE rhq_config_update DROP CONSTRAINT rhq_config_update_configuration_id_fkey;
+ </statement>
<!-- the following PL/SQL is necessary since we have to deal with generated constraint names in the ora dbs -->
<statement targetDBVendor="oracle" desc="Dropping RHQ_CONFIG_UPDATE foreign key relation to RHQ_CONFIG">
DECLARE
@@ -1040,14 +1018,13 @@
EXECUTE IMMEDIATE alter_string;
END LOOP;
END;
- </statement>
+ </statement>
<statement desc="Creating new RHQ_CONFIG_UPDATE foreign key relation to RHQ_CONFIG">
ALTER TABLE RHQ_CONFIG_UPDATE
- ADD CONSTRAINT fk_config_update_config_1 FOREIGN KEY
- (configuration_id)
+ ADD CONSTRAINT fk_config_update_config_1 FOREIGN KEY(configuration_id)
REFERENCES rhq_config ( id )
ON DELETE CASCADE
- </statement>
+ </statement>
</schema-directSQL>
@@ -1057,13 +1034,12 @@
<!--
Remove the ClusterManagerJob from the Quartz tables. It has been renamed. Note that deleting the job removes
other rows by cascade delete.
-
- -->
+ -->
<schema-directSQL>
<statement desc="Remove the ClusterManagerJob from the Quartz tables. It has been renamed.">
DELETE FROM rhq_qrtz_job_details WHERE job_name =
'org.rhq.enterprise.server.scheduler.jobs.ClusterManagerJob'
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -1079,7 +1055,7 @@
<statement desc="Removing configuration data property no longer used">
DELETE FROM rhq_system_config
WHERE property_key = 'CAM_DATA_PURGE_RAW'
- </statement>
+ </statement>
<statement desc="Removing configuration data property no longer used">
DELETE FROM rhq_system_config
WHERE property_key = 'CAM_MULTICAST_ADDRESS'
@@ -1087,11 +1063,11 @@
<statement desc="Removing configuration data property no longer used">
DELETE FROM rhq_system_config
WHERE property_key = 'CAM_MULTICAST_PORT'
- </statement>
+ </statement>
<statement desc="Removing configuration data property no longer used">
DELETE FROM rhq_system_config
WHERE property_key = 'DATA_STORE_ALL'
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -1106,24 +1082,22 @@
<schema-directSQL>
<statement desc="Deleting unique constraint on RHQ_MEASUREMENT_DEF">
DROP INDEX RHQ_METRIC_DEF_KEY_IDX
- </statement>
+ </statement>
</schema-directSQL>
<schema-deleteColumn table="RHQ_MEASUREMENT_DEF" column="PER_MINUTE" />
<schema-addColumn table="RHQ_MEASUREMENT_DEF" column="RAW_NUMERIC_TYPE" columnType="SMALLINT" />
<schema-directSQL>
<statement desc="Populating values for new column RHQ_MEASUREMENT_DEF.RAW_NUMERIC_TYPE">
- UPDATE RHQ_MEASUREMENT_DEF md SET RAW_NUMERIC_TYPE = (SELECT NUMERIC_TYPE FROM
- RHQ_MEASUREMENT_DEF
- WHERE NAME = md.NAME AND RESOURCE_TYPE_ID = md.RESOURCE_TYPE_ID AND (NUMERIC_TYPE = 1 OR
- NUMERIC_TYPE = 2))
+ UPDATE RHQ_MEASUREMENT_DEF md
+ SET RAW_NUMERIC_TYPE = (SELECT NUMERIC_TYPE FROM RHQ_MEASUREMENT_DEF
+ WHERE NAME = md.NAME AND RESOURCE_TYPE_ID = md.RESOURCE_TYPE_ID AND (NUMERIC_TYPE = 1 OR NUMERIC_TYPE = 2))
WHERE NUMERIC_TYPE = 0
- </statement>
+ </statement>
</schema-directSQL>
<schema-directSQL>
<statement desc="Creating unique index on RHQ_MEASUREMENT_DEF (RESOURCE_TYPE_ID, NAME, RAW_NUMERIC_TYPE)">
- CREATE UNIQUE INDEX RHQ_METRIC_DEF_KEY_IDX ON RHQ_MEASUREMENT_DEF (RESOURCE_TYPE_ID,
- NAME, RAW_NUMERIC_TYPE)
- </statement>
+ CREATE UNIQUE INDEX RHQ_METRIC_DEF_KEY_IDX ON RHQ_MEASUREMENT_DEF (RESOURCE_TYPE_ID, NAME, RAW_NUMERIC_TYPE)
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -1132,7 +1106,7 @@
<schema-directSQL>
<statement desc="Defaulting all group definition recalculation intervals">
UPDATE RHQ_GROUP_DEF SET CALC_INTERVAL = 0
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -1140,8 +1114,7 @@
<!-- Keep these with the same columnType=VARCHAR2, but increase size -->
<schema-alterColumn table="RHQ_CONTENT_SOURCE" column="NAME" columnType="VARCHAR2" precision="200" />
- <schema-alterColumn table="RHQ_CONTENT_SOURCE_TYPE" column="NAME" columnType="VARCHAR2"
- precision="200" />
+ <schema-alterColumn table="RHQ_CONTENT_SOURCE_TYPE" column="NAME" columnType="VARCHAR2" precision="200" />
<schema-directSQL>
<statement desc="Removing obsolete content source sync jobs">
@@ -1149,16 +1122,16 @@
</statement>
<statement>
DELETE FROM RHQ_QRTZ_JOB_DETAILS WHERE JOB_GROUP = 'syncContentSource'
- </statement>
+ </statement>
<statement>
DELETE FROM RHQ_QRTZ_SIMPLE_TRIGGERS WHERE TRIGGER_GROUP = 'syncContentSource'
- </statement>
+ </statement>
<statement>
DELETE FROM RHQ_QRTZ_TRIGGERS WHERE TRIGGER_GROUP = 'syncContentSource'
- </statement>
+ </statement>
<statement>
DELETE FROM RHQ_QRTZ_FIRED_TRIGGERS WHERE TRIGGER_GROUP = 'syncContentSource'
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -1191,15 +1164,13 @@
<schema-alterColumn table="RHQ_MEASUREMENT_OOB" column="OOB_COUNT" nullable="FALSE" />
<schema-addColumn table="RHQ_MEASUREMENT_OOB" column="OOB_FACTOR" columnType="INTEGER" />
<schema-alterColumn table="RHQ_MEASUREMENT_OOB" column="OOB_FACTOR" nullable="FALSE" />
-
</schemaSpec>
<schemaSpec version="2.40">
<schema-directSQL>
<statement desc="Changing the default event purge time in system configuration to 2 weeks">
- UPDATE RHQ_SYSTEM_CONFIG SET PROPERTY_VALUE = '1209600000' WHERE PROPERTY_KEY =
- 'EVENT_PURGE'
- </statement>
+ UPDATE RHQ_SYSTEM_CONFIG SET PROPERTY_VALUE = '1209600000' WHERE PROPERTY_KEY = 'EVENT_PURGE'
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -1229,46 +1200,46 @@
</statement>
<statement desc="Creating index on RHQ_MEAS_DATA_NUM_R01 (SCHEDULE_ID)">
CREATE INDEX RHQ_MEAS_DATA_R01_SID_IDX ON RHQ_MEAS_DATA_NUM_R01 (schedule_id)
- </statement>
+ </statement>
<statement desc="Creating index on RHQ_MEAS_DATA_NUM_R02 (SCHEDULE_ID)">
CREATE INDEX RHQ_MEAS_DATA_R02_SID_IDX ON RHQ_MEAS_DATA_NUM_R02 (schedule_id)
- </statement>
+ </statement>
<statement desc="Creating index on RHQ_MEAS_DATA_NUM_R03 (SCHEDULE_ID)">
CREATE INDEX RHQ_MEAS_DATA_R03_SID_IDX ON RHQ_MEAS_DATA_NUM_R03 (schedule_id)
- </statement>
+ </statement>
<statement desc="Creating index on RHQ_MEAS_DATA_NUM_R04 (SCHEDULE_ID)">
CREATE INDEX RHQ_MEAS_DATA_R04_SID_IDX ON RHQ_MEAS_DATA_NUM_R04 (schedule_id)
- </statement>
+ </statement>
<statement desc="Creating index on RHQ_MEAS_DATA_NUM_R05 (SCHEDULE_ID)">
CREATE INDEX RHQ_MEAS_DATA_R05_SID_IDX ON RHQ_MEAS_DATA_NUM_R05 (schedule_id)
- </statement>
+ </statement>
<statement desc="Creating index on RHQ_MEAS_DATA_NUM_R06 (SCHEDULE_ID)">
CREATE INDEX RHQ_MEAS_DATA_R06_SID_IDX ON RHQ_MEAS_DATA_NUM_R06 (schedule_id)
- </statement>
+ </statement>
<statement desc="Creating index on RHQ_MEAS_DATA_NUM_R07 (SCHEDULE_ID)">
CREATE INDEX RHQ_MEAS_DATA_R07_SID_IDX ON RHQ_MEAS_DATA_NUM_R07 (schedule_id)
- </statement>
+ </statement>
<statement desc="Creating index on RHQ_MEAS_DATA_NUM_R08 (SCHEDULE_ID)">
CREATE INDEX RHQ_MEAS_DATA_R08_SID_IDX ON RHQ_MEAS_DATA_NUM_R08 (schedule_id)
- </statement>
+ </statement>
<statement desc="Creating index on RHQ_MEAS_DATA_NUM_R09 (SCHEDULE_ID)">
CREATE INDEX RHQ_MEAS_DATA_R09_SID_IDX ON RHQ_MEAS_DATA_NUM_R09 (schedule_id)
- </statement>
+ </statement>
<statement desc="Creating index on RHQ_MEAS_DATA_NUM_R10 (SCHEDULE_ID)">
CREATE INDEX RHQ_MEAS_DATA_R10_SID_IDX ON RHQ_MEAS_DATA_NUM_R10 (schedule_id)
- </statement>
+ </statement>
<statement desc="Creating index on RHQ_MEAS_DATA_NUM_R11 (SCHEDULE_ID)">
CREATE INDEX RHQ_MEAS_DATA_R11_SID_IDX ON RHQ_MEAS_DATA_NUM_R11 (schedule_id)
- </statement>
+ </statement>
<statement desc="Creating index on RHQ_MEAS_DATA_NUM_R12 (SCHEDULE_ID)">
CREATE INDEX RHQ_MEAS_DATA_R12_SID_IDX ON RHQ_MEAS_DATA_NUM_R12 (schedule_id)
- </statement>
+ </statement>
<statement desc="Creating index on RHQ_MEAS_DATA_NUM_R13 (SCHEDULE_ID)">
CREATE INDEX RHQ_MEAS_DATA_R13_SID_IDX ON RHQ_MEAS_DATA_NUM_R13 (schedule_id)
- </statement>
+ </statement>
<statement desc="Creating index on RHQ_MEAS_DATA_NUM_R14 (SCHEDULE_ID)">
CREATE INDEX RHQ_MEAS_DATA_R14_SID_IDX ON RHQ_MEAS_DATA_NUM_R14 (schedule_id)
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -1277,14 +1248,13 @@
<schema-directSQL>
<statement desc="Updating existing servers with default STATUS flag">
UPDATE RHQ_SERVER SET STATUS = 0
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_SERVER" column="STATUS" default="0" />
</schemaSpec>
<schemaSpec version="2.46">
- <schema-alterColumn table="RHQ_MEASUREMENT_DATA_TRAIT" column="VALUE" columnType="VARCHAR2"
- precision="4000" />
+ <schema-alterColumn table="RHQ_MEASUREMENT_DATA_TRAIT" column="VALUE" columnType="VARCHAR2" precision="4000" />
</schemaSpec>
<schemaSpec version="2.47">
@@ -1296,23 +1266,22 @@
</schemaSpec>
<schemaSpec version="2.48">
- <schema-addColumn table="RHQ_RESOURCE_GROUP" column="CLUSTER_KEY" columnType="VARCHAR2"
- precision="4000" />
+ <schema-addColumn table="RHQ_RESOURCE_GROUP" column="CLUSTER_KEY" columnType="VARCHAR2" precision="4000" />
</schemaSpec>
<schemaSpec version="2.49">
<schema-directSQL>
<statement desc="Remove old data from rhq_measurement_oob">
truncate table rhq_measurement_oob
- </statement>
+ </statement>
</schema-directSQL>
<schema-directSQL>
<statement desc="Remove the composite primary key">
ALTER TABLE rhq_measurement_oob DROP CONSTRAINT rhq_meas_oob_id_t_pk
- </statement>
+ </statement>
<statement desc="Introduce a primary key on schedule_id only">
ALTER TABLE rhq_measurement_oob ADD CONSTRAINT RHQ_MEAS_OOB_ID_PK PRIMARY KEY (schedule_id)
- </statement>
+ </statement>
</schema-directSQL>
<schema-directSQL>
<statement desc="Creating table RHQ_MEASUREMENT_OOB_tmp">
@@ -1348,12 +1317,12 @@
<schema-directSQL>
<statement desc="Deleting unique name constraint on RHQ_RESOURCE_GROUP">
DROP INDEX RHQ_RES_GROUP_NAME
- </statement>
+ </statement>
</schema-directSQL>
<schema-directSQL>
<statement desc="Deleting unique name constraint on RHQ_RESOURCE_GROUP">
CREATE INDEX RHQ_RES_GROUP_NAME ON RHQ_RESOURCE_GROUP (name)
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -1362,10 +1331,10 @@
<schema-directSQL>
<statement targetDBVendor="postgresql" desc="Updating backfilled bit for all agents">
UPDATE RHQ_AGENT SET BACKFILLED = FALSE
- </statement>
+ </statement>
<statement targetDBVendor="oracle" desc="Updating backfilled bit for all agents">
UPDATE RHQ_AGENT SET BACKFILLED = 0
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_AGENT" column="BACKFILLED" nullable="FALSE" />
</schemaSpec>
@@ -1375,7 +1344,7 @@
<statement desc="Updating Agent Max Quiet Time Allowed system configuration setting">
UPDATE rhq_system_config SET property_value = '900000' WHERE property_key =
'AGENT_MAX_QUIET_TIME_ALLOWED'
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -1441,49 +1410,49 @@
<schema-directSQL>
<statement desc="Dropping index on RHQ_MEAS_DATA_R00_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R00_SID_IDX
- </statement>
+ </statement>
<statement desc="Dropping index on RHQ_MEAS_DATA_R01_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R01_SID_IDX
- </statement>
+ </statement>
<statement desc="Dropping index on RHQ_MEAS_DATA_R02_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R02_SID_IDX
- </statement>
+ </statement>
<statement desc="Dropping index on RHQ_MEAS_DATA_R03_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R03_SID_IDX
- </statement>
+ </statement>
<statement desc="Dropping index on RHQ_MEAS_DATA_R04_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R04_SID_IDX
- </statement>
+ </statement>
<statement desc="Dropping index on RHQ_MEAS_DATA_R05_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R05_SID_IDX
- </statement>
+ </statement>
<statement desc="Dropping index on RHQ_MEAS_DATA_R06_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R06_SID_IDX
- </statement>
+ </statement>
<statement desc="Dropping index on RHQ_MEAS_DATA_R07_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R07_SID_IDX
- </statement>
+ </statement>
<statement desc="Dropping index on RHQ_MEAS_DATA_R08_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R08_SID_IDX
- </statement>
+ </statement>
<statement desc="Dropping index on RHQ_MEAS_DATA_R09_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R09_SID_IDX
- </statement>
+ </statement>
<statement desc="Dropping index on RHQ_MEAS_DATA_R10_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R10_SID_IDX
- </statement>
+ </statement>
<statement desc="Dropping index on RHQ_MEAS_DATA_R11_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R11_SID_IDX
- </statement>
+ </statement>
<statement desc="Dropping index on RHQ_MEAS_DATA_R12_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R12_SID_IDX
- </statement>
+ </statement>
<statement desc="Dropping index on RHQ_MEAS_DATA_R13_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R13_SID_IDX
- </statement>
+ </statement>
<statement desc="Dropping index on RHQ_MEAS_DATA_R14_SID_IDX">
DROP INDEX RHQ_MEAS_DATA_R14_SID_IDX
- </statement>
+ </statement>
</schema-directSQL>
</schemaSpec>
@@ -1495,80 +1464,82 @@
</schema-directSQL>
</schemaSpec>
- <schemaSpec version="2.58">
- <schema-addColumn table="RHQ_ALERT_DEFINITION" column="RESOURCE_GROUP_ID" columnType="INTEGER" />
- <schema-addColumn table="RHQ_ALERT_DEFINITION" column="GROUP_ALERT_DEF_ID" columnType="INTEGER" />
- </schemaSpec>
- <schemaSpec version="2.59">
- <schema-directSQL>
- <statement desc="Creating table RHQ_RAW_CONFIG">
+ <schemaSpec version="2.58">
+ <schema-addColumn table="RHQ_ALERT_DEFINITION" column="RESOURCE_GROUP_ID" columnType="INTEGER" />
+ <schema-addColumn table="RHQ_ALERT_DEFINITION" column="GROUP_ALERT_DEF_ID" columnType="INTEGER" />
+ </schemaSpec>
+
+ <schemaSpec version="2.59">
+ <schema-directSQL>
+ <statement desc="Creating table RHQ_RAW_CONFIG">
CREATE TABLE RHQ_RAW_CONFIG (ID INTEGER)
- </statement>
- </schema-directSQL>
- <schema-alterColumn table="RHQ_RAW_CONFIG" column="ID" columnType="INTEGER" nullable="FALSE" />
- <schema-createSequence name="RHQ_RAW_CONFIG_ID_SEQ" initial="10001"/>
- <schema-directSQL>
- <statement desc="Creating primary key for RHQ_PARTITION_EVENT">
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_RAW_CONFIG" column="ID" columnType="INTEGER" nullable="FALSE" />
+ <schema-createSequence name="RHQ_RAW_CONFIG_ID_SEQ" initial="10001"/>
+ <schema-directSQL>
+ <statement desc="Creating primary key for RHQ_PARTITION_EVENT">
ALTER TABLE RHQ_RAW_CONFIG ADD PRIMARY KEY (ID)
- </statement>
- </schema-directSQL>
-
- <schema-addColumn table="RHQ_RAW_CONFIG" column="CONFIG_ID" columnType="INTEGER"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="CONFIG_ID"
- columnType="INTEGER"
- nullable="false"/>
-
- <schema-addColumn table="RHQ_RAW_CONFIG" column="PATH" columnType="VARCHAR2"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="PATH"
- columnType="VARCHAR2"
- precision="512"/>
-
- <schema-addColumn table="RHQ_RAW_CONFIG" column="CONTENTS" columnType="BLOB"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="CONTENTS"
- columnType="BLOB"
- nullable="false"/>
-
- <schema-addColumn table="RHQ_RAW_CONFIG" column="SHA256" columnType="VARCHAR2"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="SHA256"
- columnType="VARCHAR2"
- precision="64"
- nullable="false"/>
-
- <schema-addColumn table="RHQ_RAW_CONFIG" column="CTIME" columnType="LONG"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="CTIME"
- columnType="LONG"
- nullable="false"/>
-
- <schema-addColumn table="RHQ_RAW_CONFIG" column="MTIME" columnType="LONG"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="MTIME"
- columnType="LONG"
- nullable="false"/>
-
- <schema-directSQL>
- <statement desc="Creating RHQ_RAW_CONFIG foreign key relation to RHQ_CONFIG">
+ </statement>
+ </schema-directSQL>
+
+ <schema-addColumn table="RHQ_RAW_CONFIG" column="CONFIG_ID" columnType="INTEGER"/>
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="CONFIG_ID"
+ columnType="INTEGER"
+ nullable="false"/>
+
+ <schema-addColumn table="RHQ_RAW_CONFIG" column="PATH" columnType="VARCHAR2"/>
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="PATH"
+ columnType="VARCHAR2"
+ precision="512"/>
+
+ <schema-addColumn table="RHQ_RAW_CONFIG" column="CONTENTS" columnType="BLOB"/>
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="CONTENTS"
+ columnType="BLOB"
+ nullable="false"/>
+
+ <schema-addColumn table="RHQ_RAW_CONFIG" column="SHA256" columnType="VARCHAR2"/>
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="SHA256"
+ columnType="VARCHAR2"
+ precision="64"
+ nullable="false"/>
+
+ <schema-addColumn table="RHQ_RAW_CONFIG" column="CTIME" columnType="LONG"/>
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="CTIME"
+ columnType="LONG"
+ nullable="false"/>
+
+ <schema-addColumn table="RHQ_RAW_CONFIG" column="MTIME" columnType="LONG"/>
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="MTIME"
+ columnType="LONG"
+ nullable="false"/>
+
+ <schema-directSQL>
+ <statement desc="Creating RHQ_RAW_CONFIG foreign key relation to RHQ_CONFIG">
ALTER TABLE RHQ_RAW_CONFIG
ADD CONSTRAINT RHQ_RAW_CONFIG_CONFIG_ID_FK
FOREIGN KEY (CONFIG_ID)
REFERENCES RHQ_CONFIG (ID)
- </statement>
- </schema-directSQL>
+ </statement>
+ </schema-directSQL>
- </schemaSpec>
+ </schemaSpec>
+
+ <schemaSpec version="2.59.1">
+ <schema-addColumn table="RHQ_PLUGIN" column="AMPS_VERSION" columnType="VARCHAR2"/>
+ <schema-alterColumn table="RHQ_PLUGIN"
+ column="AMPS_VERSION"
+ columnType="VARCHAR2"
+ precision="16"/>
+ </schemaSpec>
- <schemaSpec version="2.59.1">
- <schema-addColumn table="RHQ_PLUGIN" column="AMPS_VERSION" columnType="VARCHAR2"/>
- <schema-alterColumn table="RHQ_PLUGIN"
- column="AMPS_VERSION"
- columnType="VARCHAR2"
- precision="16"/>
- </schemaSpec>
- <schemaSpec version="2.59.2">
+ <schemaSpec version="2.59.2">
<schema-directSQL>
<!-- RHN_CHANNEL => RHQ_REPO -->
<statement>
@@ -1626,14 +1597,15 @@
FOREIGN KEY ( CONTENT_SRC_ID )
REFERENCES RHQ_CONTENT_SOURCE( ID )
</statement>
+
<!-- RHQ_CHANNEL_PKG_VERSION_MAP => RHQ_REPO_PKG_VERSION_MAP -->
<statement>
ALTER TABLE RHQ_CHANNEL_PKG_VERSION_MAP
- RENAME TO RHQ_REPO_PKG_VERSION_MAP
+ RENAME TO RHQ_REPO_PKG_VERSION_MAP
</statement>
<statement>
ALTER TABLE RHQ_REPO_PKG_VERSION_MAP
- RENAME COLUMN CHANNEL_ID TO REPO_ID
+ RENAME COLUMN CHANNEL_ID TO REPO_ID
</statement>
<statement>
ALTER TABLE RHQ_REPO_PKG_VERSION_MAP
@@ -1642,7 +1614,7 @@
<statement>
ALTER TABLE RHQ_REPO_PKG_VERSION_MAP
ADD CONSTRAINT RHQ_REPO_PKG_VER_MAP_KEY
- PRIMARY KEY ( REPO_ID, PACKAGE_VERSION_ID )
+ PRIMARY KEY ( REPO_ID, PACKAGE_VERSION_ID )
</statement>
<statement targetDBVendor="postgresql">
ALTER TABLE RHQ_REPO_PKG_VERSION_MAP
@@ -1660,14 +1632,15 @@
FOREIGN KEY ( REPO_ID )
REFERENCES RHQ_REPO ( ID )
</statement>
+
<!-- RHQ_CHANNEL_RESOURCE_MAP => RHQ_REPO_RESOURCE_MAP -->
<statement>
ALTER TABLE RHQ_CHANNEL_RESOURCE_MAP
- RENAME TO RHQ_REPO_RESOURCE_MAP
+ RENAME TO RHQ_REPO_RESOURCE_MAP
</statement>
<statement>
ALTER TABLE RHQ_REPO_RESOURCE_MAP
- RENAME COLUMN CHANNEL_ID TO REPO_ID
+ RENAME COLUMN CHANNEL_ID TO REPO_ID
</statement>
<statement>
ALTER TABLE RHQ_REPO_RESOURCE_MAP
@@ -1676,7 +1649,7 @@
<statement>
ALTER TABLE RHQ_REPO_RESOURCE_MAP
ADD CONSTRAINT RHQ_REPO_RESOURCE_MAP_KEY
- PRIMARY KEY ( REPO_ID, RESOURCE_ID )
+ PRIMARY KEY ( REPO_ID, RESOURCE_ID )
</statement>
<statement targetDBVendor="postgresql">
ALTER TABLE RHQ_REPO_RESOURCE_MAP
@@ -1695,6 +1668,7 @@
REFERENCES RHQ_REPO ( ID )
</statement>
</schema-directSQL>
+
<!-- RHQ_REPO_GROUP_TYPE -->
<schema-createSequence name="RHQ_REPO_GROUP_TYPE_ID_SEQ" initial="10001" />
<schema-directSQL>
@@ -1712,6 +1686,7 @@
VALUES ( 1, 'family' )
</statement>
</schema-directSQL>
+
<!-- RHQ_REPO_GROUP -->
<schema-createSequence name="RHQ_REPO_GROUP_ID_SEQ" initial="10001" />
<schema-directSQL>
@@ -1746,6 +1721,7 @@
ON RHQ_REPO_GROUP ( NAME, REPO_GROUP_TYPE_ID )
</statement>
</schema-directSQL>
+
<!-- RHQ_REPO_REPO_GRP_MAP -->
<schema-directSQL>
<statement>
@@ -1786,6 +1762,7 @@
REFERENCES RHQ_REPO_GROUP ( ID )
</statement>
</schema-directSQL>
+
<!-- RHQ_REPO_RELATION_TYPE -->
<schema-createSequence name="RHQ_REPO_RELATION_TYPE_ID_SEQ" initial="10001" />
<schema-directSQL>
@@ -1809,6 +1786,7 @@
VALUES ( 2, 'clone' )
</statement>
</schema-directSQL>
+
<!-- RHQ_REPO_RELATION -->
<schema-createSequence name="RHQ_REPO_RELATION_ID_SEQ" initial="10001" />
<schema-directSQL>
@@ -1845,6 +1823,7 @@
REFERENCES RHQ_REPO_RELATION_TYPE ( ID )
</statement>
</schema-directSQL>
+
<!-- RHQ_REPO_REPO_RELATION_MAP -->
<schema-directSQL>
<statement>
@@ -1888,7 +1867,7 @@
</schemaSpec>
<schemaSpec version="2.61">
- <schema-directSQL>
+ <schema-directSQL>
<statement desc="Creating table RHQ_KICKSTARTABLE_TREE">
CREATE TABLE RHQ_KICKSTARTABLE_TREE ( ID INTEGER PRIMARY KEY )
</statement>
@@ -1901,7 +1880,7 @@
<schema-addColumn table="RHQ_KICKSTARTABLE_TREE" column="LAST_MODIFIED" columnType="LONG" />
<schema-alterColumn table="RHQ_KICKSTARTABLE_TREE" column="LAST_MODIFIED" nullable="false" />
<schema-directSQL>
- <statement targetDBVendor="postgresql">
+ <statement targetDBVendor="postgresql">
CREATE UNIQUE INDEX RHQ_KICKSTART_IDX
ON RHQ_KICKSTARTABLE_TREE ( LABEL, BASE_PATH )
</statement>
@@ -1914,7 +1893,7 @@
<schema-directSQL>
<statement desc="Creating table RHQ_REPO_KS_TREE">
CREATE TABLE RHQ_REPO_KS_TREE ( REPO_ID INTEGER )
- </statement>
+ </statement>
</schema-directSQL>
<schema-alterColumn table="RHQ_REPO_KS_TREE" column="REPO_ID" nullable="false" columnType="INTEGER"/>
@@ -1923,12 +1902,12 @@
<schema-addColumn table="RHQ_REPO_KS_TREE" column="LAST_MODIFIED" columnType="LONG" />
<schema-alterColumn table="RHQ_REPO_KS_TREE" column="LAST_MODIFIED" nullable="false" />
<schema-directSQL>
- <statement>
+ <statement>
ALTER TABLE RHQ_REPO_KS_TREE
ADD CONSTRAINT RHQ_REPO_KS_MAP_KEY
PRIMARY KEY ( REPO_ID, KICKSTART_TREE_ID )
- </statement>
- <statement targetDBVendor="postgresql">
+ </statement>
+ <statement targetDBVendor="postgresql">
ALTER TABLE RHQ_REPO_KS_TREE
ADD CONSTRAINT RHQ_KS_REPO_ID_FKEY
FOREIGN KEY ( REPO_ID )
@@ -1974,75 +1953,77 @@
</statement>
</schema-directSQL>
<schema-directSQL>
- <statement targetDBVendor="oracle">
+ <statement targetDBVendor="oracle">
ALTER TABLE RHQ_REPO_KS_TREE RENAME TO RHQ_REPO_DISTRIBUTION
- </statement>
+ </statement>
<statement targetDBVendor="postgresql">
ALTER TABLE RHQ_REPO_KS_TREE RENAME TO RHQ_REPO_DISTRIBUTION
- </statement>
- <statement targetDBVendor="oracle">
+ </statement>
+ <statement targetDBVendor="oracle">
ALTER TABLE RHQ_KICKSTARTABLE_TREE RENAME TO RHQ_DISTRIBUTION
- </statement>
- <statement targetDBVendor="postgresql">
+ </statement>
+ <statement targetDBVendor="postgresql">
ALTER TABLE RHQ_KICKSTARTABLE_TREE RENAME TO RHQ_DISTRIBUTION
- </statement>
- <statement targetDBVendor="oracle">
+ </statement>
+ <statement targetDBVendor="oracle">
ALTER TABLE RHQ_REPO_DISTRIBUTION RENAME CONSTRAINT
RHQ_REPO_KS_TREE_ID_FKEY TO RHQ_REPO_DIST_ID_FKEY
- </statement>
+ </statement>
<statement targetDBVendor="postgresql">
ALTER TABLE RHQ_REPO_DISTRIBUTION RENAME CONSTRAINT
RHQ_REPO_KS_TREE_ID_FKEY TO RHQ_REPO_DIST_ID_FKEY
- </statement>
- <statement targetDBVendor="oracle">
+ </statement>
+ <statement targetDBVendor="oracle">
ALTER TABLE RHQ_REPO_DISTRIBUTION RENAME CONSTRAINT
RHQ_REPO_KS_MAP_KEY TO RHQ_REPO_DIST_MAP_KEY
- </statement>
+ </statement>
<statement targetDBVendor="postgresql">
ALTER TABLE RHQ_REPO_DISTRIBUTION RENAME CONSTRAINT
RHQ_REPO_KS_MAP_KEY TO RHQ_REPO_DIST_MAP_KEY
- </statement>
+ </statement>
<statement targetDBVendor="oracle">
ALTER INDEX RHQ_KICKSTART_IDX RENAME TO RHQ_DISTRIBUTION_IDX
- </statement>
+ </statement>
<statement targetDBVendor="postgresql">
ALTER INDEX RHQ_KICKSTART_IDX RENAME TO RHQ_DISTRIBUTION_IDX
- </statement>
- </schema-directSQL>
+ </statement>
+ </schema-directSQL>
- <schema-directSQL>
- <statement targetDBVendor="oracle">
+ <schema-directSQL>
+ <statement targetDBVendor="oracle">
ALTER TABLE RHQ_DISTRIBUTION
ADD CONSTRAINT RHQ_DIST_FKEY
FOREIGN KEY ( DISTRIBUTION_TYPE_ID)
REFERENCES RHQ_DISTRIBUTION_TYPE ( ID )
</statement>
- <statement targetDBVendor="postgresql">
+ <statement targetDBVendor="postgresql">
ALTER TABLE RHQ_DISTRIBUTION
ADD CONSTRAINT RHQ_DIST_FKEY
FOREIGN KEY ( DISTRIBUTION_TYPE_ID)
REFERENCES RHQ_DISTRIBUTION_TYPE ( ID )
</statement>
-
</schema-directSQL>
</schemaSpec>
- <schemaSpec version="2.62">
- <schema-alterColumn
- table="RHQ_CONFIG_PROP_DEF"
- column="NAME"
- columnType="VARCHAR2"
- precision="255" />
- <schema-alterColumn
- table="RHQ_CONFIG_PROPERTY"
- column="NAME"
- columnType="VARCHAR2"
- precision="255" />
- </schemaSpec>
+ <schemaSpec version="2.62">
+ <schema-alterColumn
+ table="RHQ_CONFIG_PROP_DEF"
+ column="NAME"
+ columnType="VARCHAR2"
+ precision="255" />
+
+ <schema-alterColumn
+ table="RHQ_CONFIG_PROPERTY"
+ column="NAME"
+ columnType="VARCHAR2"
+ precision="255" />
+ </schemaSpec>
+
<schemaSpec version="2.62.1">
- <schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
- <schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
+ <schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
+ <schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
</schemaSpec>
+
</dbupgrade>
</target>
</project>
commit 7a2421a6f65866cdb8d7b9f03e5538b4fb79d4ec
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 10 17:24:27 2009 -0500
Squashed commit of the following:
commit d8668a66e4317d311661bd1a0c919635b8b9ddcb
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 10 17:23:13 2009 -0500
add schedule metadata to plugin descriptor and API
diff --git a/.classpath b/.classpath
index 478e351..2555353 100644
--- a/.classpath
+++ b/.classpath
@@ -88,7 +88,7 @@
<classpathentry kind="src" path="modules/plugins/samba/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/samba/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/sudoers/src/main/java"/>
- <classpathentry kind="src" path="modules/plugins/sudoers/src/test/java"/>
+ <classpathentry kind="src" path="modules/plugins/sudoers/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/postfix/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/postfix/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/cron/src/test/java"/>
@@ -107,8 +107,8 @@
<classpathentry kind="src" path="modules/helpers/rtfilter/src/main/java"/>
<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/plugins/augeas/src/main/java"/>
- <classpathentry kind="src" path="modules/plugins/augeas/src/test/java"/>
+ <classpathentry kind="src" path="modules/plugins/augeas/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/augeas/src/test/java"/>
<classpathentry kind="src" path="etc/samples/skeleton-plugin/src/main/java"/>
<classpathentry kind="src" path="etc/samples/custom-serverplugin/src/main/java"/>
<classpathentry kind="src" path="etc/agentspawn/src/main/java"/>
@@ -166,7 +166,7 @@
<classpathentry exported="true" kind="var" path="M2_REPO/javax/el/el-api/1.0/el-api-1.0.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/com/sun/facelets/jsf-facelets/1.1.14/jsf-facelets-1.1.14.jar" sourcepath="/M2_REPO/com/sun/facelets/jsf-facelets/1.1.13/jsf-facelets-1.1.13-sources.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/mc4j/org-mc4j-ems/1.2.11/org-mc4j-ems-1.2.11.jar" sourcepath="/M2_REPO/mc4j/org-mc4j-ems/1.2.11/org-mc4j-ems-1.2.11-sources.jar"/>
- <classpathentry exported="true" kind="var" path="M2_REPO/org/opensymphony/quartz/quartz/1.6.5/quartz-1.6.5.jar" sourcepath="/M2_REPO/org/opensymphony/quartz/1.6.5/quartz-1.6.5-sources.jar"/>
+ <classpathentry exported="true" kind="var" path="M2_REPO/org/opensymphony/quartz/quartz/1.6.5/quartz-1.6.5.jar" sourcepath="/M2_REPO/org/opensymphony/quartz/quartz/1.6.5/quartz-1.6.5-sources.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/javax/mail/mail/1.3.1/mail-1.3.1.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/commons-fileupload/commons-fileupload/1.2/commons-fileupload-1.2.jar"/>
<classpathentry exported="true" kind="var" path="M2_REPO/org/richfaces/framework/richfaces-api/3.3.0.GA/richfaces-api-3.3.0.GA.jar" sourcepath="/M2_REPO/org/richfaces/framework/richfaces-api/3.1.3.GA/richfaces-api-3.1.3.GA-sources.jar"/>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/CronSchedule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/CronSchedule.java
new file mode 100644
index 0000000..ce2a96d
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/CronSchedule.java
@@ -0,0 +1,37 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+/**
+ * A schedule that triggers based on a cron expression.
+ *
+ * @author John Mazzitelli
+ */
+public class CronSchedule extends Schedule {
+ private final String cronExpression;
+
+ public CronSchedule(String cronExpression) {
+ this.cronExpression = cronExpression;
+ }
+
+ public String getCronExpression() {
+ return this.cronExpression;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PeriodicSchedule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PeriodicSchedule.java
new file mode 100644
index 0000000..32db896
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PeriodicSchedule.java
@@ -0,0 +1,37 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+/**
+ * A schedule that triggers periodically every certain number of milliseconds.
+ *
+ * @author John Mazzitelli
+ */
+public class PeriodicSchedule extends Schedule {
+ private final long period;
+
+ public PeriodicSchedule(long period) {
+ this.period = period;
+ }
+
+ public long getPeriod() {
+ return this.period;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/Schedule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/Schedule.java
new file mode 100644
index 0000000..3cedbd6
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/Schedule.java
@@ -0,0 +1,28 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+/**
+ * Defines a schedule for a plugin component.
+ *
+ * @author John Mazzitelli
+ */
+public abstract class Schedule {
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
index f234cd1..b28c14f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
@@ -21,6 +21,8 @@ package org.rhq.enterprise.server.plugin.pc;
import java.io.File;
+import org.rhq.core.domain.configuration.Configuration;
+
/**
* A global context containing information about a server-side plugin.
*
@@ -30,18 +32,25 @@ public class ServerPluginContext {
private final ServerPluginEnvironment pluginEnvironment;
private final File temporaryDirectory;
private final File dataDirectory;
+ private final Configuration pluginConfiguration;
+ private final Schedule schedule;
/**
* Creates a new {@link ServerPluginContext} object. The plugin container is responsible for instantiating these
* objects; plugin writers should never have to actually create context objects.
*
- * @param env the environment of the plugin - includes the plugin name and other info
+ * @param env the environment of the plugin - includes the plugin name and other info
* @param dataDirectory a directory where plugins can store persisted data that survives server restarts
- * @param tmpDirectory a temporary directory for plugin use
+ * @param tmpDirectory a temporary directory for plugin use
+ * @param pluginConfiguration the configuration for the plugin itself
+ * @param schedule if not <code>null</code>, the plugin will be invoked periodically via the schedule facet
*/
- public ServerPluginContext(ServerPluginEnvironment env, File dataDirectory, File tmpDirectory) {
+ public ServerPluginContext(ServerPluginEnvironment env, File dataDirectory, File tmpDirectory,
+ Configuration pluginConfiguration, Schedule schedule) {
this.pluginEnvironment = env;
this.dataDirectory = dataDirectory;
+ this.pluginConfiguration = pluginConfiguration;
+ this.schedule = schedule;
if (tmpDirectory == null) {
this.temporaryDirectory = new File(System.getProperty("java.io.tmpdir"), "SERVERPLUGIN_TMP");
this.temporaryDirectory.mkdirs();
@@ -82,4 +91,25 @@ public class ServerPluginContext {
public File getDataDirectory() {
return this.dataDirectory;
}
+
+ /**
+ * Returns the configuration for the plugin itself. This may return <code>null</code> if the plugin did not
+ * define configuration metadata in its plugin descriptor.
+ *
+ * @return the configuration for the entire plugin (may be <code>null</code>)
+ */
+ public Configuration getPluginConfiguration() {
+ return this.pluginConfiguration;
+ }
+
+ /**
+ * The schedule in which the plugin should be periodically invoked via the schedule job facet.
+ * When this is non-null, the plugin's lifecycle listener must be prepared to be periodically
+ * invoked by the plugin container's scheduler.
+ *
+ * @return the schedule, or <code>null</code> if the plugin should not be scheduled
+ */
+ public Schedule getSchedule() {
+ return this.schedule;
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index 8c11b82..f9b4ede 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -29,7 +29,13 @@ import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.rhq.core.clientapi.agent.metadata.ConfigurationMetadataParser;
+import org.rhq.core.clientapi.agent.metadata.InvalidPluginDescriptorException;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.LifecycleListenerType;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ScheduleType;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
* Provides functionality to manage plugins for a plugin container. Plugin containers
@@ -241,12 +247,39 @@ public class ServerPluginManager {
}
protected ServerPluginContext createServerPluginContext(ServerPluginEnvironment env) {
+ String pluginName = env.getPluginName();
+ ServerPluginDescriptorType pluginDescriptor = env.getPluginDescriptor();
+
MasterServerPluginContainer masterPC = this.parentPluginContainer.getMasterServerPluginContainer();
MasterServerPluginContainerConfiguration masterConfig = masterPC.getConfiguration();
- File dataDir = new File(masterConfig.getDataDirectory(), env.getPluginName());
+ File dataDir = new File(masterConfig.getDataDirectory(), pluginName);
File tmpDir = masterConfig.getTemporaryDirectory();
- ServerPluginContext context = new ServerPluginContext(env, dataDir, tmpDir);
+ // TODO: today we have no way in the UI to customize the plugin config values
+ // for now, just use the defaults as defined in the descriptor
+ Configuration config = null;
+ try {
+ ConfigurationDefinition configDef = ConfigurationMetadataParser.parse(pluginName, pluginDescriptor
+ .getPluginConfiguration());
+ config = configDef.getDefaultTemplate().createConfiguration();
+ } catch (InvalidPluginDescriptorException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ Schedule schedule = null;
+ if (pluginDescriptor.getLifecycleListener() != null) {
+ ScheduleType scheduleType = pluginDescriptor.getLifecycleListener().getSchedule();
+ if (scheduleType != null) {
+ if (scheduleType.getPeriod() != null) {
+ schedule = new PeriodicSchedule(scheduleType.getPeriod().longValue());
+ } else {
+ schedule = new CronSchedule(scheduleType.getCron());
+ }
+ }
+ }
+
+ ServerPluginContext context = new ServerPluginContext(env, dataDir, tmpDir, config, schedule);
return context;
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
index 0fa64df..78b1681 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
@@ -29,7 +29,10 @@ import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.plugin.pc.PeriodicSchedule;
+import org.rhq.enterprise.server.plugin.pc.Schedule;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.State;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericPluginManager;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericServerPluginContainer;
@@ -55,19 +58,28 @@ public class GenericServerPluginTest extends AbstractEJB3Test {
}
public void testSimpleGenericPlugin() throws Exception {
- // tests that the lifecycle of the plugin container and the listener is correct
- createPluginJar("testSimpleGenericPlugin.jar", "serverplugins/simple-generic.xml");
+ createPluginJar("testSimpleGenericPlugin.jar", "serverplugins/simple-generic-serverplugin.xml");
this.pluginService.startMasterPluginContainer();
+ // make sure everything is started
TestGenericServerPluginContainer pc = this.pluginService.genericPC;
assert pc.state == State.STARTED;
-
TestGenericPluginManager pm = (TestGenericPluginManager) pc.getPluginManager();
TestLifecycleListener listener = (TestLifecycleListener) pm.listeners.values().iterator().next();
assert listener.state == LifecycleState.STARTED;
- this.pluginService.stopMasterPluginContainer();
+ // make sure the context is correct
+ Configuration config = listener.context.getPluginConfiguration();
+ assert config != null;
+ assert config.getSimple("plugin-simple-prop-1") != null;
+ Schedule schedule = listener.context.getSchedule();
+ assert schedule != null;
+ assert schedule instanceof PeriodicSchedule;
+ assert ((PeriodicSchedule) schedule).getPeriod() == 60000L;
+
+ // make sure everything is shutdown
+ this.pluginService.stopMasterPluginContainer();
assert pc.state == State.UNINITIALIZED;
assert listener.state == LifecycleState.UNINITIALIZED;
}
diff --git a/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml b/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml
new file mode 100644
index 0000000..ca40e8e
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic-serverplugin.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<generic-plugin name="TestSimpleGenericPlugin"
+ displayName="Test Simple Generic Plugin"
+ description="A test generic plugin that is simple."
+ version="1.0"
+ apiVersion="2.0"
+ xmlns="urn:xmlns:rhq-serverplugin.generic"
+ xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <serverplugin:lifecycle-listener class="org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener">
+ <serverplugin:schedule>
+ <serverplugin:period>60000</serverplugin:period>
+ </serverplugin:schedule>
+ </serverplugin:lifecycle-listener>
+
+ <serverplugin:plugin-configuration>
+ <c:simple-property name="plugin-simple-prop-1" defaultValue="prop1value" required="true" />
+ </serverplugin:plugin-configuration>
+</generic-plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic.xml b/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic.xml
deleted file mode 100644
index e38208d..0000000
--- a/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<generic-plugin name="TestSimpleGenericPlugin"
- displayName="Test Simple Generic Plugin"
- description="A test generic plugin that is simple."
- version="1.0"
- apiVersion="2.0"
- xmlns="urn:xmlns:rhq-serverplugin.generic"
- xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
- xmlns:c="urn:xmlns:rhq-configuration">
-
- <serverplugin:lifecycle-listener class="org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener">
-
- </serverplugin:lifecycle-listener>
-</generic-plugin>
\ No newline at end of file
commit d7e80500786e7ac9318b9b47587f2304776a871b
Author: Partha Aji <paji(a)redhat.com>
Date: Tue Nov 10 15:41:58 2009 -0500
Added a couple of checks to make sure augeas base paths are generated before unit tests are run
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
index ca948a1..3631261 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
@@ -126,7 +126,9 @@ public abstract class AbstractAugeasConfigurationComponentTest {
File tmpDir = new File(tmpDirPath);
File augeasRootPath = new File(tmpDir, "rhq-itest-augeas-root-path");
if (!augeasRootPath.exists()) {
- augeasRootPath.mkdirs();
+ if (!augeasRootPath.mkdirs()) {
+ throw new IOException("Could not create the augeasRootPath " + augeasRootPath);
+ }
}
System.setProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP, augeasRootPath.getAbsolutePath());
Resource resource = getResource();
@@ -138,7 +140,9 @@ public abstract class AbstractAugeasConfigurationComponentTest {
InputStream inputStream = this.getClass().getResourceAsStream(includeGlob);
if (inputStream != null) {
File outputFile = new File(augeasRootPath, includeGlob);
- outputFile.getParentFile().mkdirs();
+ if (!outputFile.getParentFile().exists() && !outputFile.getParentFile().mkdirs()) {
+ throw new IOException("Could not create the component base path " + outputFile.getParentFile());
+ }
FileUtil.writeFile(inputStream, outputFile);
}
}
commit 3435feb11104bb06ba8db0589763e144e34391e6
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Tue Nov 10 14:26:37 2009 -0500
change package of AbstractAugeasConfigurationComponentTest class from org.rhq.plugins.augeas to org.rhq.plugins.augeas.test to match its location on the filesystem
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
index e8f5ef3..ca948a1 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
@@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-package org.rhq.plugins.augeas;
+package org.rhq.plugins.augeas.test;
import static org.testng.Assert.fail;
@@ -45,6 +45,7 @@ import org.rhq.core.pc.inventory.InventoryManager;
import org.rhq.core.pc.plugin.FileSystemPluginFinder;
import org.rhq.core.pc.plugin.PluginManager;
import org.rhq.core.util.file.FileUtil;
+import org.rhq.plugins.augeas.AugeasConfigurationComponent;
/**
* An base class for integration tests for instances of {@link AugeasConfigurationComponent}.
diff --git a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
index fcaaa7e..af8de77 100644
--- a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
+++ b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
@@ -22,7 +22,7 @@ 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.plugins.augeas.AbstractAugeasConfigurationComponentTest;
+import org.rhq.plugins.augeas.test.AbstractAugeasConfigurationComponentTest;
/**
* An integration test for {@link HostsComponent}.
diff --git a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
index 3a091e6..93afd70 100644
--- a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
+++ b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
@@ -20,7 +20,7 @@ package org.rhq.plugins.samba;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
-import org.rhq.plugins.augeas.AbstractAugeasConfigurationComponentTest;
+import org.rhq.plugins.augeas.test.AbstractAugeasConfigurationComponentTest;
public class SambaComponentTest extends AbstractAugeasConfigurationComponentTest {
diff --git a/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java b/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
index 943455d..63bed0f 100644
--- a/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
+++ b/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
@@ -22,7 +22,7 @@ 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.plugins.augeas.AbstractAugeasConfigurationComponentTest;
+import org.rhq.plugins.augeas.test.AbstractAugeasConfigurationComponentTest;
/**
* @author Partha Aji
commit 78a696197265d0a51dee542711342cecb4caa287
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Tue Nov 10 13:19:44 2009 -0500
move augeas base test class in augeas plugin from src/test/ to src/main/ to allow mvn -Dmaven.test.skip=true to be run from project root without failures in samba/sudoers/etc. plugins because mvn cannot find the augeas plugin test jar
diff --git a/modules/plugins/augeas/pom.xml b/modules/plugins/augeas/pom.xml
index 28f3cc5..657766c 100644
--- a/modules/plugins/augeas/pom.xml
+++ b/modules/plugins/augeas/pom.xml
@@ -23,10 +23,23 @@
<dependency>
<groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-core-plugin-container</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
<artifactId>rhq-platform-plugin</artifactId>
<version>${project.version}</version>
</dependency>
-
+
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <version>5.9</version>
+ <classifier>jdk15</classifier>
+ </dependency>
+
<dependency>
<groupId>net.augeas</groupId>
<artifactId>augeas</artifactId>
@@ -48,7 +61,7 @@
<version>2.0</version>
<executions>
<execution>
- <id>copy-jna-jar</id>
+ <id>copy-plugin-libs</id>
<phase>process-resources</phase>
<goals>
<goal>copy</goal>
@@ -74,17 +87,6 @@
</execution>
</executions>
</plugin>
-
- <plugin>
- <artifactId>maven-jar-plugin</artifactId>
- <executions>
- <execution>
- <goals>
- <goal>test-jar</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
</plugins>
</build>
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
new file mode 100644
index 0000000..e8f5ef3
--- /dev/null
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/test/AbstractAugeasConfigurationComponentTest.java
@@ -0,0 +1,219 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2009 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.augeas;
+
+import static org.testng.Assert.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.Test;
+
+import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
+import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+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.configuration.ConfigurationManager;
+import org.rhq.core.pc.inventory.InventoryManager;
+import org.rhq.core.pc.plugin.FileSystemPluginFinder;
+import org.rhq.core.pc.plugin.PluginManager;
+import org.rhq.core.util.file.FileUtil;
+
+/**
+ * An base class for integration tests for instances of {@link AugeasConfigurationComponent}.
+ *
+ * @author Ian Springer
+ */
+public abstract class AbstractAugeasConfigurationComponentTest {
+ public static final String TEST_GROUP = "linux-config";
+ private static final File ITEST_DIR = new File("target/itest");
+ private static final long ONE_WEEK_IN_SECONDS = 60L * 60 * 24;
+
+ @BeforeSuite(groups = TEST_GROUP)
+ public void start() {
+ try {
+ PluginContainerConfiguration pcConfig = new PluginContainerConfiguration();
+ File pluginsDir = new File(ITEST_DIR, "plugins");
+ pcConfig.setPluginFinder(new FileSystemPluginFinder(pluginsDir));
+ pcConfig.setPluginDirectory(pluginsDir);
+ pcConfig.setInsideAgent(false);
+ pcConfig.setCreateResourceClassloaders(true);
+
+ // Set initial delays for all scheduled scans to one week to effectively disable them.
+ pcConfig.setServerDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setServiceDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setAvailabilityScanInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setConfigurationDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setContentDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+
+ File tmpDir = new File(ITEST_DIR, "tmp");
+ tmpDir.mkdirs();
+ if (!tmpDir.isDirectory() || !tmpDir.canWrite()) {
+ throw new IOException("Failed to create temporary directory (" + tmpDir + ").");
+ }
+ pcConfig.setTemporaryDirectory(tmpDir);
+ PluginContainer.getInstance().setConfiguration(pcConfig);
+ System.out.println("Starting PC...");
+ PluginContainer.getInstance().initialize();
+ Set<String> pluginNames = PluginContainer.getInstance().getPluginManager().getMetadataManager()
+ .getPluginNames();
+ System.out.println("PC started with the following plugins: " + pluginNames);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Failed to start the plugin container.", e);
+ }
+ }
+
+ @BeforeSuite(dependsOnMethods = "start", groups = TEST_GROUP)
+ public void updatePluginConfiguration() {
+ try {
+ System.out.println("Updating Augeas root in plugin configuration...");
+
+ // We need to have the Resource inventoried in order to update its plugin config.
+ InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
+ ResourceType resourceType = getResourceType();
+ switch (resourceType.getCategory()) {
+ case SERVICE:
+ System.out.println("Executing platform service scan to discover " + resourceType + " Resource...");
+ inventoryManager.performServiceScan(inventoryManager.getPlatform().getId());
+ break;
+ case SERVER:
+ System.out.println("Executing server scan to discover " + resourceType + " Resource...");
+ inventoryManager.executeServerScanImmediately();
+ break;
+ case PLATFORM:
+ throw new IllegalStateException("Huh? Using Augeas to configure a platform?");
+ }
+ resetAugeasConfigs();
+ Resource resource = getResource();
+ Configuration pluginConfig = resource.getPluginConfiguration();
+ inventoryManager.updatePluginConfiguration(resource.getId(), pluginConfig);
+ } catch (Exception e) {
+ fail("Failed to update Augeas root in plugin configuration.", e);
+ }
+ }
+
+ public void resetAugeasConfigs() throws IOException {
+ String tmpDirPath = System.getProperty("java.io.tmpdir");
+ File tmpDir = new File(tmpDirPath);
+ File augeasRootPath = new File(tmpDir, "rhq-itest-augeas-root-path");
+ if (!augeasRootPath.exists()) {
+ augeasRootPath.mkdirs();
+ }
+ System.setProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP, augeasRootPath.getAbsolutePath());
+ Resource resource = getResource();
+ Configuration pluginConfig = resource.getPluginConfiguration();
+ PropertySimple includes = pluginConfig.getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP);
+ List<String> includeGlobs = new ArrayList<String>();
+ includeGlobs.addAll(Arrays.asList(includes.getStringValue().split("\\s*\\|\\s*")));
+ for (String includeGlob : includeGlobs) {
+ InputStream inputStream = this.getClass().getResourceAsStream(includeGlob);
+ if (inputStream != null) {
+ File outputFile = new File(augeasRootPath, includeGlob);
+ outputFile.getParentFile().mkdirs();
+ FileUtil.writeFile(inputStream, outputFile);
+ }
+ }
+ }
+
+ @AfterSuite(groups = TEST_GROUP)
+ public void stop() {
+ System.clearProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP);
+ System.out.println("Stopping PC...");
+ PluginContainer.getInstance().shutdown();
+ System.out.println("PC stopped.");
+ }
+
+ @Test(groups = TEST_GROUP)
+ public void testResourceConfigLoad() throws Exception {
+ if (getResourceType().getResourceConfigurationDefinition() != null) {
+ ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
+ Resource resource = getResource();
+ Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
+ Configuration expectedResourceConfig = getExpectedResourceConfig();
+ assert resourceConfig.equals(expectedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
+ + expectedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
+ }
+ }
+
+ protected abstract Configuration getExpectedResourceConfig();
+
+ protected abstract Configuration getChangedResourceConfig();
+
+ protected static ResourceType getResourceType(String resourceTypeName, String pluginName) {
+ PluginManager pluginManager = PluginContainer.getInstance().getPluginManager();
+ PluginMetadataManager pluginMetadataManager = pluginManager.getMetadataManager();
+ return pluginMetadataManager.getType(resourceTypeName, pluginName);
+ }
+
+ protected final ResourceType getResourceType() {
+ return getResourceType(getResourceTypeName(), getPluginName());
+ }
+
+ protected abstract String getPluginName();
+
+ protected abstract String getResourceTypeName();
+
+ protected Resource getResource() {
+ InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
+ ResourceType resourceType = getResourceType();
+ Set<Resource> resources = inventoryManager.getResourcesWithType(resourceType);
+ if (resources.isEmpty()) {
+ return null;
+ }
+ if (resources.size() > 1) {
+ throw new IllegalStateException("Found more than one " + resourceType.getName()
+ + " Resource - expected there to be exactly one - resources: " + resources);
+ }
+ return resources.iterator().next();
+ }
+
+ @Test(groups = TEST_GROUP)
+ public void testResourceConfigUpdate() throws Exception {
+ if (getResourceType().getResourceConfigurationDefinition() != null) {
+ try {
+ ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
+ Resource resource = getResource();
+ Configuration updatedResourceConfig = getChangedResourceConfig();
+ configurationManager.updateResourceConfiguration(new ConfigurationUpdateRequest(0,
+ updatedResourceConfig, resource.getId()));
+
+ //give the component and the managed resource some time to properly persist the update
+ Thread.sleep(500);
+
+ Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
+ assert resourceConfig.equals(updatedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
+ + updatedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
+ } finally {
+ resetAugeasConfigs();
+ }
+ }
+ }
+}
diff --git a/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java
deleted file mode 100644
index e8f5ef3..0000000
--- a/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2009 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.augeas;
-
-import static org.testng.Assert.fail;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-
-import org.testng.annotations.AfterSuite;
-import org.testng.annotations.BeforeSuite;
-import org.testng.annotations.Test;
-
-import org.rhq.core.clientapi.agent.configuration.ConfigurationUpdateRequest;
-import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
-import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.configuration.PropertySimple;
-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.configuration.ConfigurationManager;
-import org.rhq.core.pc.inventory.InventoryManager;
-import org.rhq.core.pc.plugin.FileSystemPluginFinder;
-import org.rhq.core.pc.plugin.PluginManager;
-import org.rhq.core.util.file.FileUtil;
-
-/**
- * An base class for integration tests for instances of {@link AugeasConfigurationComponent}.
- *
- * @author Ian Springer
- */
-public abstract class AbstractAugeasConfigurationComponentTest {
- public static final String TEST_GROUP = "linux-config";
- private static final File ITEST_DIR = new File("target/itest");
- private static final long ONE_WEEK_IN_SECONDS = 60L * 60 * 24;
-
- @BeforeSuite(groups = TEST_GROUP)
- public void start() {
- try {
- PluginContainerConfiguration pcConfig = new PluginContainerConfiguration();
- File pluginsDir = new File(ITEST_DIR, "plugins");
- pcConfig.setPluginFinder(new FileSystemPluginFinder(pluginsDir));
- pcConfig.setPluginDirectory(pluginsDir);
- pcConfig.setInsideAgent(false);
- pcConfig.setCreateResourceClassloaders(true);
-
- // Set initial delays for all scheduled scans to one week to effectively disable them.
- pcConfig.setServerDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
- pcConfig.setServiceDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
- pcConfig.setAvailabilityScanInitialDelay(ONE_WEEK_IN_SECONDS);
- pcConfig.setConfigurationDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
- pcConfig.setContentDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
-
- File tmpDir = new File(ITEST_DIR, "tmp");
- tmpDir.mkdirs();
- if (!tmpDir.isDirectory() || !tmpDir.canWrite()) {
- throw new IOException("Failed to create temporary directory (" + tmpDir + ").");
- }
- pcConfig.setTemporaryDirectory(tmpDir);
- PluginContainer.getInstance().setConfiguration(pcConfig);
- System.out.println("Starting PC...");
- PluginContainer.getInstance().initialize();
- Set<String> pluginNames = PluginContainer.getInstance().getPluginManager().getMetadataManager()
- .getPluginNames();
- System.out.println("PC started with the following plugins: " + pluginNames);
- } catch (Exception e) {
- e.printStackTrace();
- fail("Failed to start the plugin container.", e);
- }
- }
-
- @BeforeSuite(dependsOnMethods = "start", groups = TEST_GROUP)
- public void updatePluginConfiguration() {
- try {
- System.out.println("Updating Augeas root in plugin configuration...");
-
- // We need to have the Resource inventoried in order to update its plugin config.
- InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
- ResourceType resourceType = getResourceType();
- switch (resourceType.getCategory()) {
- case SERVICE:
- System.out.println("Executing platform service scan to discover " + resourceType + " Resource...");
- inventoryManager.performServiceScan(inventoryManager.getPlatform().getId());
- break;
- case SERVER:
- System.out.println("Executing server scan to discover " + resourceType + " Resource...");
- inventoryManager.executeServerScanImmediately();
- break;
- case PLATFORM:
- throw new IllegalStateException("Huh? Using Augeas to configure a platform?");
- }
- resetAugeasConfigs();
- Resource resource = getResource();
- Configuration pluginConfig = resource.getPluginConfiguration();
- inventoryManager.updatePluginConfiguration(resource.getId(), pluginConfig);
- } catch (Exception e) {
- fail("Failed to update Augeas root in plugin configuration.", e);
- }
- }
-
- public void resetAugeasConfigs() throws IOException {
- String tmpDirPath = System.getProperty("java.io.tmpdir");
- File tmpDir = new File(tmpDirPath);
- File augeasRootPath = new File(tmpDir, "rhq-itest-augeas-root-path");
- if (!augeasRootPath.exists()) {
- augeasRootPath.mkdirs();
- }
- System.setProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP, augeasRootPath.getAbsolutePath());
- Resource resource = getResource();
- Configuration pluginConfig = resource.getPluginConfiguration();
- PropertySimple includes = pluginConfig.getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP);
- List<String> includeGlobs = new ArrayList<String>();
- includeGlobs.addAll(Arrays.asList(includes.getStringValue().split("\\s*\\|\\s*")));
- for (String includeGlob : includeGlobs) {
- InputStream inputStream = this.getClass().getResourceAsStream(includeGlob);
- if (inputStream != null) {
- File outputFile = new File(augeasRootPath, includeGlob);
- outputFile.getParentFile().mkdirs();
- FileUtil.writeFile(inputStream, outputFile);
- }
- }
- }
-
- @AfterSuite(groups = TEST_GROUP)
- public void stop() {
- System.clearProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP);
- System.out.println("Stopping PC...");
- PluginContainer.getInstance().shutdown();
- System.out.println("PC stopped.");
- }
-
- @Test(groups = TEST_GROUP)
- public void testResourceConfigLoad() throws Exception {
- if (getResourceType().getResourceConfigurationDefinition() != null) {
- ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
- Resource resource = getResource();
- Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
- Configuration expectedResourceConfig = getExpectedResourceConfig();
- assert resourceConfig.equals(expectedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
- + expectedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
- }
- }
-
- protected abstract Configuration getExpectedResourceConfig();
-
- protected abstract Configuration getChangedResourceConfig();
-
- protected static ResourceType getResourceType(String resourceTypeName, String pluginName) {
- PluginManager pluginManager = PluginContainer.getInstance().getPluginManager();
- PluginMetadataManager pluginMetadataManager = pluginManager.getMetadataManager();
- return pluginMetadataManager.getType(resourceTypeName, pluginName);
- }
-
- protected final ResourceType getResourceType() {
- return getResourceType(getResourceTypeName(), getPluginName());
- }
-
- protected abstract String getPluginName();
-
- protected abstract String getResourceTypeName();
-
- protected Resource getResource() {
- InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
- ResourceType resourceType = getResourceType();
- Set<Resource> resources = inventoryManager.getResourcesWithType(resourceType);
- if (resources.isEmpty()) {
- return null;
- }
- if (resources.size() > 1) {
- throw new IllegalStateException("Found more than one " + resourceType.getName()
- + " Resource - expected there to be exactly one - resources: " + resources);
- }
- return resources.iterator().next();
- }
-
- @Test(groups = TEST_GROUP)
- public void testResourceConfigUpdate() throws Exception {
- if (getResourceType().getResourceConfigurationDefinition() != null) {
- try {
- ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
- Resource resource = getResource();
- Configuration updatedResourceConfig = getChangedResourceConfig();
- configurationManager.updateResourceConfiguration(new ConfigurationUpdateRequest(0,
- updatedResourceConfig, resource.getId()));
-
- //give the component and the managed resource some time to properly persist the update
- Thread.sleep(500);
-
- Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
- assert resourceConfig.equals(updatedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
- + updatedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
- } finally {
- resetAugeasConfigs();
- }
- }
- }
-}
diff --git a/modules/plugins/hosts/pom.xml b/modules/plugins/hosts/pom.xml
index 3c6522b..2d7452d 100644
--- a/modules/plugins/hosts/pom.xml
+++ b/modules/plugins/hosts/pom.xml
@@ -35,14 +35,6 @@
<artifactId>rhq-augeas-plugin</artifactId>
<version>${project.version}</version>
</dependency>
-
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-augeas-plugin</artifactId>
- <version>${project.version}</version>
- <type>test-jar</type>
- <scope>test</scope>
- </dependency>
</dependencies>
diff --git a/modules/plugins/postfix/pom.xml b/modules/plugins/postfix/pom.xml
index 15ffac1..ff5acc4 100644
--- a/modules/plugins/postfix/pom.xml
+++ b/modules/plugins/postfix/pom.xml
@@ -25,25 +25,12 @@
</properties>
<dependencies>
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-platform-plugin</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
+
+ <dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-augeas-plugin</artifactId>
<version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-augeas-plugin</artifactId>
- <version>${project.version}</version>
- <type>test-jar</type>
- <scope>test</scope>
- </dependency>
-
+ </dependency>
</dependencies>
diff --git a/modules/plugins/samba/pom.xml b/modules/plugins/samba/pom.xml
index c93989f..d1376a8 100644
--- a/modules/plugins/samba/pom.xml
+++ b/modules/plugins/samba/pom.xml
@@ -25,25 +25,12 @@
</properties>
<dependencies>
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-platform-plugin</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
+
+ <dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-augeas-plugin</artifactId>
<version>${project.version}</version>
- </dependency>
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-augeas-plugin</artifactId>
- <version>${project.version}</version>
- <type>test-jar</type>
- <scope>test</scope>
- </dependency>
-
+ </dependency>
</dependencies>
diff --git a/modules/plugins/sudoers/pom.xml b/modules/plugins/sudoers/pom.xml
index ae7960b..28fbed5 100644
--- a/modules/plugins/sudoers/pom.xml
+++ b/modules/plugins/sudoers/pom.xml
@@ -25,25 +25,13 @@
</properties>
<dependencies>
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-platform-plugin</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
-
+
<dependency>
<groupId>org.rhq</groupId>
<artifactId>rhq-augeas-plugin</artifactId>
<version>${project.version}</version>
</dependency>
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-augeas-plugin</artifactId>
- <version>${project.version}</version>
- <type>test-jar</type>
- <scope>test</scope>
- </dependency>
+
</dependencies>
<profiles>
commit fbfe2ed2f3415a4a68e64748fe68d878448a3035
Author: Sayli Karmarkar <skarmark(a)redhat.com>
Date: Tue Nov 10 12:44:28 2009 -0500
removing @overrides - not required
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
index 07df700..fe4d6e7 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
@@ -448,17 +448,14 @@ public class ContentSource implements Serializable, Taggable {
return true;
}
- @Override
public Set<Tag> getTags() {
return tags;
}
- @Override
public void setTags(Set<Tag> tags) {
this.tags = tags;
}
- @Override
public boolean hasTag(Tag tag) {
if ((this.tags == null) || (tag == null)) {
return false;
@@ -476,7 +473,6 @@ public class ContentSource implements Serializable, Taggable {
}
- @Override
public void addTag(Tag tag) {
if (this.tags == null) {
this.tags = new HashSet<Tag>();
@@ -485,7 +481,6 @@ public class ContentSource implements Serializable, Taggable {
this.tags.add(tag);
}
- @Override
public void removeTag(Tag tag) {
if ((this.tags == null) || (tag == null)) {
return;
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
index 9dc25f0..20e6d7d 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
@@ -221,17 +221,14 @@ public class Package implements Serializable, Taggable {
return result;
}
- @Override
public Set<Tag> getTags() {
return tags;
}
- @Override
public void setTags(Set<Tag> tags) {
this.tags = tags;
}
- @Override
public boolean hasTag(Tag tag) {
if ((this.tags == null) || (tag == null)) {
return false;
@@ -249,7 +246,6 @@ public class Package implements Serializable, Taggable {
}
- @Override
public void addTag(Tag tag) {
if (this.tags == null) {
this.tags = new HashSet<Tag>();
@@ -258,7 +254,6 @@ public class Package implements Serializable, Taggable {
this.tags.add(tag);
}
- @Override
public void removeTag(Tag tag) {
if ((this.tags == null) || (tag == null)) {
return;
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
index b3d5785..5dfd421 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
@@ -1813,17 +1813,14 @@ public class Resource implements Comparable<Resource>, Externalizable, Taggable
this.currentAvailability = new ResourceAvailability(this, null);
}
- @Override
public Set<Tag> getTags() {
return tags;
}
- @Override
public void setTags(Set<Tag> tags) {
this.tags = tags;
}
- @Override
public boolean hasTag(Tag tag) {
if ((this.tags == null) || (tag == null)) {
return false;
@@ -1841,7 +1838,6 @@ public class Resource implements Comparable<Resource>, Externalizable, Taggable
}
- @Override
public void addTag(Tag tag) {
if (this.tags == null) {
this.tags = new HashSet<Tag>();
@@ -1850,7 +1846,6 @@ public class Resource implements Comparable<Resource>, Externalizable, Taggable
this.tags.add(tag);
}
- @Override
public void removeTag(Tag tag) {
if ((this.tags == null) || (tag == null)) {
return;
commit 7cd1224b6f2510a1aee0906c2c54c415c26aea29
Merge: 850c634... a0c60c8...
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Tue Nov 10 09:42:43 2009 -0800
Merge branch 'content' of ssh://git.fedorahosted.org/git/rhq/rhq into content2
commit 850c634aa22058a6bc7cbdcb9c55e28193625ba8
Merge: 42c5c6c... 961fba0...
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Tue Nov 10 09:42:16 2009 -0800
Merge branch 'master' into content2
Conflicts:
modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
diff --cc modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index 5dfb7e9,1737386..a2512a6
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@@ -2029,81 -2027,22 +2027,78 @@@
</schema-directSQL>
</schemaSpec>
- <schemaSpec version="2.62">
- <schema-alterColumn
- table="RHQ_CONFIG_PROP_DEF"
- column="NAME"
- columnType="VARCHAR2"
- precision="255" />
+ <schemaSpec version="2.62">
<schema-alterColumn
- table="RHQ_CONFIG_PROPERTY"
- column="NAME"
- columnType="VARCHAR2"
- precision="255" />
- </schemaSpec>
+ table="RHQ_CONFIG_PROP_DEF"
+ column="NAME"
+ columnType="VARCHAR2"
+ precision="255" />
+ <schema-alterColumn
+ table="RHQ_CONFIG_PROPERTY"
+ column="NAME"
+ columnType="VARCHAR2"
+ precision="255" />
+ </schemaSpec>
- <schemaSpec version="2.62.1">
+
+ <schemaSpec version="2.63">
<schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
<schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
</schemaSpec>
+
+ <!-- Generic tagging support -->
+ <schemaSpec version="2.64">
+ <schema-createSequence name="RHQ_TAG_ID_SEQ" initial="10001" />
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_TAG ( ID INTEGER PRIMARY KEY )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_TAG" column="ID" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="NAME" precision="200" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_TAG" column="NAME" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="DESCRIPTION" precision="500" columnType="VARCHAR2" />
+ </schemaSpec>
+
+ <!-- Distribution Files -->
+ <schemaSpec version="2.65">
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID INTEGER )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="DISTRIBUTION_ID" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" precision="256" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" precision="64" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" columnType="LONG" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" nullable="false" />
+ <schema-directSQL>
+ <statement targetDBVendor="postgresql">
+ CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
+ ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
+ </statement>
+ <statement targetDBVendor="oracle">
+ CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
+ ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
+ </statement>
+ </schema-directSQL>
+ <schema-directSQL>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_DISTRIBUTION_FILE
+ ADD CONSTRAINT RHQ_DIST_FILE_FKEY
+ FOREIGN KEY ( DISTRIBUTION_ID)
+ REFERENCES RHQ_DISTRIBUTION ( ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_DISTRIBUTION_FILE
+ ADD CONSTRAINT RHQ_DIST_FILE_FKEY
+ FOREIGN KEY ( DISTRIBUTION_ID)
+ REFERENCES RHQ_DISTRIBUTION ( ID )
+ </statement>
+ </schema-directSQL>
+
+ </schemaSpec>
-
-
-
</dbupgrade>
</target>
</project>
diff --cc modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
index 77b6c27,9e63460..cbd28b8
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
@@@ -65,8 -65,10 +65,9 @@@ import org.rhq.enterprise.server.util.L
*/
public class ContentProviderManager {
private static final Log log = LogFactory.getLog(ContentProviderManager.class);
--
- private ContentProviderPluginManager pluginManager;
- private static final String PARENT_RELATIONSHIP_NAME = "parent";
-
++
+ private ContentServerPluginManager pluginManager;
++ private static final String PARENT_RELATIONSHIP_NAME = "parent";
private Map<ContentSource, ContentProvider> adapters;
// This is used as a monitor lock to the synchronizeContentSource method;
@@@ -608,4 -704,4 +618,4 @@@
}
}
}
--}
++}
diff --cc modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
index 0ced439,3a091e6..57ba0ec
--- a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
+++ b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
@@@ -18,73 -18,46 +18,48 @@@
*/
package org.rhq.plugins.samba;
- import java.util.Collection;
-
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.testng.annotations.BeforeSuite;
- import org.testng.annotations.Test;
-
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.plugins.augeas.AbstractAugeasConfigurationComponentTest;
- /**
- * @author Jason Dobies
- */
- public class SambaComponentTest {
+ public class SambaComponentTest extends AbstractAugeasConfigurationComponentTest {
- private SambaServerComponent component = new SambaServerComponent();
+ @Override
+ protected Configuration getExpectedResourceConfig() {
+ Configuration config = new Configuration();
- private Configuration pluginConfiguration = new Configuration();
+ config.put(new PropertySimple("workgroup", "SCOOBY"));
+ config.put(new PropertySimple("server string", "MysteryMachine"));
+ config.put(new PropertySimple("security", "user"));
+ config.put(new PropertySimple("encrypt passwords", "yes"));
+ config.put(new PropertySimple("load printers", "yes"));
+ config.put(new PropertySimple("cups options", "raw"));
- private final Log log = LogFactory.getLog(this.getClass());
-
- @BeforeSuite
- public void initPluginConfiguration() throws Exception {
- pluginConfiguration.put(new PropertySimple("lenses-path", "/usr/share/augeas/lenses"));
- pluginConfiguration.put(new PropertySimple("root-path", "/"));
- pluginConfiguration.put(new PropertySimple("hosts-path", "/etc/hosts"));
- pluginConfiguration.put(new PropertySimple("augeas-hosts-path", "/files/etc/hosts/*"));
+ return config;
}
+
- @Test
- public void loadResourceConfiguration() throws Exception {
- // Just bail because this test wont work yet
- if (true) {
- return;
- }
- Configuration configuration;
- try {
- configuration = component.loadResourceConfiguration(pluginConfiguration);
- } catch (UnsatisfiedLinkError ule) {
- // Skip tests if augeas not available
- return;
- }
-
- assert configuration != null : "Null configuration returned from load call";
-
- Collection<Property> allProperties = configuration.getProperties();
-
- assert allProperties.size() == 1 : "Incorrect number of properties found. Expected: 1, Found: "
- + allProperties.size();
-
- PropertyList entryList = (PropertyList) allProperties.iterator().next();
+ @Override
+ protected String getPluginName() {
+ return "Samba";
+ }
- for (Property property : entryList.getList()) {
- PropertyMap entry = (PropertyMap) property;
+ @Override
+ protected String getResourceTypeName() {
+ return "Samba Server";
+ }
- Property ipProperty = entry.get("ip");
- Property canonicalProperty = entry.get("canonical");
+
- assert ipProperty != null : "IP was null in entry";
- assert canonicalProperty != null : "Canonical was null in entry";
+ @Override
+ protected Configuration getChangedResourceConfig() {
+ Configuration config = new Configuration();
- log.info("IP: " + ((PropertySimple) ipProperty).getStringValue());
- log.info("Canonical: " + ((PropertySimple) canonicalProperty).getStringValue());
- }
+ config.put(new PropertySimple("workgroup", "DUMBCHANGE"));
+ config.put(new PropertySimple("server string", "DUMBCHANGE"));
+ config.put(new PropertySimple("security", "DUMBCHANGE"));
+ config.put(new PropertySimple("encrypt passwords", "DUMBCHANGE"));
+ config.put(new PropertySimple("load printers", "DUMBCHANGE"));
+ config.put(new PropertySimple("cups options", "DUMBCHANGE"));
+ return config;
}
}
commit 3fc36885ca8922c084a877484de21ea958b1bb94
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 10 12:38:38 2009 -0500
why did git not know that I removed these?
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java
deleted file mode 100644
index 1d68798..0000000
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java
+++ /dev/null
@@ -1,187 +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.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.rhq.core.domain.content.ContentSource;
-import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
-import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
-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.ContentProviderPackageDetails;
-import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginManager;
-import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
-import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
-import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
-
-/**
- * Used as a mock service for the content source plugin container.
- */
-public class TestContentServerPluginService extends ServerPluginService implements TestContentServerPluginServiceMBean {
- // public so tests can directly set these
- public Map<ContentSource, ContentProvider> testAdapters;
- public PackageSyncReport testLastSyncReport;
- public Map<ContentSource, Collection<ContentProviderPackageDetails>> testExistingPackages;
- public TestMasterServerPluginContainer master;
-
- @Override
- protected MasterServerPluginContainer createMasterPluginContainer() {
- this.master = new TestMasterServerPluginContainer();
- File dir = new File(System.getProperty("java.io.tmpdir"), "test-server-plugins");
- MasterServerPluginContainerConfiguration config = new MasterServerPluginContainerConfiguration(dir, dir, dir,
- null);
- this.master.initialize(config);
- return this.master;
- }
-
- /**
- * The test master PC
- */
- class TestMasterServerPluginContainer extends MasterServerPluginContainer {
- @Override
- protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
- ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(1);
- pcs.add(new TestContentServerPluginContainer(this));
- return pcs;
- }
-
- @Override
- protected ClassLoader createRootServerPluginClassLoader() {
- return this.getClass().getClassLoader();
- }
-
- @Override
- protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
- return new HashMap<URL, ServerPluginDescriptorType>();
- }
- }
-
- /**
- * The test content PC.
- */
- class TestContentServerPluginContainer extends ContentServerPluginContainer {
- public TestContentServerPluginContainer(MasterServerPluginContainer master) {
- super(master);
- }
-
- @Override
- protected ContentProviderManager createAdapterManager() {
- TestContentProviderManager am = new TestContentProviderManager();
- return am;
- }
-
- @Override
- protected ContentServerPluginManager createPluginManager() {
- TestContentProviderPluginManager pm = new TestContentProviderPluginManager(this);
- return pm;
- }
- }
-
- /**
- * The test plugin manager.
- */
- class TestContentProviderPluginManager extends ContentServerPluginManager {
- public TestContentProviderPluginManager(ContentServerPluginContainer pc) {
- super(pc);
- }
- }
-
- /**
- * The test adapter manager.
- */
- class TestContentProviderManager extends ContentProviderManager {
- @Override
- public Set<ContentSource> getAllContentSources() {
- return (testAdapters != null) ? testAdapters.keySet() : new HashSet<ContentSource>();
- }
-
- @Override
- protected void initialize(ContentServerPluginManager pluginManager) {
- createInitialAdaptersMap();
- }
-
- @Override
- public void shutdown() {
- }
-
- @Override
- public InputStream loadPackageBits(int contentSourceId, String location) throws Exception {
- if (testAdapters != null) {
- for (ContentSource cs : testAdapters.keySet()) {
- if (cs.getId() == contentSourceId) {
- PackageSource packageSource = (PackageSource) testAdapters.get(cs);
- return packageSource.getInputStream(location);
- }
- }
- }
-
- System.out.println("!!!!!!!!!!");
- System.out.println("STREAM: TEST DID NOT SETUP ADAPTER - EMPTY STREAM FOR [" + contentSourceId + "]");
- return new ByteArrayInputStream(new byte[0]);
- }
-
- @Override
- public boolean synchronizeContentSource(int contentSourceId) throws Exception {
- if (testAdapters != null) {
- for (ContentSource cs : testAdapters.keySet()) {
- if (cs.getId() == contentSourceId) {
- testLastSyncReport = new PackageSyncReport();
- PackageSource packageSource = (PackageSource) testAdapters.get(cs);
- packageSource.synchronizePackages(testLastSyncReport, testExistingPackages.get(cs));
- return true;
- }
- }
- }
-
- System.out.println("!!!!!!!!!!");
- System.out.println("SYNC: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
- return true;
- }
-
- @Override
- public boolean testConnection(int contentSourceId) throws Exception {
- if (testAdapters != null) {
- for (ContentSource cs : testAdapters.keySet()) {
- if (cs.getId() == contentSourceId) {
- testAdapters.get(cs).testConnection();
- return true;
- }
- }
- }
-
- System.out.println("!!!!!!!!!!");
- System.out.println("CONN: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
- return true;
- }
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginServiceMBean.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginServiceMBean.java
deleted file mode 100644
index bbdebaf..0000000
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginServiceMBean.java
+++ /dev/null
@@ -1,24 +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.test;
-
-import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
-
-public interface TestContentServerPluginServiceMBean extends ServerPluginServiceManagement {
-}
\ No newline at end of file
commit 9c04d763bd263eee20e3632b86c4b8412a9dbfb1
Merge: 961fba0... 5908572...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 10 12:29:09 2009 -0500
Merge branch 'mazz'
Conflicts:
etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginService.java
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginServiceMBean.java
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginServiceMBean.java
modules/plugins/postfix/src/main/java/org/rhq/plugins/postfix/PostfixServerDiscoveryComponent.java
diff --cc etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
index 928f635,b183bdc..1e48ef8
--- a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
@@@ -15,4 -17,4 +17,4 @@@
<c:simple-property name="myCustomProperty" type="string" required="true" description="A property my plugin needs to be properly configured" />
</serverplugin:plugin-configuration>
--</generic-plugin>
++</generic-plugin>
diff --cc modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
index a5fa70c,529193b..ceb4ee0
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
@@@ -308,4 -308,4 +308,4 @@@ public abstract class AbstractEJB3Test
schedulerService = null;
}
}
--}
++}
commit a0c60c8b21032a0e49b8602d962503c8cc685829
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Tue Nov 10 11:39:46 2009 -0500
Cleaned up inappropriate use of @Overrides
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
index ba732e6..975199d 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
@@ -659,17 +659,14 @@ public class Repo implements Serializable, Taggable {
this.lastModifiedDate = System.currentTimeMillis();
}
- @Override
public Set<Tag> getTags() {
return tags;
}
- @Override
public void setTags(Set<Tag> tags) {
this.tags = tags;
}
- @Override
public boolean hasTag(Tag tag) {
if ((this.tags == null) || (tag == null)) {
return false;
@@ -687,7 +684,6 @@ public class Repo implements Serializable, Taggable {
}
- @Override
public void addTag(Tag tag) {
if (this.tags == null) {
this.tags = new HashSet<Tag>();
@@ -696,7 +692,6 @@ public class Repo implements Serializable, Taggable {
this.tags.add(tag);
}
- @Override
public void removeTag(Tag tag) {
if ((this.tags == null) || (tag == null)) {
return;
commit 59085723f1a77638233e2624f1cc555977ebba6a
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 10 10:14:49 2009 -0500
add a new "schedule" element to all plugin descriptors - this can allow us to implement the ability to schedule plugins for periodic work.
this isn't hooked into any implementation yet, though. just xml schema supports it
diff --git a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
index 928f635..b183bdc 100644
--- a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -4,13 +4,15 @@
displayName="My Custom Generic Plugin"
description="A custom generic plugin."
package="org.custom"
- pluginLifecycleListener="MyLifecycleListener"
version="1.0"
apiVersion="2.0"
xmlns="urn:xmlns:rhq-serverplugin.generic"
xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
xmlns:c="urn:xmlns:rhq-configuration">
+ <serverplugin:lifecycle-listener class="MyLifecycleListener">
+ </serverplugin:lifecycle-listener>
+
<serverplugin:plugin-configuration>
<c:simple-property name="myCustomProperty" type="string" required="true" description="A property my plugin needs to be properly configured" />
</serverplugin:plugin-configuration>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
index b1300f0..8c11b82 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -29,6 +29,8 @@ import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.LifecycleListenerType;
+
/**
* Provides functionality to manage plugins for a plugin container. Plugin containers
* can install their own plugin managers that are extensions to this class if they need to.
@@ -269,8 +271,9 @@ public class ServerPluginManager {
String pluginName = environment.getPluginName();
ServerPluginLifecycleListener instance = null;
- String className = environment.getPluginDescriptor().getPluginLifecycleListener();
- if (className != null) {
+ LifecycleListenerType lifecycleListener = environment.getPluginDescriptor().getLifecycleListener();
+ if (lifecycleListener != null) {
+ String className = lifecycleListener.getClazz();
String pkg = environment.getPluginDescriptor().getPackage();
if ((className.indexOf('.') == -1) && (pkg != null)) {
className = pkg + '.' + className;
diff --git a/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic.xml b/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic.xml
index 411c739..e38208d 100644
--- a/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic.xml
+++ b/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic.xml
@@ -3,11 +3,13 @@
<generic-plugin name="TestSimpleGenericPlugin"
displayName="Test Simple Generic Plugin"
description="A test generic plugin that is simple."
- pluginLifecycleListener="org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener"
version="1.0"
apiVersion="2.0"
xmlns="urn:xmlns:rhq-serverplugin.generic"
xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
xmlns:c="urn:xmlns:rhq-configuration">
+ <serverplugin:lifecycle-listener class="org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener">
+
+ </serverplugin:lifecycle-listener>
</generic-plugin>
\ No newline at end of file
diff --git a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
index 774d054..2ee2a5c 100644
--- a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
+++ b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd
@@ -42,7 +42,25 @@
<xs:complexType name="ServerPluginDescriptorType">
<xs:sequence minOccurs="0" maxOccurs="1">
- <xs:element name="plugin-configuration" type="config:configuration" />
+ <xs:element name="lifecycle-listener" minOccurs="0" maxOccurs="1" type="serverplugin:LifecycleListenerType">
+ <xs:annotation>
+ <xs:documentation>
+ A class that performs global initialization and shutdown of the plugin. If specified,
+ this class will be notified when the plugin is loaded and unloaded. This provides a place
+ for plugin developers to allocate global resources needed by all plugin components and
+ a place to clean up those resources. It can also be scheduled to perform periodic work.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="plugin-configuration" minOccurs="0" maxOccurs="1" type="config:configuration">
+ <xs:annotation>
+ <xs:documentation>
+ Plugin-wide configuration that can be useful to define the behavior of the plugin as
+ a whole. This is optional; only those plugins that require global configuration
+ will need to define plugin configuration.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
</xs:sequence>
<xs:attribute name="name" use="required">
<xs:annotation>
@@ -80,16 +98,6 @@
</xs:documentation>
</xs:annotation>
</xs:attribute>
- <xs:attribute name="pluginLifecycleListener" type="serverplugin:classNameType" use="optional">
- <xs:annotation>
- <xs:documentation>
- A class that performs global initialization and shutdown of the plugin. If specified,
- this class will be notified when the plugin is loaded and unloaded. This provides a place
- for plugin developers to allocate global resources needed by all plugin components and
- a place to clean up those resources.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
<xs:attribute name="version" type="xs:string">
<xs:annotation>
<xs:documentation>
@@ -106,6 +114,51 @@
</xs:attribute>
</xs:complexType>
+ <xs:complexType name="LifecycleListenerType">
+ <xs:sequence>
+ <xs:element name="schedule" minOccurs="0" maxOccurs="1" type="serverplugin:ScheduleType">
+ <xs:annotation>
+ <xs:documentation>
+ A schedule that defines when and how often to invoke the plugin listener. This is optional; only
+ those plugins that need to do work periodically will define a schedule.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ <xs:attribute name="class" type="serverplugin:classNameType" use="required">
+ <xs:annotation>
+ <xs:documentation>
+ The class that will be instantiated. This is a stateful object, once initialized, the same
+ instance will be used to start, stop and shutdown the plugin.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+
+ <xs:complexType name="ScheduleType">
+ <xs:sequence minOccurs="0" maxOccurs="1">
+ <xs:choice>
+ <xs:element name="period" type="xs:long">
+ <xs:annotation>
+ <xs:documentation>
+ A time period, in milliseconds, that define how often the schedule will trigger.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cron" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>
+ A "cron expression" which defines when the schedule should fire. A cron expression can be evaluated
+ to mean things such as: "At 8:00am every Monday through Friday" or "At 1:30am every last Friday of the month".
+ The cron expression syntax follows the rules defined by Quartz - see
+ http://www.opensymphony.com/quartz/api/org/quartz/CronExpression.html
+ </xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ </xs:choice>
+ </xs:sequence>
+ </xs:complexType>
+
<xs:simpleType name="classNameType">
<xs:restriction base="xs:string">
<xs:whiteSpace value="collapse" />
diff --git a/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java b/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
index 456e662..7f2029d 100644
--- a/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
+++ b/modules/enterprise/server/xml-schemas/src/test/java/org/rhq/enterprise/server/xmlschema/ServerPluginDescriptorUtilTest.java
@@ -22,14 +22,23 @@
*/
package org.rhq.enterprise.server.xmlschema;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
import java.net.URL;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Unmarshaller;
+import org.testng.annotations.AfterMethod;
import org.testng.annotations.Test;
import org.rhq.core.clientapi.descriptor.configuration.ConfigurationDescriptor;
+import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.LifecycleListenerType;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ScheduleType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.alert.AlertPluginDescriptorType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.generic.GenericPluginDescriptorType;
@@ -42,8 +51,14 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.generic.Generi
@Test
public class ServerPluginDescriptorUtilTest {
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() {
+ deleteAllTestPluginJars();
+ }
+
public void testGenericPluginDescriptorInJar() throws Exception {
- URL url = this.getClass().getClassLoader().getResource("test-serverplugin-generic.jar");
+ File jar = createPluginJar("test-serverplugin-generic.jar", "test-serverplugin-generic.xml");
+ URL url = jar.toURI().toURL();
ServerPluginDescriptorType descriptor = ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(url);
assert descriptor != null;
assert descriptor instanceof GenericPluginDescriptorType;
@@ -53,7 +68,12 @@ public class ServerPluginDescriptorUtilTest {
assert descriptor.getDisplayName().equals("generic display");
assert descriptor.getDescription().equals("generic description");
assert descriptor.getPackage().equals("generic.package");
- assert descriptor.getPluginLifecycleListener().equals("generic.plugin.lifecycle.listener");
+
+ LifecycleListenerType lifecycleListener = descriptor.getLifecycleListener();
+ ScheduleType schedule = lifecycleListener.getSchedule();
+ assert lifecycleListener.getClazz().equals("generic.plugin.lifecycle.listener");
+ assert schedule.getCron().equals("0 15 10 ? * MON-FRI");
+ assert schedule.getPeriod() == null;
ConfigurationDescriptor config = descriptor.getPluginConfiguration();
assert config != null;
@@ -74,7 +94,12 @@ public class ServerPluginDescriptorUtilTest {
assert descriptor.getDisplayName().equals("alert plugin display name");
assert descriptor.getDescription().equals("alert plugin wotgorilla?");
assert descriptor.getPackage().equals("org.alert.package.name.here");
- assert descriptor.getPluginLifecycleListener().equals("alertPluginLifecycleListener");
+
+ LifecycleListenerType lifecycleListener = descriptor.getLifecycleListener();
+ ScheduleType schedule = lifecycleListener.getSchedule();
+ assert lifecycleListener.getClazz().equals("alertPluginLifecycleListener");
+ assert schedule.getCron() == null;
+ assert schedule.getPeriod().longValue() == 1000L;
ConfigurationDescriptor config = descriptor.getPluginConfiguration();
assert config != null;
@@ -91,4 +116,55 @@ public class ServerPluginDescriptorUtilTest {
assert type instanceof ServerPluginDescriptorType : (testXml + ": invalid server plugin descriptor: " + type);
return (ServerPluginDescriptorType) type;
}
+
+ private File createPluginJar(String jarName, String descriptorXmlFilename) throws Exception {
+ FileOutputStream stream = null;
+ JarOutputStream out = null;
+ InputStream in = null;
+
+ try {
+ File pluginDir = getPluginDirectory();
+ pluginDir.mkdirs();
+ File jarFile = new File(pluginDir, jarName);
+ stream = new FileOutputStream(jarFile);
+ out = new JarOutputStream(stream);
+
+ // Add archive entry for the descriptor
+ JarEntry jarAdd = new JarEntry("META-INF/rhq-serverplugin.xml");
+ jarAdd.setTime(System.currentTimeMillis());
+ out.putNextEntry(jarAdd);
+
+ // Write the descriptor - note that we assume the xml file is in the test classloader
+ in = getClass().getClassLoader().getResourceAsStream(descriptorXmlFilename);
+ StreamUtil.copy(in, out, false);
+
+ return jarFile;
+ } finally {
+ if (in != null) {
+ in.close();
+ }
+ if (out != null) {
+ out.close();
+ }
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ }
+
+ private void deleteAllTestPluginJars() {
+ File[] files = getPluginDirectory().listFiles();
+ if (files != null) {
+ for (File file : files) {
+ if (file.getName().endsWith(".jar")) {
+ file.delete();
+ }
+ }
+ }
+ return;
+ }
+
+ private File getPluginDirectory() {
+ return new File(System.getProperty("java.io.tmpdir"), "xml-schemas-test");
+ }
}
diff --git a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-alert.xml b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-alert.xml
index 8d6af78..b7affce 100644
--- a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-alert.xml
+++ b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-alert.xml
@@ -6,12 +6,17 @@
displayName="alert plugin display name"
name="alert plugin name"
package="org.alert.package.name.here"
- pluginLifecycleListener="alertPluginLifecycleListener"
xmlns="urn:xmlns:rhq-serverplugin.alert"
xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
xmlns:c="urn:xmlns:rhq-configuration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <serverplugin:lifecycle-listener class="alertPluginLifecycleListener">
+ <serverplugin:schedule>
+ <serverplugin:period>1000</serverplugin:period>
+ </serverplugin:schedule>
+ </serverplugin:lifecycle-listener>
+
<serverplugin:plugin-configuration>
<c:simple-property name="alertprop1" />
</serverplugin:plugin-configuration>
diff --git a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.jar b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.jar
deleted file mode 100644
index 94d653f..0000000
Binary files a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.jar and /dev/null differ
diff --git a/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
new file mode 100644
index 0000000..a72f0a3
--- /dev/null
+++ b/modules/enterprise/server/xml-schemas/src/test/resources/test-serverplugin-generic.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<generic-plugin apiVersion="1.2"
+ version="2.3"
+ name="generic name"
+ displayName="generic display"
+ description="generic description"
+ package="generic.package"
+ xmlns="urn:xmlns:rhq-serverplugin.generic"
+ xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
+ xmlns:c="urn:xmlns:rhq-configuration"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+ <serverplugin:lifecycle-listener class="generic.plugin.lifecycle.listener">
+ <serverplugin:schedule>
+ <!-- Fire at 10:15am every weekday -->
+ <serverplugin:cron>0 15 10 ? * MON-FRI</serverplugin:cron>
+ </serverplugin:schedule>
+ </serverplugin:lifecycle-listener>
+
+ <serverplugin:plugin-configuration>
+ <c:simple-property name="prop1" />
+ </serverplugin:plugin-configuration>
+</generic-plugin>
commit 42c5c6c3fa083199ac862fe61045668c4e45eb80
Author: Pradeep Kilambi <pkilambi(a)redhat.com>
Date: Mon Nov 9 19:03:18 2009 -0500
test to check delete query
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java
index a07264e..fd33580 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java
@@ -81,5 +81,15 @@ public class DistributionManagerBeanTest extends AbstractEJB3Test {
assert results.size() != 0;
+ Query querydel = em.createNamedQuery(distfile.DELETE_BY_DIST_ID);
+
+ querydel.setParameter("distId", distro.getId());
+
+ querydel.executeUpdate();
+
+ List<DistributionFile> resultsdel = query.getResultList();
+
+ assert resultsdel.size() == 0;
+
}
}
commit e833d3cb42ec732c2d46402f719bf5a43f715405
Author: Pradeep Kilambi <pkilambi(a)redhat.com>
Date: Mon Nov 9 18:57:03 2009 -0500
tests for new distrofiles support
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java
index cb06066..a07264e 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java
@@ -1,5 +1,9 @@
package org.rhq.enterprise.server.content.test;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
import javax.transaction.TransactionManager;
import org.testng.annotations.AfterMethod;
@@ -8,6 +12,7 @@ import org.testng.annotations.Test;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.content.Distribution;
+import org.rhq.core.domain.content.DistributionFile;
import org.rhq.core.domain.content.DistributionType;
import org.rhq.enterprise.server.content.DistributionManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
@@ -57,4 +62,24 @@ public class DistributionManagerBeanTest extends AbstractEJB3Test {
distro = distManager.getDistributionByLabel(kslabel);
assert distro == null;
}
+
+ @Test(enabled = ENABLED)
+ public void testDistributionFiles() throws Exception {
+ String kslabel = "testCreateDeleteRepo";
+ String kspath = "/tmp";
+ int id = distManager.createDistribution(overlord, kslabel, kspath, distType).getId();
+ Distribution distro = distManager.getDistributionByLabel(kslabel);
+
+ DistributionFile distfile = new DistributionFile(distro, "vmlinux", "d41d8cd98f00b204e9800998ecf8427e");
+
+ EntityManager em = getEntityManager();
+ em.persist(distfile);
+ Query query = em.createNamedQuery(distfile.SELECT_BY_DIST_ID);
+
+ query.setParameter("distId", distro.getId());
+ List<DistributionFile> results = query.getResultList();
+
+ assert results.size() != 0;
+
+ }
}
commit 13cc2dfe18028033071bd01316a5ab4015bb0e9b
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 9 18:41:20 2009 -0500
write a test that confirms the PC and listener lifecycle is correct
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index c61849a..a8696dd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -259,21 +259,28 @@ public class MasterServerPluginContainer {
plugins = new HashMap<URL, ServerPluginDescriptorType>();
- File[] pluginFiles = this.configuration.getPluginDirectory().listFiles();
- for (File pluginFile : pluginFiles) {
- if (pluginFile.getName().endsWith(".jar")) {
- URL pluginUrl = pluginFile.toURI().toURL();
-
- try {
- ServerPluginDescriptorType descriptor;
- descriptor = ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginUrl);
- if (descriptor != null) {
- log.debug("pre-loaded server plugin from URL: " + pluginUrl);
- plugins.put(pluginUrl, descriptor);
+ File pluginDirectory = this.configuration.getPluginDirectory();
+
+ if (pluginDirectory != null) {
+ File[] pluginFiles = pluginDirectory.listFiles();
+
+ if (pluginFiles != null) {
+ for (File pluginFile : pluginFiles) {
+ if (pluginFile.getName().endsWith(".jar")) {
+ URL pluginUrl = pluginFile.toURI().toURL();
+
+ try {
+ ServerPluginDescriptorType descriptor;
+ descriptor = ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginUrl);
+ if (descriptor != null) {
+ log.debug("pre-loaded server plugin from URL: " + pluginUrl);
+ plugins.put(pluginUrl, descriptor);
+ }
+ } catch (Throwable t) {
+ // for some reason, the plugin failed to load - it will be ignored
+ log.error("Plugin at [" + pluginUrl + "] could not be pre-loaded. Ignoring it.", t);
+ }
}
- } catch (Throwable t) {
- // for some reason, the plugin failed to load - it will be ignored
- log.error("Plugin at [" + pluginUrl + "] could not be pre-loaded. Ignoring it.", t);
}
}
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
new file mode 100644
index 0000000..0fa64df
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
@@ -0,0 +1,121 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc.generic;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.util.jar.JarEntry;
+import java.util.jar.JarOutputStream;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.State;
+import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericPluginManager;
+import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener.LifecycleState;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+
+@Test
+public class GenericServerPluginTest extends AbstractEJB3Test {
+ private TestGenericServerPluginService pluginService;
+
+ @BeforeMethod
+ public void beforeMethod() throws Exception {
+ this.pluginService = new TestGenericServerPluginService();
+ deleteAllTestPluginJars(); // remove any old server plugins that might be still around
+ prepareCustomServerPluginService(this.pluginService);
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() throws Exception {
+ unprepareServerPluginService();
+ deleteAllTestPluginJars(); // remove any server plugins that tests created
+ this.pluginService = null;
+ }
+
+ public void testSimpleGenericPlugin() throws Exception {
+ // tests that the lifecycle of the plugin container and the listener is correct
+ createPluginJar("testSimpleGenericPlugin.jar", "serverplugins/simple-generic.xml");
+ this.pluginService.startMasterPluginContainer();
+
+ TestGenericServerPluginContainer pc = this.pluginService.genericPC;
+ assert pc.state == State.STARTED;
+
+ TestGenericPluginManager pm = (TestGenericPluginManager) pc.getPluginManager();
+ TestLifecycleListener listener = (TestLifecycleListener) pm.listeners.values().iterator().next();
+ assert listener.state == LifecycleState.STARTED;
+
+ this.pluginService.stopMasterPluginContainer();
+
+ assert pc.state == State.UNINITIALIZED;
+ assert listener.state == LifecycleState.UNINITIALIZED;
+ }
+
+ private File createPluginJar(String jarName, String descriptorXmlFilename) throws Exception {
+ FileOutputStream stream = null;
+ JarOutputStream out = null;
+ InputStream in = null;
+
+ try {
+ this.pluginService.masterConfig.getPluginDirectory().mkdirs();
+ File jarFile = new File(this.pluginService.masterConfig.getPluginDirectory(), jarName);
+ stream = new FileOutputStream(jarFile);
+ out = new JarOutputStream(stream);
+
+ // Add archive entry for the descriptor
+ JarEntry jarAdd = new JarEntry("META-INF/rhq-serverplugin.xml");
+ jarAdd.setTime(System.currentTimeMillis());
+ out.putNextEntry(jarAdd);
+
+ // Write the descriptor - note that we assume the xml file is in the test classloader
+ in = getClass().getClassLoader().getResourceAsStream(descriptorXmlFilename);
+ StreamUtil.copy(in, out, false);
+
+ return jarFile;
+ } finally {
+ if (in != null) {
+ in.close();
+ }
+ if (out != null) {
+ out.close();
+ }
+ if (stream != null) {
+ stream.close();
+ }
+ }
+ }
+
+ private void deleteAllTestPluginJars() {
+ File[] files = this.pluginService.masterConfig.getPluginDirectory().listFiles();
+ if (files != null) {
+ for (File file : files) {
+ if (file.getName().endsWith(".jar")) {
+ file.delete();
+ }
+ }
+ }
+ return;
+ }
+
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
new file mode 100644
index 0000000..b6822e0
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
@@ -0,0 +1,172 @@
+/*
+ * 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.plugin.pc.generic;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginManager;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
+
+/**
+ * Used as a mock service for the generic server plugin container.
+ */
+public class TestGenericServerPluginService extends ServerPluginService implements TestGenericServerPluginServiceMBean {
+ public enum State {
+ INITIALIZED, STARTED, STOPPED, UNINITIALIZED
+ }
+
+ // public so tests can directly set these
+ public TestMasterServerPluginContainer master;
+ public TestGenericServerPluginContainer genericPC;
+ public MasterServerPluginContainerConfiguration masterConfig;
+
+ public TestGenericServerPluginService() {
+ // build the config at constructor time so tests have it even before the PC is initialized
+ File dir = new File(System.getProperty("java.io.tmpdir"), "test-server-plugins");
+ this.masterConfig = new MasterServerPluginContainerConfiguration(dir, dir, dir, null);
+ }
+
+ @Override
+ public MasterServerPluginContainer createMasterPluginContainer() {
+ this.master = new TestMasterServerPluginContainer();
+ this.master.initialize(this.masterConfig);
+ return this.master;
+ }
+
+ /**
+ * The test master PC
+ */
+ class TestMasterServerPluginContainer extends MasterServerPluginContainer {
+ @Override
+ protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
+ ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(1);
+ genericPC = new TestGenericServerPluginContainer(this);
+ pcs.add(genericPC);
+ return pcs;
+ }
+
+ @Override
+ protected ClassLoader createRootServerPluginClassLoader() {
+ return this.getClass().getClassLoader();
+ }
+
+ @Override
+ protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
+ // if our test never setup any plugins, ignore it and just return an empty map
+ File pluginDir = getConfiguration().getPluginDirectory();
+ if (pluginDir == null || pluginDir.listFiles() == null || pluginDir.listFiles().length == 0) {
+ return new HashMap<URL, ServerPluginDescriptorType>();
+ } else {
+ return super.preloadAllPlugins();
+ }
+ }
+ }
+
+ /**
+ * The test generic PC.
+ */
+ class TestGenericServerPluginContainer extends GenericServerPluginContainer {
+ public State state = State.UNINITIALIZED;
+
+ public TestGenericServerPluginContainer(MasterServerPluginContainer master) {
+ super(master);
+ }
+
+ @Override
+ protected ServerPluginManager createPluginManager() {
+ TestGenericPluginManager pm = new TestGenericPluginManager(this);
+ return pm;
+ }
+
+ @Override
+ public synchronized void initialize() throws Exception {
+ if (state == State.UNINITIALIZED) {
+ state = State.INITIALIZED;
+ } else {
+ System.out.println("!!! PC LIFECYCLE WAS BAD - THIS IS A BUG !!!");
+ throw new IllegalStateException("not uninitialized: " + state);
+ }
+ super.initialize();
+ }
+
+ @Override
+ public synchronized void start() {
+ if (state == State.INITIALIZED) {
+ state = State.STARTED;
+ } else {
+ System.out.println("!!! PC LIFECYCLE WAS BAD - THIS IS A BUG !!!");
+ throw new IllegalStateException("not initialized: " + state);
+ }
+ super.start();
+ }
+
+ @Override
+ public synchronized void stop() {
+ if (state == State.STARTED) {
+ state = State.STOPPED;
+ } else {
+ System.out.println("!!! PC LIFECYCLE WAS BAD - THIS IS A BUG !!!");
+ throw new IllegalStateException("not started: " + state);
+ }
+ super.stop();
+ }
+
+ @Override
+ public synchronized void shutdown() {
+ if (state == State.STOPPED) {
+ state = State.UNINITIALIZED;
+ } else {
+ System.out.println("!!! PC LIFECYCLE WAS BAD - THIS IS A BUG !!!");
+ throw new IllegalStateException("not stopped: " + state);
+ }
+ super.shutdown();
+ }
+ }
+
+ /**
+ * The test plugin manager.
+ */
+ class TestGenericPluginManager extends ServerPluginManager {
+ public final Map<String, ServerPluginLifecycleListener> listeners;
+
+ public TestGenericPluginManager(TestGenericServerPluginContainer pc) {
+ super(pc);
+ listeners = new HashMap<String, ServerPluginLifecycleListener>();
+ }
+
+ @Override
+ protected ServerPluginLifecycleListener createServerPluginLifecycleListener(ServerPluginEnvironment environment)
+ throws Exception {
+ ServerPluginLifecycleListener listener = super.createServerPluginLifecycleListener(environment);
+ listeners.put(environment.getPluginName(), listener);
+ return listener;
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginServiceMBean.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginServiceMBean.java
new file mode 100644
index 0000000..4ef9c65
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginServiceMBean.java
@@ -0,0 +1,24 @@
+/*
+ * 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.plugin.pc.generic;
+
+import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
+
+public interface TestGenericServerPluginServiceMBean extends ServerPluginServiceManagement {
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestLifecycleListener.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestLifecycleListener.java
new file mode 100644
index 0000000..c49b22c
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestLifecycleListener.java
@@ -0,0 +1,91 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc.generic;
+
+import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
+
+/**
+ * A sample lifecycle listener for the sample generic plugin. This listener will be
+ * the main interface the server uses to start and stop the plugin.
+ */
+public class TestLifecycleListener implements ServerPluginLifecycleListener {
+
+ public enum LifecycleState {
+ UNINITIALIZED, INITIALIZED, STARTED, STOPPED
+ };
+
+ public ServerPluginContext context;
+ public LifecycleState state = LifecycleState.UNINITIALIZED;
+
+ public void initialize(ServerPluginContext context) throws Exception {
+ this.context = context;
+ if (state == LifecycleState.UNINITIALIZED) {
+ state = LifecycleState.INITIALIZED;
+ } else {
+ println("!!! lifecycle listener is in a bad state - this is a BUG !!!: " + state);
+ }
+ println("test server plugin has been initialized");
+ }
+
+ public void start() {
+ if (state == LifecycleState.INITIALIZED) {
+ state = LifecycleState.STARTED;
+ } else {
+ println("!!! lifecycle listener is in a bad state - this is a BUG !!!: " + state);
+ }
+ println("test server plugin has started");
+ }
+
+ public void stop() {
+ if (state == LifecycleState.STARTED) {
+ state = LifecycleState.STOPPED;
+ } else {
+ println("!!! lifecycle listener is in a bad state - this is a BUG !!!: " + state);
+ }
+ println("test server plugin has stopped");
+ }
+
+ public void shutdown() {
+ if (state == LifecycleState.STOPPED) {
+ state = LifecycleState.UNINITIALIZED;
+ } else {
+ println("!!! lifecycle listener is in a bad state - this is a BUG !!!: " + state);
+ }
+ println("test server plugin has been shut down");
+ }
+
+ private void println(String msg) {
+ System.out.println(msg + "!!! : " + this);
+ }
+
+ @Override
+ public String toString() {
+ if (this.context == null) {
+ return "<no context>";
+ }
+
+ StringBuilder str = new StringBuilder();
+ str.append("plugin-name=").append(this.context.getPluginEnvironment().getPluginName()).append(",");
+ str.append("plugin-url=").append(this.context.getPluginEnvironment().getPluginUrl()).append(",");
+ str.append("data-dir=").append(this.context.getDataDirectory()).append(",");
+ str.append("tmp-dir=").append(this.context.getTemporaryDirectory()); // do not append ,
+ return str.toString();
+ }
+}
diff --git a/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic.xml b/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic.xml
new file mode 100644
index 0000000..411c739
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/resources/serverplugins/simple-generic.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<generic-plugin name="TestSimpleGenericPlugin"
+ displayName="Test Simple Generic Plugin"
+ description="A test generic plugin that is simple."
+ pluginLifecycleListener="org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener"
+ version="1.0"
+ apiVersion="2.0"
+ xmlns="urn:xmlns:rhq-serverplugin.generic"
+ xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+</generic-plugin>
\ No newline at end of file
commit f0d7e99c5c82f43da612d4708bc2909f36e9a23b
Merge: b895aba... 961fba0...
Author: Partha Aji <paji(a)redhat.com>
Date: Mon Nov 9 17:21:16 2009 -0500
Merge branch 'master' into linux-config
commit 2b01c0c015b94e11f42f9093004e46ea157ee8fb
Author: Pradeep Kilambi <pkilambi(a)redhat.com>
Date: Mon Nov 9 16:59:40 2009 -0500
Task#822 Adding new database tables and domain logic to handle kickstart files associated to each distribution tree
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index 19bd11e..a35452d 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -22,7 +22,7 @@
<properties>
<scm.module.path>modules/core/dbutils/</scm.module.path>
- <db.schema.version>2.64</db.schema.version>
+ <db.schema.version>2.65</db.schema.version>
</properties>
<dependencies>
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml
index 4528186..8b2d89f 100644
--- a/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml
+++ b/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml
@@ -354,6 +354,18 @@
<column name="NAME" size="200" type="VARCHAR2" required="true"/>
<column name="DESCRIPTION" size="500" type="VARCHAR2" required="false"/>
</table>
+
+ <table name="RHQ_DISTRIBUTION_FILE">
+ <column name="DISTRIBUTION_ID" type="INTEGER" primarykey="true" required="true" references="RHQ_DISTRIBUTION"/>
+ <column name="RELATIVE_FILENAME" size="256" type="VARCHAR2" required="true"/>
+ <column name="MD5SUM" size="64" type="VARCHAR2" required="true"/>
+ <column name="LAST_MODIFIED" type="LONG" required="true"/>
+
+ <index name="RHQ_DISTRIBUTION_FILE_IDX" unique="true">
+ <field ref="DISTRIBUTION_ID"/>
+ <field ref="RELATIVE_FILENAME"/>
+ </index>
+ </table>
</dbsetup>
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 e93ff69..5dfb7e9 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -2046,23 +2046,64 @@
<schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
<schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
</schemaSpec>
-
-
- <!-- Generic tagging support -->
+
+ <!-- Generic tagging support -->
<schemaSpec version="2.64">
- <schema-createSequence name="RHQ_TAG_ID_SEQ" initial="10001" />
- <schema-directSQL>
- <statement>
- CREATE TABLE RHQ_TAG ( ID INTEGER PRIMARY KEY )
- </statement>
- </schema-directSQL>
- <schema-alterColumn table="RHQ_TAG" column="ID" nullable="false" />
- <schema-addColumn table="RHQ_TAG" column="NAME" precision="200" columnType="VARCHAR2" />
- <schema-alterColumn table="RHQ_TAG" column="NAME" nullable="false" />
- <schema-addColumn table="RHQ_TAG" column="DESCRIPTION" precision="500" columnType="VARCHAR2" />
+ <schema-createSequence name="RHQ_TAG_ID_SEQ" initial="10001" />
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_TAG ( ID INTEGER PRIMARY KEY )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_TAG" column="ID" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="NAME" precision="200" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_TAG" column="NAME" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="DESCRIPTION" precision="500" columnType="VARCHAR2" />
+ </schemaSpec>
+
+ <!-- Distribution Files -->
+ <schemaSpec version="2.65">
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID INTEGER )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="DISTRIBUTION_ID" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" precision="256" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" precision="64" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" columnType="LONG" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" nullable="false" />
+ <schema-directSQL>
+ <statement targetDBVendor="postgresql">
+ CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
+ ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
+ </statement>
+ <statement targetDBVendor="oracle">
+ CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
+ ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
+ </statement>
+ </schema-directSQL>
+ <schema-directSQL>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_DISTRIBUTION_FILE
+ ADD CONSTRAINT RHQ_DIST_FILE_FKEY
+ FOREIGN KEY ( DISTRIBUTION_ID)
+ REFERENCES RHQ_DISTRIBUTION ( ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_DISTRIBUTION_FILE
+ ADD CONSTRAINT RHQ_DIST_FILE_FKEY
+ FOREIGN KEY ( DISTRIBUTION_ID)
+ REFERENCES RHQ_DISTRIBUTION ( ID )
+ </statement>
+ </schema-directSQL>
+
</schemaSpec>
+
</dbupgrade>
</target>
</project>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFile.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFile.java
new file mode 100644
index 0000000..30493a5
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFile.java
@@ -0,0 +1,165 @@
+/*
+ * 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.content;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.persistence.PrePersist;
+import javax.persistence.Table;
+
+/**
+ * This is the many-to-many entity that correlates a distribution with its associated files.
+ *
+ * @author Pradeep Kilambi
+ */
+@Entity
+(a)IdClass(DistributionFilePK.class)
+@NamedQueries( {
+ @NamedQuery(name = DistributionFile.SELECT_BY_DIST_ID, query = "SELECT df from DistributionFile df WHERE df.distribution.id = :distId"),
+ @NamedQuery(name = DistributionFile.DELETE_BY_DIST_ID, query = "DELETE DistributionFile df WHERE df.distribution.id = :distId") })
+@Table(name = "RHQ_DISTRIBUTION_FILE")
+public class DistributionFile {
+ public static final String SELECT_BY_DIST_ID = "DistributionFile.selectByDistId";
+ public static final String DELETE_BY_DIST_ID = "DistributionFile.deleteByDistId";
+
+ private static final long serialVersionUID = 1L;
+
+ /*
+ * http://opensource.atlassian.com/projects/hibernate/browse/EJB-286 Hibernate seems to want these mappings in the
+ * @IdClass and ignore these here, even though the mappings should be here and no mappings should be needed in the
+ * @IdClass.
+ */
+
+ @Id
+ @ManyToOne
+ @JoinColumn(name = "DISTRIBUTION_ID", referencedColumnName = "ID", nullable = false, insertable = false, updatable = false)
+ private Distribution distribution;
+
+ @Column(name = "RELATIVE_FILENAME", nullable = false)
+ private String relative_filename;
+
+ @Column(name = "LAST_MODIFIED", nullable = false)
+ private long last_modified;
+
+ @Column(name = "MD5SUM", nullable = false)
+ private String md5sum;
+
+ protected DistributionFile() {
+ }
+
+ public DistributionFile(Distribution dist, String filenameIn, String md5sum) {
+ this.distribution = dist;
+ this.relative_filename = filenameIn;
+ this.md5sum = md5sum;
+ }
+
+ public DistributionFilePK getDistributionFilePK() {
+ return new DistributionFilePK(distribution);
+ }
+
+ public void setDistributionFilePK(DistributionFilePK pk) {
+ this.distribution = pk.getDistribution();
+ }
+
+ public long getLastModified() {
+ return last_modified;
+ }
+
+ public Distribution getDistribution() {
+ return distribution;
+ }
+
+ public void setDistribution(Distribution dist) {
+ this.distribution = dist;
+ }
+
+ public String getRelativeFilename() {
+ return relative_filename;
+ }
+
+ public void setRelativeFilename(String relative_filename) {
+ this.relative_filename = relative_filename;
+ }
+
+ public String getMd5sum() {
+ return md5sum;
+ }
+
+ public void setMd5sum(String md5sum) {
+ this.md5sum = md5sum;
+ }
+
+ @PrePersist
+ void onPersist() {
+ this.last_modified = System.currentTimeMillis();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder str = new StringBuilder("DistributionFile: ");
+ str.append("ctime=[").append(new Date(this.last_modified)).append("]");
+ str.append(", ch=[").append(this.relative_filename).append("]");
+ str.append(", ch=[").append(this.md5sum).append("]");
+ str.append(", cs=[").append(this.distribution).append("]");
+ return str.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = (31 * result) + ((distribution == null) ? 0 : distribution.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if ((obj == null) || (!(obj instanceof DistributionFile))) {
+ return false;
+ }
+
+ final DistributionFile other = (DistributionFile) obj;
+
+ if (distribution == null) {
+ if (distribution != null) {
+ return false;
+ }
+ } else if (!distribution.equals(other.distribution)) {
+ return false;
+ }
+
+ return true;
+ }
+
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFilePK.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFilePK.java
new file mode 100644
index 0000000..525d3aa
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/DistributionFilePK.java
@@ -0,0 +1,93 @@
+/*
+ * 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.content;
+
+import java.io.Serializable;
+
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+public class DistributionFilePK implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /*
+ * http://opensource.atlassian.com/projects/hibernate/browse/EJB-286 Hibernate seems to want these mappings here,
+ * even though this class is an @IdClass and it should not need the mappings here. The mappings belong in the
+ * entity itself.
+ */
+
+ @JoinColumn(name = "DISTRIBUTION_ID", referencedColumnName = "ID", nullable = false)
+ @ManyToOne
+ private Distribution distribution;
+
+ public DistributionFilePK() {
+ }
+
+ public DistributionFilePK(Distribution dist) {
+ this.distribution = dist;
+ }
+
+ public Distribution getDistribution() {
+ return distribution;
+ }
+
+ public void setDistribution(Distribution kstree) {
+ this.distribution = kstree;
+ }
+
+ @Override
+ public String toString() {
+ return "DistributionFilePK: Distribution=[" + distribution + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = (31 * result) + ((distribution == null) ? 0 : distribution.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if ((obj == null) || (!(obj instanceof DistributionFilePK))) {
+ return false;
+ }
+
+ final DistributionFilePK other = (DistributionFilePK) obj;
+
+ if (distribution == null) {
+ if (other.distribution != null) {
+ return false;
+ }
+ } else if (!distribution.equals(other.distribution)) {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
index 522cbc2..078fc84 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
@@ -47,7 +47,7 @@ import javax.persistence.Table;
@NamedQueries( {
@NamedQuery(name = RepoDistribution.DELETE_BY_KICKSTART_TREE_ID, query = "DELETE RepoDistribution rkt WHERE rkt.dist.id = :distId"),
@NamedQuery(name = RepoDistribution.DELETE_BY_REPO_ID, query = "DELETE RepoDistribution rkt WHERE rkt.repo.id = :repoId") })
-@Table(name = "RHQ_REPO_DIST_MAP_KEY")
+@Table(name = "RHQ_REPO_DISTRIBUTION")
public class RepoDistribution implements Serializable {
public static final String DELETE_BY_KICKSTART_TREE_ID = "RepoDistribution.deleteByKickstartTreeId";
public static final String DELETE_BY_REPO_ID = "RepoDistribution.deleteByRepoId";
@@ -80,13 +80,13 @@ public class RepoDistribution implements Serializable {
this.dist = dist;
}
- public RepoDistributionPK getRepoKickstartTreePK() {
+ public RepoDistributionPK getRepoDistributionPK() {
return new RepoDistributionPK(repo, dist);
}
- public void setRepoKickstartTreePK(RepoDistributionPK pk) {
+ public void setRepoDistributionPK(RepoDistributionPK pk) {
this.repo = pk.getRepo();
- this.dist = pk.getKickstartTree();
+ this.dist = pk.getDistribution();
}
/**
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistributionPK.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistributionPK.java
index 4679484..3cd7d2e 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistributionPK.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistributionPK.java
@@ -67,17 +67,17 @@ public class RepoDistributionPK implements Serializable {
this.repo = repo;
}
- public Distribution getKickstartTree() {
+ public Distribution getDistribution() {
return dist;
}
- public void setContentSource(Distribution kstree) {
+ public void setDistribution(Distribution kstree) {
this.dist = kstree;
}
@Override
public String toString() {
- return "RepoContentSourcePK: repo=[" + repo + "]; contentSource=[" + dist + "]";
+ return "RepoDistributionPK: repo=[" + repo + "]; distribution=[" + dist + "]";
}
@Override
@@ -94,7 +94,7 @@ public class RepoDistributionPK implements Serializable {
return true;
}
- if ((obj == null) || (!(obj instanceof RepoContentSourcePK))) {
+ if ((obj == null) || (!(obj instanceof RepoDistributionPK))) {
return false;
}
commit 46e6fba95ce4961fd6b1a2a467040d5e3138f35c
Author: Sayli Karmarkar <skarmark(a)redhat.com>
Date: Mon Nov 9 16:34:29 2009 -0500
552 - updating db.schema.version in dbutil pom.xml for db changes
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index e60e46b..19bd11e 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -22,7 +22,7 @@
<properties>
<scm.module.path>modules/core/dbutils/</scm.module.path>
- <db.schema.version>2.63</db.schema.version>
+ <db.schema.version>2.64</db.schema.version>
</properties>
<dependencies>
commit 22bac4f38df454fc020f396c1af0f6cbe33148ef
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Mon Nov 9 15:56:05 2009 -0500
801 - Added EJB logic to import a candidate repo into a "real" repo in the system.
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 f991c5d..df0933a 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
@@ -430,6 +430,24 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
}
@RequiredPermission(Permission.MANAGE_INVENTORY)
+ public void importCandidateRepo(Subject subject, List<Integer> repoIds) throws RepoException {
+
+ for (Integer repoId : repoIds) {
+ Repo repo = entityManager.find(Repo.class, repoId);
+
+ if (repo == null) {
+ throw new RepoException("Unable to find candidate repo for import. ID: " + repoId);
+ }
+
+ if (!repo.isCandidate()) {
+ throw new RepoException("Unable to import repo, repo is already imported. ID: " + repoId);
+ }
+
+ repo.setCandidate(false);
+ }
+ }
+
+ @RequiredPermission(Permission.MANAGE_INVENTORY)
public RepoGroup createRepoGroup(Subject subject, RepoGroup repoGroup) throws RepoException {
validateRepoGroup(repoGroup);
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 6ab999b..b0a2dca 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
@@ -151,6 +151,17 @@ public interface RepoManagerLocal {
*/
void processRepoImportReport(Subject subject, RepoImportReport report, int contentSourceId, StringBuilder result);
+ /**
+ * Changes the specified repos from being candidates in the system into full blown repositories,
+ * allowing their packages to be syncced and resources to subscribe to them.
+ *
+ * @param subject user performing the import
+ * @param repoIds the repos being imported; they must refer to repos in the database and must be flagged
+ * as candidates (i.e. an error will occur if an already imported repo is specified)
+ * @throws RepoException if one or more of the repo IDs does not exist in the DB or is not a candidate
+ */
+ void importCandidateRepo(Subject subject, List<Integer> repoIds) throws RepoException;
+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// The following are shared with the Remote Interface
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
index 4aaf6d1..4cd6378 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
@@ -45,6 +45,8 @@ import org.rhq.enterprise.server.util.LookupUtil;
import java.util.Set;
import java.util.HashSet;
+import java.util.List;
+import java.util.ArrayList;
public class RepoManagerBeanTest extends AbstractEJB3Test {
@@ -296,4 +298,59 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
// Cleanup handled by rollback in tear down method
}
+ @Test(enabled = ENABLED)
+ public void importCandidateRepo() throws Exception {
+ // Setup
+ Repo candidate = new Repo("create me");
+ Repo created = repoManager.createCandidateRepo(overlord, candidate);
+
+ // Test
+ List<Integer> repoIds = new ArrayList<Integer>(1);
+ repoIds.add(created.getId());
+ repoManager.importCandidateRepo(overlord, repoIds);
+
+ // Verify
+ RepoCriteria repoCriteria = new RepoCriteria();
+ repoCriteria.addFilterId(created.getId());
+
+ PageList<Repo> repoList = repoManager.findReposByCriteria(overlord, repoCriteria);
+ assert repoList.size() == 1;
+
+ Repo verify = repoList.get(0);
+ assert verify != null;
+ assert !verify.isCandidate();
+ }
+
+ @Test(enabled = ENABLED)
+ public void importCandidateRepoBadId() throws Exception {
+ // Test
+ try {
+ List<Integer> repoIds = new ArrayList<Integer>(1);
+ repoIds.add(12345);
+ repoManager.importCandidateRepo(overlord, repoIds);
+ assert false;
+ }
+ catch (RepoException e) {
+ // Expected
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void importNonCandidateRepo() throws Exception {
+ // Setup
+ Repo nonCandidate = new Repo("create me");
+ Repo created = repoManager.createRepo(overlord, nonCandidate);
+
+ // Test
+ try {
+ List<Integer> repoIds = new ArrayList<Integer>(1);
+ repoIds.add(created.getId());
+ repoManager.importCandidateRepo(overlord, repoIds);
+ assert false;
+ }
+ catch (RepoException e) {
+ // Expected
+ }
+
+ }
}
\ No newline at end of file
commit b895aba9016245fe4d7f31180f30507955e66a34
Author: Shannon Hughes <shughes(a)scooby.rdu.redhat.com>
Date: Mon Nov 9 15:53:28 2009 -0500
modifying aliases agueas paths
diff --git a/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml
index a937098..01f5862 100644
--- a/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml
@@ -28,7 +28,7 @@
default="/etc/aliases"
description="the absolute paths of the configuration files, delimited with pipe characters"/>
<c:simple-property name="resourceConfigurationRootNode" required="true" readOnly="true"
- default="/files/etc/aliases/*"/>
+ default="/files/etc/aliases"/>
</plugin-configuration>
<resource-configuration>
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index e78033b..31c5bb9 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -117,6 +117,7 @@
<module>perftest</module>
<module>samba</module>
<module>postfix</module>
+ <module>aliases</module>
<module>snmptrapd</module>
<module>sshd</module>
<module>twitter</module>
commit 70ce7524abc85b87572fd7654bc53703d76e1838
Author: Sayli Karmarkar <skarmark(a)redhat.com>
Date: Mon Nov 9 15:03:22 2009 -0500
552 - adding db upgrade script for new table for tagging
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 0f0af77..e93ff69 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -2048,6 +2048,21 @@
</schemaSpec>
+ <!-- Generic tagging support -->
+ <schemaSpec version="2.64">
+ <schema-createSequence name="RHQ_TAG_ID_SEQ" initial="10001" />
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_TAG ( ID INTEGER PRIMARY KEY )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_TAG" column="ID" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="NAME" precision="200" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_TAG" column="NAME" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="DESCRIPTION" precision="500" columnType="VARCHAR2" />
+ </schemaSpec>
+
+
</dbupgrade>
</target>
</project>
commit 3d3be9b30f2a841693a07c2358499779c4cac3d5
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Mon Nov 9 13:57:08 2009 -0500
799 - Moved the logic to handle importing candidate repos to the EJB layer. Updated to add them as candidate repos and delete candidates that have previously been returned for a given provider.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoException.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoException.java
index 20082f8..7b9ae57 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoException.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/RepoException.java
@@ -18,10 +18,18 @@
*/
package org.rhq.enterprise.server.content;
+/**
+ * General exception used to convey issues in CRUD operations on a repo or repo group.
+ *
+ * @see org.rhq.core.domain.content.Repo
+ * @see org.rhq.core.domain.content.RepoGroup
+ */
public class RepoException extends ContentException {
private static final long serialVersionUID = 1L;
+ private RepoExceptionType type = RepoExceptionType.GENERAL;
+
public RepoException() {
}
@@ -37,4 +45,21 @@ public class RepoException extends ContentException {
super(message, cause);
}
+ /**
+ * Programmatic hook to determine if a repo operation failure was related to the repo name
+ * already existing.
+ *
+ * @return
+ */
+ public RepoExceptionType getType() {
+ return type;
+ }
+
+ public void setType(RepoExceptionType type) {
+ this.type = type;
+ }
+
+ public enum RepoExceptionType {
+ GENERAL, NAME_ALREADY_EXISTS
+ }
}
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 fd8301f..f991c5d 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
@@ -58,15 +58,29 @@ import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
import org.rhq.core.domain.util.PersistenceUtility;
import org.rhq.enterprise.server.RHQConstants;
+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.ContentServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.content.RepoImportReport;
+import org.rhq.enterprise.server.plugin.pc.content.RepoGroupDetails;
+import org.rhq.enterprise.server.plugin.pc.content.RepoDetails;
import org.rhq.enterprise.server.util.CriteriaQueryGenerator;
import org.rhq.enterprise.server.util.CriteriaQueryRunner;
@Stateless
public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
+
+ /**
+ * Refers to the default repo relationship created at DB setup time to represent a parent/child repo
+ * relationship.
+ * <p/>
+ * This probably isn't the best place to store this, but for now this is the primary usage of this
+ * relationship type.
+ */
+ private static final String PARENT_RELATIONSHIP_NAME = "parent";
+
private final Log log = LogFactory.getLog(RepoManagerBean.class);
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
@@ -74,10 +88,14 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
@EJB
private AuthorizationManagerLocal authzManager;
+
@IgnoreDependency
@EJB
private ContentSourceManagerLocal contentSourceManager;
+ @EJB
+ private SubjectManagerLocal subjectManager;
+
@RequiredPermission(Permission.MANAGE_INVENTORY)
public void deleteRepo(Subject subject, int repoId) {
log.debug("User [" + subject + "] is deleting repo [" + repoId + "]");
@@ -310,6 +328,108 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
}
@RequiredPermission(Permission.MANAGE_INVENTORY)
+ public void processRepoImportReport(Subject subject, RepoImportReport report,
+ int contentSourceId, StringBuilder result) {
+
+ // Import groups first
+ List<RepoGroupDetails> repoGroups = report.getRepoGroups();
+ int repoGroupCounter = 0;
+
+ for (RepoGroupDetails createMe : repoGroups) {
+ String name = createMe.getName();
+
+ RepoGroup existingGroup = getRepoGroupByName(name);
+ if (existingGroup == null) {
+ existingGroup = new RepoGroup(name);
+ existingGroup.setDescription(createMe.getDescription());
+
+ RepoGroupType groupType = getRepoGroupTypeByName(subject, createMe.getTypeName());
+ existingGroup.setRepoGroupType(groupType);
+
+ // Don't let the whole report blow up if one of these fails,
+ // but be sure to mention it to the report
+ try {
+ createRepoGroup(subject, existingGroup);
+ repoGroupCounter++;
+ }
+ catch (RepoException e) {
+
+ if (e.getType() == RepoException.RepoExceptionType.NAME_ALREADY_EXISTS) {
+ result.append("Skipping existing repo group [").append(name).append("]").append('\n');
+ }
+ else {
+ log.error("Error adding repo group [" + name + "]", e);
+ result.append("Could not add repo group [").append(name).append("]. See log for more information.").append('\n');
+ }
+ }
+ }
+ }
+ result.append("Imported [").append(repoGroupCounter).append("] repo groups.").append('\n');
+
+ // Hold on to all current candidate repos for the content provider. If any were not present in this
+ // report, remove them from the system (the rationale being, the content provider no longer knows
+ // about them and thus they cannot be imported).
+ RepoCriteria candidateReposCriteria = new RepoCriteria();
+ candidateReposCriteria.addFilterContentSourceIds(contentSourceId);
+ candidateReposCriteria.addFilterCandidate(true);
+
+ PageList<Repo> candidatesForThisProvider = findReposByCriteria(subject, candidateReposCriteria);
+
+ // Once the groups are in the system, import any repos that were added
+ List<RepoDetails> repos = report.getRepos();
+ int repoCounter = 0;
+
+ // First add repos that have no parent. We later add repos with a parent afterwards to prevent
+ // issues where both the parent and child are specified in this report.
+ for (RepoDetails createMe : repos) {
+
+ if (createMe.getParentRepoName() == null) {
+ try {
+ addCandidateRepo(contentSourceId, createMe);
+ removeRepoFromList(createMe.getName(), candidatesForThisProvider);
+ repoCounter++;
+ }
+ catch (Exception e) {
+
+ if (e instanceof RepoException &&
+ ((RepoException) e).getType() == RepoException.RepoExceptionType.NAME_ALREADY_EXISTS) {
+ result.append("Skipping addition of existing repo [").append(createMe.getName()).append("]").append('\n');
+ }
+ else {
+ log.error("Error processing repo [" + createMe + "]", e);
+ result.append("Could not add repo [").append(createMe.getName()).append("]. See log for more information.").append('\n');
+ }
+ }
+ }
+ }
+
+ // Take a second pass through the list checking for any repos that were created to be
+ // a child of another repo.
+ for (RepoDetails createMe : repos) {
+
+ if (createMe.getParentRepoName() != null) {
+ try {
+ addCandidateRepo(contentSourceId, createMe);
+ removeRepoFromList(createMe.getName(), candidatesForThisProvider);
+ repoCounter++;
+ }
+ catch (Exception e) {
+ log.error("Error processing repo [" + createMe + "]", e);
+ result.append("Could not add repo [").append(createMe.getName()).append("]. See log for more information.").append('\n');
+ }
+ }
+ }
+
+ result.append("Imported [").append(repoCounter).append("] repos.").append('\n');
+
+ // Any repos that haven't been removed from candidatesForThisProvider were not returned in this
+ // report, so remove them from the database.
+ for (Repo deleteMe : candidatesForThisProvider) {
+ deleteRepo(subject, deleteMe.getId());
+ }
+ }
+
+ @RequiredPermission(Permission.MANAGE_INVENTORY)
public RepoGroup createRepoGroup(Subject subject, RepoGroup repoGroup) throws RepoException {
validateRepoGroup(repoGroup);
@@ -604,7 +724,10 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
List<Repo> repos = getRepoByName(c.getName());
if (repos.size() != 0) {
- throw new RepoException("There is already a repo with the name of [" + c.getName() + "]");
+ RepoException e =
+ new RepoException("There is already a repo with the name of [" + c.getName() + "]");
+ e.setType(RepoException.RepoExceptionType.NAME_ALREADY_EXISTS);
+ throw e;
}
}
@@ -622,8 +745,81 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
RepoGroup existingRepoGroup = getRepoGroupByName(repoGroup.getName());
if (existingRepoGroup != null) {
- throw new RepoException("There is already a repo group with the name [" + repoGroup.getName() + "]");
+ RepoException e =
+ new RepoException("There is already a repo group with the name [" + repoGroup.getName() + "]");
+ e.setType(RepoException.RepoExceptionType.NAME_ALREADY_EXISTS);
+ throw e;
}
}
+ /**
+ * Performs the necessary logic to determine if a candidate repo should be added to the system, adding it
+ * in the process if it needs to. If the repo already exists in the system, this method is a no-op.
+ * <p/>
+ * Calling this method with a repo that has a parent assumes the parent has already been created. This call
+ * assumes the repo group has been created as well.
+ *
+ * @param contentSourceId identifies the content provider that introduced the candidate into the system
+ * @param createMe describes the candidate to be created
+ * @throws Exception if there is an error associating the content source with the repo or if the repo
+ * indicates a parent or repo group that does not exist
+ */
+ private void addCandidateRepo(int contentSourceId, RepoDetails createMe) throws Exception {
+
+ Subject overlord = subjectManager.getOverlord();
+ String name = createMe.getName();
+
+ List<Repo> existingRepo = getRepoByName(name);
+
+ // If the repo doesn't exist, create it.
+ if (existingRepo.size() != 0) {
+ return;
+ }
+
+ // Create and populate the repo
+ Repo addMe = new Repo(name);
+ addMe.setDescription(createMe.getDescription());
+
+ String createMeGroup = createMe.getRepoGroup();
+ if (createMeGroup != null) {
+ RepoGroup group = getRepoGroupByName(createMeGroup);
+ addMe.addRepoGroup(group);
+ }
+
+ // Add the new candidate to the database
+ addMe = createCandidateRepo(overlord, addMe);
+
+ // Associate the content provider that introduced the candidate with the repo
+ addContentSourcesToRepo(overlord, addMe.getId(), new int[] { contentSourceId });
+
+ // If the repo indicates it has a parent, create that relationship
+ String parentName = createMe.getParentRepoName();
+ if (parentName != null) {
+ List<Repo> parentList = getRepoByName(parentName);
+
+ if (parentList.size() == 0) {
+ String error = "Attempting to create repo [" + name + "] with parent [" + parentName
+ + "] but cannot find the parent";
+ log.error(error);
+ throw new RepoException(error);
+ } else {
+ Repo parent = parentList.get(0);
+ addRepoRelationship(overlord, addMe.getId(), parent.getId(), PARENT_RELATIONSHIP_NAME);
+ }
+ }
+ }
+
+ private void removeRepoFromList(String repoName, List<Repo> repoList) {
+ Repo deleteMe = null;
+ for (Repo checkMe : repoList) {
+ if (checkMe.getName().equals(repoName)) {
+ deleteMe = checkMe;
+ break;
+ }
+ }
+
+ if (deleteMe != null) {
+ repoList.remove(deleteMe);
+ }
+ }
}
\ No newline at end of file
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 f837a7c..6ab999b 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
@@ -34,6 +34,7 @@ import org.rhq.core.domain.criteria.PackageVersionCriteria;
import org.rhq.core.domain.resource.Resource;
import org.rhq.core.domain.util.PageControl;
import org.rhq.core.domain.util.PageList;
+import org.rhq.enterprise.server.plugin.pc.content.RepoImportReport;
@Local
public interface RepoManagerLocal {
@@ -139,6 +140,16 @@ public interface RepoManagerLocal {
*/
Repo createCandidateRepo(Subject subject, Repo repo) throws RepoException;
+ /**
+ * Handles a repo report from a content provider, adding and removing candidate repos as necessary into the
+ * database.
+ *
+ * @param subject user triggering the report processing
+ * @param report cannot be <code>null</code>
+ * @param contentSourceId identifies the content source that
+ * @param result buffer used to store the results of dealing with the report
+ */
+ void processRepoImportReport(Subject subject, RepoImportReport report, int contentSourceId, StringBuilder result);
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
index da42dca..77b6c27 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
@@ -66,8 +66,6 @@ import org.rhq.enterprise.server.util.LookupUtil;
public class ContentProviderManager {
private static final Log log = LogFactory.getLog(ContentProviderManager.class);
- private static final String PARENT_RELATIONSHIP_NAME = "parent";
-
private ContentProviderPluginManager pluginManager;
private Map<ContentSource, ContentProvider> adapters;
@@ -171,52 +169,16 @@ public class ContentProviderManager {
// Call to the plugin
RepoImportReport report = repoSource.importRepos();
- // Import groups first
- List<RepoGroupDetails> repoGroups = report.getRepoGroups();
-
- for (RepoGroupDetails createMe : repoGroups) {
- String name = createMe.getName();
-
- RepoGroup existingGroup = repoManager.getRepoGroupByName(name);
- if (existingGroup == null) {
- existingGroup = new RepoGroup(name);
- existingGroup.setDescription(createMe.getDescription());
-
- RepoGroupType groupType = repoManager.getRepoGroupTypeByName(overlord, createMe.getTypeName());
- existingGroup.setRepoGroupType(groupType);
-
- repoManager.createRepoGroup(overlord, existingGroup);
- }
- }
- progress.append("Number of repo groups imported: ").append(repoGroups.size());
-
- // Once the groups are in the system, import any repos that were added
- List<RepoDetails> repos = report.getRepos();
-
- for (RepoDetails createMe : repos) {
-
- // Will add repos with a parent afterwards to prevent issues where both the parent and
- // child are specified in this report.
- if (createMe.getParentRepoName() == null) {
- processRepo(contentSourceId, createMe);
- }
- }
-
- // Take a second pass through the list checking for any repos that were created to be
- // a child of another repo
- for (RepoDetails createMe : repos) {
-
- if (createMe.getParentRepoName() != null) {
- processRepo(contentSourceId, createMe);
- }
- }
+ repoManager.processRepoImportReport(overlord, report, contentSourceId, progress);
log.info("importRepos: [" + contentSource.getName() + "]: report has been merged ("
+ (System.currentTimeMillis() - start) + ")ms");
-
- progress.append("Number of new repos imported: ").append(repos.size());
}
+ // ------------------
+ // NOTE: This is being moved to the repo synchronization as part of Core Team A - Sprint 2
+ // ------------------
+
// If the provider is capable of handling packages, perform the package synchronization portion of the sync
if (provider instanceof PackageSource) {
PackageSource packageSource = (PackageSource) provider;
@@ -335,7 +297,7 @@ public class ContentProviderManager {
throw new Exception("Failed to sync content source [" + contentSourceId + "]", t);
} finally {
if (results != null) {
- results.setEndTime(new Long(System.currentTimeMillis()));
+ results.setEndTime(System.currentTimeMillis());
manager.mergeContentSourceSyncResults(results);
}
}
@@ -343,55 +305,6 @@ public class ContentProviderManager {
return true;
}
- private void processRepo(int contentSourceId, RepoDetails createMe) throws Exception {
-
- RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
- SubjectManagerLocal subjMgr = LookupUtil.getSubjectManager();
- Subject overlord = subjMgr.getOverlord();
-
- String name = createMe.getName();
-
- List<Repo> existingRepo = repoManager.getRepoByName(name);
- Repo repo;
-
- // If the repo doesn't exist, create it.
- if (existingRepo.size() == 0) {
- repo = new Repo(name);
- repo.setDescription(createMe.getDescription());
-
- String createMeGroup = createMe.getRepoGroup();
- if (createMeGroup != null) {
- RepoGroup group = repoManager.getRepoGroupByName(createMeGroup);
- repo.addRepoGroup(group);
- }
-
- repo = repoManager.createRepo(overlord, repo);
-
- String parentName = createMe.getParentRepoName();
- if (parentName != null) {
- List<Repo> parentList = repoManager.getRepoByName(parentName);
-
- if (parentList.size() == 0) {
- String error = "Attempting to create repo [" + name + "] with parent [" + parentName
- + "] but cannot find the parent";
- log.error(error);
- throw new RepoException(error);
- } else {
- Repo parent = parentList.get(0);
- repoManager.addRepoRelationship(overlord, repo.getId(), parent.getId(), PARENT_RELATIONSHIP_NAME);
- }
- }
-
- } else {
- repo = existingRepo.get(0);
- }
-
- // This call is safe even if the content source is already associated.
- // We either need to associate the content source with the newly created repo, or
- // associate the content source with the repo that was created elsewhere.
- repoManager.addContentSourcesToRepo(overlord, repo.getId(), new int[] { contentSourceId });
- }
-
/**
* Tests the connection to the content source that has the given ID.
*
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
index 139062c..e7a1212 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
@@ -71,6 +71,11 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
private static final String PACKAGE_VERSION = "1.0";
private static final String PACKAGE_ARCH = "noarch";
+ private static final String EXISTING_IMPORTED_REPO_NAME = "testRepoImportedExisting";
+ private static final String EXISTING_CANDIDATE_REPO_NAME = "testRepoCandidateExisting";
+
+ private static final String PREVIOUS_CANDIDATE_REPO_NAME = "testPreviousCandidate";
+
// The following variables need to be cleaned up at the end of the test
private ContentSourceType testSourceType;
@@ -189,13 +194,33 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
public void synchronizeContentSource() throws Exception {
// Setup
+ // --------------------------------------------
RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
Subject overlord = subjectManager.getOverlord();
TestContentProviderManager providerManager = new TestContentProviderManager();
+ // -> Add an already imported repo to the system so it already exists when the report introduces it
+ Repo existingImportedRepo = new Repo(EXISTING_IMPORTED_REPO_NAME);
+ existingImportedRepo.setCandidate(false);
+ existingImportedRepo.addContentSource(testSource);
+ repoManager.createRepo(overlord, existingImportedRepo);
+
+ // -> Simulate a candidate repo from a previous import that will be in this report as well
+ Repo existingCandidateRepo = new Repo(EXISTING_CANDIDATE_REPO_NAME);
+ existingCandidateRepo.setCandidate(true);
+ existingCandidateRepo.addContentSource(testSource);
+ repoManager.createCandidateRepo(overlord, existingCandidateRepo);
+
+ // -> Simulate a candidate repo from a previous import that will *NOT* be in this report
+ Repo previousRepo = new Repo(PREVIOUS_CANDIDATE_REPO_NAME);
+ previousRepo.setCandidate(true);
+ previousRepo.addContentSource(testSource);
+ repoManager.createCandidateRepo(overlord, previousRepo);
+
// Test
+ // --------------------------------------------
boolean completed = providerManager.synchronizeContentSource(testSource.getId());
assert completed;
@@ -205,16 +230,19 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
repoGroupsToDelete.add(repoGroup.getId());
// Verify Repos
+ // --------------------------------------------
List<Repo> retrievedRepos;
// -> Simple Repo
retrievedRepos = repoManager.getRepoByName("testRepo1");
assert retrievedRepos.size() == 1;
+ assert retrievedRepos.get(0).isCandidate();
reposToDelete.add(retrievedRepos.get(0).getId());
// -> Repo in a group
retrievedRepos = repoManager.getRepoByName("testRepo2");
assert retrievedRepos.size() == 1;
+ assert retrievedRepos.get(0).isCandidate();
reposToDelete.add(retrievedRepos.get(0).getId());
Repo repoInGroup = retrievedRepos.get(0);
@@ -236,11 +264,13 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
// -> Repo with a parent
retrievedRepos = repoManager.getRepoByName("testRepo3");
assert retrievedRepos.size() == 1;
+ assert retrievedRepos.get(0).isCandidate();
reposToDelete.add(retrievedRepos.get(0).getId());
relatedRepoId = retrievedRepos.get(0).getId();
retrievedRepos = repoManager.getRepoByName("testRepo4");
assert retrievedRepos.size() == 1;
+ assert retrievedRepos.get(0).isCandidate();
reposToDelete.add(retrievedRepos.get(0).getId());
repoId = retrievedRepos.get(0).getId();
@@ -254,11 +284,27 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
Set<RepoRepoRelationship> childRepoRepoRelationship = childRepo.getRepoRepoRelationships();
assert childRepoRepoRelationship.size() == 1;
+ // -> Repo that was already imported in the system (make sure there is still only one)
+ retrievedRepos = repoManager.getRepoByName(EXISTING_IMPORTED_REPO_NAME);
+ assert retrievedRepos.size() == 1;
+ reposToDelete.add(retrievedRepos.get(0).getId());
+
+ // -> Repo that was already a candidate in the system (make sure it's not added again)
+ retrievedRepos = repoManager.getRepoByName(EXISTING_CANDIDATE_REPO_NAME);
+ assert retrievedRepos.size() == 1;
+ reposToDelete.add(retrievedRepos.get(0).getId());
+
+ // -> Make sure a repo that was previously a candidate of this content provider but did not
+ // come back in the latest sync is removed
+ retrievedRepos = repoManager.getRepoByName(PREVIOUS_CANDIDATE_REPO_NAME);
+ assert retrievedRepos.size() == 0;
+
// -> Non-existent repo
retrievedRepos = repoManager.getRepoByName("testRepoFoo");
assert retrievedRepos.size() == 0;
// Verify Packages
+ // --------------------------------------------
TransactionManager tx = getTransactionManager();
tx.begin();
EntityManager entityManager = getEntityManager();
@@ -311,6 +357,14 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
repo4.setParentRepoName("testRepo3");
report.addRepo(repo4);
+ // Repo that was already imported in the system
+ RepoDetails repo5 = new RepoDetails(EXISTING_IMPORTED_REPO_NAME);
+ report.addRepo(repo5);
+
+ // Repo that was already a candidate in the system
+ RepoDetails repo6 = new RepoDetails(EXISTING_CANDIDATE_REPO_NAME);
+ report.addRepo(repo6);
+
return report;
}
@@ -340,7 +394,6 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
// No-op
return null;
}
-
}
/**
commit 1cb378ac619910d6ae3a8eff60f346c0561fdacc
Author: Sayli Karmarkar <skarmark(a)redhat.com>
Date: Mon Nov 9 11:37:46 2009 -0500
552 - Uncommenting tag related functions after fixing db issues
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
index a8629fd..9dc25f0 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
@@ -24,7 +24,9 @@ package org.rhq.core.domain.content;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
@@ -42,6 +44,9 @@ import javax.persistence.Table;
import org.hibernate.annotations.NamedQueries;
import org.hibernate.annotations.NamedQuery;
+import org.rhq.core.domain.common.Tag;
+import org.rhq.core.domain.common.Taggable;
+
/**
* Represents a package inventoried in the system. A package can be created by either a {@link ContentSource} (on the
* server side) or via a plugin discovery (on the agent side). A package has no knowledge of how it was created (i.e. it
@@ -64,7 +69,7 @@ import org.hibernate.annotations.NamedQuery;
+ "AND p.packageType.resourceType.id = :resourceTypeId") })
@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_PACKAGE_ID_SEQ")
@Table(name = "RHQ_PACKAGE")
-public class Package implements Serializable {
+public class Package implements Serializable, Taggable {
// Constants --------------------------------------------
private static final long serialVersionUID = 1L;
@@ -93,7 +98,8 @@ public class Package implements Serializable {
@OneToMany(mappedBy = "generalPackage", fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
private List<PackageVersion> versions;
- //private Set<Tag> tags;
+ @OneToMany()
+ private Set<Tag> tags;
// Constructor ----------------------------------------
@@ -215,52 +221,51 @@ public class Package implements Serializable {
return result;
}
- // @Override
- // public Set<Tag> getTags() {
- // return tags;
- // }
- //
- // @Override
- // public void setTags(Set<Tag> tags) {
- // this.tags = tags;
- // }
- //
- // @Override
- // public boolean hasTag(Tag tag) {
- // if ((this.tags == null) || (tag == null)) {
- // return false;
- // }
- //
- // if (name == null) {
- // if (tag.getName() != null) {
- // return false;
- // }
- // } else if (!name.equals(tag.getName())) {
- // return false;
- // }
- //
- // return true;
- //
- // }
- //
- // @Override
- // public void addTag(Tag tag) {
- // if (this.tags == null) {
- // this.tags = new HashSet<Tag>();
- // }
- //
- // this.tags.add(tag);
- // }
- //
- // @Override
- // public void removeTag(Tag tag) {
- // if ((this.tags == null) || (tag == null)) {
- // return;
- // }
- //
- // if (tags.contains(tag)) {
- // tags.remove(tag);
- // }
- // }
-
-}
\ No newline at end of file
+ @Override
+ public Set<Tag> getTags() {
+ return tags;
+ }
+
+ @Override
+ public void setTags(Set<Tag> tags) {
+ this.tags = tags;
+ }
+
+ @Override
+ public boolean hasTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return false;
+ }
+
+ if (name == null) {
+ if (tag.getName() != null) {
+ return false;
+ }
+ } else if (!name.equals(tag.getName())) {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ @Override
+ public void addTag(Tag tag) {
+ if (this.tags == null) {
+ this.tags = new HashSet<Tag>();
+ }
+
+ this.tags.add(tag);
+ }
+
+ @Override
+ public void removeTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return;
+ }
+
+ if (tags.contains(tag)) {
+ tags.remove(tag);
+ }
+ }
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
index 4b90561..b3d5785 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
@@ -66,6 +66,8 @@ import org.jetbrains.annotations.Nullable;
import org.rhq.core.domain.alert.AlertDefinition;
import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.common.Tag;
+import org.rhq.core.domain.common.Taggable;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PluginConfigurationUpdate;
import org.rhq.core.domain.configuration.ResourceConfigurationUpdate;
@@ -729,7 +731,7 @@ import org.rhq.core.domain.util.serial.ExternalizableStrategy;
@Table(name = "RHQ_RESOURCE")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
-public class Resource implements Comparable<Resource>, Externalizable {
+public class Resource implements Comparable<Resource>, Externalizable, Taggable {
public static final String QUERY_FIND_PROBLEM_RESOURCES_ALERT = "Resource.findProblemResourcesAlert";
public static final String QUERY_FIND_PROBLEM_RESOURCES_ALERT_ADMIN = "Resource.findProblemResourcesAlert_admin";
public static final String QUERY_FIND_PROBLEM_RESOURCES_ALERT_COUNT = "Resource.findProblemResourcesAlertCount";
@@ -1017,7 +1019,8 @@ public class Resource implements Comparable<Resource>, Externalizable {
@ManyToOne(fetch = FetchType.LAZY)
private ProductVersion productVersion;
- //private Set<Tag> tags;
+ @OneToMany()
+ private Set<Tag> tags;
public Resource() {
this.uuid = UUID.randomUUID().toString();
@@ -1810,52 +1813,52 @@ public class Resource implements Comparable<Resource>, Externalizable {
this.currentAvailability = new ResourceAvailability(this, null);
}
- // @Override
- // public Set<Tag> getTags() {
- // return tags;
- // }
- //
- // @Override
- // public void setTags(Set<Tag> tags) {
- // this.tags = tags;
- // }
- //
- // @Override
- // public boolean hasTag(Tag tag) {
- // if ((this.tags == null) || (tag == null)) {
- // return false;
- // }
- //
- // if (name == null) {
- // if (tag.getName() != null) {
- // return false;
- // }
- // } else if (!name.equals(tag.getName())) {
- // return false;
- // }
- //
- // return true;
- //
- // }
- //
- // @Override
- // public void addTag(Tag tag) {
- // if (this.tags == null) {
- // this.tags = new HashSet<Tag>();
- // }
- //
- // this.tags.add(tag);
- // }
- //
- // @Override
- // public void removeTag(Tag tag) {
- // if ((this.tags == null) || (tag == null)) {
- // return;
- // }
- //
- // if (tags.contains(tag)) {
- // tags.remove(tag);
- // }
- // }
- //
+ @Override
+ public Set<Tag> getTags() {
+ return tags;
+ }
+
+ @Override
+ public void setTags(Set<Tag> tags) {
+ this.tags = tags;
+ }
+
+ @Override
+ public boolean hasTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return false;
+ }
+
+ if (name == null) {
+ if (tag.getName() != null) {
+ return false;
+ }
+ } else if (!name.equals(tag.getName())) {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ @Override
+ public void addTag(Tag tag) {
+ if (this.tags == null) {
+ this.tags = new HashSet<Tag>();
+ }
+
+ this.tags.add(tag);
+ }
+
+ @Override
+ public void removeTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return;
+ }
+
+ if (tags.contains(tag)) {
+ tags.remove(tag);
+ }
+ }
+
}
commit 961fba02c89dd09bb8c0dd99fb9260dd1dea9860
Merge: 77dfdc3... 0e71f99...
Author: Partha Aji <paji(a)redhat.com>
Date: Mon Nov 9 11:13:22 2009 -0500
Merge branch 'linux-config' into master-merge
commit 77dfdc32257519c35827197ff6cf70857e5c0735
Merge: 0551264... 0516076...
Author: Partha Aji <paji(a)redhat.com>
Date: Mon Nov 9 11:13:13 2009 -0500
Merge branch 'master' into master-merge
diff --cc .classpath
index eda889b,12cfe43..478e351
--- a/.classpath
+++ b/.classpath
@@@ -107,9 -104,8 +107,10 @@@
<classpathentry kind="src" path="modules/helpers/rtfilter/src/main/java"/>
<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/plugins/augeas/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/augeas/src/test/java"/>
<classpathentry kind="src" path="etc/samples/skeleton-plugin/src/main/java"/>
+ <classpathentry kind="src" path="etc/samples/custom-serverplugin/src/main/java"/>
<classpathentry kind="src" path="etc/agentspawn/src/main/java"/>
<classpathentry excluding="**" kind="src" path="modules/enterprise/comm/src/test/resources"/>
<classpathentry excluding="**" kind="src" path="modules/enterprise/agent/src/main/resources"/>
commit e30e5f15f06eba07b977c8eda9cbdb5c83f727b3
Author: Sayli Karmarkar <skarmark(a)redhat.com>
Date: Mon Nov 9 10:43:08 2009 -0500
552 - Adding db changes for generic tag object
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml
index 244f30a..4528186 100644
--- a/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml
+++ b/modules/core/dbutils/src/main/scripts/dbsetup/content-schema.xml
@@ -348,6 +348,12 @@
</primaryKey>
</constraint>
</table>
+
+ <table name="RHQ_TAG">
+ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/>
+ <column name="NAME" size="200" type="VARCHAR2" required="true"/>
+ <column name="DESCRIPTION" size="500" type="VARCHAR2" required="false"/>
+ </table>
</dbsetup>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/common/Tag.java b/modules/core/domain/src/main/java/org/rhq/core/domain/common/Tag.java
index 843d3c2..65fc3bb 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/common/Tag.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/common/Tag.java
@@ -24,33 +24,49 @@ package org.rhq.core.domain.common;
import java.io.Serializable;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+
/**
* A generic tag that can be associated with domain objects such as
* Repository, Content Provider, Resource, Package etc.
* @author Sayli Karmarkar
*/
-//@Entity
-//@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_TAG_ID_SEQ")
-//@Table(name = "RHQ_TAG")
+@Entity
+@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_TAG_ID_SEQ")
+@Table(name = "RHQ_TAG")
public class Tag implements Serializable {
private static final long serialVersionUID = 1L;
- //@Column(name = "ID", nullable = false)
- //@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ")
- //@Id
- //private int id;
+ @Column(name = "ID", nullable = false)
+ @GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ")
+ @Id
+ private int id;
- //@Column(name = "NAME", nullable = false)
+ @Column(name = "NAME", nullable = false)
private String name;
- //@Column(name = "DESCRIPTION", nullable = true)
+ @Column(name = "DESCRIPTION", nullable = true)
private String description;
public Tag() {
}
+ public int getId() {
+ return this.id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
/**
* String representation of tag
*/
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
index 74ad58f..07df700 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
@@ -49,6 +49,8 @@ import javax.persistence.PreUpdate;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
+import org.rhq.core.domain.common.Tag;
+import org.rhq.core.domain.common.Taggable;
import org.rhq.core.domain.configuration.Configuration;
/**
@@ -78,7 +80,7 @@ import org.rhq.core.domain.configuration.Configuration;
+ " WHERE ccs.repo.id = :repoId ) ") })
@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_CONTENT_SOURCE_ID_SEQ")
@Table(name = "RHQ_CONTENT_SOURCE")
-public class ContentSource implements Serializable {
+public class ContentSource implements Serializable, Taggable {
public static final String QUERY_FIND_ALL = "ContentSource.findAll";
public static final String QUERY_FIND_ALL_WITH_CONFIG = "ContentSource.findAllWithConfig";
public static final String QUERY_FIND_BY_NAME_AND_TYPENAME = "ContentSource.findByNameAndTypeName";
@@ -138,7 +140,8 @@ public class ContentSource implements Serializable {
@OneToMany(mappedBy = "contentSource", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private Set<RepoContentSource> repoContentSources;
- //private Set<Tag> tags;
+ @OneToMany()
+ private Set<Tag> tags;
// Constructor
@@ -445,51 +448,51 @@ public class ContentSource implements Serializable {
return true;
}
- // @Override
- // public Set<Tag> getTags() {
- // return tags;
- // }
- //
- // @Override
- // public void setTags(Set<Tag> tags) {
- // this.tags = tags;
- // }
- //
- // @Override
- // public boolean hasTag(Tag tag) {
- // if ((this.tags == null) || (tag == null)) {
- // return false;
- // }
- //
- // if (name == null) {
- // if (tag.getName() != null) {
- // return false;
- // }
- // } else if (!name.equals(tag.getName())) {
- // return false;
- // }
- //
- // return true;
- //
- // }
- //
- // @Override
- // public void addTag(Tag tag) {
- // if (this.tags == null) {
- // this.tags = new HashSet<Tag>();
- // }
- //
- // this.tags.add(tag);
- // }
- //
- // @Override
- // public void removeTag(Tag tag) {
- // if ((this.tags == null) || (tag == null)) {
- // return;
- // }
- //
- // if (tags.contains(tag)) {
- // tags.remove(tag);
- // }
- // }
-}
\ No newline at end of file
+ @Override
+ public Set<Tag> getTags() {
+ return tags;
+ }
+
+ @Override
+ public void setTags(Set<Tag> tags) {
+ this.tags = tags;
+ }
+
+ @Override
+ public boolean hasTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return false;
+ }
+
+ if (name == null) {
+ if (tag.getName() != null) {
+ return false;
+ }
+ } else if (!name.equals(tag.getName())) {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ @Override
+ public void addTag(Tag tag) {
+ if (this.tags == null) {
+ this.tags = new HashSet<Tag>();
+ }
+
+ this.tags.add(tag);
+ }
+
+ @Override
+ public void removeTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return;
+ }
+
+ if (tags.contains(tag)) {
+ tags.remove(tag);
+ }
+ }
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
index f09faea..ba732e6 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
@@ -41,6 +41,8 @@ import javax.persistence.PreUpdate;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
+import org.rhq.core.domain.common.Tag;
+import org.rhq.core.domain.common.Taggable;
import org.rhq.core.domain.resource.Resource;
/**
@@ -85,7 +87,7 @@ import org.rhq.core.domain.resource.Resource;
+ "AND c.candidate = false ") })
@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_REPO_ID_SEQ")
@Table(name = "RHQ_REPO")
-public class Repo implements Serializable {
+public class Repo implements Serializable, Taggable {
// Constants --------------------------------------------
public static final String QUERY_FIND_ALL_IMPORTED_REPOS = "Repo.findAll";
@@ -139,7 +141,8 @@ public class Repo implements Serializable {
@OneToMany(mappedBy = "repo", fetch = FetchType.LAZY)
private Set<RepoRepoRelationship> repoRepoRelationships;
- //private Set<Tag> tags;
+ @OneToMany()
+ private Set<Tag> tags;
// Constructor ----------------------------------------
@@ -656,52 +659,52 @@ public class Repo implements Serializable {
this.lastModifiedDate = System.currentTimeMillis();
}
- // @Override
- // public Set<Tag> getTags() {
- // return tags;
- // }
- //
- // @Override
- // public void setTags(Set<Tag> tags) {
- // this.tags = tags;
- // }
- //
- // @Override
- // public boolean hasTag(Tag tag) {
- // if ((this.tags == null) || (tag == null)) {
- // return false;
- // }
- //
- // if (name == null) {
- // if (tag.getName() != null) {
- // return false;
- // }
- // } else if (!name.equals(tag.getName())) {
- // return false;
- // }
- //
- // return true;
- //
- // }
- //
- // @Override
- // public void addTag(Tag tag) {
- // if (this.tags == null) {
- // this.tags = new HashSet<Tag>();
- // }
- //
- // this.tags.add(tag);
- // }
- //
- // @Override
- // public void removeTag(Tag tag) {
- // if ((this.tags == null) || (tag == null)) {
- // return;
- // }
- //
- // if (tags.contains(tag)) {
- // tags.remove(tag);
- // }
- // }
- //
-}
\ No newline at end of file
+ @Override
+ public Set<Tag> getTags() {
+ return tags;
+ }
+
+ @Override
+ public void setTags(Set<Tag> tags) {
+ this.tags = tags;
+ }
+
+ @Override
+ public boolean hasTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return false;
+ }
+
+ if (name == null) {
+ if (tag.getName() != null) {
+ return false;
+ }
+ } else if (!name.equals(tag.getName())) {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ @Override
+ public void addTag(Tag tag) {
+ if (this.tags == null) {
+ this.tags = new HashSet<Tag>();
+ }
+
+ this.tags.add(tag);
+ }
+
+ @Override
+ public void removeTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return;
+ }
+
+ if (tags.contains(tag)) {
+ tags.remove(tag);
+ }
+ }
+
+}
commit c08d18cf78d6b11757f3984deadbc486131667fc
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 9 09:55:19 2009 -0500
move the content server plugin test classes to content test package
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
index 6fdd8f4..7dcd2ff 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
@@ -65,8 +65,8 @@ import org.rhq.enterprise.server.content.metadata.ContentSourceMetadataManagerLo
import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails;
import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetailsKey;
import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
+import org.rhq.enterprise.server.plugin.pc.content.TestContentServerPluginService;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
-import org.rhq.enterprise.server.test.TestContentServerPluginService;
import org.rhq.enterprise.server.util.LookupUtil;
@Test
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
index 19e77ef..9bb4750 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
@@ -56,7 +56,6 @@ import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
-import org.rhq.enterprise.server.test.TestContentServerPluginService;
import org.rhq.enterprise.server.util.LookupUtil;
/**
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginService.java
new file mode 100644
index 0000000..cfc59b7
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginService.java
@@ -0,0 +1,187 @@
+/*
+ * 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.plugin.pc.content;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.rhq.core.domain.content.ContentSource;
+import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+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.ContentProviderPackageDetails;
+import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginManager;
+import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
+import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
+
+/**
+ * Used as a mock service for the content source plugin container.
+ */
+public class TestContentServerPluginService extends ServerPluginService implements TestContentServerPluginServiceMBean {
+ // public so tests can directly set these
+ public Map<ContentSource, ContentProvider> testAdapters;
+ public PackageSyncReport testLastSyncReport;
+ public Map<ContentSource, Collection<ContentProviderPackageDetails>> testExistingPackages;
+ public TestMasterServerPluginContainer master;
+
+ @Override
+ protected MasterServerPluginContainer createMasterPluginContainer() {
+ this.master = new TestMasterServerPluginContainer();
+ File dir = new File(System.getProperty("java.io.tmpdir"), "test-server-plugins");
+ MasterServerPluginContainerConfiguration config = new MasterServerPluginContainerConfiguration(dir, dir, dir,
+ null);
+ this.master.initialize(config);
+ return this.master;
+ }
+
+ /**
+ * The test master PC
+ */
+ class TestMasterServerPluginContainer extends MasterServerPluginContainer {
+ @Override
+ protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
+ ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(1);
+ pcs.add(new TestContentServerPluginContainer(this));
+ return pcs;
+ }
+
+ @Override
+ protected ClassLoader createRootServerPluginClassLoader() {
+ return this.getClass().getClassLoader();
+ }
+
+ @Override
+ protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
+ return new HashMap<URL, ServerPluginDescriptorType>();
+ }
+ }
+
+ /**
+ * The test content PC.
+ */
+ class TestContentServerPluginContainer extends ContentServerPluginContainer {
+ public TestContentServerPluginContainer(MasterServerPluginContainer master) {
+ super(master);
+ }
+
+ @Override
+ protected ContentProviderManager createAdapterManager() {
+ TestContentProviderManager am = new TestContentProviderManager();
+ return am;
+ }
+
+ @Override
+ protected ContentServerPluginManager createPluginManager() {
+ TestContentProviderPluginManager pm = new TestContentProviderPluginManager(this);
+ return pm;
+ }
+ }
+
+ /**
+ * The test plugin manager.
+ */
+ class TestContentProviderPluginManager extends ContentServerPluginManager {
+ public TestContentProviderPluginManager(ContentServerPluginContainer pc) {
+ super(pc);
+ }
+ }
+
+ /**
+ * The test adapter manager.
+ */
+ class TestContentProviderManager extends ContentProviderManager {
+ @Override
+ public Set<ContentSource> getAllContentSources() {
+ return (testAdapters != null) ? testAdapters.keySet() : new HashSet<ContentSource>();
+ }
+
+ @Override
+ protected void initialize(ContentServerPluginManager pluginManager) {
+ createInitialAdaptersMap();
+ }
+
+ @Override
+ public void shutdown() {
+ }
+
+ @Override
+ public InputStream loadPackageBits(int contentSourceId, String location) throws Exception {
+ if (testAdapters != null) {
+ for (ContentSource cs : testAdapters.keySet()) {
+ if (cs.getId() == contentSourceId) {
+ PackageSource packageSource = (PackageSource) testAdapters.get(cs);
+ return packageSource.getInputStream(location);
+ }
+ }
+ }
+
+ System.out.println("!!!!!!!!!!");
+ System.out.println("STREAM: TEST DID NOT SETUP ADAPTER - EMPTY STREAM FOR [" + contentSourceId + "]");
+ return new ByteArrayInputStream(new byte[0]);
+ }
+
+ @Override
+ public boolean synchronizeContentSource(int contentSourceId) throws Exception {
+ if (testAdapters != null) {
+ for (ContentSource cs : testAdapters.keySet()) {
+ if (cs.getId() == contentSourceId) {
+ testLastSyncReport = new PackageSyncReport();
+ PackageSource packageSource = (PackageSource) testAdapters.get(cs);
+ packageSource.synchronizePackages(testLastSyncReport, testExistingPackages.get(cs));
+ return true;
+ }
+ }
+ }
+
+ System.out.println("!!!!!!!!!!");
+ System.out.println("SYNC: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
+ return true;
+ }
+
+ @Override
+ public boolean testConnection(int contentSourceId) throws Exception {
+ if (testAdapters != null) {
+ for (ContentSource cs : testAdapters.keySet()) {
+ if (cs.getId() == contentSourceId) {
+ testAdapters.get(cs).testConnection();
+ return true;
+ }
+ }
+ }
+
+ System.out.println("!!!!!!!!!!");
+ System.out.println("CONN: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginServiceMBean.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginServiceMBean.java
new file mode 100644
index 0000000..9d61488
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/TestContentServerPluginServiceMBean.java
@@ -0,0 +1,24 @@
+/*
+ * 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.plugin.pc.content;
+
+import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
+
+public interface TestContentServerPluginServiceMBean extends ServerPluginServiceManagement {
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java
deleted file mode 100644
index 1d68798..0000000
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java
+++ /dev/null
@@ -1,187 +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.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.rhq.core.domain.content.ContentSource;
-import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
-import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
-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.ContentProviderPackageDetails;
-import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginManager;
-import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
-import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
-import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
-
-/**
- * Used as a mock service for the content source plugin container.
- */
-public class TestContentServerPluginService extends ServerPluginService implements TestContentServerPluginServiceMBean {
- // public so tests can directly set these
- public Map<ContentSource, ContentProvider> testAdapters;
- public PackageSyncReport testLastSyncReport;
- public Map<ContentSource, Collection<ContentProviderPackageDetails>> testExistingPackages;
- public TestMasterServerPluginContainer master;
-
- @Override
- protected MasterServerPluginContainer createMasterPluginContainer() {
- this.master = new TestMasterServerPluginContainer();
- File dir = new File(System.getProperty("java.io.tmpdir"), "test-server-plugins");
- MasterServerPluginContainerConfiguration config = new MasterServerPluginContainerConfiguration(dir, dir, dir,
- null);
- this.master.initialize(config);
- return this.master;
- }
-
- /**
- * The test master PC
- */
- class TestMasterServerPluginContainer extends MasterServerPluginContainer {
- @Override
- protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
- ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(1);
- pcs.add(new TestContentServerPluginContainer(this));
- return pcs;
- }
-
- @Override
- protected ClassLoader createRootServerPluginClassLoader() {
- return this.getClass().getClassLoader();
- }
-
- @Override
- protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
- return new HashMap<URL, ServerPluginDescriptorType>();
- }
- }
-
- /**
- * The test content PC.
- */
- class TestContentServerPluginContainer extends ContentServerPluginContainer {
- public TestContentServerPluginContainer(MasterServerPluginContainer master) {
- super(master);
- }
-
- @Override
- protected ContentProviderManager createAdapterManager() {
- TestContentProviderManager am = new TestContentProviderManager();
- return am;
- }
-
- @Override
- protected ContentServerPluginManager createPluginManager() {
- TestContentProviderPluginManager pm = new TestContentProviderPluginManager(this);
- return pm;
- }
- }
-
- /**
- * The test plugin manager.
- */
- class TestContentProviderPluginManager extends ContentServerPluginManager {
- public TestContentProviderPluginManager(ContentServerPluginContainer pc) {
- super(pc);
- }
- }
-
- /**
- * The test adapter manager.
- */
- class TestContentProviderManager extends ContentProviderManager {
- @Override
- public Set<ContentSource> getAllContentSources() {
- return (testAdapters != null) ? testAdapters.keySet() : new HashSet<ContentSource>();
- }
-
- @Override
- protected void initialize(ContentServerPluginManager pluginManager) {
- createInitialAdaptersMap();
- }
-
- @Override
- public void shutdown() {
- }
-
- @Override
- public InputStream loadPackageBits(int contentSourceId, String location) throws Exception {
- if (testAdapters != null) {
- for (ContentSource cs : testAdapters.keySet()) {
- if (cs.getId() == contentSourceId) {
- PackageSource packageSource = (PackageSource) testAdapters.get(cs);
- return packageSource.getInputStream(location);
- }
- }
- }
-
- System.out.println("!!!!!!!!!!");
- System.out.println("STREAM: TEST DID NOT SETUP ADAPTER - EMPTY STREAM FOR [" + contentSourceId + "]");
- return new ByteArrayInputStream(new byte[0]);
- }
-
- @Override
- public boolean synchronizeContentSource(int contentSourceId) throws Exception {
- if (testAdapters != null) {
- for (ContentSource cs : testAdapters.keySet()) {
- if (cs.getId() == contentSourceId) {
- testLastSyncReport = new PackageSyncReport();
- PackageSource packageSource = (PackageSource) testAdapters.get(cs);
- packageSource.synchronizePackages(testLastSyncReport, testExistingPackages.get(cs));
- return true;
- }
- }
- }
-
- System.out.println("!!!!!!!!!!");
- System.out.println("SYNC: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
- return true;
- }
-
- @Override
- public boolean testConnection(int contentSourceId) throws Exception {
- if (testAdapters != null) {
- for (ContentSource cs : testAdapters.keySet()) {
- if (cs.getId() == contentSourceId) {
- testAdapters.get(cs).testConnection();
- return true;
- }
- }
- }
-
- System.out.println("!!!!!!!!!!");
- System.out.println("CONN: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
- return true;
- }
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginServiceMBean.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginServiceMBean.java
deleted file mode 100644
index bbdebaf..0000000
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginServiceMBean.java
+++ /dev/null
@@ -1,24 +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.test;
-
-import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
-
-public interface TestContentServerPluginServiceMBean extends ServerPluginServiceManagement {
-}
\ No newline at end of file
commit 0d68f392e56718671399b1cc80d50434a7a91d71
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 9 09:49:11 2009 -0500
refactor the server plugin test code so its easier to install different
test mbeans for different server plugins
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
index ea0e8a3..6fdd8f4 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
@@ -151,7 +151,8 @@ public class ContentSourceManagerBeanTest extends AbstractEJB3Test {
setupTestEnvironment();
overlord = LookupUtil.getSubjectManager().getOverlord();
prepareScheduler();
- pluginService = prepareContentServerPluginService();
+ TestContentServerPluginService pluginService = new TestContentServerPluginService();
+ prepareCustomServerPluginService(pluginService);
pluginService.startMasterPluginContainer();
cleanupPreviousTestRuns();
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
index e1d4fe9..19e77ef 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
@@ -90,7 +90,8 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
// Plugin service setup
prepareScheduler();
- TestContentServerPluginService pluginService = prepareContentServerPluginService();
+ TestContentServerPluginService pluginService = new TestContentServerPluginService();
+ prepareCustomServerPluginService(pluginService);
pluginService.startMasterPluginContainer();
// Because of the (current) transaction settings of some of the nested methods (i.e. REQUIRES_NEW),
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
index a5fa70c..529193b 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
@@ -50,6 +50,7 @@ import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.auth.SessionManager;
import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceMBean;
import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
import org.rhq.enterprise.server.scheduler.SchedulerService;
import org.rhq.enterprise.server.scheduler.SchedulerServiceMBean;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -249,22 +250,21 @@ public abstract class AbstractEJB3Test extends AssertJUnit {
private ServerPluginService serverPluginService;
/**
- * If you need to test content source server plugins, you must first prepare the server plugin service via
- * this method. The caller must explicitly start the PC by using the appropriate API on the returned object; this
- * method will only start the service, it will NOT start the master PC.
+ * If you need to test server plugins, you must first prepare the server plugin service.
+ * After this returns, the caller must explicitly start the PC by using the appropriate API
+ * on the given mbean; this method will only start the service, it will NOT start the master PC.
*
- * @return the object that will house your test server plugins
+ * @param testServiceMBean the object that will house your test server plugins
*
* @throws RuntimeException
*/
- public TestContentServerPluginService prepareContentServerPluginService() {
+ public void prepareCustomServerPluginService(ServerPluginService testServiceMBean) {
try {
MBeanServer mbs = getJBossMBeanServer();
- TestContentServerPluginService mbean = new TestContentServerPluginService();
- mbean.start();
- mbs.registerMBean(mbean, TestContentServerPluginService.OBJECT_NAME);
- serverPluginService = mbean;
- return mbean;
+ testServiceMBean.start();
+ mbs.registerMBean(testServiceMBean, ServerPluginServiceManagement.OBJECT_NAME);
+ serverPluginService = testServiceMBean;
+ return;
} catch (Exception e) {
throw new RuntimeException(e);
}
commit 05160766ecb64f91124b5a7adf791863613a33a1
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 9 00:53:02 2009 -0500
Squashed commit of the following:
commit dbdbb5e9566363fa1977f700cc88268a91463df2
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 9 00:48:16 2009 -0500
add a sample server plugin to demo generic plugins and lifecycle
listeners
commit b5a7aece77f027d756352bac5eb16ecf9ed47b10
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 8 19:00:09 2009 -0500
add lifecycle listener to server plugin stuff. change unit tests to explicitly create a server plugin server for content, leaving room for us to add different types later
diff --git a/.classpath b/.classpath
index d88d80c..12cfe43 100644
--- a/.classpath
+++ b/.classpath
@@ -105,6 +105,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="etc/samples/skeleton-plugin/src/main/java"/>
+ <classpathentry kind="src" path="etc/samples/custom-serverplugin/src/main/java"/>
<classpathentry kind="src" path="etc/agentspawn/src/main/java"/>
<classpathentry excluding="**" kind="src" path="modules/enterprise/comm/src/test/resources"/>
<classpathentry excluding="**" kind="src" path="modules/enterprise/agent/src/main/resources"/>
diff --git a/etc/custom-serverplugin/pom.xml b/etc/custom-serverplugin/pom.xml
deleted file mode 100644
index 13270f4..0000000
--- a/etc/custom-serverplugin/pom.xml
+++ /dev/null
@@ -1,165 +0,0 @@
-<?xml version="1.0"?>
-
-<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>
-
- <groupId>org.custom</groupId>
- <artifactId>custom-serverplugin</artifactId>
- <version>1.0-SNAPSHOT</version>
- <packaging>jar</packaging>
-
- <name>Custom RHQ Content Source Server Plugin Template</name>
- <description>a template for building a custom RHQ server plugin for a custom content source</description>
-
- <properties>
- <rhq.version>1.2.0.GA</rhq.version>
- </properties>
-
- <dependencies>
-
- <!-- Below are the core modules that are required dependencies of all plugins -->
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-core-domain</artifactId>
- <version>${rhq.version}</version>
- <scope>provided</scope> <!-- provided by the server/plugin-container -->
- </dependency>
-
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-core-client-api</artifactId>
- <version>${rhq.version}</version>
- <scope>provided</scope> <!-- provided by the server/plugin-container -->
- </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>javax.persistence</groupId>
- <artifactId>persistence-api</artifactId>
- <version>1.0</version>
- <scope>provided</scope> <!-- provided by the server/plugin-container -->
- </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> <!-- provided by the server/plugin-container -->
- </dependency>
-
- <!-- uncomment the one of the three logging systems your plugin uses: log4j, commons-logging or i18nlog -->
- <!-- all three are provided to your plugin by the server/plugin-container -->
- <!--
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- <version>1.2.14</version>
- <scope>provided</scope>
- </dependency>
- -->
-
- <!--
- <dependency>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- <version>1.1</version>
- <scope>provided</scope>
- </dependency>
- -->
-
- <!--
- <dependency>
- <groupId>i18nlog</groupId>
- <artifactId>i18nlog</artifactId>
- <version>1.0.9</version>
- </dependency>
- -->
-
- <!-- Define any third-party dependencies your plugin has here. -->
- <!--
- <dependency>
- <groupId>group-id-of-dependency-goes-here</groupId>
- <artifactId>artifact-id-of-dependency-goes-here</artifactId>
- <version>version-of-dependency-goes-here</version>
- </dependency>
- -->
-
- </dependencies>
-
- <build>
- <plugins>
-
- <plugin>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>1.5</source>
- <target>1.5</target>
- </configuration>
- </plugin>
-
- <!--
- If your plugin has third-party jar dependencies that are not already
- available when deployed in the plugin container, you can package these
- jars in your plugin. They go in your plugin jar's "lib" directory.
- Uncomment the maven plugin definition below and define one or more jar
- files (aka "artifactItem" elements) that you want to include in your
- plugin jar.
- -->
-
-<!--
- <plugin>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>copy-dependencies</id>
- <phase>process-resources</phase>
- <goals>
- <goal>copy</goal>
- </goals>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>your-third-party-dep-group</groupId>
- <artifactId>your-third-party-dep-artifact</artifactId>
- <version>your-third-party-dep-version</version>
- </artifactItem>
- </artifactItems>
- <outputDirectory>${project.build.outputDirectory}/lib</outputDirectory>
- </configuration>
- </execution>
- </executions>
- </plugin>
--->
-
- </plugins>
- </build>
-
- <repositories>
- <repository>
- <id>jboss</id>
- <name>JBoss Repository</name>
- <url>http://repository.jboss.org/maven2/</url>
- <snapshots>
- <enabled>false</enabled>
- </snapshots>
- </repository>
- </repositories>
-
- <pluginRepositories>
- <pluginRepository>
- <id>jboss</id>
- <name>JBoss Plugin Repository</name>
- <url>http://repository.jboss.org/maven2/</url>
- <snapshots>
- <enabled>false</enabled>
- </snapshots>
- </pluginRepository>
- </pluginRepositories>
-
-</project>
diff --git a/etc/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin-content.xml b/etc/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin-content.xml
deleted file mode 100644
index de569b1..0000000
--- a/etc/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin-content.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<plugin name="MyCustomContentSourcePlugin"
- xmlns="urn:xmlns:rhq-serverplugin.content"
- xmlns:c="urn:xmlns:rhq-configuration">
-
- <contentSourceType name="MyCustomContentSource"
- displayName="My Custom Content Source"
- description="This is my custom content source that retrieves packages from some custom repository."
- lazyLoad="true"
- syncSchedule="0 0 3 * * ?"
- apiClass="org.custom.serverplugin.MyCustomContentSource">
-
- <configuration>
- <c:simple-property name="myCustomProperty" type="string" required="true" description="A property my plugin needs to be properly configured" />
- </configuration>
-
- </contentSourceType>
-
-</plugin>
\ No newline at end of file
diff --git a/etc/samples/custom-serverplugin/pom.xml b/etc/samples/custom-serverplugin/pom.xml
new file mode 100644
index 0000000..833ce0c
--- /dev/null
+++ b/etc/samples/custom-serverplugin/pom.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0"?>
+
+<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>
+
+ <groupId>org.custom</groupId>
+ <artifactId>custom-serverplugin</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>Custom RHQ Server Plugin Template</name>
+ <description>A template for building a custom generic RHQ server plugin</description>
+
+ <properties>
+ <rhq.version>1.4.0-SNAPSHOT</rhq.version>
+ </properties>
+
+ <dependencies>
+
+ <!-- Below are the core modules that are required dependencies of all plugins -->
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-server</artifactId>
+ <version>${rhq.version}</version>
+ <scope>provided</scope> <!-- provided by the server/plugin-container -->
+ </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>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope> <!-- provided by the server/plugin-container -->
+ </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> <!-- provided by the server/plugin-container -->
+ </dependency>
+
+ <!-- uncomment the one of the three logging systems your plugin uses: log4j, commons-logging or i18nlog -->
+ <!-- all three are provided to your plugin by the server/plugin-container -->
+ <!--
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.14</version>
+ <scope>provided</scope>
+ </dependency>
+ -->
+
+ <!--
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.1</version>
+ <scope>provided</scope>
+ </dependency>
+ -->
+
+ <!--
+ <dependency>
+ <groupId>i18nlog</groupId>
+ <artifactId>i18nlog</artifactId>
+ <version>1.0.9</version>
+ </dependency>
+ -->
+
+ <!-- Define any third-party dependencies your plugin has here. -->
+ <!--
+ <dependency>
+ <groupId>group-id-of-dependency-goes-here</groupId>
+ <artifactId>artifact-id-of-dependency-goes-here</artifactId>
+ <version>version-of-dependency-goes-here</version>
+ </dependency>
+ -->
+
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+
+ <!--
+ If your plugin has third-party jar dependencies that are not already
+ available when deployed in the plugin container, you can package these
+ jars in your plugin. They go in your plugin jar's "lib" directory.
+ Uncomment the maven plugin definition below and define one or more jar
+ files (aka "artifactItem" elements) that you want to include in your
+ plugin jar.
+ -->
+
+<!--
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>your-third-party-dep-group</groupId>
+ <artifactId>your-third-party-dep-artifact</artifactId>
+ <version>your-third-party-dep-version</version>
+ </artifactItem>
+ </artifactItems>
+ <outputDirectory>${project.build.outputDirectory}/lib</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+-->
+
+ </plugins>
+ </build>
+
+ <repositories>
+ <repository>
+ <id>jboss</id>
+ <name>JBoss Repository</name>
+ <url>http://repository.jboss.org/maven2/</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>jboss</id>
+ <name>JBoss Plugin Repository</name>
+ <url>http://repository.jboss.org/maven2/</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </pluginRepository>
+ </pluginRepositories>
+
+</project>
diff --git a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
new file mode 100644
index 0000000..a2deeef
--- /dev/null
+++ b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
@@ -0,0 +1,63 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.custom;
+
+import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
+
+/**
+ * A sample lifecycle listener for the sample generic plugin. This listener will be
+ * the main interface the server uses to start and stop the plugin.
+ */
+public class MyLifecycleListener implements ServerPluginLifecycleListener {
+
+ private ServerPluginContext context;
+
+ public void initialize(ServerPluginContext context) throws Exception {
+ this.context = context;
+ System.out.println("The sample plugin has been initialized!!! : " + this);
+ }
+
+ public void start() {
+ System.out.println("The sample plugin has started!!! : " + this);
+ }
+
+ public void stop() {
+ System.out.println("The sample plugin has stopped!!! : " + this);
+ }
+
+ public void shutdown() {
+ System.out.println("The sample plugin has been shut down!!! : " + this);
+ }
+
+ @Override
+ public String toString() {
+ if (this.context == null) {
+ return "<no context>";
+ }
+
+ StringBuilder str = new StringBuilder();
+ str.append("plugin-name=").append(this.context.getPluginEnvironment().getPluginName()).append(",");
+ str.append("plugin-url=").append(this.context.getPluginEnvironment().getPluginUrl()).append(",");
+ str.append("data-dir=").append(this.context.getDataDirectory()).append(",");
+ str.append("tmp-dir=").append(this.context.getTemporaryDirectory()); // do not append ,
+ return str.toString();
+ }
+}
diff --git a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
new file mode 100644
index 0000000..928f635
--- /dev/null
+++ b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<generic-plugin name="CustomGenericPlugin"
+ displayName="My Custom Generic Plugin"
+ description="A custom generic plugin."
+ package="org.custom"
+ pluginLifecycleListener="MyLifecycleListener"
+ version="1.0"
+ apiVersion="2.0"
+ xmlns="urn:xmlns:rhq-serverplugin.generic"
+ xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <serverplugin:plugin-configuration>
+ <c:simple-property name="myCustomProperty" type="string" required="true" description="A property my plugin needs to be properly configured" />
+ </serverplugin:plugin-configuration>
+
+</generic-plugin>
\ No newline at end of file
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginManager.java
index 1b9399a..005b427 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginManager.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2009 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index a7a166d..0d94174 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -34,7 +34,7 @@ public abstract class AbstractTypeServerPluginContainer {
private final Log log = LogFactory.getLog(this.getClass());
private final MasterServerPluginContainer master;
- private PluginManager pluginManager;
+ private ServerPluginManager pluginManager;
/**
* Instantiates the plugin container. All subclasses must support this and only this
@@ -69,7 +69,7 @@ public abstract class AbstractTypeServerPluginContainer {
*
* @return the plugin manager for this container
*/
- public PluginManager getPluginManager() {
+ public ServerPluginManager getPluginManager() {
return this.pluginManager;
}
@@ -82,6 +82,7 @@ public abstract class AbstractTypeServerPluginContainer {
* @throws Exception if the plugin container failed to initialize for some reason
*/
public synchronized void initialize() throws Exception {
+ log.debug("Server plugin container initializing");
this.pluginManager = createPluginManager();
this.pluginManager.initialize();
}
@@ -92,7 +93,9 @@ public abstract class AbstractTypeServerPluginContainer {
* ever know about have been {@link #loadPlugin(ServerPluginEnvironment) loaded}.
*/
public synchronized void start() {
- return; // no-op
+ log.debug("Server plugin container starting");
+ this.pluginManager.startPlugins();
+ return;
}
/**
@@ -100,7 +103,9 @@ public abstract class AbstractTypeServerPluginContainer {
* the plugin container must assume that soon it will be asked to {@link #shutdown()}.
*/
public synchronized void stop() {
- return; // no-op
+ log.debug("Server plugin container stopping");
+ this.pluginManager.stopPlugins();
+ return;
}
/**
@@ -109,6 +114,8 @@ public abstract class AbstractTypeServerPluginContainer {
* Subclasses are free to perform additional tasks by overriding this method.
*/
public synchronized void shutdown() {
+ log.debug("Server plugin container shutting down");
+
if (this.pluginManager != null) {
Collection<ServerPluginEnvironment> envs = this.pluginManager.getPluginEnvironments();
for (ServerPluginEnvironment env : envs) {
@@ -166,8 +173,8 @@ public abstract class AbstractTypeServerPluginContainer {
*
* @return the plugin manager for use by this plugin container
*/
- protected PluginManager createPluginManager() {
- return new PluginManager(this);
+ protected ServerPluginManager createPluginManager() {
+ return new ServerPluginManager(this);
}
/**
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainerConfiguration.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainerConfiguration.java
index f22ff59..5bf6d0c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainerConfiguration.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainerConfiguration.java
@@ -27,31 +27,41 @@ import java.io.File;
*/
public class MasterServerPluginContainerConfiguration {
private File pluginDirectory;
+ private File dataDirectory;
private File tmpDirectory;
private String rootClassLoaderRegex;
- public File getPluginDirectory() {
- return this.pluginDirectory;
- }
+ public MasterServerPluginContainerConfiguration(File pluginDirectory, File dataDirectory, File tmpDirectory,
+ String rootClassLoaderRegex) {
- public void setPluginDirectory(File pluginDirectory) {
if (pluginDirectory == null) {
throw new IllegalArgumentException("pluginDirectory == null");
}
-
this.pluginDirectory = pluginDirectory;
- }
- public File getTemporaryDirectory() {
- if (this.tmpDirectory != null) {
- return this.tmpDirectory;
+ if (dataDirectory == null) {
+ throw new IllegalArgumentException("dataDirectory == null");
}
+ this.dataDirectory = dataDirectory;
+
+ if (tmpDirectory == null) {
+ tmpDirectory = new File(System.getProperty("java.io.tmpdir", "."));
+ }
+ this.tmpDirectory = tmpDirectory;
+
+ this.rootClassLoaderRegex = rootClassLoaderRegex;
+ }
+
+ public File getPluginDirectory() {
+ return this.pluginDirectory;
+ }
- return new File(System.getProperty("java.io.tmpdir", "."));
+ public File getDataDirectory() {
+ return this.dataDirectory;
}
- public void setTemporaryDirectory(File tmpDir) {
- this.tmpDirectory = tmpDir;
+ public File getTemporaryDirectory() {
+ return this.tmpDirectory;
}
/**
@@ -70,26 +80,17 @@ public class MasterServerPluginContainerConfiguration {
return this.rootClassLoaderRegex;
}
- /**
- * Sets the regex that defines what classes the plugin container should hide from its plugins.
- *
- * @param regex regular expression
- *
- * @see RootServerPluginClassLoader
- */
- public void setRootPluginClassLoaderRegex(String regex) {
- this.rootClassLoaderRegex = regex;
- }
-
@Override
public String toString() {
File pdir = getPluginDirectory();
File tdir = getTemporaryDirectory();
+ File ddir = getDataDirectory();
String regex = getRootServerPluginClassLoaderRegex();
StringBuilder str = new StringBuilder(MasterServerPluginContainerConfiguration.class + ": ");
str.append("plugin-dir=[" + ((pdir != null) ? pdir.getAbsolutePath() : "<null>"));
str.append("], tmp-dir=[" + ((tdir != null) ? tdir.getAbsolutePath() : "<null>"));
+ str.append("], data-dir=[" + ((ddir != null) ? ddir.getAbsolutePath() : "<null>"));
str.append("], root-cl-regex=[" + ((regex != null) ? regex : "<null>"));
str.append("]");
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
deleted file mode 100644
index 20c66ae..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2009 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.plugin.pc;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Provides functionality to manage plugins for a plugin container. Plugin containers
- * can install their own plugin managers that are extensions to this class if they need to.
- *
- * @author John Mazzitelli
- */
-public class PluginManager {
- private final Log log = LogFactory.getLog(this.getClass());
-
- /**
- * The map of all plugins keyed on plugin name.
- */
- private Map<String, ServerPluginEnvironment> loadedPlugins = new HashMap<String, ServerPluginEnvironment>();
- private AbstractTypeServerPluginContainer parentPluginContainer;
-
- /**
- * Creates a plugin manager for the given plugin container.
- *
- * @param pc the plugin manager's owning plugin container
- */
- public PluginManager(AbstractTypeServerPluginContainer pc) {
- this.parentPluginContainer = pc;
- }
-
- /**
- * Initializes the plugin manager to prepare it to start loading plugins.
- *
- * @throws Exception if failed to initialize
- */
- public synchronized void initialize() throws Exception {
- return; // no-op
- }
-
- /**
- * Shuts down this manager. This should be called only after all of its plugins
- * have been {@link #unloadPlugin(ServerPluginEnvironment) unloaded}.
- */
- public synchronized void shutdown() {
- if (this.loadedPlugins.size() > 0) {
- log.warn("Server plugin manager is being shutdown while some plugins are still loaded: "
- + this.loadedPlugins);
- }
-
- this.loadedPlugins.clear();
- return;
- }
-
- /**
- * Informs the plugin manager that a plugin with the given environment needs to be loaded.
- * Once this method returns, the plugin's components are ready to be created and used.
- *
- * @param env the environment of the plugin to be loaded
- *
- * @throws Exception if the plugin manager cannot load the plugin or deems the plugin invalid
- */
- public synchronized void loadPlugin(ServerPluginEnvironment env) throws Exception {
- log.debug("Loading server plugin [" + env.getPluginName() + "] from: " + env.getPluginUrl());
- this.loadedPlugins.put(env.getPluginName(), env);
- return;
- }
-
- /**
- * Informs the plugin manager that a plugin with the given environment is to be unloaded.
- * Once this method returns, the plugin's components are should no longer be created or used.
- *
- * @param env the environment of the plugin to be unloaded
- *
- * @throws Exception if the plugin manager cannot unload the plugin
- */
- public synchronized void unloadPlugin(ServerPluginEnvironment env) throws Exception {
- log.debug("Unloading server plugin [" + env.getPluginName() + "]");
- this.loadedPlugins.remove(env.getPluginName());
- return;
- }
-
- /**
- * Returns the {@link ServerPluginEnvironment}s for every plugin this manager has loaded.
- * The returned collection is a copy and not backed by this manager.
- *
- * @return environments for all the plugins
- */
- public synchronized Collection<ServerPluginEnvironment> getPluginEnvironments() {
- return new ArrayList<ServerPluginEnvironment>(this.loadedPlugins.values());
- }
-
- /**
- * Given a plugin name, this returns that plugin's environment.
- *
- * <p>The plugin's name is defined in its plugin descriptor - specifically the XML root node's "name" attribute
- * (e.g. <server-plugin name="thePluginName").</p>
- *
- * @param pluginName the plugin whose environment is to be returned
- * @return given plugin's environment
- */
- public synchronized ServerPluginEnvironment getPluginEnvironment(String pluginName) {
- return this.loadedPlugins.get(pluginName);
- }
-
- public AbstractTypeServerPluginContainer getParentPluginContainer() {
- return this.parentPluginContainer;
- }
-
- protected Log getLog() {
- return this.log;
- }
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
new file mode 100644
index 0000000..f234cd1
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
@@ -0,0 +1,85 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import java.io.File;
+
+/**
+ * A global context containing information about a server-side plugin.
+ *
+ * @author John Mazzitelli
+ */
+public class ServerPluginContext {
+ private final ServerPluginEnvironment pluginEnvironment;
+ private final File temporaryDirectory;
+ private final File dataDirectory;
+
+ /**
+ * Creates a new {@link ServerPluginContext} object. The plugin container is responsible for instantiating these
+ * objects; plugin writers should never have to actually create context objects.
+ *
+ * @param env the environment of the plugin - includes the plugin name and other info
+ * @param dataDirectory a directory where plugins can store persisted data that survives server restarts
+ * @param tmpDirectory a temporary directory for plugin use
+ */
+ public ServerPluginContext(ServerPluginEnvironment env, File dataDirectory, File tmpDirectory) {
+ this.pluginEnvironment = env;
+ this.dataDirectory = dataDirectory;
+ if (tmpDirectory == null) {
+ this.temporaryDirectory = new File(System.getProperty("java.io.tmpdir"), "SERVERPLUGIN_TMP");
+ this.temporaryDirectory.mkdirs();
+ } else {
+ this.temporaryDirectory = tmpDirectory;
+ }
+ }
+
+ /**
+ * The environment of the plugin, including its name and other information.
+ *
+ * @return plugin environment
+ */
+ public ServerPluginEnvironment getPluginEnvironment() {
+ return pluginEnvironment;
+ }
+
+ /**
+ * A temporary directory for plugin use. Plugins should use this if they need to
+ * write temporary files that they do not expect to remain after the server is restarted. This directory is shared
+ * among all plugins - plugins must ensure they write unique files here, as other plugins may be using this same
+ * directory. Typically, plugins will use the {@link File#createTempFile(String, String, File)} API when writing to
+ * this directory.
+ *
+ * @return location for plugin temporary files
+ */
+ public File getTemporaryDirectory() {
+ return temporaryDirectory;
+ }
+
+ /**
+ * Directory where plugins can store persisted data that survives agent restarts. Each plugin will have their own
+ * data directory. The returned directory may not yet exist - it is up to each individual plugin to manage this
+ * directory as they see fit (this includes performing the initial creation when the directory is first needed).
+ *
+ * @return location for plugins to store persisted data
+ */
+ public File getDataDirectory() {
+ return this.dataDirectory;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java
index 093c017..e0809a6 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java
@@ -58,7 +58,7 @@ public class ServerPluginEnvironment {
return this.pluginUrl;
}
- public ClassLoader getClassLoader() {
+ public ClassLoader getPluginClassLoader() {
return this.pluginClassLoader;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginLifecycleListener.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginLifecycleListener.java
new file mode 100644
index 0000000..bb7b05f
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginLifecycleListener.java
@@ -0,0 +1,73 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.rhq.enterprise.server.plugin.pc;
+
+/**
+ * Performs global initialization and shutdown of a server side plugin. This provides a place
+ * for plugin developers to allocate global resources needed by all plugin components and
+ * a place to clean up those resources.
+ *
+ * Lifecycle listeners are required of generic server plugins because they provide
+ * the only mechanism to start and stop.
+ *
+ * @author John Mazzitelli
+ */
+public interface ServerPluginLifecycleListener {
+ /**
+ * When a plugin's container loads a plugin, this method will be called.
+ * When this is called, no other plugin components have been instantiated
+ * or invoked yet. This is merely called to notify the plugin that it is about to be
+ * placed into service and its components will soon be asked to perform work.
+ *
+ * If this method returns normally, the plugin is saying it is ready and able to {@link #start()}.
+ *
+ * @param context a context with information about the runtime plugin environment
+ *
+ * @throws Exception if the plugin finds that it should not be loaded, an exception should be thrown.
+ * If thrown, this plugin will not be started and will be considered disabled. If
+ * other plugins are dependent on this failed plugin, those other plugins will
+ * fail to operate correctly.
+ */
+ void initialize(ServerPluginContext context) throws Exception;
+
+ /**
+ * When a plugin container has been started (which occurs after all plugins are loaded), this
+ * method is called to inform the plugin is can begin performing work.
+ */
+ void start();
+
+ /**
+ * When a plugin container has been stopped (but before it unloads plugins), this
+ * method is called to inform the plugin it should stop performing work and prepare
+ * to shutdown.
+ */
+ void stop();
+
+ /**
+ * When the plugin container shuts down and it unloads the plugin, this method will be called.
+ * This provides an opportunity for the plugin to clean up any global resources it has previously
+ * allocated. After this method is called, invocations of this plugin's discovery or
+ * resource components will no longer occur.
+ */
+ void shutdown();
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
new file mode 100644
index 0000000..b1300f0
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -0,0 +1,319 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Provides functionality to manage plugins for a plugin container. Plugin containers
+ * can install their own plugin managers that are extensions to this class if they need to.
+ *
+ * @author John Mazzitelli
+ */
+public class ServerPluginManager {
+ private final Log log = LogFactory.getLog(this.getClass());
+
+ private final AbstractTypeServerPluginContainer parentPluginContainer;
+
+ /**
+ * The map of all plugin environments keyed on plugin name.
+ */
+ private final Map<String, ServerPluginEnvironment> loadedPlugins;
+
+ /**
+ * Cached instances of objects used to initialize and shutdown individual plugins.
+ * Only plugins that declare their own lifecycle listener will have objects in this cache.
+ * This is keyed on plugin name.
+ */
+ private final Map<String, ServerPluginLifecycleListener> pluginLifecycleListenerCache;
+
+ /**
+ * Creates a plugin manager for the given plugin container.
+ *
+ * @param pc the plugin manager's owning plugin container
+ */
+ public ServerPluginManager(AbstractTypeServerPluginContainer pc) {
+ this.parentPluginContainer = pc;
+ this.loadedPlugins = new HashMap<String, ServerPluginEnvironment>();
+ this.pluginLifecycleListenerCache = new HashMap<String, ServerPluginLifecycleListener>();
+ }
+
+ /**
+ * Initializes the plugin manager to prepare it to start loading plugins.
+ *
+ * @throws Exception if failed to initialize
+ */
+ public synchronized void initialize() throws Exception {
+ log.debug("Plugin manager initializing");
+ return; // no-op
+ }
+
+ /**
+ * Shuts down this manager. This should be called only after all of its plugins
+ * have been {@link #unloadPlugin(ServerPluginEnvironment) unloaded}.
+ */
+ public synchronized void shutdown() {
+ log.debug("Plugin manager shutting down");
+
+ if (this.loadedPlugins.size() > 0) {
+ log.warn("Server plugin manager is being shutdown while some plugins are still loaded: "
+ + this.loadedPlugins);
+ this.loadedPlugins.clear();
+ }
+
+ this.pluginLifecycleListenerCache.clear();
+
+ return;
+ }
+
+ /**
+ * Informs the plugin manager that a plugin with the given environment needs to be loaded.
+ * Once this method returns, the plugin's components are ready to be created and used.
+ *
+ * @param env the environment of the plugin to be loaded
+ *
+ * @throws Exception if the plugin manager cannot load the plugin or deems the plugin invalid
+ */
+ public synchronized void loadPlugin(ServerPluginEnvironment env) throws Exception {
+ String pluginName = env.getPluginName();
+ log.debug("Loading server plugin [" + pluginName + "] from: " + env.getPluginUrl());
+
+ // tell the plugin we are loading it
+ ServerPluginLifecycleListener listener = createServerPluginLifecycleListener(env);
+ if (listener != null) {
+ ServerPluginContext context = createServerPluginContext(env);
+ log.debug("Initializing lifecycle listener for server plugin [" + pluginName + "]");
+ ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(env.getPluginClassLoader());
+ listener.initialize(context);
+ } catch (Throwable t) {
+ throw new Exception("Lifecycle listener failed to initialize plugin", t);
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalContextClassLoader);
+ }
+ this.pluginLifecycleListenerCache.put(pluginName, listener);
+ }
+
+ // note that we only cache it if the lifecycle listener was successful
+ this.loadedPlugins.put(pluginName, env);
+
+ return;
+ }
+
+ public synchronized void startPlugins() {
+ log.debug("Starting plugins");
+
+ // tell all lifecycle listeners to start
+ for (Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
+ String pluginName = entry.getKey();
+ ServerPluginLifecycleListener listener = entry.getValue();
+ ServerPluginEnvironment env = this.loadedPlugins.get(pluginName);
+ log.debug("Starting lifecycle listener for server plugin [" + pluginName + "]");
+ ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(env.getPluginClassLoader());
+ listener.start();
+ } catch (Throwable t) {
+ log.warn("Lifecycle listener failed to start plugin [" + pluginName + "]", t);
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalContextClassLoader);
+ }
+ }
+
+ return;
+ }
+
+ public synchronized void stopPlugins() {
+ log.debug("Stopping plugins");
+
+ // tell all lifecycle listeners to stop
+ for (Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
+ String pluginName = entry.getKey();
+ ServerPluginLifecycleListener listener = entry.getValue();
+ ServerPluginEnvironment env = this.loadedPlugins.get(pluginName);
+ log.debug("Stopping lifecycle listener for server plugin [" + pluginName + "]");
+ ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(env.getPluginClassLoader());
+ listener.stop();
+ } catch (Throwable t) {
+ log.warn("Lifecycle listener failed to stop plugin [" + pluginName + "]", t);
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalContextClassLoader);
+ }
+ }
+
+ return;
+ }
+
+ /**
+ * Informs the plugin manager that a plugin with the given environment is to be unloaded.
+ * Once this method returns, the plugin's components are should no longer be created or used.
+ *
+ * @param env the environment of the plugin to be unloaded
+ *
+ * @throws Exception if the plugin manager cannot unload the plugin
+ */
+ public synchronized void unloadPlugin(ServerPluginEnvironment env) throws Exception {
+ String pluginName = env.getPluginName();
+ log.debug("Unloading server plugin [" + pluginName + "]");
+
+ try {
+ // tell the plugin we are unloading it
+ ServerPluginLifecycleListener listener = this.pluginLifecycleListenerCache.get(pluginName);
+ if (listener != null) {
+ log.debug("Shutting down lifecycle listener for server plugin [" + pluginName + "]");
+ ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(env.getPluginClassLoader());
+ listener.shutdown();
+ } catch (Throwable t) {
+ throw new Exception("Plugin Lifecycle Listener failed to initialize plugin", t);
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalContextClassLoader);
+ this.pluginLifecycleListenerCache.remove(pluginName);
+ }
+ }
+ } finally {
+ this.loadedPlugins.remove(pluginName);
+ }
+
+ return;
+ }
+
+ /**
+ * Returns the {@link ServerPluginEnvironment}s for every plugin this manager has loaded.
+ * The returned collection is a copy and not backed by this manager.
+ *
+ * @return environments for all the plugins
+ */
+ public synchronized Collection<ServerPluginEnvironment> getPluginEnvironments() {
+ return new ArrayList<ServerPluginEnvironment>(this.loadedPlugins.values());
+ }
+
+ /**
+ * Given a plugin name, this returns that plugin's environment.
+ *
+ * <p>The plugin's name is defined in its plugin descriptor - specifically the XML root node's "name" attribute
+ * (e.g. <server-plugin name="thePluginName").</p>
+ *
+ * @param pluginName the plugin whose environment is to be returned
+ * @return given plugin's environment
+ */
+ public synchronized ServerPluginEnvironment getPluginEnvironment(String pluginName) {
+ return this.loadedPlugins.get(pluginName);
+ }
+
+ public AbstractTypeServerPluginContainer getParentPluginContainer() {
+ return this.parentPluginContainer;
+ }
+
+ protected Log getLog() {
+ return this.log;
+ }
+
+ protected ServerPluginContext createServerPluginContext(ServerPluginEnvironment env) {
+ MasterServerPluginContainer masterPC = this.parentPluginContainer.getMasterServerPluginContainer();
+ MasterServerPluginContainerConfiguration masterConfig = masterPC.getConfiguration();
+ File dataDir = new File(masterConfig.getDataDirectory(), env.getPluginName());
+ File tmpDir = masterConfig.getTemporaryDirectory();
+
+ ServerPluginContext context = new ServerPluginContext(env, dataDir, tmpDir);
+ return context;
+ }
+
+ /**
+ * This will create a new {@link ServerPluginLifecycleListener} instance for that is used to
+ * initialize and shutdown a particular server plugin. If there is no plugin lifecycle listener
+ * configured for the given plugin, <code>null</code> is returned.
+ *
+ * The new object will be loaded in the plugin's specific classloader.
+ *
+ * @param pluginName the name of the plugin whose listener is to be retrieved
+ * @param environment the environment in which the plugin will execute
+ *
+ * @return a new object loaded in the proper plugin classloader that can initialize/shutdown the plugin,
+ * or <code>null</code> if there is no plugin lifecycle listener to be associated with the given plugin
+ *
+ * @throws Exception if failed to create the instance
+ */
+ protected ServerPluginLifecycleListener createServerPluginLifecycleListener(ServerPluginEnvironment environment)
+ throws Exception {
+
+ String pluginName = environment.getPluginName();
+ ServerPluginLifecycleListener instance = null;
+
+ String className = environment.getPluginDescriptor().getPluginLifecycleListener();
+ if (className != null) {
+ String pkg = environment.getPluginDescriptor().getPackage();
+ if ((className.indexOf('.') == -1) && (pkg != null)) {
+ className = pkg + '.' + className;
+ }
+
+ log.debug("Creating plugin lifecycle listener [" + className + "] for plugin [" + pluginName + "]");
+ instance = (ServerPluginLifecycleListener) instantiatePluginClass(environment, className);
+ log.debug("Created plugin lifecycle listener [" + className + "] for plugin [" + pluginName + "]");
+ }
+
+ return instance;
+ }
+
+ /**
+ * Instantiates a class with the given name within the given environment's classloader using
+ * the class' no-arg constructor.
+ *
+ * @param environment the environment that has the classloader where the class will be loaded
+ * @param className the class to instantiate
+ * @return the new object that is an instance of the given class
+ * @throws Exception if failed to instantiate the class
+ */
+ protected Object instantiatePluginClass(ServerPluginEnvironment environment, String className) throws Exception {
+
+ ClassLoader loader = environment.getPluginClassLoader();
+
+ log.debug("Loading server plugin class [" + className + "]...");
+
+ try {
+ Class<?> clazz = Class.forName(className, true, loader);
+ log.debug("Loaded server plugin class [" + clazz + "].");
+ return clazz.newInstance();
+ } catch (InstantiationException e) {
+ throw new Exception("Could not instantiate plugin class [" + className + "] from plugin environment ["
+ + environment + "]", e);
+ } catch (IllegalAccessException e) {
+ throw new Exception("Could not access plugin class " + className + "] from plugin environment ["
+ + environment + "]", e);
+ } catch (ClassNotFoundException e) {
+ throw new Exception("Could not find plugin class " + className + "] from plugin environment ["
+ + environment + "]", e);
+ } catch (NullPointerException npe) {
+ throw new Exception("Plugin class was 'null' in plugin environment [" + environment + "]", npe);
+ }
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
index 2e470dc..d6bae90 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
@@ -113,21 +113,22 @@ public class ServerPluginService implements ServerPluginServiceManagement {
protected MasterServerPluginContainer createMasterPluginContainer() {
MasterServerPluginContainer pc = new MasterServerPluginContainer();
- MasterServerPluginContainerConfiguration config = new MasterServerPluginContainerConfiguration();
-
String pluginDirStr = System.getProperty(ServerConfig.SERVER_HOME_DIR);
File pluginDir = new File(pluginDirStr, "deploy/" + RHQConstants.EAR_FILE_NAME + "/rhq-serverplugins");
- config.setPluginDirectory(pluginDir);
+
+ String dataDirStr = System.getProperty(ServerConfig.SERVER_DATA_DIR);
+ File dataDir = new File(dataDirStr, "server-plugins");
+ dataDir.mkdirs(); // make sure the data directory exists
String tmpDirStr = System.getProperty(ServerConfig.SERVER_TEMP_DIR);
- config.setTemporaryDirectory(new File(tmpDirStr));
+ File tmpDir = new File(tmpDirStr);
// TODO: determine what things to hide from our war classloader
//StringBuilder defaultRegex = new StringBuilder();
//defaultRegex.append("(package\\.with\\.classes\\.to\\.hide\\..*)|");
- config.setRootPluginClassLoaderRegex(null);
-
+ MasterServerPluginContainerConfiguration config;
+ config = new MasterServerPluginContainerConfiguration(pluginDir, dataDir, tmpDir, null);
pc.initialize(config);
return pc;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
index 999bfba..9e63460 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
@@ -585,7 +585,7 @@ public class ContentProviderManager {
pluginName = this.pluginManager.getMetadataManager().getPluginNameFromContentSourceType(type);
ServerPluginEnvironment pluginEnv = this.pluginManager.getPluginEnvironment(pluginName);
- ClassLoader pluginClassloader = pluginEnv.getClassLoader();
+ ClassLoader pluginClassloader = pluginEnv.getPluginClassLoader();
ClassLoader startingClassLoader = Thread.currentThread().getContextClassLoader();
try {
@@ -663,7 +663,7 @@ public class ContentProviderManager {
throw new RuntimeException("There is no plugin env. for content source [" + contentSource + "]");
}
- ClassLoader classLoader = env.getClassLoader();
+ ClassLoader classLoader = env.getPluginClassLoader();
IsolatedInvocationHandler handler = new IsolatedInvocationHandler(adapter, classLoader);
List<Class<?>> ifacesList = new ArrayList<Class<?>>(1);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
index 3c5427d..3edba4d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
@@ -28,7 +28,7 @@ import org.rhq.core.domain.content.ContentSource;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.PluginManager;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginManager;
import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.scheduler.SchedulerLocal;
import org.rhq.enterprise.server.scheduler.jobs.ContentSourceSyncJob;
@@ -181,7 +181,7 @@ public class ContentServerPluginContainer extends AbstractTypeServerPluginContai
}
@Override
- protected PluginManager createPluginManager() {
+ protected ServerPluginManager createPluginManager() {
return new ContentServerPluginManager(this);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginManager.java
index 03a4b5f..6f42c5e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginManager.java
@@ -23,8 +23,8 @@ import java.util.HashSet;
import java.util.Set;
import org.rhq.core.domain.content.ContentSourceType;
-import org.rhq.enterprise.server.plugin.pc.PluginManager;
import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginManager;
import org.rhq.enterprise.server.plugin.pc.content.metadata.ContentSourcePluginMetadataManager;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.content.ContentPluginDescriptorType;
@@ -36,7 +36,7 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.content.Conten
*
* @author John Mazzitelli
*/
-public class ContentServerPluginManager extends PluginManager {
+public class ContentServerPluginManager extends ServerPluginManager {
private ContentSourcePluginMetadataManager metadataManager;
@@ -91,7 +91,7 @@ public class ContentServerPluginManager extends PluginManager {
for (ContentSourceType newType : newTypesCopy) {
try {
String className = newType.getContentSourceApiClass();
- Class<?> apiClass = Class.forName(className, false, env.getClassLoader());
+ Class<?> apiClass = Class.forName(className, false, env.getPluginClassLoader());
if (!ContentProvider.class.isAssignableFrom(apiClass)) {
throw new Exception("The API class [" + className + "] should implement ["
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
index 04de1a5..ea0e8a3 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
@@ -66,7 +66,7 @@ import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails
import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetailsKey;
import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
-import org.rhq.enterprise.server.test.TestServerPluginService;
+import org.rhq.enterprise.server.test.TestContentServerPluginService;
import org.rhq.enterprise.server.util.LookupUtil;
@Test
@@ -123,7 +123,7 @@ public class ContentSourceManagerBeanTest extends AbstractEJB3Test {
private ResourceType resourceType1;
private Resource resource1;
- private TestServerPluginService pluginService;
+ private TestContentServerPluginService pluginService;
@BeforeClass
public void setupBeforeClass() throws Exception {
@@ -151,7 +151,7 @@ public class ContentSourceManagerBeanTest extends AbstractEJB3Test {
setupTestEnvironment();
overlord = LookupUtil.getSubjectManager().getOverlord();
prepareScheduler();
- pluginService = prepareServerPluginService();
+ pluginService = prepareContentServerPluginService();
pluginService.startMasterPluginContainer();
cleanupPreviousTestRuns();
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
index 139062c..e1d4fe9 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
@@ -56,7 +56,7 @@ import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
-import org.rhq.enterprise.server.test.TestServerPluginService;
+import org.rhq.enterprise.server.test.TestContentServerPluginService;
import org.rhq.enterprise.server.util.LookupUtil;
/**
@@ -90,7 +90,7 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
// Plugin service setup
prepareScheduler();
- TestServerPluginService pluginService = prepareServerPluginService();
+ TestContentServerPluginService pluginService = prepareContentServerPluginService();
pluginService.startMasterPluginContainer();
// Because of the (current) transaction settings of some of the nested methods (i.e. REQUIRES_NEW),
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
index 448a38f..a5fa70c 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
@@ -49,6 +49,7 @@ import org.rhq.core.domain.util.PersistenceUtility;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.auth.SessionManager;
import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceMBean;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
import org.rhq.enterprise.server.scheduler.SchedulerService;
import org.rhq.enterprise.server.scheduler.SchedulerServiceMBean;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -245,10 +246,10 @@ public abstract class AbstractEJB3Test extends AssertJUnit {
}
}
- private TestServerPluginService serverPluginService;
+ private ServerPluginService serverPluginService;
/**
- * If you need to test content source server plugins, or other server plugins, you must first prepare the server plugin service via
+ * If you need to test content source server plugins, you must first prepare the server plugin service via
* this method. The caller must explicitly start the PC by using the appropriate API on the returned object; this
* method will only start the service, it will NOT start the master PC.
*
@@ -256,12 +257,12 @@ public abstract class AbstractEJB3Test extends AssertJUnit {
*
* @throws RuntimeException
*/
- public TestServerPluginService prepareServerPluginService() {
+ public TestContentServerPluginService prepareContentServerPluginService() {
try {
MBeanServer mbs = getJBossMBeanServer();
- TestServerPluginService mbean = new TestServerPluginService();
+ TestContentServerPluginService mbean = new TestContentServerPluginService();
mbean.start();
- mbs.registerMBean(mbean, TestServerPluginService.OBJECT_NAME);
+ mbs.registerMBean(mbean, TestContentServerPluginService.OBJECT_NAME);
serverPluginService = mbean;
return mbean;
} catch (Exception e) {
@@ -273,7 +274,7 @@ public abstract class AbstractEJB3Test extends AssertJUnit {
if (serverPluginService != null) {
serverPluginService.stopMasterPluginContainer();
serverPluginService.stop();
- getJBossMBeanServer().unregisterMBean(TestServerPluginService.OBJECT_NAME);
+ getJBossMBeanServer().unregisterMBean(ServerPluginService.OBJECT_NAME);
serverPluginService = null;
}
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java
new file mode 100644
index 0000000..1d68798
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java
@@ -0,0 +1,187 @@
+/*
+ * 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.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.rhq.core.domain.content.ContentSource;
+import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+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.ContentProviderPackageDetails;
+import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginManager;
+import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
+import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
+
+/**
+ * Used as a mock service for the content source plugin container.
+ */
+public class TestContentServerPluginService extends ServerPluginService implements TestContentServerPluginServiceMBean {
+ // public so tests can directly set these
+ public Map<ContentSource, ContentProvider> testAdapters;
+ public PackageSyncReport testLastSyncReport;
+ public Map<ContentSource, Collection<ContentProviderPackageDetails>> testExistingPackages;
+ public TestMasterServerPluginContainer master;
+
+ @Override
+ protected MasterServerPluginContainer createMasterPluginContainer() {
+ this.master = new TestMasterServerPluginContainer();
+ File dir = new File(System.getProperty("java.io.tmpdir"), "test-server-plugins");
+ MasterServerPluginContainerConfiguration config = new MasterServerPluginContainerConfiguration(dir, dir, dir,
+ null);
+ this.master.initialize(config);
+ return this.master;
+ }
+
+ /**
+ * The test master PC
+ */
+ class TestMasterServerPluginContainer extends MasterServerPluginContainer {
+ @Override
+ protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
+ ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(1);
+ pcs.add(new TestContentServerPluginContainer(this));
+ return pcs;
+ }
+
+ @Override
+ protected ClassLoader createRootServerPluginClassLoader() {
+ return this.getClass().getClassLoader();
+ }
+
+ @Override
+ protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
+ return new HashMap<URL, ServerPluginDescriptorType>();
+ }
+ }
+
+ /**
+ * The test content PC.
+ */
+ class TestContentServerPluginContainer extends ContentServerPluginContainer {
+ public TestContentServerPluginContainer(MasterServerPluginContainer master) {
+ super(master);
+ }
+
+ @Override
+ protected ContentProviderManager createAdapterManager() {
+ TestContentProviderManager am = new TestContentProviderManager();
+ return am;
+ }
+
+ @Override
+ protected ContentServerPluginManager createPluginManager() {
+ TestContentProviderPluginManager pm = new TestContentProviderPluginManager(this);
+ return pm;
+ }
+ }
+
+ /**
+ * The test plugin manager.
+ */
+ class TestContentProviderPluginManager extends ContentServerPluginManager {
+ public TestContentProviderPluginManager(ContentServerPluginContainer pc) {
+ super(pc);
+ }
+ }
+
+ /**
+ * The test adapter manager.
+ */
+ class TestContentProviderManager extends ContentProviderManager {
+ @Override
+ public Set<ContentSource> getAllContentSources() {
+ return (testAdapters != null) ? testAdapters.keySet() : new HashSet<ContentSource>();
+ }
+
+ @Override
+ protected void initialize(ContentServerPluginManager pluginManager) {
+ createInitialAdaptersMap();
+ }
+
+ @Override
+ public void shutdown() {
+ }
+
+ @Override
+ public InputStream loadPackageBits(int contentSourceId, String location) throws Exception {
+ if (testAdapters != null) {
+ for (ContentSource cs : testAdapters.keySet()) {
+ if (cs.getId() == contentSourceId) {
+ PackageSource packageSource = (PackageSource) testAdapters.get(cs);
+ return packageSource.getInputStream(location);
+ }
+ }
+ }
+
+ System.out.println("!!!!!!!!!!");
+ System.out.println("STREAM: TEST DID NOT SETUP ADAPTER - EMPTY STREAM FOR [" + contentSourceId + "]");
+ return new ByteArrayInputStream(new byte[0]);
+ }
+
+ @Override
+ public boolean synchronizeContentSource(int contentSourceId) throws Exception {
+ if (testAdapters != null) {
+ for (ContentSource cs : testAdapters.keySet()) {
+ if (cs.getId() == contentSourceId) {
+ testLastSyncReport = new PackageSyncReport();
+ PackageSource packageSource = (PackageSource) testAdapters.get(cs);
+ packageSource.synchronizePackages(testLastSyncReport, testExistingPackages.get(cs));
+ return true;
+ }
+ }
+ }
+
+ System.out.println("!!!!!!!!!!");
+ System.out.println("SYNC: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
+ return true;
+ }
+
+ @Override
+ public boolean testConnection(int contentSourceId) throws Exception {
+ if (testAdapters != null) {
+ for (ContentSource cs : testAdapters.keySet()) {
+ if (cs.getId() == contentSourceId) {
+ testAdapters.get(cs).testConnection();
+ return true;
+ }
+ }
+ }
+
+ System.out.println("!!!!!!!!!!");
+ System.out.println("CONN: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginServiceMBean.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginServiceMBean.java
new file mode 100644
index 0000000..bbdebaf
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginServiceMBean.java
@@ -0,0 +1,24 @@
+/*
+ * 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.test;
+
+import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
+
+public interface TestContentServerPluginServiceMBean extends ServerPluginServiceManagement {
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
deleted file mode 100644
index a9dcef4..0000000
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
+++ /dev/null
@@ -1,184 +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.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.rhq.core.domain.content.ContentSource;
-import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
-import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
-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.ContentProviderPackageDetails;
-import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginManager;
-import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
-import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
-import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
-
-/**
- * Used as a mock service for the content source plugin container.
- */
-public class TestServerPluginService extends ServerPluginService implements TestServerPluginServiceMBean {
- // public so tests can directly set these
- public Map<ContentSource, ContentProvider> testAdapters;
- public PackageSyncReport testLastSyncReport;
- public Map<ContentSource, Collection<ContentProviderPackageDetails>> testExistingPackages;
- public TestMasterServerPluginContainer master;
-
- @Override
- protected MasterServerPluginContainer createMasterPluginContainer() {
- this.master = new TestMasterServerPluginContainer();
- MasterServerPluginContainerConfiguration config = new MasterServerPluginContainerConfiguration();
- this.master.initialize(config);
- return this.master;
- }
-
- /**
- * The test master PC
- */
- class TestMasterServerPluginContainer extends MasterServerPluginContainer {
- @Override
- protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
- ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(1);
- pcs.add(new TestContentServerPluginContainer(this));
- return pcs;
- }
-
- @Override
- protected ClassLoader createRootServerPluginClassLoader() {
- return this.getClass().getClassLoader();
- }
-
- @Override
- protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
- return new HashMap<URL, ServerPluginDescriptorType>();
- }
- }
-
- /**
- * The test content PC.
- */
- class TestContentServerPluginContainer extends ContentServerPluginContainer {
- public TestContentServerPluginContainer(MasterServerPluginContainer master) {
- super(master);
- }
-
- @Override
- protected ContentProviderManager createAdapterManager() {
- TestContentProviderManager am = new TestContentProviderManager();
- return am;
- }
-
- @Override
- protected ContentServerPluginManager createPluginManager() {
- TestContentProviderPluginManager pm = new TestContentProviderPluginManager(this);
- return pm;
- }
- }
-
- /**
- * The test plugin manager.
- */
- class TestContentProviderPluginManager extends ContentServerPluginManager {
- public TestContentProviderPluginManager(ContentServerPluginContainer pc) {
- super(pc);
- }
- }
-
- /**
- * The test adapter manager.
- */
- class TestContentProviderManager extends ContentProviderManager {
- @Override
- public Set<ContentSource> getAllContentSources() {
- return (testAdapters != null) ? testAdapters.keySet() : new HashSet<ContentSource>();
- }
-
- @Override
- protected void initialize(ContentServerPluginManager pluginManager) {
- createInitialAdaptersMap();
- }
-
- @Override
- public void shutdown() {
- }
-
- @Override
- public InputStream loadPackageBits(int contentSourceId, String location) throws Exception {
- if (testAdapters != null) {
- for (ContentSource cs : testAdapters.keySet()) {
- if (cs.getId() == contentSourceId) {
- PackageSource packageSource = (PackageSource) testAdapters.get(cs);
- return packageSource.getInputStream(location);
- }
- }
- }
-
- System.out.println("!!!!!!!!!!");
- System.out.println("STREAM: TEST DID NOT SETUP ADAPTER - EMPTY STREAM FOR [" + contentSourceId + "]");
- return new ByteArrayInputStream(new byte[0]);
- }
-
- @Override
- public boolean synchronizeContentSource(int contentSourceId) throws Exception {
- if (testAdapters != null) {
- for (ContentSource cs : testAdapters.keySet()) {
- if (cs.getId() == contentSourceId) {
- testLastSyncReport = new PackageSyncReport();
- PackageSource packageSource = (PackageSource) testAdapters.get(cs);
- packageSource.synchronizePackages(testLastSyncReport, testExistingPackages.get(cs));
- return true;
- }
- }
- }
-
- System.out.println("!!!!!!!!!!");
- System.out.println("SYNC: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
- return true;
- }
-
- @Override
- public boolean testConnection(int contentSourceId) throws Exception {
- if (testAdapters != null) {
- for (ContentSource cs : testAdapters.keySet()) {
- if (cs.getId() == contentSourceId) {
- testAdapters.get(cs).testConnection();
- return true;
- }
- }
- }
-
- System.out.println("!!!!!!!!!!");
- System.out.println("CONN: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
- return true;
- }
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginServiceMBean.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginServiceMBean.java
deleted file mode 100644
index 945f6e5..0000000
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginServiceMBean.java
+++ /dev/null
@@ -1,24 +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.test;
-
-import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
-
-public interface TestServerPluginServiceMBean extends ServerPluginServiceManagement {
-}
\ No newline at end of file
commit dbdbb5e9566363fa1977f700cc88268a91463df2
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 9 00:48:16 2009 -0500
add a sample server plugin to demo generic plugins and lifecycle
listeners
diff --git a/.classpath b/.classpath
index d88d80c..12cfe43 100644
--- a/.classpath
+++ b/.classpath
@@ -105,6 +105,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="etc/samples/skeleton-plugin/src/main/java"/>
+ <classpathentry kind="src" path="etc/samples/custom-serverplugin/src/main/java"/>
<classpathentry kind="src" path="etc/agentspawn/src/main/java"/>
<classpathentry excluding="**" kind="src" path="modules/enterprise/comm/src/test/resources"/>
<classpathentry excluding="**" kind="src" path="modules/enterprise/agent/src/main/resources"/>
diff --git a/etc/custom-serverplugin/pom.xml b/etc/custom-serverplugin/pom.xml
deleted file mode 100644
index 13270f4..0000000
--- a/etc/custom-serverplugin/pom.xml
+++ /dev/null
@@ -1,165 +0,0 @@
-<?xml version="1.0"?>
-
-<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>
-
- <groupId>org.custom</groupId>
- <artifactId>custom-serverplugin</artifactId>
- <version>1.0-SNAPSHOT</version>
- <packaging>jar</packaging>
-
- <name>Custom RHQ Content Source Server Plugin Template</name>
- <description>a template for building a custom RHQ server plugin for a custom content source</description>
-
- <properties>
- <rhq.version>1.2.0.GA</rhq.version>
- </properties>
-
- <dependencies>
-
- <!-- Below are the core modules that are required dependencies of all plugins -->
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-core-domain</artifactId>
- <version>${rhq.version}</version>
- <scope>provided</scope> <!-- provided by the server/plugin-container -->
- </dependency>
-
- <dependency>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-core-client-api</artifactId>
- <version>${rhq.version}</version>
- <scope>provided</scope> <!-- provided by the server/plugin-container -->
- </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>javax.persistence</groupId>
- <artifactId>persistence-api</artifactId>
- <version>1.0</version>
- <scope>provided</scope> <!-- provided by the server/plugin-container -->
- </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> <!-- provided by the server/plugin-container -->
- </dependency>
-
- <!-- uncomment the one of the three logging systems your plugin uses: log4j, commons-logging or i18nlog -->
- <!-- all three are provided to your plugin by the server/plugin-container -->
- <!--
- <dependency>
- <groupId>log4j</groupId>
- <artifactId>log4j</artifactId>
- <version>1.2.14</version>
- <scope>provided</scope>
- </dependency>
- -->
-
- <!--
- <dependency>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- <version>1.1</version>
- <scope>provided</scope>
- </dependency>
- -->
-
- <!--
- <dependency>
- <groupId>i18nlog</groupId>
- <artifactId>i18nlog</artifactId>
- <version>1.0.9</version>
- </dependency>
- -->
-
- <!-- Define any third-party dependencies your plugin has here. -->
- <!--
- <dependency>
- <groupId>group-id-of-dependency-goes-here</groupId>
- <artifactId>artifact-id-of-dependency-goes-here</artifactId>
- <version>version-of-dependency-goes-here</version>
- </dependency>
- -->
-
- </dependencies>
-
- <build>
- <plugins>
-
- <plugin>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>1.5</source>
- <target>1.5</target>
- </configuration>
- </plugin>
-
- <!--
- If your plugin has third-party jar dependencies that are not already
- available when deployed in the plugin container, you can package these
- jars in your plugin. They go in your plugin jar's "lib" directory.
- Uncomment the maven plugin definition below and define one or more jar
- files (aka "artifactItem" elements) that you want to include in your
- plugin jar.
- -->
-
-<!--
- <plugin>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>copy-dependencies</id>
- <phase>process-resources</phase>
- <goals>
- <goal>copy</goal>
- </goals>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>your-third-party-dep-group</groupId>
- <artifactId>your-third-party-dep-artifact</artifactId>
- <version>your-third-party-dep-version</version>
- </artifactItem>
- </artifactItems>
- <outputDirectory>${project.build.outputDirectory}/lib</outputDirectory>
- </configuration>
- </execution>
- </executions>
- </plugin>
--->
-
- </plugins>
- </build>
-
- <repositories>
- <repository>
- <id>jboss</id>
- <name>JBoss Repository</name>
- <url>http://repository.jboss.org/maven2/</url>
- <snapshots>
- <enabled>false</enabled>
- </snapshots>
- </repository>
- </repositories>
-
- <pluginRepositories>
- <pluginRepository>
- <id>jboss</id>
- <name>JBoss Plugin Repository</name>
- <url>http://repository.jboss.org/maven2/</url>
- <snapshots>
- <enabled>false</enabled>
- </snapshots>
- </pluginRepository>
- </pluginRepositories>
-
-</project>
diff --git a/etc/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin-content.xml b/etc/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin-content.xml
deleted file mode 100644
index de569b1..0000000
--- a/etc/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin-content.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-
-<plugin name="MyCustomContentSourcePlugin"
- xmlns="urn:xmlns:rhq-serverplugin.content"
- xmlns:c="urn:xmlns:rhq-configuration">
-
- <contentSourceType name="MyCustomContentSource"
- displayName="My Custom Content Source"
- description="This is my custom content source that retrieves packages from some custom repository."
- lazyLoad="true"
- syncSchedule="0 0 3 * * ?"
- apiClass="org.custom.serverplugin.MyCustomContentSource">
-
- <configuration>
- <c:simple-property name="myCustomProperty" type="string" required="true" description="A property my plugin needs to be properly configured" />
- </configuration>
-
- </contentSourceType>
-
-</plugin>
\ No newline at end of file
diff --git a/etc/samples/custom-serverplugin/pom.xml b/etc/samples/custom-serverplugin/pom.xml
new file mode 100644
index 0000000..833ce0c
--- /dev/null
+++ b/etc/samples/custom-serverplugin/pom.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0"?>
+
+<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>
+
+ <groupId>org.custom</groupId>
+ <artifactId>custom-serverplugin</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>Custom RHQ Server Plugin Template</name>
+ <description>A template for building a custom generic RHQ server plugin</description>
+
+ <properties>
+ <rhq.version>1.4.0-SNAPSHOT</rhq.version>
+ </properties>
+
+ <dependencies>
+
+ <!-- Below are the core modules that are required dependencies of all plugins -->
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-server</artifactId>
+ <version>${rhq.version}</version>
+ <scope>provided</scope> <!-- provided by the server/plugin-container -->
+ </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>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope> <!-- provided by the server/plugin-container -->
+ </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> <!-- provided by the server/plugin-container -->
+ </dependency>
+
+ <!-- uncomment the one of the three logging systems your plugin uses: log4j, commons-logging or i18nlog -->
+ <!-- all three are provided to your plugin by the server/plugin-container -->
+ <!--
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.14</version>
+ <scope>provided</scope>
+ </dependency>
+ -->
+
+ <!--
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.1</version>
+ <scope>provided</scope>
+ </dependency>
+ -->
+
+ <!--
+ <dependency>
+ <groupId>i18nlog</groupId>
+ <artifactId>i18nlog</artifactId>
+ <version>1.0.9</version>
+ </dependency>
+ -->
+
+ <!-- Define any third-party dependencies your plugin has here. -->
+ <!--
+ <dependency>
+ <groupId>group-id-of-dependency-goes-here</groupId>
+ <artifactId>artifact-id-of-dependency-goes-here</artifactId>
+ <version>version-of-dependency-goes-here</version>
+ </dependency>
+ -->
+
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.5</source>
+ <target>1.5</target>
+ </configuration>
+ </plugin>
+
+ <!--
+ If your plugin has third-party jar dependencies that are not already
+ available when deployed in the plugin container, you can package these
+ jars in your plugin. They go in your plugin jar's "lib" directory.
+ Uncomment the maven plugin definition below and define one or more jar
+ files (aka "artifactItem" elements) that you want to include in your
+ plugin jar.
+ -->
+
+<!--
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>your-third-party-dep-group</groupId>
+ <artifactId>your-third-party-dep-artifact</artifactId>
+ <version>your-third-party-dep-version</version>
+ </artifactItem>
+ </artifactItems>
+ <outputDirectory>${project.build.outputDirectory}/lib</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+-->
+
+ </plugins>
+ </build>
+
+ <repositories>
+ <repository>
+ <id>jboss</id>
+ <name>JBoss Repository</name>
+ <url>http://repository.jboss.org/maven2/</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>jboss</id>
+ <name>JBoss Plugin Repository</name>
+ <url>http://repository.jboss.org/maven2/</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </pluginRepository>
+ </pluginRepositories>
+
+</project>
diff --git a/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
new file mode 100644
index 0000000..a2deeef
--- /dev/null
+++ b/etc/samples/custom-serverplugin/src/main/java/org/custom/MyLifecycleListener.java
@@ -0,0 +1,63 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.custom;
+
+import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginLifecycleListener;
+
+/**
+ * A sample lifecycle listener for the sample generic plugin. This listener will be
+ * the main interface the server uses to start and stop the plugin.
+ */
+public class MyLifecycleListener implements ServerPluginLifecycleListener {
+
+ private ServerPluginContext context;
+
+ public void initialize(ServerPluginContext context) throws Exception {
+ this.context = context;
+ System.out.println("The sample plugin has been initialized!!! : " + this);
+ }
+
+ public void start() {
+ System.out.println("The sample plugin has started!!! : " + this);
+ }
+
+ public void stop() {
+ System.out.println("The sample plugin has stopped!!! : " + this);
+ }
+
+ public void shutdown() {
+ System.out.println("The sample plugin has been shut down!!! : " + this);
+ }
+
+ @Override
+ public String toString() {
+ if (this.context == null) {
+ return "<no context>";
+ }
+
+ StringBuilder str = new StringBuilder();
+ str.append("plugin-name=").append(this.context.getPluginEnvironment().getPluginName()).append(",");
+ str.append("plugin-url=").append(this.context.getPluginEnvironment().getPluginUrl()).append(",");
+ str.append("data-dir=").append(this.context.getDataDirectory()).append(",");
+ str.append("tmp-dir=").append(this.context.getTemporaryDirectory()); // do not append ,
+ return str.toString();
+ }
+}
diff --git a/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
new file mode 100644
index 0000000..928f635
--- /dev/null
+++ b/etc/samples/custom-serverplugin/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<generic-plugin name="CustomGenericPlugin"
+ displayName="My Custom Generic Plugin"
+ description="A custom generic plugin."
+ package="org.custom"
+ pluginLifecycleListener="MyLifecycleListener"
+ version="1.0"
+ apiVersion="2.0"
+ xmlns="urn:xmlns:rhq-serverplugin.generic"
+ xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <serverplugin:plugin-configuration>
+ <c:simple-property name="myCustomProperty" type="string" required="true" description="A property my plugin needs to be properly configured" />
+ </serverplugin:plugin-configuration>
+
+</generic-plugin>
\ No newline at end of file
commit b5a7aece77f027d756352bac5eb16ecf9ed47b10
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 8 19:00:09 2009 -0500
add lifecycle listener to server plugin stuff. change unit tests to explicitly create a server plugin server for content, leaving room for us to add different types later
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginManager.java
index 1b9399a..005b427 100644
--- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginManager.java
+++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/plugin/PluginManager.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2009 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index a7a166d..0d94174 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -34,7 +34,7 @@ public abstract class AbstractTypeServerPluginContainer {
private final Log log = LogFactory.getLog(this.getClass());
private final MasterServerPluginContainer master;
- private PluginManager pluginManager;
+ private ServerPluginManager pluginManager;
/**
* Instantiates the plugin container. All subclasses must support this and only this
@@ -69,7 +69,7 @@ public abstract class AbstractTypeServerPluginContainer {
*
* @return the plugin manager for this container
*/
- public PluginManager getPluginManager() {
+ public ServerPluginManager getPluginManager() {
return this.pluginManager;
}
@@ -82,6 +82,7 @@ public abstract class AbstractTypeServerPluginContainer {
* @throws Exception if the plugin container failed to initialize for some reason
*/
public synchronized void initialize() throws Exception {
+ log.debug("Server plugin container initializing");
this.pluginManager = createPluginManager();
this.pluginManager.initialize();
}
@@ -92,7 +93,9 @@ public abstract class AbstractTypeServerPluginContainer {
* ever know about have been {@link #loadPlugin(ServerPluginEnvironment) loaded}.
*/
public synchronized void start() {
- return; // no-op
+ log.debug("Server plugin container starting");
+ this.pluginManager.startPlugins();
+ return;
}
/**
@@ -100,7 +103,9 @@ public abstract class AbstractTypeServerPluginContainer {
* the plugin container must assume that soon it will be asked to {@link #shutdown()}.
*/
public synchronized void stop() {
- return; // no-op
+ log.debug("Server plugin container stopping");
+ this.pluginManager.stopPlugins();
+ return;
}
/**
@@ -109,6 +114,8 @@ public abstract class AbstractTypeServerPluginContainer {
* Subclasses are free to perform additional tasks by overriding this method.
*/
public synchronized void shutdown() {
+ log.debug("Server plugin container shutting down");
+
if (this.pluginManager != null) {
Collection<ServerPluginEnvironment> envs = this.pluginManager.getPluginEnvironments();
for (ServerPluginEnvironment env : envs) {
@@ -166,8 +173,8 @@ public abstract class AbstractTypeServerPluginContainer {
*
* @return the plugin manager for use by this plugin container
*/
- protected PluginManager createPluginManager() {
- return new PluginManager(this);
+ protected ServerPluginManager createPluginManager() {
+ return new ServerPluginManager(this);
}
/**
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainerConfiguration.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainerConfiguration.java
index f22ff59..5bf6d0c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainerConfiguration.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainerConfiguration.java
@@ -27,31 +27,41 @@ import java.io.File;
*/
public class MasterServerPluginContainerConfiguration {
private File pluginDirectory;
+ private File dataDirectory;
private File tmpDirectory;
private String rootClassLoaderRegex;
- public File getPluginDirectory() {
- return this.pluginDirectory;
- }
+ public MasterServerPluginContainerConfiguration(File pluginDirectory, File dataDirectory, File tmpDirectory,
+ String rootClassLoaderRegex) {
- public void setPluginDirectory(File pluginDirectory) {
if (pluginDirectory == null) {
throw new IllegalArgumentException("pluginDirectory == null");
}
-
this.pluginDirectory = pluginDirectory;
- }
- public File getTemporaryDirectory() {
- if (this.tmpDirectory != null) {
- return this.tmpDirectory;
+ if (dataDirectory == null) {
+ throw new IllegalArgumentException("dataDirectory == null");
}
+ this.dataDirectory = dataDirectory;
+
+ if (tmpDirectory == null) {
+ tmpDirectory = new File(System.getProperty("java.io.tmpdir", "."));
+ }
+ this.tmpDirectory = tmpDirectory;
+
+ this.rootClassLoaderRegex = rootClassLoaderRegex;
+ }
+
+ public File getPluginDirectory() {
+ return this.pluginDirectory;
+ }
- return new File(System.getProperty("java.io.tmpdir", "."));
+ public File getDataDirectory() {
+ return this.dataDirectory;
}
- public void setTemporaryDirectory(File tmpDir) {
- this.tmpDirectory = tmpDir;
+ public File getTemporaryDirectory() {
+ return this.tmpDirectory;
}
/**
@@ -70,26 +80,17 @@ public class MasterServerPluginContainerConfiguration {
return this.rootClassLoaderRegex;
}
- /**
- * Sets the regex that defines what classes the plugin container should hide from its plugins.
- *
- * @param regex regular expression
- *
- * @see RootServerPluginClassLoader
- */
- public void setRootPluginClassLoaderRegex(String regex) {
- this.rootClassLoaderRegex = regex;
- }
-
@Override
public String toString() {
File pdir = getPluginDirectory();
File tdir = getTemporaryDirectory();
+ File ddir = getDataDirectory();
String regex = getRootServerPluginClassLoaderRegex();
StringBuilder str = new StringBuilder(MasterServerPluginContainerConfiguration.class + ": ");
str.append("plugin-dir=[" + ((pdir != null) ? pdir.getAbsolutePath() : "<null>"));
str.append("], tmp-dir=[" + ((tdir != null) ? tdir.getAbsolutePath() : "<null>"));
+ str.append("], data-dir=[" + ((ddir != null) ? ddir.getAbsolutePath() : "<null>"));
str.append("], root-cl-regex=[" + ((regex != null) ? regex : "<null>"));
str.append("]");
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
deleted file mode 100644
index 20c66ae..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2009 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.plugin.pc;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Provides functionality to manage plugins for a plugin container. Plugin containers
- * can install their own plugin managers that are extensions to this class if they need to.
- *
- * @author John Mazzitelli
- */
-public class PluginManager {
- private final Log log = LogFactory.getLog(this.getClass());
-
- /**
- * The map of all plugins keyed on plugin name.
- */
- private Map<String, ServerPluginEnvironment> loadedPlugins = new HashMap<String, ServerPluginEnvironment>();
- private AbstractTypeServerPluginContainer parentPluginContainer;
-
- /**
- * Creates a plugin manager for the given plugin container.
- *
- * @param pc the plugin manager's owning plugin container
- */
- public PluginManager(AbstractTypeServerPluginContainer pc) {
- this.parentPluginContainer = pc;
- }
-
- /**
- * Initializes the plugin manager to prepare it to start loading plugins.
- *
- * @throws Exception if failed to initialize
- */
- public synchronized void initialize() throws Exception {
- return; // no-op
- }
-
- /**
- * Shuts down this manager. This should be called only after all of its plugins
- * have been {@link #unloadPlugin(ServerPluginEnvironment) unloaded}.
- */
- public synchronized void shutdown() {
- if (this.loadedPlugins.size() > 0) {
- log.warn("Server plugin manager is being shutdown while some plugins are still loaded: "
- + this.loadedPlugins);
- }
-
- this.loadedPlugins.clear();
- return;
- }
-
- /**
- * Informs the plugin manager that a plugin with the given environment needs to be loaded.
- * Once this method returns, the plugin's components are ready to be created and used.
- *
- * @param env the environment of the plugin to be loaded
- *
- * @throws Exception if the plugin manager cannot load the plugin or deems the plugin invalid
- */
- public synchronized void loadPlugin(ServerPluginEnvironment env) throws Exception {
- log.debug("Loading server plugin [" + env.getPluginName() + "] from: " + env.getPluginUrl());
- this.loadedPlugins.put(env.getPluginName(), env);
- return;
- }
-
- /**
- * Informs the plugin manager that a plugin with the given environment is to be unloaded.
- * Once this method returns, the plugin's components are should no longer be created or used.
- *
- * @param env the environment of the plugin to be unloaded
- *
- * @throws Exception if the plugin manager cannot unload the plugin
- */
- public synchronized void unloadPlugin(ServerPluginEnvironment env) throws Exception {
- log.debug("Unloading server plugin [" + env.getPluginName() + "]");
- this.loadedPlugins.remove(env.getPluginName());
- return;
- }
-
- /**
- * Returns the {@link ServerPluginEnvironment}s for every plugin this manager has loaded.
- * The returned collection is a copy and not backed by this manager.
- *
- * @return environments for all the plugins
- */
- public synchronized Collection<ServerPluginEnvironment> getPluginEnvironments() {
- return new ArrayList<ServerPluginEnvironment>(this.loadedPlugins.values());
- }
-
- /**
- * Given a plugin name, this returns that plugin's environment.
- *
- * <p>The plugin's name is defined in its plugin descriptor - specifically the XML root node's "name" attribute
- * (e.g. <server-plugin name="thePluginName").</p>
- *
- * @param pluginName the plugin whose environment is to be returned
- * @return given plugin's environment
- */
- public synchronized ServerPluginEnvironment getPluginEnvironment(String pluginName) {
- return this.loadedPlugins.get(pluginName);
- }
-
- public AbstractTypeServerPluginContainer getParentPluginContainer() {
- return this.parentPluginContainer;
- }
-
- protected Log getLog() {
- return this.log;
- }
-}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
new file mode 100644
index 0000000..f234cd1
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginContext.java
@@ -0,0 +1,85 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import java.io.File;
+
+/**
+ * A global context containing information about a server-side plugin.
+ *
+ * @author John Mazzitelli
+ */
+public class ServerPluginContext {
+ private final ServerPluginEnvironment pluginEnvironment;
+ private final File temporaryDirectory;
+ private final File dataDirectory;
+
+ /**
+ * Creates a new {@link ServerPluginContext} object. The plugin container is responsible for instantiating these
+ * objects; plugin writers should never have to actually create context objects.
+ *
+ * @param env the environment of the plugin - includes the plugin name and other info
+ * @param dataDirectory a directory where plugins can store persisted data that survives server restarts
+ * @param tmpDirectory a temporary directory for plugin use
+ */
+ public ServerPluginContext(ServerPluginEnvironment env, File dataDirectory, File tmpDirectory) {
+ this.pluginEnvironment = env;
+ this.dataDirectory = dataDirectory;
+ if (tmpDirectory == null) {
+ this.temporaryDirectory = new File(System.getProperty("java.io.tmpdir"), "SERVERPLUGIN_TMP");
+ this.temporaryDirectory.mkdirs();
+ } else {
+ this.temporaryDirectory = tmpDirectory;
+ }
+ }
+
+ /**
+ * The environment of the plugin, including its name and other information.
+ *
+ * @return plugin environment
+ */
+ public ServerPluginEnvironment getPluginEnvironment() {
+ return pluginEnvironment;
+ }
+
+ /**
+ * A temporary directory for plugin use. Plugins should use this if they need to
+ * write temporary files that they do not expect to remain after the server is restarted. This directory is shared
+ * among all plugins - plugins must ensure they write unique files here, as other plugins may be using this same
+ * directory. Typically, plugins will use the {@link File#createTempFile(String, String, File)} API when writing to
+ * this directory.
+ *
+ * @return location for plugin temporary files
+ */
+ public File getTemporaryDirectory() {
+ return temporaryDirectory;
+ }
+
+ /**
+ * Directory where plugins can store persisted data that survives agent restarts. Each plugin will have their own
+ * data directory. The returned directory may not yet exist - it is up to each individual plugin to manage this
+ * directory as they see fit (this includes performing the initial creation when the directory is first needed).
+ *
+ * @return location for plugins to store persisted data
+ */
+ public File getDataDirectory() {
+ return this.dataDirectory;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java
index 093c017..e0809a6 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java
@@ -58,7 +58,7 @@ public class ServerPluginEnvironment {
return this.pluginUrl;
}
- public ClassLoader getClassLoader() {
+ public ClassLoader getPluginClassLoader() {
return this.pluginClassLoader;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginLifecycleListener.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginLifecycleListener.java
new file mode 100644
index 0000000..bb7b05f
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginLifecycleListener.java
@@ -0,0 +1,73 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.rhq.enterprise.server.plugin.pc;
+
+/**
+ * Performs global initialization and shutdown of a server side plugin. This provides a place
+ * for plugin developers to allocate global resources needed by all plugin components and
+ * a place to clean up those resources.
+ *
+ * Lifecycle listeners are required of generic server plugins because they provide
+ * the only mechanism to start and stop.
+ *
+ * @author John Mazzitelli
+ */
+public interface ServerPluginLifecycleListener {
+ /**
+ * When a plugin's container loads a plugin, this method will be called.
+ * When this is called, no other plugin components have been instantiated
+ * or invoked yet. This is merely called to notify the plugin that it is about to be
+ * placed into service and its components will soon be asked to perform work.
+ *
+ * If this method returns normally, the plugin is saying it is ready and able to {@link #start()}.
+ *
+ * @param context a context with information about the runtime plugin environment
+ *
+ * @throws Exception if the plugin finds that it should not be loaded, an exception should be thrown.
+ * If thrown, this plugin will not be started and will be considered disabled. If
+ * other plugins are dependent on this failed plugin, those other plugins will
+ * fail to operate correctly.
+ */
+ void initialize(ServerPluginContext context) throws Exception;
+
+ /**
+ * When a plugin container has been started (which occurs after all plugins are loaded), this
+ * method is called to inform the plugin is can begin performing work.
+ */
+ void start();
+
+ /**
+ * When a plugin container has been stopped (but before it unloads plugins), this
+ * method is called to inform the plugin it should stop performing work and prepare
+ * to shutdown.
+ */
+ void stop();
+
+ /**
+ * When the plugin container shuts down and it unloads the plugin, this method will be called.
+ * This provides an opportunity for the plugin to clean up any global resources it has previously
+ * allocated. After this method is called, invocations of this plugin's discovery or
+ * resource components will no longer occur.
+ */
+ void shutdown();
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
new file mode 100644
index 0000000..b1300f0
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginManager.java
@@ -0,0 +1,319 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Provides functionality to manage plugins for a plugin container. Plugin containers
+ * can install their own plugin managers that are extensions to this class if they need to.
+ *
+ * @author John Mazzitelli
+ */
+public class ServerPluginManager {
+ private final Log log = LogFactory.getLog(this.getClass());
+
+ private final AbstractTypeServerPluginContainer parentPluginContainer;
+
+ /**
+ * The map of all plugin environments keyed on plugin name.
+ */
+ private final Map<String, ServerPluginEnvironment> loadedPlugins;
+
+ /**
+ * Cached instances of objects used to initialize and shutdown individual plugins.
+ * Only plugins that declare their own lifecycle listener will have objects in this cache.
+ * This is keyed on plugin name.
+ */
+ private final Map<String, ServerPluginLifecycleListener> pluginLifecycleListenerCache;
+
+ /**
+ * Creates a plugin manager for the given plugin container.
+ *
+ * @param pc the plugin manager's owning plugin container
+ */
+ public ServerPluginManager(AbstractTypeServerPluginContainer pc) {
+ this.parentPluginContainer = pc;
+ this.loadedPlugins = new HashMap<String, ServerPluginEnvironment>();
+ this.pluginLifecycleListenerCache = new HashMap<String, ServerPluginLifecycleListener>();
+ }
+
+ /**
+ * Initializes the plugin manager to prepare it to start loading plugins.
+ *
+ * @throws Exception if failed to initialize
+ */
+ public synchronized void initialize() throws Exception {
+ log.debug("Plugin manager initializing");
+ return; // no-op
+ }
+
+ /**
+ * Shuts down this manager. This should be called only after all of its plugins
+ * have been {@link #unloadPlugin(ServerPluginEnvironment) unloaded}.
+ */
+ public synchronized void shutdown() {
+ log.debug("Plugin manager shutting down");
+
+ if (this.loadedPlugins.size() > 0) {
+ log.warn("Server plugin manager is being shutdown while some plugins are still loaded: "
+ + this.loadedPlugins);
+ this.loadedPlugins.clear();
+ }
+
+ this.pluginLifecycleListenerCache.clear();
+
+ return;
+ }
+
+ /**
+ * Informs the plugin manager that a plugin with the given environment needs to be loaded.
+ * Once this method returns, the plugin's components are ready to be created and used.
+ *
+ * @param env the environment of the plugin to be loaded
+ *
+ * @throws Exception if the plugin manager cannot load the plugin or deems the plugin invalid
+ */
+ public synchronized void loadPlugin(ServerPluginEnvironment env) throws Exception {
+ String pluginName = env.getPluginName();
+ log.debug("Loading server plugin [" + pluginName + "] from: " + env.getPluginUrl());
+
+ // tell the plugin we are loading it
+ ServerPluginLifecycleListener listener = createServerPluginLifecycleListener(env);
+ if (listener != null) {
+ ServerPluginContext context = createServerPluginContext(env);
+ log.debug("Initializing lifecycle listener for server plugin [" + pluginName + "]");
+ ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(env.getPluginClassLoader());
+ listener.initialize(context);
+ } catch (Throwable t) {
+ throw new Exception("Lifecycle listener failed to initialize plugin", t);
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalContextClassLoader);
+ }
+ this.pluginLifecycleListenerCache.put(pluginName, listener);
+ }
+
+ // note that we only cache it if the lifecycle listener was successful
+ this.loadedPlugins.put(pluginName, env);
+
+ return;
+ }
+
+ public synchronized void startPlugins() {
+ log.debug("Starting plugins");
+
+ // tell all lifecycle listeners to start
+ for (Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
+ String pluginName = entry.getKey();
+ ServerPluginLifecycleListener listener = entry.getValue();
+ ServerPluginEnvironment env = this.loadedPlugins.get(pluginName);
+ log.debug("Starting lifecycle listener for server plugin [" + pluginName + "]");
+ ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(env.getPluginClassLoader());
+ listener.start();
+ } catch (Throwable t) {
+ log.warn("Lifecycle listener failed to start plugin [" + pluginName + "]", t);
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalContextClassLoader);
+ }
+ }
+
+ return;
+ }
+
+ public synchronized void stopPlugins() {
+ log.debug("Stopping plugins");
+
+ // tell all lifecycle listeners to stop
+ for (Entry<String, ServerPluginLifecycleListener> entry : this.pluginLifecycleListenerCache.entrySet()) {
+ String pluginName = entry.getKey();
+ ServerPluginLifecycleListener listener = entry.getValue();
+ ServerPluginEnvironment env = this.loadedPlugins.get(pluginName);
+ log.debug("Stopping lifecycle listener for server plugin [" + pluginName + "]");
+ ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(env.getPluginClassLoader());
+ listener.stop();
+ } catch (Throwable t) {
+ log.warn("Lifecycle listener failed to stop plugin [" + pluginName + "]", t);
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalContextClassLoader);
+ }
+ }
+
+ return;
+ }
+
+ /**
+ * Informs the plugin manager that a plugin with the given environment is to be unloaded.
+ * Once this method returns, the plugin's components are should no longer be created or used.
+ *
+ * @param env the environment of the plugin to be unloaded
+ *
+ * @throws Exception if the plugin manager cannot unload the plugin
+ */
+ public synchronized void unloadPlugin(ServerPluginEnvironment env) throws Exception {
+ String pluginName = env.getPluginName();
+ log.debug("Unloading server plugin [" + pluginName + "]");
+
+ try {
+ // tell the plugin we are unloading it
+ ServerPluginLifecycleListener listener = this.pluginLifecycleListenerCache.get(pluginName);
+ if (listener != null) {
+ log.debug("Shutting down lifecycle listener for server plugin [" + pluginName + "]");
+ ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(env.getPluginClassLoader());
+ listener.shutdown();
+ } catch (Throwable t) {
+ throw new Exception("Plugin Lifecycle Listener failed to initialize plugin", t);
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalContextClassLoader);
+ this.pluginLifecycleListenerCache.remove(pluginName);
+ }
+ }
+ } finally {
+ this.loadedPlugins.remove(pluginName);
+ }
+
+ return;
+ }
+
+ /**
+ * Returns the {@link ServerPluginEnvironment}s for every plugin this manager has loaded.
+ * The returned collection is a copy and not backed by this manager.
+ *
+ * @return environments for all the plugins
+ */
+ public synchronized Collection<ServerPluginEnvironment> getPluginEnvironments() {
+ return new ArrayList<ServerPluginEnvironment>(this.loadedPlugins.values());
+ }
+
+ /**
+ * Given a plugin name, this returns that plugin's environment.
+ *
+ * <p>The plugin's name is defined in its plugin descriptor - specifically the XML root node's "name" attribute
+ * (e.g. <server-plugin name="thePluginName").</p>
+ *
+ * @param pluginName the plugin whose environment is to be returned
+ * @return given plugin's environment
+ */
+ public synchronized ServerPluginEnvironment getPluginEnvironment(String pluginName) {
+ return this.loadedPlugins.get(pluginName);
+ }
+
+ public AbstractTypeServerPluginContainer getParentPluginContainer() {
+ return this.parentPluginContainer;
+ }
+
+ protected Log getLog() {
+ return this.log;
+ }
+
+ protected ServerPluginContext createServerPluginContext(ServerPluginEnvironment env) {
+ MasterServerPluginContainer masterPC = this.parentPluginContainer.getMasterServerPluginContainer();
+ MasterServerPluginContainerConfiguration masterConfig = masterPC.getConfiguration();
+ File dataDir = new File(masterConfig.getDataDirectory(), env.getPluginName());
+ File tmpDir = masterConfig.getTemporaryDirectory();
+
+ ServerPluginContext context = new ServerPluginContext(env, dataDir, tmpDir);
+ return context;
+ }
+
+ /**
+ * This will create a new {@link ServerPluginLifecycleListener} instance for that is used to
+ * initialize and shutdown a particular server plugin. If there is no plugin lifecycle listener
+ * configured for the given plugin, <code>null</code> is returned.
+ *
+ * The new object will be loaded in the plugin's specific classloader.
+ *
+ * @param pluginName the name of the plugin whose listener is to be retrieved
+ * @param environment the environment in which the plugin will execute
+ *
+ * @return a new object loaded in the proper plugin classloader that can initialize/shutdown the plugin,
+ * or <code>null</code> if there is no plugin lifecycle listener to be associated with the given plugin
+ *
+ * @throws Exception if failed to create the instance
+ */
+ protected ServerPluginLifecycleListener createServerPluginLifecycleListener(ServerPluginEnvironment environment)
+ throws Exception {
+
+ String pluginName = environment.getPluginName();
+ ServerPluginLifecycleListener instance = null;
+
+ String className = environment.getPluginDescriptor().getPluginLifecycleListener();
+ if (className != null) {
+ String pkg = environment.getPluginDescriptor().getPackage();
+ if ((className.indexOf('.') == -1) && (pkg != null)) {
+ className = pkg + '.' + className;
+ }
+
+ log.debug("Creating plugin lifecycle listener [" + className + "] for plugin [" + pluginName + "]");
+ instance = (ServerPluginLifecycleListener) instantiatePluginClass(environment, className);
+ log.debug("Created plugin lifecycle listener [" + className + "] for plugin [" + pluginName + "]");
+ }
+
+ return instance;
+ }
+
+ /**
+ * Instantiates a class with the given name within the given environment's classloader using
+ * the class' no-arg constructor.
+ *
+ * @param environment the environment that has the classloader where the class will be loaded
+ * @param className the class to instantiate
+ * @return the new object that is an instance of the given class
+ * @throws Exception if failed to instantiate the class
+ */
+ protected Object instantiatePluginClass(ServerPluginEnvironment environment, String className) throws Exception {
+
+ ClassLoader loader = environment.getPluginClassLoader();
+
+ log.debug("Loading server plugin class [" + className + "]...");
+
+ try {
+ Class<?> clazz = Class.forName(className, true, loader);
+ log.debug("Loaded server plugin class [" + clazz + "].");
+ return clazz.newInstance();
+ } catch (InstantiationException e) {
+ throw new Exception("Could not instantiate plugin class [" + className + "] from plugin environment ["
+ + environment + "]", e);
+ } catch (IllegalAccessException e) {
+ throw new Exception("Could not access plugin class " + className + "] from plugin environment ["
+ + environment + "]", e);
+ } catch (ClassNotFoundException e) {
+ throw new Exception("Could not find plugin class " + className + "] from plugin environment ["
+ + environment + "]", e);
+ } catch (NullPointerException npe) {
+ throw new Exception("Plugin class was 'null' in plugin environment [" + environment + "]", npe);
+ }
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
index 2e470dc..d6bae90 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginService.java
@@ -113,21 +113,22 @@ public class ServerPluginService implements ServerPluginServiceManagement {
protected MasterServerPluginContainer createMasterPluginContainer() {
MasterServerPluginContainer pc = new MasterServerPluginContainer();
- MasterServerPluginContainerConfiguration config = new MasterServerPluginContainerConfiguration();
-
String pluginDirStr = System.getProperty(ServerConfig.SERVER_HOME_DIR);
File pluginDir = new File(pluginDirStr, "deploy/" + RHQConstants.EAR_FILE_NAME + "/rhq-serverplugins");
- config.setPluginDirectory(pluginDir);
+
+ String dataDirStr = System.getProperty(ServerConfig.SERVER_DATA_DIR);
+ File dataDir = new File(dataDirStr, "server-plugins");
+ dataDir.mkdirs(); // make sure the data directory exists
String tmpDirStr = System.getProperty(ServerConfig.SERVER_TEMP_DIR);
- config.setTemporaryDirectory(new File(tmpDirStr));
+ File tmpDir = new File(tmpDirStr);
// TODO: determine what things to hide from our war classloader
//StringBuilder defaultRegex = new StringBuilder();
//defaultRegex.append("(package\\.with\\.classes\\.to\\.hide\\..*)|");
- config.setRootPluginClassLoaderRegex(null);
-
+ MasterServerPluginContainerConfiguration config;
+ config = new MasterServerPluginContainerConfiguration(pluginDir, dataDir, tmpDir, null);
pc.initialize(config);
return pc;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
index 999bfba..9e63460 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
@@ -585,7 +585,7 @@ public class ContentProviderManager {
pluginName = this.pluginManager.getMetadataManager().getPluginNameFromContentSourceType(type);
ServerPluginEnvironment pluginEnv = this.pluginManager.getPluginEnvironment(pluginName);
- ClassLoader pluginClassloader = pluginEnv.getClassLoader();
+ ClassLoader pluginClassloader = pluginEnv.getPluginClassLoader();
ClassLoader startingClassLoader = Thread.currentThread().getContextClassLoader();
try {
@@ -663,7 +663,7 @@ public class ContentProviderManager {
throw new RuntimeException("There is no plugin env. for content source [" + contentSource + "]");
}
- ClassLoader classLoader = env.getClassLoader();
+ ClassLoader classLoader = env.getPluginClassLoader();
IsolatedInvocationHandler handler = new IsolatedInvocationHandler(adapter, classLoader);
List<Class<?>> ifacesList = new ArrayList<Class<?>>(1);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
index 3c5427d..3edba4d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
@@ -28,7 +28,7 @@ import org.rhq.core.domain.content.ContentSource;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.PluginManager;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginManager;
import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.scheduler.SchedulerLocal;
import org.rhq.enterprise.server.scheduler.jobs.ContentSourceSyncJob;
@@ -181,7 +181,7 @@ public class ContentServerPluginContainer extends AbstractTypeServerPluginContai
}
@Override
- protected PluginManager createPluginManager() {
+ protected ServerPluginManager createPluginManager() {
return new ContentServerPluginManager(this);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginManager.java
index 03a4b5f..6f42c5e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginManager.java
@@ -23,8 +23,8 @@ import java.util.HashSet;
import java.util.Set;
import org.rhq.core.domain.content.ContentSourceType;
-import org.rhq.enterprise.server.plugin.pc.PluginManager;
import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginManager;
import org.rhq.enterprise.server.plugin.pc.content.metadata.ContentSourcePluginMetadataManager;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.content.ContentPluginDescriptorType;
@@ -36,7 +36,7 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.content.Conten
*
* @author John Mazzitelli
*/
-public class ContentServerPluginManager extends PluginManager {
+public class ContentServerPluginManager extends ServerPluginManager {
private ContentSourcePluginMetadataManager metadataManager;
@@ -91,7 +91,7 @@ public class ContentServerPluginManager extends PluginManager {
for (ContentSourceType newType : newTypesCopy) {
try {
String className = newType.getContentSourceApiClass();
- Class<?> apiClass = Class.forName(className, false, env.getClassLoader());
+ Class<?> apiClass = Class.forName(className, false, env.getPluginClassLoader());
if (!ContentProvider.class.isAssignableFrom(apiClass)) {
throw new Exception("The API class [" + className + "] should implement ["
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
index 04de1a5..ea0e8a3 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/ContentSourceManagerBeanTest.java
@@ -66,7 +66,7 @@ import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails
import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetailsKey;
import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
-import org.rhq.enterprise.server.test.TestServerPluginService;
+import org.rhq.enterprise.server.test.TestContentServerPluginService;
import org.rhq.enterprise.server.util.LookupUtil;
@Test
@@ -123,7 +123,7 @@ public class ContentSourceManagerBeanTest extends AbstractEJB3Test {
private ResourceType resourceType1;
private Resource resource1;
- private TestServerPluginService pluginService;
+ private TestContentServerPluginService pluginService;
@BeforeClass
public void setupBeforeClass() throws Exception {
@@ -151,7 +151,7 @@ public class ContentSourceManagerBeanTest extends AbstractEJB3Test {
setupTestEnvironment();
overlord = LookupUtil.getSubjectManager().getOverlord();
prepareScheduler();
- pluginService = prepareServerPluginService();
+ pluginService = prepareContentServerPluginService();
pluginService.startMasterPluginContainer();
cleanupPreviousTestRuns();
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
index 139062c..e1d4fe9 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManagerTest.java
@@ -56,7 +56,7 @@ import org.rhq.enterprise.server.auth.SubjectManagerLocal;
import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
-import org.rhq.enterprise.server.test.TestServerPluginService;
+import org.rhq.enterprise.server.test.TestContentServerPluginService;
import org.rhq.enterprise.server.util.LookupUtil;
/**
@@ -90,7 +90,7 @@ public class ContentProviderManagerTest extends AbstractEJB3Test {
// Plugin service setup
prepareScheduler();
- TestServerPluginService pluginService = prepareServerPluginService();
+ TestContentServerPluginService pluginService = prepareContentServerPluginService();
pluginService.startMasterPluginContainer();
// Because of the (current) transaction settings of some of the nested methods (i.e. REQUIRES_NEW),
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
index 448a38f..a5fa70c 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/AbstractEJB3Test.java
@@ -49,6 +49,7 @@ import org.rhq.core.domain.util.PersistenceUtility;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.auth.SessionManager;
import org.rhq.enterprise.server.core.comm.ServerCommunicationsServiceMBean;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
import org.rhq.enterprise.server.scheduler.SchedulerService;
import org.rhq.enterprise.server.scheduler.SchedulerServiceMBean;
import org.rhq.enterprise.server.util.LookupUtil;
@@ -245,10 +246,10 @@ public abstract class AbstractEJB3Test extends AssertJUnit {
}
}
- private TestServerPluginService serverPluginService;
+ private ServerPluginService serverPluginService;
/**
- * If you need to test content source server plugins, or other server plugins, you must first prepare the server plugin service via
+ * If you need to test content source server plugins, you must first prepare the server plugin service via
* this method. The caller must explicitly start the PC by using the appropriate API on the returned object; this
* method will only start the service, it will NOT start the master PC.
*
@@ -256,12 +257,12 @@ public abstract class AbstractEJB3Test extends AssertJUnit {
*
* @throws RuntimeException
*/
- public TestServerPluginService prepareServerPluginService() {
+ public TestContentServerPluginService prepareContentServerPluginService() {
try {
MBeanServer mbs = getJBossMBeanServer();
- TestServerPluginService mbean = new TestServerPluginService();
+ TestContentServerPluginService mbean = new TestContentServerPluginService();
mbean.start();
- mbs.registerMBean(mbean, TestServerPluginService.OBJECT_NAME);
+ mbs.registerMBean(mbean, TestContentServerPluginService.OBJECT_NAME);
serverPluginService = mbean;
return mbean;
} catch (Exception e) {
@@ -273,7 +274,7 @@ public abstract class AbstractEJB3Test extends AssertJUnit {
if (serverPluginService != null) {
serverPluginService.stopMasterPluginContainer();
serverPluginService.stop();
- getJBossMBeanServer().unregisterMBean(TestServerPluginService.OBJECT_NAME);
+ getJBossMBeanServer().unregisterMBean(ServerPluginService.OBJECT_NAME);
serverPluginService = null;
}
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java
new file mode 100644
index 0000000..1d68798
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginService.java
@@ -0,0 +1,187 @@
+/*
+ * 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.test;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.rhq.core.domain.content.ContentSource;
+import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
+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.ContentProviderPackageDetails;
+import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginManager;
+import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
+import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
+
+/**
+ * Used as a mock service for the content source plugin container.
+ */
+public class TestContentServerPluginService extends ServerPluginService implements TestContentServerPluginServiceMBean {
+ // public so tests can directly set these
+ public Map<ContentSource, ContentProvider> testAdapters;
+ public PackageSyncReport testLastSyncReport;
+ public Map<ContentSource, Collection<ContentProviderPackageDetails>> testExistingPackages;
+ public TestMasterServerPluginContainer master;
+
+ @Override
+ protected MasterServerPluginContainer createMasterPluginContainer() {
+ this.master = new TestMasterServerPluginContainer();
+ File dir = new File(System.getProperty("java.io.tmpdir"), "test-server-plugins");
+ MasterServerPluginContainerConfiguration config = new MasterServerPluginContainerConfiguration(dir, dir, dir,
+ null);
+ this.master.initialize(config);
+ return this.master;
+ }
+
+ /**
+ * The test master PC
+ */
+ class TestMasterServerPluginContainer extends MasterServerPluginContainer {
+ @Override
+ protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
+ ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(1);
+ pcs.add(new TestContentServerPluginContainer(this));
+ return pcs;
+ }
+
+ @Override
+ protected ClassLoader createRootServerPluginClassLoader() {
+ return this.getClass().getClassLoader();
+ }
+
+ @Override
+ protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
+ return new HashMap<URL, ServerPluginDescriptorType>();
+ }
+ }
+
+ /**
+ * The test content PC.
+ */
+ class TestContentServerPluginContainer extends ContentServerPluginContainer {
+ public TestContentServerPluginContainer(MasterServerPluginContainer master) {
+ super(master);
+ }
+
+ @Override
+ protected ContentProviderManager createAdapterManager() {
+ TestContentProviderManager am = new TestContentProviderManager();
+ return am;
+ }
+
+ @Override
+ protected ContentServerPluginManager createPluginManager() {
+ TestContentProviderPluginManager pm = new TestContentProviderPluginManager(this);
+ return pm;
+ }
+ }
+
+ /**
+ * The test plugin manager.
+ */
+ class TestContentProviderPluginManager extends ContentServerPluginManager {
+ public TestContentProviderPluginManager(ContentServerPluginContainer pc) {
+ super(pc);
+ }
+ }
+
+ /**
+ * The test adapter manager.
+ */
+ class TestContentProviderManager extends ContentProviderManager {
+ @Override
+ public Set<ContentSource> getAllContentSources() {
+ return (testAdapters != null) ? testAdapters.keySet() : new HashSet<ContentSource>();
+ }
+
+ @Override
+ protected void initialize(ContentServerPluginManager pluginManager) {
+ createInitialAdaptersMap();
+ }
+
+ @Override
+ public void shutdown() {
+ }
+
+ @Override
+ public InputStream loadPackageBits(int contentSourceId, String location) throws Exception {
+ if (testAdapters != null) {
+ for (ContentSource cs : testAdapters.keySet()) {
+ if (cs.getId() == contentSourceId) {
+ PackageSource packageSource = (PackageSource) testAdapters.get(cs);
+ return packageSource.getInputStream(location);
+ }
+ }
+ }
+
+ System.out.println("!!!!!!!!!!");
+ System.out.println("STREAM: TEST DID NOT SETUP ADAPTER - EMPTY STREAM FOR [" + contentSourceId + "]");
+ return new ByteArrayInputStream(new byte[0]);
+ }
+
+ @Override
+ public boolean synchronizeContentSource(int contentSourceId) throws Exception {
+ if (testAdapters != null) {
+ for (ContentSource cs : testAdapters.keySet()) {
+ if (cs.getId() == contentSourceId) {
+ testLastSyncReport = new PackageSyncReport();
+ PackageSource packageSource = (PackageSource) testAdapters.get(cs);
+ packageSource.synchronizePackages(testLastSyncReport, testExistingPackages.get(cs));
+ return true;
+ }
+ }
+ }
+
+ System.out.println("!!!!!!!!!!");
+ System.out.println("SYNC: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
+ return true;
+ }
+
+ @Override
+ public boolean testConnection(int contentSourceId) throws Exception {
+ if (testAdapters != null) {
+ for (ContentSource cs : testAdapters.keySet()) {
+ if (cs.getId() == contentSourceId) {
+ testAdapters.get(cs).testConnection();
+ return true;
+ }
+ }
+ }
+
+ System.out.println("!!!!!!!!!!");
+ System.out.println("CONN: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginServiceMBean.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginServiceMBean.java
new file mode 100644
index 0000000..bbdebaf
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestContentServerPluginServiceMBean.java
@@ -0,0 +1,24 @@
+/*
+ * 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.test;
+
+import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
+
+public interface TestContentServerPluginServiceMBean extends ServerPluginServiceManagement {
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
deleted file mode 100644
index a9dcef4..0000000
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
+++ /dev/null
@@ -1,184 +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.test;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.rhq.core.domain.content.ContentSource;
-import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
-import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
-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.ContentProviderPackageDetails;
-import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginManager;
-import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
-import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
-import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
-
-/**
- * Used as a mock service for the content source plugin container.
- */
-public class TestServerPluginService extends ServerPluginService implements TestServerPluginServiceMBean {
- // public so tests can directly set these
- public Map<ContentSource, ContentProvider> testAdapters;
- public PackageSyncReport testLastSyncReport;
- public Map<ContentSource, Collection<ContentProviderPackageDetails>> testExistingPackages;
- public TestMasterServerPluginContainer master;
-
- @Override
- protected MasterServerPluginContainer createMasterPluginContainer() {
- this.master = new TestMasterServerPluginContainer();
- MasterServerPluginContainerConfiguration config = new MasterServerPluginContainerConfiguration();
- this.master.initialize(config);
- return this.master;
- }
-
- /**
- * The test master PC
- */
- class TestMasterServerPluginContainer extends MasterServerPluginContainer {
- @Override
- protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
- ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(1);
- pcs.add(new TestContentServerPluginContainer(this));
- return pcs;
- }
-
- @Override
- protected ClassLoader createRootServerPluginClassLoader() {
- return this.getClass().getClassLoader();
- }
-
- @Override
- protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
- return new HashMap<URL, ServerPluginDescriptorType>();
- }
- }
-
- /**
- * The test content PC.
- */
- class TestContentServerPluginContainer extends ContentServerPluginContainer {
- public TestContentServerPluginContainer(MasterServerPluginContainer master) {
- super(master);
- }
-
- @Override
- protected ContentProviderManager createAdapterManager() {
- TestContentProviderManager am = new TestContentProviderManager();
- return am;
- }
-
- @Override
- protected ContentServerPluginManager createPluginManager() {
- TestContentProviderPluginManager pm = new TestContentProviderPluginManager(this);
- return pm;
- }
- }
-
- /**
- * The test plugin manager.
- */
- class TestContentProviderPluginManager extends ContentServerPluginManager {
- public TestContentProviderPluginManager(ContentServerPluginContainer pc) {
- super(pc);
- }
- }
-
- /**
- * The test adapter manager.
- */
- class TestContentProviderManager extends ContentProviderManager {
- @Override
- public Set<ContentSource> getAllContentSources() {
- return (testAdapters != null) ? testAdapters.keySet() : new HashSet<ContentSource>();
- }
-
- @Override
- protected void initialize(ContentServerPluginManager pluginManager) {
- createInitialAdaptersMap();
- }
-
- @Override
- public void shutdown() {
- }
-
- @Override
- public InputStream loadPackageBits(int contentSourceId, String location) throws Exception {
- if (testAdapters != null) {
- for (ContentSource cs : testAdapters.keySet()) {
- if (cs.getId() == contentSourceId) {
- PackageSource packageSource = (PackageSource) testAdapters.get(cs);
- return packageSource.getInputStream(location);
- }
- }
- }
-
- System.out.println("!!!!!!!!!!");
- System.out.println("STREAM: TEST DID NOT SETUP ADAPTER - EMPTY STREAM FOR [" + contentSourceId + "]");
- return new ByteArrayInputStream(new byte[0]);
- }
-
- @Override
- public boolean synchronizeContentSource(int contentSourceId) throws Exception {
- if (testAdapters != null) {
- for (ContentSource cs : testAdapters.keySet()) {
- if (cs.getId() == contentSourceId) {
- testLastSyncReport = new PackageSyncReport();
- PackageSource packageSource = (PackageSource) testAdapters.get(cs);
- packageSource.synchronizePackages(testLastSyncReport, testExistingPackages.get(cs));
- return true;
- }
- }
- }
-
- System.out.println("!!!!!!!!!!");
- System.out.println("SYNC: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
- return true;
- }
-
- @Override
- public boolean testConnection(int contentSourceId) throws Exception {
- if (testAdapters != null) {
- for (ContentSource cs : testAdapters.keySet()) {
- if (cs.getId() == contentSourceId) {
- testAdapters.get(cs).testConnection();
- return true;
- }
- }
- }
-
- System.out.println("!!!!!!!!!!");
- System.out.println("CONN: TEST DID NOT SETUP ADAPTER - NO-OP FOR [" + contentSourceId + "]");
- return true;
- }
- }
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginServiceMBean.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginServiceMBean.java
deleted file mode 100644
index 945f6e5..0000000
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginServiceMBean.java
+++ /dev/null
@@ -1,24 +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.test;
-
-import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
-
-public interface TestServerPluginServiceMBean extends ServerPluginServiceManagement {
-}
\ No newline at end of file
commit 0e71f9918315256c9d3cb348e126e15937710a22
Author: Shannon Hughes <shughes(a)fred.hughes.lan>
Date: Sun Nov 8 14:54:48 2009 -0500
minor updates to aliases service
diff --git a/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesComponent.java b/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesComponent.java
index 53d1ac5..53f6447 100644
--- a/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesComponent.java
+++ b/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesComponent.java
@@ -26,8 +26,10 @@ import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.core.pluginapi.inventory.CreateResourceReport;
import org.rhq.plugins.augeas.AugeasConfigurationComponent;
import org.rhq.plugins.augeas.helper.AugeasNode;
+import org.rhq.plugins.augeas.helper.AugeasUtility;
import net.augeas.Augeas;
import java.util.List;
@@ -59,8 +61,12 @@ public class AliasesComponent extends AugeasConfigurationComponent {
}
@Override
+ public CreateResourceReport createResource(CreateResourceReport report) {
+ return super.createResource(report);
+ }
+
+ @Override
protected AugeasNode getNewListMemberNode(AugeasNode listNode, PropertyDefinitionMap listMemberPropDefMap, int listIndex) {
- PropertyDefinitionMap member = listMemberPropDefMap;
AugeasNode node = new AugeasNode(listNode, "0" + listIndex);
return node;
}
@@ -70,12 +76,14 @@ public class AliasesComponent extends AugeasConfigurationComponent {
// First find all child nodes with the same 'name' value as the PropertyMap.
Augeas augeas = getAugeas();
- String name = propMap.getSimple("name").getStringValue();
- String nameFilter = parentNode.getPath() + "/name";
- List<String> namePaths = augeas.match(String.format(nameFilter + "/name[.='%s']", name));
+ String nameFilter = parentNode.getPath() + "/*/name";
+ String canonical = propMap.getSimple("name").getStringValue();
+ List<String> namePaths = AugeasUtility.matchFilter(augeas, nameFilter, canonical);
+
if (namePaths == null || namePaths.isEmpty()) {
return null;
}
+
AugeasNode node = new AugeasNode(namePaths.get(0));
return node.getParent();
}
diff --git a/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesDiscoveryComponent.java b/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesDiscoveryComponent.java
index d876c3c..dc9b97e 100644
--- a/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesDiscoveryComponent.java
+++ b/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesDiscoveryComponent.java
@@ -21,12 +21,15 @@ package org.rhq.plugins.aliases;
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.ResourceDiscoveryContext;
import org.rhq.plugins.augeas.AugeasConfigurationDiscoveryComponent;
+import org.rhq.plugins.augeas.AugeasConfigurationComponent;
import java.util.Set;
+import java.util.List;
/**
* The ResourceDiscoveryComponent for the "Aliases File" ResourceType.
@@ -46,4 +49,10 @@ public class AliasesDiscoveryComponent extends AugeasConfigurationDiscoveryCompo
DiscoveredResourceDetails details = super.discoverResource(pluginConfig, discoveryContext);
return details;
}
+
+ @Override
+ protected List<String> determineIncludeGlobs(ResourceDiscoveryContext discoveryContext) {
+ List<String> s = super.determineIncludeGlobs(discoveryContext);
+ return s;
+ }
}
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
index c03f7b2..99c1730 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
@@ -514,14 +514,20 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
PropertyDefinitionMap listMemberPropDefMap = (PropertyDefinitionMap) listMemberPropDef;
int listIndex = 0;
+
+ // grab all the list member paths
String listMemberPropDefMapPath = getAugeasPathRelativeToParent(listMemberPropDefMap, listNode, augeas);
List<String> existingListMemberPaths = augeas.match(listNode.getPath() + AugeasNode.SEPARATOR_CHAR
+ listMemberPropDefMapPath);
+
+ // now turn paths into augeas nodes
List<AugeasNode> existingListMemberNodes = new ArrayList<AugeasNode>();
for (String existingListMemberPath : existingListMemberPaths) {
existingListMemberNodes.add(new AugeasNode(existingListMemberPath));
}
+
Set<AugeasNode> updatedListMemberNodes = new HashSet<AugeasNode>();
+
for (Property listMemberProp : propList.getList()) {
PropertyMap listMemberPropMap = (PropertyMap) listMemberProp;
AugeasNode memberNodeToUpdate = getExistingChildNodeForListMemberPropertyMap(listNode, propDefList,
@@ -535,7 +541,8 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
// being added, so create a new node for the map to add to the list.
AugeasNode basePathNode = getNewListMemberNode(listNode, listMemberPropDefMap, listIndex);
String var = "prop" + listIndex;
- augeas.defineNode(var, basePathNode.getPath(), null);
+ String bpath = basePathNode.getPath();
+ augeas.defineNode(var, bpath, null);
memberNodeToUpdate = new AugeasNode("$" + var);
listIndex++;
}
commit 05512646759f67779a2fc568ce45232b2b325ac0
Author: Partha Aji <paji(a)redhat.com>
Date: Fri Nov 6 23:58:30 2009 -0500
Fixed a couple of unit tests
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
index c03f7b2..d1ca584 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
@@ -89,14 +89,18 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
private AugeasNode resourceConfigRootNode;
private String augeasRootPath;
+ public static String getAugeasRootPath() {
+ if (System.getProperty(AUGEAS_ROOT_PATH_PROP) != null) {
+ return System.getProperty(AUGEAS_ROOT_PATH_PROP);
+ }
+ return DEFAULT_AUGEAS_ROOT_PATH;
+ }
+
public void start(ResourceContext<T> resourceContext) throws InvalidPluginConfigurationException, Exception {
this.resourceContext = resourceContext;
Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
- this.augeasRootPath = DEFAULT_AUGEAS_ROOT_PATH;
- if (System.getProperty(AUGEAS_ROOT_PATH_PROP) != null) {
- this.augeasRootPath = System.getProperty(AUGEAS_ROOT_PATH_PROP);
- }
+ this.augeasRootPath = getAugeasRootPath();
log.debug("Augeas Root Path = \"" + this.augeasRootPath + "\"");
initGlobs(pluginConfig);
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
index 22bd9bd..cea1974 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
@@ -116,9 +116,8 @@ public class AugeasConfigurationDiscoveryComponent<T extends ResourceComponent>
.getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP);
PropertySimple excludeGlobsProp = pluginConfiguration
.getSimple(AugeasConfigurationComponent.EXCLUDE_GLOBS_PROP);
-
- String augeasRootPath = pluginConfiguration.getSimpleValue(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP,
- AugeasConfigurationComponent.DEFAULT_AUGEAS_ROOT_PATH);
+
+ String augeasRootPath = AugeasConfigurationComponent.getAugeasRootPath();
File root = new File(augeasRootPath);
List<String> includeGlobs = getGlobList(includeGlobsProp);
commit db6359b1d2cdec6a357143817f39dbbdf315fdec
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 6 23:27:24 2009 -0500
add some thread-saftety due to my paranoia
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index cb01ad0..a7a166d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2009 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -81,7 +81,7 @@ public abstract class AbstractTypeServerPluginContainer {
*
* @throws Exception if the plugin container failed to initialize for some reason
*/
- public void initialize() throws Exception {
+ public synchronized void initialize() throws Exception {
this.pluginManager = createPluginManager();
this.pluginManager.initialize();
}
@@ -91,7 +91,7 @@ public abstract class AbstractTypeServerPluginContainer {
* Once this is called, the plugin container can assume all plugins that it will
* ever know about have been {@link #loadPlugin(ServerPluginEnvironment) loaded}.
*/
- public void start() {
+ public synchronized void start() {
return; // no-op
}
@@ -99,7 +99,7 @@ public abstract class AbstractTypeServerPluginContainer {
* This will inform the plugin container that it must stop doing its work. Once called,
* the plugin container must assume that soon it will be asked to {@link #shutdown()}.
*/
- public void stop() {
+ public synchronized void stop() {
return; // no-op
}
@@ -108,20 +108,22 @@ public abstract class AbstractTypeServerPluginContainer {
*
* Subclasses are free to perform additional tasks by overriding this method.
*/
- public void shutdown() {
- Collection<ServerPluginEnvironment> envs = this.pluginManager.getPluginEnvironments();
- for (ServerPluginEnvironment env : envs) {
- try {
- unloadPlugin(env);
- } catch (Exception e) {
- this.log.warn("Failed to unload plugin [" + env.getPluginName() + "].", e);
+ public synchronized void shutdown() {
+ if (this.pluginManager != null) {
+ Collection<ServerPluginEnvironment> envs = this.pluginManager.getPluginEnvironments();
+ for (ServerPluginEnvironment env : envs) {
+ try {
+ unloadPlugin(env);
+ } catch (Exception e) {
+ this.log.warn("Failed to unload plugin [" + env.getPluginName() + "].", e);
+ }
}
- }
- try {
- this.pluginManager.shutdown();
- } finally {
- this.pluginManager = null;
+ try {
+ this.pluginManager.shutdown();
+ } finally {
+ this.pluginManager = null;
+ }
}
return;
@@ -134,8 +136,12 @@ public abstract class AbstractTypeServerPluginContainer {
*
* @throws Exception if failed to load the plugin
*/
- public void loadPlugin(ServerPluginEnvironment env) throws Exception {
- this.pluginManager.loadPlugin(env);
+ public synchronized void loadPlugin(ServerPluginEnvironment env) throws Exception {
+ if (this.pluginManager != null) {
+ this.pluginManager.loadPlugin(env);
+ } else {
+ throw new Exception("Cannot load a plugin; plugin container is not initialized yet");
+ }
}
/**
@@ -146,8 +152,12 @@ public abstract class AbstractTypeServerPluginContainer {
*
* @throws Exception if failed to unload the plugin
*/
- public void unloadPlugin(ServerPluginEnvironment env) throws Exception {
- this.pluginManager.unloadPlugin(env);
+ public synchronized void unloadPlugin(ServerPluginEnvironment env) throws Exception {
+ if (this.pluginManager != null) {
+ this.pluginManager.unloadPlugin(env);
+ } else {
+ throw new Exception("Cannot unload a plugin; plugin container has been shutdown");
+ }
}
/**
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ClassLoaderManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ClassLoaderManager.java
index 7c543b3..0a9b61c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ClassLoaderManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ClassLoaderManager.java
@@ -92,7 +92,7 @@ public class ClassLoaderManager {
/**
* Cleans up this object and all classloaders it has created.
*/
- public void shutdown() {
+ public synchronized void shutdown() {
for (ClassLoader doomedCL : getUniqueServerPluginClassLoaders()) {
if (doomedCL instanceof ServerPluginClassLoader) {
try {
@@ -179,7 +179,7 @@ public class ClassLoaderManager {
return new HashMap<String, ClassLoader>(this.serverPluginClassLoaders);
}
- private Set<ClassLoader> getUniqueServerPluginClassLoaders() {
+ private synchronized Set<ClassLoader> getUniqueServerPluginClassLoaders() {
HashSet<ClassLoader> uniqueClassLoaders = new HashSet<ClassLoader>(this.serverPluginClassLoaders.values());
return uniqueClassLoaders;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index fe18b8c..c61849a 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -54,7 +54,7 @@ public class MasterServerPluginContainer {
*
* @param config the master configuration
*/
- public void initialize(MasterServerPluginContainerConfiguration config) {
+ public synchronized void initialize(MasterServerPluginContainerConfiguration config) {
try {
log.debug("Master server plugin container is being initialized with config: " + config);
@@ -149,7 +149,7 @@ public class MasterServerPluginContainer {
/**
* Stops all plugins and cleans up after them.
*/
- public void shutdown() {
+ public synchronized void shutdown() {
log.debug("Master server plugin container is being shutdown");
// stop all the plugin containers, giving them a chance to do things like stop threads they have running
@@ -205,13 +205,22 @@ public class MasterServerPluginContainer {
}
/**
+ * Returns the manager that is responsible for created classloaders for plugins.
+ *
+ * @return classloader manager
+ */
+ public ClassLoaderManager getClassLoaderManager() {
+ return this.classLoaderManager;
+ }
+
+ /**
* Get the plugin container of the given class. This method provides a strongly typed return value,
* based on the type of plugin container the caller wants returned.
*
* @param clazz the class name of the plugin container that the caller wants
* @return the plugin container of the given class (<code>null</code> if none found)
*/
- public <T extends AbstractTypeServerPluginContainer> T getPluginContainer(Class<T> clazz) {
+ public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainer(Class<T> clazz) {
for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
if (clazz.isInstance(pc)) {
return (T) pc;
@@ -221,28 +230,22 @@ public class MasterServerPluginContainer {
}
/**
- * Returns the manager that is responsible for created classloaders for plugins.
- *
- * @return classloader manager
- */
- public ClassLoaderManager getClassLoaderManager() {
- return this.classLoaderManager;
- }
-
- /**
* Given a plugin's descriptor, this will return the plugin container that can manage the plugin.
*
* @param descriptor descriptor to identify a plugin whose container is to be returned
* @return a plugin container that can handle the plugin with the given descriptor
*/
- protected AbstractTypeServerPluginContainer getPluginContainerByDescriptor(ServerPluginDescriptorType descriptor) {
+ protected synchronized AbstractTypeServerPluginContainer getPluginContainerByDescriptor(
+ ServerPluginDescriptorType descriptor) {
+
ServerPluginType pluginType = new ServerPluginType(descriptor.getClass());
AbstractTypeServerPluginContainer pc = this.pluginContainers.get(pluginType);
return pc;
}
/**
- * Finds all plugins and parses their descriptors.
+ * Finds all plugins and parses their descriptors. This is only called during
+ * this master plugin container's {@link #initialize(MasterServerPluginContainerConfiguration) initialization}.
*
* If a plugin fails to load, it will be ignored - other plugins will still load.
*
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
index 68500c8..20c66ae 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
@@ -56,7 +56,7 @@ public class PluginManager {
*
* @throws Exception if failed to initialize
*/
- public void initialize() throws Exception {
+ public synchronized void initialize() throws Exception {
return; // no-op
}
@@ -64,7 +64,7 @@ public class PluginManager {
* Shuts down this manager. This should be called only after all of its plugins
* have been {@link #unloadPlugin(ServerPluginEnvironment) unloaded}.
*/
- public void shutdown() {
+ public synchronized void shutdown() {
if (this.loadedPlugins.size() > 0) {
log.warn("Server plugin manager is being shutdown while some plugins are still loaded: "
+ this.loadedPlugins);
@@ -82,7 +82,7 @@ public class PluginManager {
*
* @throws Exception if the plugin manager cannot load the plugin or deems the plugin invalid
*/
- public void loadPlugin(ServerPluginEnvironment env) throws Exception {
+ public synchronized void loadPlugin(ServerPluginEnvironment env) throws Exception {
log.debug("Loading server plugin [" + env.getPluginName() + "] from: " + env.getPluginUrl());
this.loadedPlugins.put(env.getPluginName(), env);
return;
@@ -96,7 +96,7 @@ public class PluginManager {
*
* @throws Exception if the plugin manager cannot unload the plugin
*/
- public void unloadPlugin(ServerPluginEnvironment env) throws Exception {
+ public synchronized void unloadPlugin(ServerPluginEnvironment env) throws Exception {
log.debug("Unloading server plugin [" + env.getPluginName() + "]");
this.loadedPlugins.remove(env.getPluginName());
return;
@@ -108,7 +108,7 @@ public class PluginManager {
*
* @return environments for all the plugins
*/
- public Collection<ServerPluginEnvironment> getPluginEnvironments() {
+ public synchronized Collection<ServerPluginEnvironment> getPluginEnvironments() {
return new ArrayList<ServerPluginEnvironment>(this.loadedPlugins.values());
}
@@ -121,7 +121,7 @@ public class PluginManager {
* @param pluginName the plugin whose environment is to be returned
* @return given plugin's environment
*/
- public ServerPluginEnvironment getPluginEnvironment(String pluginName) {
+ public synchronized ServerPluginEnvironment getPluginEnvironment(String pluginName) {
return this.loadedPlugins.get(pluginName);
}
commit ac12a09334d58862bca1451b3189064250c25fc7
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 6 22:39:41 2009 -0500
more small bug fixes that cause problems at shutdown
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index 160eb37..fe18b8c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -159,7 +159,7 @@ public class MasterServerPluginContainer {
log.debug("Master PC is stopping server plugin container for plugin type [" + pluginType + "]");
try {
- pc.shutdown();
+ pc.stop();
log.debug("Master PC stopped server plugin container for plugin type [" + pluginType + "]");
} catch (Exception e) {
log.error("Failed to stop server plugin container for plugin type [" + pluginType + "]", e);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
index 08c2251..68500c8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
@@ -19,6 +19,7 @@
package org.rhq.enterprise.server.plugin.pc;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -103,11 +104,12 @@ public class PluginManager {
/**
* Returns the {@link ServerPluginEnvironment}s for every plugin this manager has loaded.
+ * The returned collection is a copy and not backed by this manager.
*
* @return environments for all the plugins
*/
public Collection<ServerPluginEnvironment> getPluginEnvironments() {
- return this.loadedPlugins.values();
+ return new ArrayList<ServerPluginEnvironment>(this.loadedPlugins.values());
}
/**
commit aaf92c6e0b9cb4ce6b052ed4e6914f10b014e6d4
Author: Partha Aji <paji(a)redhat.com>
Date: Fri Nov 6 19:39:49 2009 -0500
Mixed merged conflicts resulting from revert of d9f656b50586750124a3d3bbecee95ade22c3885
diff --git a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
index 7e55df7..3a091e6 100644
--- a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
+++ b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
@@ -19,13 +19,11 @@
package org.rhq.plugins.samba;
import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.configuration.PropertyList;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.plugins.augeas.AbstractAugeasConfigurationComponentTest;
public class SambaComponentTest extends AbstractAugeasConfigurationComponentTest {
-
@Override
protected Configuration getExpectedResourceConfig() {
Configuration config = new Configuration();
@@ -46,6 +44,20 @@ public class SambaComponentTest extends AbstractAugeasConfigurationComponentTest
@Override
protected String getResourceTypeName() {
- return "Samba Server";
+ return "Samba Server";
+ }
+
+ @Override
+ protected Configuration getChangedResourceConfig() {
+ Configuration config = new Configuration();
+
+ config.put(new PropertySimple("workgroup", "DUMBCHANGE"));
+ config.put(new PropertySimple("server string", "DUMBCHANGE"));
+ config.put(new PropertySimple("security", "DUMBCHANGE"));
+ config.put(new PropertySimple("encrypt passwords", "DUMBCHANGE"));
+ config.put(new PropertySimple("load printers", "DUMBCHANGE"));
+ config.put(new PropertySimple("cups options", "DUMBCHANGE"));
+
+ return config;
}
}
diff --git a/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java b/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
index f27ac40..943455d 100644
--- a/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
+++ b/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
@@ -70,6 +70,46 @@ public class SudoersComponentTest extends AbstractAugeasConfigurationComponentTe
}
@Override
+ protected Configuration getChangedResourceConfig() {
+ Configuration config = new Configuration();
+ PropertyList entries = new PropertyList(".");
+ config.put(entries);
+ PropertyMap entry;
+ entry = new PropertyMap("spec");
+ entry.put(new PropertySimple("user", "root"));
+ entry.put(new PropertySimple("host_group/host", "fooo"));
+ entry.put(new PropertySimple("host_group/command", "/bin/env"));
+ entry.put(new PropertySimple("host_group/command/runas_user", "ALL"));
+ entry.put(new PropertySimple("host_group/command/tag", true));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("spec");
+ entry.put(new PropertySimple("user", "%wheel"));
+ entry.put(new PropertySimple("host_group/host", "ALL"));
+ entry.put(new PropertySimple("host_group/command", "ALL"));
+ entry.put(new PropertySimple("host_group/command/runas_user", "ALL"));
+ entry.put(new PropertySimple("host_group/command/tag", false));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("spec");
+ entry.put(new PropertySimple("user", "apache"));
+ entry.put(new PropertySimple("host_group/host", "ALL"));
+ entry.put(new PropertySimple("host_group/command", "/bin/env"));
+ entry.put(new PropertySimple("host_group/command/runas_user", "root"));
+ entry.put(new PropertySimple("host_group/command/tag", false));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("spec");
+ entry.put(new PropertySimple("user", "foo"));
+ entry.put(new PropertySimple("host_group/host", "ALL"));
+ entry.put(new PropertySimple("host_group/command", "NETWORKING"));
+ entry.put(new PropertySimple("host_group/command/runas_user", "root"));
+ entry.put(new PropertySimple("host_group/command/tag", true));
+ entries.getList().add(entry);
+ return config;
+ }
+
+ @Override
protected String getPluginName() {
return "Sudoers";
}
commit 3e80440f5f03801efffa9d68ff297fc673e4c2a1
Merge: 0d5dfc0... 74ccaaf...
Author: Partha Aji <paji(a)redhat.com>
Date: Fri Nov 6 18:57:40 2009 -0500
Merge branch 'linux-config' into master-merge
commit 73b56bd2a7b32678899755f211bd4acfff9203a6
Author: Pradeep Kilambi <pkilambi(a)redhat.com>
Date: Fri Nov 6 18:08:58 2009 -0500
adding calls to initialize repos for availabel syncable channels
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
index 16f9aba..c06826e 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
@@ -32,7 +32,12 @@ import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.content.Repo;
+import org.rhq.enterprise.server.content.RepoException;
+import org.rhq.enterprise.server.content.RepoManagerLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
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.InitializationException;
@@ -48,6 +53,7 @@ import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartableTreeType;
import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartFilesType;
import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartFileType;
+
/**
* @author pkilambi
*
@@ -125,6 +131,12 @@ public class RHNProvider implements ContentProvider, PackageSource, Distribution
// RHQ Server is now active, initialize the handler for the bits.
helper = new RHNHelper(locationIn, repos, rhnObject.getSystemid());
+
+ // Now that the server is activated, spawn all syncable channels
+ ArrayList<String> channels = helper.getSyncableChannels();
+
+ // Eventually we should pass in a subset of selected channels to spawn
+ initializeRepos(channels);
}
/**
@@ -232,6 +244,26 @@ public class RHNProvider implements ContentProvider, PackageSource, Distribution
}
/**
+ * Spawns a list of repos for all available channels from RHN hosted.
+ * @param channels The list of channels to be initialized as repos
+ * @throws RepoException
+ */
+ public void initializeRepos(ArrayList<String> channels) throws RepoException {
+ log.info("list of channels: " + channels);
+ if (channels.size() == 0) {
+ // No repos to create
+ return;
+ }
+ RepoManagerLocal repoManager = LookupUtil.getRepoManagerLocal();
+ Subject subject = LookupUtil.getSubjectManager().getOverlord();
+ for (String clabel : channels) {
+ Repo newRepo = new Repo(clabel.toString());
+ newRepo = repoManager.createRepo(subject, newRepo);
+ log.info("New " + newRepo + " repo created");
+ }
+ }
+
+ /**
* Trim white space and trailing (/) characters.
*
* @param path A url/directory path string.
commit e48ef58098e8e145170a95949999d7d3ab1bf961
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 6 17:43:38 2009 -0500
add a start lifecycle method to support how the content stuff wants to
work
diff --git a/etc/eclipse-tools/RHQ Remote Debugging - Agent.launch b/etc/eclipse-tools/RHQ Remote Debugging - Agent.launch
index 50ef310..a7a8bc9 100644
--- a/etc/eclipse-tools/RHQ Remote Debugging - Agent.launch
+++ b/etc/eclipse-tools/RHQ Remote Debugging - Agent.launch
@@ -1,22 +1,21 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.jdt.launching.remoteJavaApplication">
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
-<listEntry value="/rhq"/>
-</listAttribute>
-<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
-<listEntry value="4"/>
-</listAttribute>
-<stringAttribute key="org.eclipse.debug.core.source_locator_id" value="org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector"/>
-<stringAttribute key="org.eclipse.debug.core.source_locator_memento" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <sourceLookupDirector> <sourceContainers duplicates="false"> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;javaProject name=&quot;jopr&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.javaProject"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathContainer path=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathContainer"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/commons-httpclient/commons-httpclient/3.0.1/commons-httpclient-3.0.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;javaProject name=&quot;rhq&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.javaProject"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/i18nlog/i18nlog/1.0.9/i18nlog-1.0.9.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/gnu-getopt/getopt/1.0.13/getopt-1.0.13.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/commons-httpclient/commons-httpclient/2.0.2/commons-httpclient-2.0.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jboss/jboss-remoting/2.2.1.GA/jboss-remoting-2.2.1.GA.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/oswego-concurrent/concurrent/1.3.4/concurrent-1.3.4.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/rss4j/rss4j/0.92-on.2/rss4j-0.92-on.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/ant/ant/1.6.5/ant-1.6.5.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/servlet/servlet-api/2.4/servlet-api-2.4.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/struts/struts/1.2.9/struts-1.2.9.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/servlet/jsp-api/2.0/jsp-api-2.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/commons-validator/commons-validator/1.1.4/commons-validator-1.1.4.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/testng/testng/5.7/testng-5.7-jdk15.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/snmp4j/snmp4j/1.8.2/snmp4j-1.8.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/log4j/log4j/1.2.14/log4j-1.2.14.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/tomcat/tomcat-jk/4.1.31/tomcat-jk-4.1.31.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jdom/jdom/1.0/jdom-1.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/commons-collections/commons-collections/3.1/commons-collections-3.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/persistence/persistence-api/1.0/persistence-api-1.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jboss/jboss-jmx/4.2.1.GA/jboss-jmx-4.2.1.GA.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/tomcat/catalina/5.5.20/catalina-5.5.20.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/commons-beanutils/commons-beanutils/1.7.0/commons-beanutils-1.7.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/taglibs/standard/1.1.2/standard-1.1.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jboss/jboss-common/1.2.0.GA/jboss-common-1.2.0.GA.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/servlet/jstl/1.1.2/jstl-1.1.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/struts-menu/struts-menu/2.3/struts-menu-2.3.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/junit/junit/3.8.2/junit-3.8.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/apache/velocity/velocity/1.5/velocity-1.5.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/xalan/xalan/2.5.1/xalan-2.5.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/xml/bind/jaxb-api/2.1/jaxb-api-2.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/xml/bind/jsr173_api/1.0/jsr173_api-1.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jboss/jboss-embeddable-ejb3/jboss-ejb3-all/1.0.0.Alpha9/jboss-ejb3-all-1.0.0.Alpha9.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jboss/jbpm/3.1.1/jbpm-3.1.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jboss/jboss-embeddable-ejb3/hibernate-all/1.0.0.Alpha9/hibernate-all-1.0.0.Alpha9.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/jetbrains/annotations/7.0.2/annotations-7.0.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/ant/ant-launcher/1.6.5/ant-launcher-1.6.5.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/commons-logging/commons-logging/1.1/commons-logging-1.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/faces/jsf-api/1.2_06/jsf-api-1.2_06.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/faces/jsf-impl/1.2_06/jsf-impl-1.2_06.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/el/el-api/1.0/el-api-1.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/com/sun/facelets/jsf-facelets/1.1.14/jsf-facelets-1.1.14.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/mc4j/org-mc4j-ems/1.2.6/org-mc4j-ems-1.2.6.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/opensymphony/quartz/quartz/1.6.5/quartz-1.6.5.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/mail/mail/1.3.1/mail-1.3.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/commons-fileupload/commons-fileupload/1.2/commons-fileupload-1.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/postgresql/postgresql/8.3-604.jdbc3/postgresql-8.3-604.jdbc3.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jboss/jboss-cache/1.4.1.SP3/jboss-cache-1.4.1.SP3.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/hyperic/sigar/1.5.0.3/sigar-1.5.0.3.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/jboss/transaction/jboss-jta/4.2.3.SP5/jboss-jta-4.2.3.SP5.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/jboss/transaction/jboss-jts-common/4.2.3.SP5/jboss-jts-common-4.2.3.SP5.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/jboss/jboss-jaxws/2.0.1.SP2/jboss-jaxws-2.0.1.SP2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/jboss/jbossws-spi/1.0.0.GA/jbossws-spi-1.0.0.GA.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/jboss/jbossws-client/2.0.1.SP2/jbossws-client-2.0.1.SP2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/apache/maven/maven-project/2.0.8/maven-project-2.0.8.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/apache/maven/maven-plugin-api/2.0.8/maven-plugin-api-2.0.8.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/codehaus/swizzle/swizzle-confluence/1.2.Alpha1/swizzle-confluence-1.2.Alpha1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/jvnet/inflector/0.7.0/inflector-0.7.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/apache/axis/axis/1.4/axis-1.4.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/apache/axis/axis-jaxrpc/1.4/axis-jaxrpc-1.4.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/apache/axis/axis-saaj/1.4/axis-saaj-1.4.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/net/augeas/java-augeas/1.0/java-augeas-1.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/json/json/20080701/json-20080701.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/com/sun/jna/jna/3.0.1/jna-3.0.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/freemarker/freemarker/2.3.11/freemarker-2.3.11.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;default/&gt;&#13;&#10;" typeId="org.eclipse.debug.core.containerType.default"/> </sourceContainers> </sourceLookupDirector> "/>
-<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
-<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
-</listAttribute>
-<booleanAttribute key="org.eclipse.jdt.launching.ALLOW_TERMINATE" value="true"/>
-<mapAttribute key="org.eclipse.jdt.launching.CONNECT_MAP">
-<mapEntry key="port" value="9797"/>
-<mapEntry key="hostname" value="localhost"/>
-<mapEntry key="timeout" value="20000"/>
-</mapAttribute>
-<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="rhq"/>
-<stringAttribute key="org.eclipse.jdt.launching.VM_CONNECTOR_ID" value="org.eclipse.jdt.launching.socketAttachConnector"/>
-</launchConfiguration>
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<launchConfiguration type="org.eclipse.jdt.launching.remoteJavaApplication">
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS">
+<listEntry value="/rhq"/>
+</listAttribute>
+<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES">
+<listEntry value="4"/>
+</listAttribute>
+<stringAttribute key="org.eclipse.debug.core.source_locator_id" value="org.eclipse.jdt.launching.sourceLocator.JavaSourceLookupDirector"/>
+<stringAttribute key="org.eclipse.debug.core.source_locator_memento" value="<?xml version="1.0" encoding="UTF-8" standalone="no"?> <sourceLookupDirector> <sourceContainers duplicates="false"> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;javaProject name=&quot;jopr&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.javaProject"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathContainer path=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathContainer"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/commons-httpclient/commons-httpclient/3.0.1/commons-httpclient-3.0.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;javaProject name=&quot;rhq&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.javaProject"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/i18nlog/i18nlog/1.0.9/i18nlog-1.0.9.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/gnu-getopt/getopt/1.0.13/getopt-1.0.13.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/commons-httpclient/commons-httpclient/2.0.2/commons-httpclient-2.0.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jboss/jboss-remoting/2.2.1.GA/jboss-remoting-2.2.1.GA.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/oswego-concurrent/concurrent/1.3.4/concurrent-1.3.4.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/rss4j/rss4j/0.92-on.2/rss4j-0.92-on.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/ant/ant/1.6.5/ant-1.6.5.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/servlet/servlet-api/2.4/servlet-api-2.4.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/struts/struts/1.2.9/struts-1.2.9.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/servlet/jsp-api/2.0/jsp-api-2.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/commons-validator/commons-validator/1.1.4/commons-validator-1.1.4.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/testng/testng/5.7/testng-5.7-jdk15.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/snmp4j/snmp4j/1.8.2/snmp4j-1.8.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/log4j/log4j/1.2.14/log4j-1.2.14.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/tomcat/tomcat-jk/4.1.31/tomcat-jk-4.1.31.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jdom/jdom/1.0/jdom-1.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/commons-collections/commons-collections/3.1/commons-collections-3.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/persistence/persistence-api/1.0/persistence-api-1.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jboss/jboss-jmx/4.2.1.GA/jboss-jmx-4.2.1.GA.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/tomcat/catalina/5.5.20/catalina-5.5.20.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/commons-beanutils/commons-beanutils/1.7.0/commons-beanutils-1.7.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/taglibs/standard/1.1.2/standard-1.1.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jboss/jboss-common/1.2.0.GA/jboss-common-1.2.0.GA.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/servlet/jstl/1.1.2/jstl-1.1.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/struts-menu/struts-menu/2.3/struts-menu-2.3.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/junit/junit/3.8.2/junit-3.8.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/apache/velocity/velocity/1.5/velocity-1.5.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/xalan/xalan/2.5.1/xalan-2.5.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/xml/bind/jaxb-api/2.1/jaxb-api-2.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/xml/bind/jsr173_api/1.0/jsr173_api-1.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jboss/jboss-embeddable-ejb3/jboss-ejb3-all/1.0.0.Alpha9/jboss-ejb3-all-1.0.0.Alpha9.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jboss/jbpm/3.1.1/jbpm-3.1.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jboss/jboss-embeddable-ejb3/hibernate-all/1.0.0.Alpha9/hibernate-all-1.0.0.Alpha9.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/jetbrains/annotations/7.0.2/annotations-7.0.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/ant/ant-launcher/1.6.5/ant-launcher-1.6.5.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/cglib/cglib-nodep/2.1_3/cglib-nodep-2.1_3.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/commons-logging/commons-logging/1.1/commons-logging-1.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/faces/jsf-api/1.2_06/jsf-api-1.2_06.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/faces/jsf-impl/1.2_06/jsf-impl-1.2_06.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/el/el-api/1.0/el-api-1.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/com/sun/facelets/jsf-facelets/1.1.14/jsf-facelets-1.1.14.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/mc4j/org-mc4j-ems/1.2.6/org-mc4j-ems-1.2.6.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/opensymphony/quartz/quartz/1.6.5/quartz-1.6.5.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/javax/mail/mail/1.3.1/mail-1.3.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/commons-fileupload/commons-fileupload/1.2/commons-fileupload-1.2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/postgresql/postgresql/8.3-604.jdbc3/postgresql-8.3-604.jdbc3.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/jboss/jboss-cache/1.4.1.SP3/jboss-cache-1.4.1.SP3.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/hyperic/sigar/1.5.0.3/sigar-1.5.0.3.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/jboss/transaction/jboss-jta/4.2.3.SP5/jboss-jta-4.2.3.SP5.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/jboss/transaction/jboss-jts-common/4.2.3.SP5/jboss-jts-common-4.2.3.SP5.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/jboss/jboss-jaxws/2.0.1.SP2/jboss-jaxws-2.0.1.SP2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/jboss/jbossws-spi/1.0.0.GA/jbossws-spi-1.0.0.GA.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/jboss/jbossws-client/2.0.1.SP2/jbossws-client-2.0.1.SP2.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/apache/maven/maven-project/2.0.8/maven-project-2.0.8.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/apache/maven/maven-plugin-api/2.0.8/maven-plugin-api-2.0.8.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/codehaus/swizzle/swizzle-confluence/1.2.Alpha1/swizzle-confluence-1.2.Alpha1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/jvnet/inflector/0.7.0/inflector-0.7.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/apache/axis/axis/1.4/axis-1.4.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/apache/axis/axis-jaxrpc/1.4/axis-jaxrpc-1.4.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/apache/axis/axis-saaj/1.4/axis-saaj-1.4.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/net/augeas/java-augeas/1.0/java-augeas-1.0.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/json/json/20080701/json-20080701.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/com/sun/jna/jna/3.0.1/jna-3.0.1.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;classpathVariable path=&quot;M2_REPO/org/freemarker/freemarker/2.3.11/freemarker-2.3.11.jar&quot;/&gt;&#13;&#10;" typeId="org.eclipse.jdt.launching.sourceContainer.classpathVariable"/> <container memento="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#13;&#10;&lt;default/&gt;&#13;&#10;" typeId="org.eclipse.debug.core.containerType.default"/> </sourceContainers> </sourceLookupDirector> "/>
+<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
+<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
+</listAttribute>
+<booleanAttribute key="org.eclipse.jdt.launching.ALLOW_TERMINATE" value="true"/>
+<mapAttribute key="org.eclipse.jdt.launching.CONNECT_MAP">
+<mapEntry key="port" value="9797"/>
+<mapEntry key="hostname" value="localhost"/>
+</mapAttribute>
+<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="rhq"/>
+<stringAttribute key="org.eclipse.jdt.launching.VM_CONNECTOR_ID" value="org.eclipse.jdt.launching.socketAttachConnector"/>
+</launchConfiguration>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index ef1085c..cb01ad0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -74,7 +74,8 @@ public abstract class AbstractTypeServerPluginContainer {
}
/**
- * The initialize method that prepares the plugin container.
+ * The initialize method that prepares the plugin container. This should get the plugin
+ * container ready to accept plugins.
*
* Subclasses are free to perform additional tasks by overriding this method.
*
@@ -86,6 +87,23 @@ public abstract class AbstractTypeServerPluginContainer {
}
/**
+ * This method informs the plugin container that all of its plugins have been loaded.
+ * Once this is called, the plugin container can assume all plugins that it will
+ * ever know about have been {@link #loadPlugin(ServerPluginEnvironment) loaded}.
+ */
+ public void start() {
+ return; // no-op
+ }
+
+ /**
+ * This will inform the plugin container that it must stop doing its work. Once called,
+ * the plugin container must assume that soon it will be asked to {@link #shutdown()}.
+ */
+ public void stop() {
+ return; // no-op
+ }
+
+ /**
* The shutdown method that will stop and unload all plugins.
*
* Subclasses are free to perform additional tasks by overriding this method.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index c477897..160eb37 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -89,7 +89,7 @@ public class MasterServerPluginContainer {
log.debug("Master PC is initializing server plugin container for plugin type [" + pluginType + "]");
try {
pc.initialize();
- log.info("Master PC initialized server plugin container for plugin type [" + pluginType + "]");
+ log.debug("Master PC initialized server plugin container for plugin type [" + pluginType + "]");
} catch (Exception e) {
log.warn("Failed to initialize server plugin container for plugin type [" + pluginType + "]", e);
iterator.remove();
@@ -118,6 +118,24 @@ public class MasterServerPluginContainer {
}
}
+ // now that all plugins have been loaded, we need to tell all the plugin containers to start
+ iterator = this.pluginContainers.entrySet().iterator();
+
+ while (iterator.hasNext()) {
+ Map.Entry<ServerPluginType, AbstractTypeServerPluginContainer> entry = iterator.next();
+
+ ServerPluginType pluginType = entry.getKey();
+ AbstractTypeServerPluginContainer pc = entry.getValue();
+
+ log.debug("Master PC is starting server plugin container for plugin type [" + pluginType + "]");
+ try {
+ pc.start();
+ log.info("Master PC started server plugin container for plugin type [" + pluginType + "]");
+ } catch (Exception e) {
+ log.warn("Failed to start server plugin container for plugin type [" + pluginType + "]", e);
+ }
+ }
+
log.info("Master server plugin container has been initialized");
} catch (Throwable t) {
@@ -134,7 +152,21 @@ public class MasterServerPluginContainer {
public void shutdown() {
log.debug("Master server plugin container is being shutdown");
- // Shutdown all the plugin containers which in turn shuts down all their plugins.
+ // stop all the plugin containers, giving them a chance to do things like stop threads they have running
+ for (Map.Entry<ServerPluginType, AbstractTypeServerPluginContainer> entry : this.pluginContainers.entrySet()) {
+ ServerPluginType pluginType = entry.getKey();
+ AbstractTypeServerPluginContainer pc = entry.getValue();
+
+ log.debug("Master PC is stopping server plugin container for plugin type [" + pluginType + "]");
+ try {
+ pc.shutdown();
+ log.debug("Master PC stopped server plugin container for plugin type [" + pluginType + "]");
+ } catch (Exception e) {
+ log.error("Failed to stop server plugin container for plugin type [" + pluginType + "]", e);
+ }
+ }
+
+ // shutdown all the plugin containers which in turn shuts down all their plugins.
for (Map.Entry<ServerPluginType, AbstractTypeServerPluginContainer> entry : this.pluginContainers.entrySet()) {
ServerPluginType pluginType = entry.getKey();
AbstractTypeServerPluginContainer pc = entry.getValue();
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/RootServerPluginClassLoader.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/RootServerPluginClassLoader.java
index 500b775..10a4be7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/RootServerPluginClassLoader.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/RootServerPluginClassLoader.java
@@ -65,7 +65,7 @@ public class RootServerPluginClassLoader extends URLClassLoader {
* @throws PatternSyntaxException if the given regex is invalid (see {@link Pattern#compile(String)})
*/
public RootServerPluginClassLoader(URL[] urls, ClassLoader parent, String... classesToHideRegexStr) {
- super(urls, parent);
+ super((urls != null) ? urls : new URL[0], parent);
Pattern pattern;
@@ -85,7 +85,7 @@ public class RootServerPluginClassLoader extends URLClassLoader {
this.classesToHideRegex = pattern;
log.debug("Root server plugin classloader: regex=[" + this.classesToHideRegex + "], urls="
- + Arrays.asList(urls));
+ + Arrays.asList((urls != null) ? urls : new URL[0]));
}
protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
index ff7d1e7..999bfba 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
@@ -68,7 +68,7 @@ public class ContentProviderManager {
private static final String PARENT_RELATIONSHIP_NAME = "parent";
- private ContentProviderPluginManager pluginManager;
+ private ContentServerPluginManager pluginManager;
private Map<ContentSource, ContentProvider> adapters;
// This is used as a monitor lock to the synchronizeContentSource method;
@@ -432,6 +432,8 @@ public class ContentProviderManager {
* <p>If there is already an adapter currently started for the given content source, this returns silently.</p>
*
* @param contentSource the new content source that was added
+ *
+ * @throws InitializationException failed to initialize the adapter that processes the content source
*/
public void startAdapter(ContentSource contentSource) throws InitializationException {
synchronized (this.adapters) {
@@ -450,9 +452,10 @@ public class ContentProviderManager {
adapter.initialize(contentSource.getConfiguration());
} catch (Exception e) {
log.warn("Failed to initialize adapter for content source [" + contentSource.getName() + "]", e);
- throw new InitializationException(e.getCause());
+ throw new InitializationException(e);
}
+ return;
}
/**
@@ -502,7 +505,7 @@ public class ContentProviderManager {
*
* @param pluginManager the plugin manager this object can use to obtain information from (like classloaders)
*/
- protected void initialize(ContentProviderPluginManager pluginManager) throws InitializationException {
+ protected void initialize(ContentServerPluginManager pluginManager) {
this.pluginManager = pluginManager;
ContentSourceMetadataManagerLocal metadataManager = LookupUtil.getContentSourceMetadataManager();
@@ -524,9 +527,15 @@ public class ContentProviderManager {
// let's initalize all adapters for all content sources
if (contentSources != null) {
for (ContentSource contentSource : contentSources) {
- startAdapter(contentSource);
+ try {
+ startAdapter(contentSource);
+ } catch (Exception e) {
+ log.warn("Failed to start adapator for content source [" + contentSource + "]");
+ }
}
}
+
+ return;
}
/**
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderPluginManager.java
deleted file mode 100644
index f3b0e3d..0000000
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderPluginManager.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * RHQ Management Platform
- * Copyright (C) 2005-2009 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.plugin.pc.content;
-
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.rhq.core.domain.content.ContentSourceType;
-import org.rhq.enterprise.server.plugin.pc.PluginManager;
-import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
-import org.rhq.enterprise.server.plugin.pc.content.metadata.ContentSourcePluginMetadataManager;
-import org.rhq.enterprise.server.xmlschema.generated.serverplugin.content.ContentPluginDescriptorType;
-
-/**
- * This loads in all content source server plugins that can be found and will maintain the complete set of
- * {@link #getMetadataManager() metadata} found in all plugin descriptors from all loaded plugins. You can obtain a
- * loaded plugin's {@link ServerPluginEnvironment environment}, including its classloader, from this object as
- * well.
- *
- * @author John Mazzitelli
- */
-public class ContentProviderPluginManager extends PluginManager {
-
- private ContentSourcePluginMetadataManager metadataManager;
-
- public ContentProviderPluginManager(ContentServerPluginContainer pc) {
- super(pc);
- }
-
- @Override
- public void initialize() throws Exception {
- super.initialize();
- metadataManager = new ContentSourcePluginMetadataManager();
- }
-
- @Override
- public void shutdown() {
- super.shutdown();
- metadataManager = null;
- }
-
- /**
- * Gets the plugin environment for the plugin responsible for managing the given content source type.
- *
- * @param type
- *
- * @return plugin environment
- */
- public ServerPluginEnvironment getPluginEnvironment(ContentSourceType type) {
- String pluginName = this.metadataManager.getPluginNameFromContentSourceType(type);
- return getPluginEnvironment(pluginName);
- }
-
- /**
- * An object that can be used to process and store all metadata from all content plugins. This object will contain all the
- * metadata found in all loaded content plugins.
- *
- * @return object to retrieve plugin metadata from
- */
- public ContentSourcePluginMetadataManager getMetadataManager() {
- return metadataManager;
- }
-
- @Override
- public void loadPlugin(ServerPluginEnvironment env) throws Exception {
-
- super.loadPlugin(env);
-
- Collection<ContentSourceType> newTypes;
- newTypes = this.metadataManager.loadPlugin((ContentPluginDescriptorType) env.getPluginDescriptor());
-
- // double check that the api classes are loadable, if not, very bad
- Set<ContentSourceType> newTypesCopy = new HashSet<ContentSourceType>(newTypes);
- for (ContentSourceType newType : newTypesCopy) {
- try {
- String className = newType.getContentSourceApiClass();
- Class<?> apiClass = Class.forName(className, false, env.getClassLoader());
-
- if (!ContentProvider.class.isAssignableFrom(apiClass)) {
- throw new Exception("The API class [" + className + "] should implement ["
- + ContentProvider.class.getName() + "] but does not");
- }
- } catch (Exception e) {
- // do not deploy this plugin - its stinky
- try {
- unloadPlugin(env);
- } catch (Exception ignore) {
- }
- throw e;
- }
- }
-
- return;
- }
-
- @Override
- public void unloadPlugin(ServerPluginEnvironment env) throws Exception {
- metadataManager.unloadPlugin(env.getPluginName());
- super.unloadPlugin(env);
- };
-}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
index d66b6b4..3c5427d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
@@ -54,11 +54,17 @@ public class ContentServerPluginContainer extends AbstractTypeServerPluginContai
public void initialize() throws Exception {
getLog().debug("Content server plugin container initializing");
super.initialize();
- this.adapterManager = createAdapterManager((ContentProviderPluginManager) getPluginManager()); // initializes, too
+ this.adapterManager = createAdapterManager();
getLog().debug("Content server plugin container initialized");
}
@Override
+ public void start() {
+ super.start();
+ this.adapterManager.initialize((ContentServerPluginManager) getPluginManager());
+ }
+
+ @Override
public void shutdown() {
getLog().debug("Content server plugin container is shutting down");
this.adapterManager.shutdown();
@@ -176,24 +182,19 @@ public class ContentServerPluginContainer extends AbstractTypeServerPluginContai
@Override
protected PluginManager createPluginManager() {
- return new ContentProviderPluginManager(this);
+ return new ContentServerPluginManager(this);
}
/**
- * Creates, configures and initializes the adapter manager that the PC will use.
+ * Creates the adapter manager that the PC will use.
*
* <p>This is protected scope so subclasses can define their own adapter manager to use. This is mainly to support
* tests.</p>
*
- * @param pluginManager the plugin manager that was {@link #createPluginManager() created} for use in the PC. The
- * adapter manager can use this to obtain information about plugins.
- *
* @return the new adapter manager
*/
- protected ContentProviderManager createAdapterManager(ContentProviderPluginManager pluginManager)
- throws InitializationException {
+ protected ContentProviderManager createAdapterManager() {
ContentProviderManager am = new ContentProviderManager();
- am.initialize(pluginManager);
return am;
}
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginManager.java
new file mode 100644
index 0000000..03a4b5f
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginManager.java
@@ -0,0 +1,118 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc.content;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.rhq.core.domain.content.ContentSourceType;
+import org.rhq.enterprise.server.plugin.pc.PluginManager;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
+import org.rhq.enterprise.server.plugin.pc.content.metadata.ContentSourcePluginMetadataManager;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.content.ContentPluginDescriptorType;
+
+/**
+ * This loads in all content source server plugins that can be found and will maintain the complete set of
+ * {@link #getMetadataManager() metadata} found in all plugin descriptors from all loaded plugins. You can obtain a
+ * loaded plugin's {@link ServerPluginEnvironment environment}, including its classloader, from this object as
+ * well.
+ *
+ * @author John Mazzitelli
+ */
+public class ContentServerPluginManager extends PluginManager {
+
+ private ContentSourcePluginMetadataManager metadataManager;
+
+ public ContentServerPluginManager(ContentServerPluginContainer pc) {
+ super(pc);
+ }
+
+ @Override
+ public void initialize() throws Exception {
+ super.initialize();
+ metadataManager = new ContentSourcePluginMetadataManager();
+ }
+
+ @Override
+ public void shutdown() {
+ super.shutdown();
+ metadataManager = null;
+ }
+
+ /**
+ * Gets the plugin environment for the plugin responsible for managing the given content source type.
+ *
+ * @param type
+ *
+ * @return plugin environment
+ */
+ public ServerPluginEnvironment getPluginEnvironment(ContentSourceType type) {
+ String pluginName = this.metadataManager.getPluginNameFromContentSourceType(type);
+ return getPluginEnvironment(pluginName);
+ }
+
+ /**
+ * An object that can be used to process and store all metadata from all content plugins. This object will contain all the
+ * metadata found in all loaded content plugins.
+ *
+ * @return object to retrieve plugin metadata from
+ */
+ public ContentSourcePluginMetadataManager getMetadataManager() {
+ return metadataManager;
+ }
+
+ @Override
+ public void loadPlugin(ServerPluginEnvironment env) throws Exception {
+
+ super.loadPlugin(env);
+
+ Collection<ContentSourceType> newTypes;
+ newTypes = this.metadataManager.loadPlugin((ContentPluginDescriptorType) env.getPluginDescriptor());
+
+ // double check that the api classes are loadable, if not, very bad
+ Set<ContentSourceType> newTypesCopy = new HashSet<ContentSourceType>(newTypes);
+ for (ContentSourceType newType : newTypesCopy) {
+ try {
+ String className = newType.getContentSourceApiClass();
+ Class<?> apiClass = Class.forName(className, false, env.getClassLoader());
+
+ if (!ContentProvider.class.isAssignableFrom(apiClass)) {
+ throw new Exception("The API class [" + className + "] should implement ["
+ + ContentProvider.class.getName() + "] but does not");
+ }
+ } catch (Exception e) {
+ // do not deploy this plugin - its stinky
+ try {
+ unloadPlugin(env);
+ } catch (Exception ignore) {
+ }
+ throw e;
+ }
+ }
+
+ return;
+ }
+
+ @Override
+ public void unloadPlugin(ServerPluginEnvironment env) throws Exception {
+ metadataManager.unloadPlugin(env.getPluginName());
+ super.unloadPlugin(env);
+ };
+}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
index 22cc264..a9dcef4 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
@@ -37,8 +37,8 @@ import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
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.ContentProviderPackageDetails;
-import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPluginManager;
import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginManager;
import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
@@ -92,14 +92,13 @@ public class TestServerPluginService extends ServerPluginService implements Test
}
@Override
- protected ContentProviderManager createAdapterManager(ContentProviderPluginManager pluginManager) {
+ protected ContentProviderManager createAdapterManager() {
TestContentProviderManager am = new TestContentProviderManager();
- am.initialize(pluginManager);
return am;
}
@Override
- protected ContentProviderPluginManager createPluginManager() {
+ protected ContentServerPluginManager createPluginManager() {
TestContentProviderPluginManager pm = new TestContentProviderPluginManager(this);
return pm;
}
@@ -108,7 +107,7 @@ public class TestServerPluginService extends ServerPluginService implements Test
/**
* The test plugin manager.
*/
- class TestContentProviderPluginManager extends ContentProviderPluginManager {
+ class TestContentProviderPluginManager extends ContentServerPluginManager {
public TestContentProviderPluginManager(ContentServerPluginContainer pc) {
super(pc);
}
@@ -124,7 +123,7 @@ public class TestServerPluginService extends ServerPluginService implements Test
}
@Override
- protected void initialize(ContentProviderPluginManager pluginManager) {
+ protected void initialize(ContentServerPluginManager pluginManager) {
createInitialAdaptersMap();
}
commit 521ad2540a603a4ec755544deeb7d3aae64ed857
Author: John Matthews <jmatthew(a)redhat.com>
Date: Fri Nov 6 17:37:17 2009 -0500
555 - work in progress, what I think we'll need to sync kickstarts from hosted.
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
index 056e273..4f0d4c5 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
@@ -32,10 +32,13 @@ import org.apache.xmlrpc.XmlRpcException;
import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnChannelFamilyType;
import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnChannelType;
import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnPackageType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartableTreeType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartFileType;
import org.rhq.enterprise.server.plugins.rhnhosted.xmlrpc.RhnComm;
import org.rhq.enterprise.server.plugins.rhnhosted.xmlrpc.RhnDownloader;
import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails;
import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetailsKey;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionDetails;
/**
* @author pkilambi
@@ -48,6 +51,9 @@ public class RHNHelper {
private final RhnComm rhndata;
private final RhnDownloader rhndownload;
private final String systemid;
+
+ //TODO: Need to determine what the ksTreeType should be for RHN Kickstarts
+ private final String ksTreeType = "CHANGE_ME";
private final Log log = LogFactory.getLog(RHNHelper.class);
@@ -68,6 +74,22 @@ public class RHNHelper {
}
+ public List<DistributionDetails> getDistributionDetails(List<String> ksLabels)
+ throws IOException, XmlRpcException {
+
+ List<DistributionDetails> ddList = new ArrayList<DistributionDetails>();
+ List<RhnKickstartableTreeType> ksTreeTypes = rhndata.getKickstartTreeMetadata(this.systemid, ksLabels);
+ for (RhnKickstartableTreeType ksTree: ksTreeTypes) {
+ List<RhnKickstartFileType> ksFiles = ksTree.getRhnKickstartFiles().getRhnKickstartFile();
+ for (RhnKickstartFileType ksFile: ksFiles) {
+ String path = ksTree.getBasePath() + "/" + ksFile.getRelativePath();
+ //TODO: Should add fileSize and md5sum to DistributionDetails
+ ddList.add(new DistributionDetails(ksTree.getLabel(), path, ksTreeType));
+ }
+ }
+ return ddList;
+ }
+
/**
* Extract the package metadata for all available packages to sync
* @param packageIds Valid package ids for getPackageMatadata call to fetch from hosted
@@ -168,11 +190,15 @@ public class RHNHelper {
return allchannels;
}
- public List<String> getSyncableKickstartLabels() throws IOException, XmlRpcException {
- List<String> ksLabels = new ArrayList<String>();
+ public List<String> getSyncableKickstartLabels() throws IOException, XmlRpcException {
List<String> allChannels = getSyncableChannels();
- List<RhnChannelType> rct = rhndata.getChannels(this.systemid, allChannels);
+ return getSyncableKickstartLabels(allChannels);
+ }
+
+ public List<String> getSyncableKickstartLabels(List<String> channelLabels) throws IOException, XmlRpcException {
+ List<String> ksLabels = new ArrayList<String>();
+ List<RhnChannelType> rct = rhndata.getChannels(this.systemid, channelLabels);
for (RhnChannelType ct: rct) {
String ksTrees = ct.getKickstartableTrees();
String[] trees = ksTrees.split(" ");
@@ -181,6 +207,7 @@ public class RHNHelper {
return ksLabels;
}
+
/**
* Open an input stream to specifed relative url. Prepends the baseurl to the <i>url</i> and opens and opens and
* input stream. Files with a .gz suffix will be unziped (inline).
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
index 77ac620..16f9aba 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
@@ -38,15 +38,22 @@ import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPackageDetails
import org.rhq.enterprise.server.plugin.pc.content.InitializationException;
import org.rhq.enterprise.server.plugin.pc.content.PackageSource;
import org.rhq.enterprise.server.plugin.pc.content.PackageSyncReport;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionSource;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionSyncReport;
+import org.rhq.enterprise.server.plugin.pc.content.DistributionDetails;
import org.rhq.enterprise.server.plugins.rhnhosted.certificate.Certificate;
import org.rhq.enterprise.server.plugins.rhnhosted.certificate.CertificateFactory;
import org.rhq.enterprise.server.plugins.rhnhosted.certificate.PublicKeyRing;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartableTreeType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartFilesType;
+import org.rhq.enterprise.server.plugins.rhnhosted.xml.RhnKickstartFileType;
/**
* @author pkilambi
*
*/
-public class RHNProvider implements ContentProvider, PackageSource {
+public class RHNProvider implements ContentProvider, PackageSource, DistributionSource
+{
private final Log log = LogFactory.getLog(RHNProvider.class);
private RHNActivator rhnObject;
@@ -127,6 +134,7 @@ public class RHNProvider implements ContentProvider, PackageSource {
log.debug("shutdown");
}
+
/**
* Get an input stream for the specified package (bits).
*
@@ -182,6 +190,25 @@ public class RHNProvider implements ContentProvider, PackageSource {
}
+ public void synchronizeDistribution(DistributionSyncReport report) throws Exception {
+ // hard coding a kickstart label for testing.
+ List<String> distLabels = new ArrayList<String>();
+ distLabels.add("ks-rhel-i386-server-5");
+ synchronizeDistribution(report, distLabels);
+ }
+
+ public void synchronizeDistribution(DistributionSyncReport report, List<String> distLabels) throws Exception {
+
+ // Goal:
+ // This method will create the metadata representing what kickstart tree files need to be downloaded.
+ // the metadata will be returned through the DistributionSyncReport object.
+ // NOTE: This method DOES not do the actual downloading of data.
+ List<DistributionDetails> ddList = helper.getDistributionDetails(distLabels);
+ //TODO: Need to add logic to determine what has already been synced, what needs to be synced.
+
+ report.addDistros(ddList);
+ }
+
/**
* Test's the adapter's connection.
*
commit 18e39a0b72b9202762c363acd65fa2e92c9dca4a
Author: John Matthews <jmatthew(a)redhat.com>
Date: Fri Nov 6 16:16:07 2009 -0500
555 - adding method to get list of kickstart labels from hosted
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
index c7aa22a..056e273 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
@@ -168,6 +168,19 @@ public class RHNHelper {
return allchannels;
}
+ public List<String> getSyncableKickstartLabels() throws IOException, XmlRpcException {
+ List<String> ksLabels = new ArrayList<String>();
+
+ List<String> allChannels = getSyncableChannels();
+ List<RhnChannelType> rct = rhndata.getChannels(this.systemid, allChannels);
+ for (RhnChannelType ct: rct) {
+ String ksTrees = ct.getKickstartableTrees();
+ String[] trees = ksTrees.split(" ");
+ ksLabels.addAll(Arrays.asList(trees));
+ }
+ return ksLabels;
+ }
+
/**
* Open an input stream to specifed relative url. Prepends the baseurl to the <i>url</i> and opens and opens and
* input stream. Files with a .gz suffix will be unziped (inline).
@@ -183,7 +196,7 @@ public class RHNHelper {
public InputStream openStream(String location) throws IOException, XmlRpcException {
log.info("Package Fetched from: " + location);
- return rhndownload.getRPMStream(this.systemid, location);
+ return rhndownload.getFileStream(this.systemid, location);
}
/**
@@ -198,6 +211,19 @@ public class RHNHelper {
return baseurl + appendurl;
}
+ /**
+ * Constructs a downloadable url for package downloads.
+ * @param channelName channel label to be synced.
+ * @param ksTreeLabel kickstart tree label name
+ * @param ksFilePath path to kickstart file
+ * @return a valid url location to fetch the rpm from.
+ */
+ private String constructKickstartFileUrl(String channelName, String ksTreeLabel, String ksFilePath) {
+
+ String appendurl = "/SAT/$RHN/" + channelName + "/getKickstartFile/" + ksTreeLabel + "/" + ksFilePath;
+ return baseurl + appendurl;
+ }
+
/**
* Method to construct an rpm format filename for download url
* @param name rpm package name
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnDownloader.java b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnDownloader.java
index 0d71ac0..0414f6a 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnDownloader.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/RhnDownloader.java
@@ -92,7 +92,7 @@ public class RhnDownloader {
return true;
}
- public InputStream getRPMStream(String systemId, String locationUrl) throws IOException, XmlRpcException {
+ public InputStream getFileStream(String systemId, String locationUrl) throws IOException, XmlRpcException {
HttpURLConnection conn = getNewConnection(locationUrl);
Map props = login(systemId);
@@ -120,4 +120,5 @@ public class RhnDownloader {
InputStream in = conn.getInputStream();
return in;
}
+
}
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/BaseRHNTest.java b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/BaseRHNTest.java
index fbd5f40..7939df7 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/BaseRHNTest.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/BaseRHNTest.java
@@ -96,4 +96,12 @@ public class BaseRHNTest extends TestCase {
+ "<value><string>REAL</string></value>\n" + "</member>\n" + "</struct></value>\n" + "</param>\n"
+ "</params>\n";
+ /**
+ * Adding this empty test method to make command line tests execute from maven.
+ * The lack of a test method in this class, was causing an exception to be thrown
+ * @throws Exception
+ */
+ public void testDoNothing() throws Exception {
+ assertTrue(true);
+ }
}
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelperTest.java b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelperTest.java
index cb2720e..582b41f 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelperTest.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelperTest.java
@@ -68,4 +68,16 @@ public class RHNHelperTest extends BaseRHNTest {
assertTrue(success);
}
+ public void testGetSyncableKickstartTrees() throws Exception {
+ boolean success = true;
+ try {
+ List<String> ksLabels = helper.getSyncableKickstartLabels();
+ assertTrue(ksLabels.size() > 0);
+ } catch (Exception e) {
+ e.printStackTrace();
+ success = false;
+ }
+ assertTrue(success);
+ }
+
}
diff --git a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/MockRhnXmlRpcExecutor.java b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/MockRhnXmlRpcExecutor.java
index 6d5892e..bcdfe41 100644
--- a/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/MockRhnXmlRpcExecutor.java
+++ b/modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/xmlrpc/MockRhnXmlRpcExecutor.java
@@ -217,6 +217,7 @@ public class MockRhnXmlRpcExecutor implements XmlRpcExecutor {
chantype.setRhnChannelName("channel name");
chantype.setRhnChannelSummary("channel summary");
chantype.setPackages("1 2 3 4");
+ chantype.setKickstartableTrees("ks-rhel-i386-server-5 ks-rhel-i386-server-5-u1 ks-rhel-i386-server-5-u2");
rhnChannel.add(chantype);
RhnChannelsType chantypes = new RhnChannelsType();
commit 0d5dfc0bcd08bf67ec110c4b84e816166966d082
Merge: c62e843... 70a72d6...
Author: Partha Aji <paji(a)redhat.com>
Date: Fri Nov 6 14:59:23 2009 -0500
Fixed more conflicts from the linux-config branch
diff --cc .classpath
index a742310,9bfb3c8..eda889b
--- a/.classpath
+++ b/.classpath
@@@ -83,12 -86,14 +83,14 @@@
<classpathentry kind="src" path="modules/plugins/sshd/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/hardware/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/oracle/src/main/java"/>
- <classpathentry kind="src" path="modules/plugins/grub/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/grub/src/main/java"/>
- <classpathentry kind="src" path="modules/plugins/samba/src/test/java"/>
+ <classpathentry kind="src" path="modules/plugins/grub/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/samba/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/samba/src/test/java"/>
+ <classpathentry kind="src" path="modules/plugins/sudoers/src/main/java"/>
- <classpathentry kind="src" path="modules/plugins/sudoers/src/test/java"/>
++ <classpathentry kind="src" path="modules/plugins/sudoers/src/test/java"/>
+ <classpathentry kind="src" path="modules/plugins/postfix/src/test/java"/>
+ <classpathentry kind="src" path="modules/plugins/postfix/src/main/java"/>
- <classpathentry kind="src" path="modules/plugins/sudoers/src/test/java"/>
- <classpathentry kind="src" path="modules/plugins/sudoers/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/cron/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/cron/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/hudson/src/main/java"/>
diff --cc modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java
index 423ac15,dee0b0d..e8f5ef3
--- a/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java
+++ b/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java
@@@ -137,15 -120,30 +120,27 @@@ public abstract class AbstractAugeasCon
}
}
- @BeforeSuite(dependsOnMethods = "updatePluginConfiguration", groups = TEST_GROUP)
- public void scanInventory() {
- /*try {
- System.out.println("Executing full discovery scan...");
- PluginContainer.getInstance().getInventoryManager().executeServerScanImmediately();
- PluginContainer.getInstance().getInventoryManager().executeServiceScanImmediately();
- } catch (Exception e) {
- fail("Failed to execute full discovery scan.", e);
- }*/
+ public void resetAugeasConfigs() throws IOException {
+ String tmpDirPath = System.getProperty("java.io.tmpdir");
+ File tmpDir = new File(tmpDirPath);
+ File augeasRootPath = new File(tmpDir, "rhq-itest-augeas-root-path");
+ if (!augeasRootPath.exists()) {
+ augeasRootPath.mkdirs();
+ }
+ System.setProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP, augeasRootPath.getAbsolutePath());
+ Resource resource = getResource();
+ Configuration pluginConfig = resource.getPluginConfiguration();
-
+ PropertySimple includes = pluginConfig.getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP);
+ List<String> includeGlobs = new ArrayList<String>();
+ includeGlobs.addAll(Arrays.asList(includes.getStringValue().split("\\s*\\|\\s*")));
+ for (String includeGlob : includeGlobs) {
+ InputStream inputStream = this.getClass().getResourceAsStream(includeGlob);
+ if (inputStream != null) {
+ File outputFile = new File(augeasRootPath, includeGlob);
- if (!outputFile.getParentFile().exists()) {
- outputFile.getParentFile().mkdirs();
- }
++ outputFile.getParentFile().mkdirs();
+ FileUtil.writeFile(inputStream, outputFile);
+ }
+ }
}
@AfterSuite(groups = TEST_GROUP)
commit c62e843ac3858244a6210c9b878ab028a6b675fc
Author: Partha Aji <paji(a)redhat.com>
Date: Fri Nov 6 14:44:42 2009 -0500
Fixed Merge conflicts
diff --git a/.classpath b/.classpath
index d88d80c..a742310 100644
--- a/.classpath
+++ b/.classpath
@@ -89,6 +89,8 @@
<classpathentry kind="src" path="modules/plugins/samba/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/sudoers/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/sudoers/src/test/java"/>
+ <classpathentry kind="src" path="modules/plugins/cron/src/test/java"/>
+ <classpathentry kind="src" path="modules/plugins/cron/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/hudson/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/platform/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/apt/src/main/java"/>
@@ -98,12 +100,13 @@
<classpathentry kind="src" path="modules/plugins/virt/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/snmptrapd/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/script/src/main/java"/>
- <classpathentry kind="src" path="modules/plugins/augeas/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/antlr-config/src/main/antlr3"/>
<classpathentry kind="src" path="modules/plugins/antlr-config/target/generated-sources/antlr3"/>
<classpathentry kind="src" path="modules/helpers/rtfilter/src/main/java"/>
<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/plugins/augeas/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/augeas/src/test/java"/>
<classpathentry kind="src" path="etc/samples/skeleton-plugin/src/main/java"/>
<classpathentry kind="src" path="etc/agentspawn/src/main/java"/>
<classpathentry excluding="**" kind="src" path="modules/enterprise/comm/src/test/resources"/>
diff --git a/modules/core/client-api/src/main/resources/rhq-configuration.xsd b/modules/core/client-api/src/main/resources/rhq-configuration.xsd
index 20c74e3..d173134 100644
--- a/modules/core/client-api/src/main/resources/rhq-configuration.xsd
+++ b/modules/core/client-api/src/main/resources/rhq-configuration.xsd
@@ -142,7 +142,7 @@
<xs:restriction base="xs:string">
<xs:whiteSpace value="collapse"/>
<xs:minLength value="1"/>
- <xs:maxLength value="100"/>
+ <xs:maxLength value="255"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
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 a31c8e6..4a218ba 100644
--- a/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml
+++ b/modules/core/dbutils/src/main/scripts/dbsetup/config-schema.xml
@@ -23,7 +23,7 @@
<table name="RHQ_CONFIG_PROP_DEF">
<column name="ID" type="INTEGER" required="true" default="sequence-only" initial="10001" primarykey="true"/>
- <column name="NAME" type="VARCHAR2" required="false" size="100"/>
+ <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="DEFAULT_VALUE" type="VARCHAR2" required="false" size="2000"/>
@@ -78,7 +78,7 @@
<column name="CONFIGURATION_ID" type="INTEGER" required="false" references="RHQ_CONFIG" ondelete="cascade"/>
<column name="STRING_VALUE" type="VARCHAR2" required="false" size="2000"/>
<column name="OVERRIDE" type="BOOLEAN" required="false"/>
- <column name="NAME" type="VARCHAR2" required="true" size="100"/>
+ <column name="NAME" type="VARCHAR2" required="true" size="255"/>
<column name="DTYPE" type="VARCHAR2" required="true" size="10"/>
<!-- Recursive cascade path to RHQ_CONFIG_PROPERTY causes constraint creation errors on SQL Server, see
http://support.microsoft.com/kb/321843 -->
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 02864f1..1737386 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -1499,7 +1499,6 @@
<schema-addColumn table="RHQ_ALERT_DEFINITION" column="RESOURCE_GROUP_ID" columnType="INTEGER" />
<schema-addColumn table="RHQ_ALERT_DEFINITION" column="GROUP_ALERT_DEF_ID" columnType="INTEGER" />
</schemaSpec>
-
<schemaSpec version="2.59">
<schema-directSQL>
<statement desc="Creating table RHQ_RAW_CONFIG">
@@ -1569,7 +1568,6 @@
columnType="VARCHAR2"
precision="16"/>
</schemaSpec>
-
<schemaSpec version="2.59.2">
<schema-directSQL>
<!-- RHN_CHANNEL => RHQ_REPO -->
@@ -2029,11 +2027,22 @@
</schema-directSQL>
</schemaSpec>
+ <schemaSpec version="2.62">
+ <schema-alterColumn
+ table="RHQ_CONFIG_PROP_DEF"
+ column="NAME"
+ columnType="VARCHAR2"
+ precision="255" />
+ <schema-alterColumn
+ table="RHQ_CONFIG_PROPERTY"
+ column="NAME"
+ columnType="VARCHAR2"
+ precision="255" />
+ </schemaSpec>
<schemaSpec version="2.62.1">
<schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
<schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
</schemaSpec>
-
</dbupgrade>
</target>
</project>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
index 3fab412..3ce2965 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
@@ -577,19 +577,21 @@ public class Configuration implements Externalizable, Cloneable, AbstractPropert
public String toString(boolean verbose) {
StringBuilder builder = new StringBuilder("Configuration[id=").append(this.id);
- if (this.notes != null)
+ if (this.notes != null) {
builder.append(", notes=").append(this.notes);
+ }
if (verbose) {
- builder.append("properties[");
+ builder.append(", properties[");
for (Property property : this.getMap().values()) {
builder.append(", ");
builder.append(property.getName());
builder.append("=");
- if (property instanceof PropertySimple)
+ if (property instanceof PropertySimple) {
builder.append(((PropertySimple) property).getStringValue());
- else
+ } else {
builder.append(property);
+ }
}
builder.append("], rawConfigurations[");
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 0508fc8..1244ecc 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
@@ -35,6 +35,7 @@ import java.util.Map;
import java.util.Set;
import java.util.Stack;
+import org.rhq.core.clientapi.agent.PluginContainerException;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.discovery.AvailabilityReport;
@@ -344,7 +345,12 @@ public class StandaloneContainer {
case WAIT:
Thread.sleep(Integer.valueOf(tokens[1]));
break;
-
+ case P_CONFIG:
+ showPluginConfig();
+ break;
+ case R_CONFIG:
+ showResourceConfig();
+ break;
}
return false;
@@ -659,6 +665,30 @@ public class StandaloneContainer {
return config;
}
+ private void showPluginConfig() {
+ if (resourceId == 0) {
+ System.err.println("You must first set the resource to work with.");
+ return;
+ }
+
+ Configuration config = pc.getInventoryManager().getResourceContainer(resourceId).getResource().getPluginConfiguration();
+ showConfig(config);
+ }
+
+ private void showResourceConfig() throws PluginContainerException {
+ if (resourceId == 0) {
+ System.err.println("You must first set the resource to work with.");
+ return;
+ }
+
+ Configuration config = pc.getConfigurationManager().loadResourceConfiguration(resourceId);
+ showConfig(config);
+ }
+
+ private void showConfig(Configuration config) {
+ System.out.println(config.getProperties());
+ }
+
/**
* List of possible commands
*/
@@ -679,8 +709,10 @@ public class StandaloneContainer {
RESOURCES("res", "", 0, "Shows the discovere resources"), //
SET("set", "resourceId n", 2,
"Sets the resource id to work with. N can be a number or '$r' as result of last find resource call"), //
- WAIT("w", "milliseconds", 1, "Waits the given amount of time");
-
+ WAIT("w", "milliseconds", 1, "Waits the given amount of time"),
+ P_CONFIG("pc", "", 0, "Shows the plugin configuration of the current resource."),
+ R_CONFIG("rc", "", 0, "Shows the resource configuration of the current resource.");
+
private String abbrev;
private String args;
private String help;
diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml
index 0aaf838..6668703 100644
--- a/modules/enterprise/server/ear/pom.xml
+++ b/modules/enterprise/server/ear/pom.xml
@@ -247,6 +247,12 @@
<artifactItem>
<groupId>org.rhq</groupId>
+ <artifactId>rhq-cron-plugin</artifactId>
+ <version>${project.version}</version>
+ </artifactItem>
+
+ <artifactItem>
+ <groupId>org.rhq</groupId>
<artifactId>rhq-database-plugin</artifactId>
<version>${project.version}</version>
</artifactItem>
@@ -326,6 +332,12 @@
<artifactItem>
<groupId>org.rhq</groupId>
+ <artifactId>rhq-samba-plugin</artifactId>
+ <version>${project.version}</version>
+ </artifactItem>
+
+ <artifactItem>
+ <groupId>org.rhq</groupId>
<artifactId>rhq-script-plugin</artifactId>
<version>${project.version}</version>
</artifactItem>
@@ -341,6 +353,13 @@
<artifactId>rhq-sshd-plugin</artifactId>
<version>${project.version}</version>
</artifactItem>
+
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-sudoers-plugin</artifactId>
+ <version>${project.version}</version>
+ </artifactItem>
+
<!-- TODO: Uncomment once errors in virt plugin have been fixed.
<artifactItem>
<groupId>org.rhq</groupId>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java
index 16bf6cb..152f3fc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/discovery/DiscoveryBossBean.java
@@ -272,7 +272,7 @@ public class DiscoveryBossBean implements DiscoveryBossLocal, DiscoveryBossRemot
}
/**
- * Updates statuses according to the inventory rules This is used internally. Never call this yourself without
+ * Updates statuses according to the inventory rules. This is used internally - never call this yourself without
* knowing what you do. See {@link #updateInventoryStatus(Subject, List, List, InventoryStatus)} for the "public"
* version.
*/
diff --git a/modules/plugins/augeas/pom.xml b/modules/plugins/augeas/pom.xml
index a6c5939..28f3cc5 100644
--- a/modules/plugins/augeas/pom.xml
+++ b/modules/plugins/augeas/pom.xml
@@ -74,6 +74,18 @@
</execution>
</executions>
</plugin>
+
+ <plugin>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
</plugins>
</build>
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
index 3ef73bd..a541f25 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
@@ -20,6 +20,7 @@ package org.rhq.plugins.augeas;
import java.io.File;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
@@ -32,6 +33,7 @@ import net.augeas.jna.Aug;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.rhq.core.domain.configuration.AbstractPropertyMap;
@@ -48,57 +50,66 @@ import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
import org.rhq.core.domain.configuration.definition.PropertySimpleType;
import org.rhq.core.domain.measurement.AvailabilityType;
+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.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
import org.rhq.core.pluginapi.inventory.ResourceContext;
import org.rhq.plugins.augeas.helper.AugeasNode;
-import org.rhq.plugins.platform.PlatformComponent;
+import org.rhq.plugins.augeas.helper.Glob;
/**
* @author Ian Springer
+ * @author Lukas Krejci
*/
-public class AugeasConfigurationComponent implements ResourceComponent<PlatformComponent>, ConfigurationFacet {
- public static final String CONFIGURATION_FILE_PROP = "configurationFile";
+public class AugeasConfigurationComponent<T extends ResourceComponent> implements ResourceComponent<T>,
+ ConfigurationFacet, CreateChildResourceFacet, DeleteResourceFacet {
+ public static final String INCLUDE_GLOBS_PROP = "configurationFilesInclusionPatterns";
+ public static final String EXCLUDE_GLOBS_PROP = "configurationFilesExclusionPatterns";
public static final String RESOURCE_CONFIGURATION_ROOT_NODE_PROP = "resourceConfigurationRootNode";
public static final String AUGEAS_MODULE_NAME_PROP = "augeasModuleName";
+ public static final String AUGEAS_ROOT_PATH_PROP = "augeasRootPath";
+
+ public static final String DEFAULT_AUGEAS_ROOT_PATH = "/";
private static final boolean IS_WINDOWS = (File.separatorChar == '\\');
- private static final String AUGEAS_LOAD_PATH = "/usr/local/share/augeas/lenses";
- private static final String AUGEAS_ROOT_PATH = "/";
+ private static final String AUGEAS_LOAD_PATH = "/usr/share/augeas/lenses";
private final Log log = LogFactory.getLog(this.getClass());
- private ResourceContext resourceContext;
- private File configFile;
+ private ResourceContext<T> resourceContext;
+ private List<String> includeGlobs;
+ private List<String> excludeGlobs;
private Augeas augeas;
- private AugeasNode augeasConfigFileMetadataNode;
private AugeasNode resourceConfigRootNode;
+ private String augeasRootPath;
- public void start(ResourceContext<PlatformComponent> resourceContext) throws InvalidPluginConfigurationException,
- Exception {
+ public void start(ResourceContext<T> resourceContext) throws InvalidPluginConfigurationException, Exception {
this.resourceContext = resourceContext;
Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
- String configFilePath = pluginConfig.getSimple(CONFIGURATION_FILE_PROP).getStringValue();
- this.configFile = new File(configFilePath);
+
+ this.augeasRootPath = pluginConfig.getSimpleValue(AUGEAS_ROOT_PATH_PROP, DEFAULT_AUGEAS_ROOT_PATH);
+ log.debug("Augeas Root Path = \"" + this.augeasRootPath + "\"");
+
+ initGlobs(pluginConfig);
+
this.augeas = createAugeas();
+
if (this.augeas != null) {
- AugeasNode augeasConfigFileNode = new AugeasNode("/files" + AugeasNode.SEPARATOR_CHAR + this.configFile.getPath());
- // This is the metadata portion of the tree for this config file (e.g. /augeas/files/etc/hosts, where error
- // messages are stored as node values.
- this.augeasConfigFileMetadataNode = new AugeasNode("/augeas/files" + AugeasNode.SEPARATOR_CHAR
- + this.configFile.getPath());
- String resourceConfigRootNodePath = pluginConfig.getSimpleValue(RESOURCE_CONFIGURATION_ROOT_NODE_PROP, null);
- if (resourceConfigRootNodePath != null) {
- if (resourceConfigRootNodePath.indexOf(AugeasNode.SEPARATOR_CHAR) == 0) {
- this.resourceConfigRootNode = new AugeasNode(resourceConfigRootNodePath);
- } else {
- this.resourceConfigRootNode = new AugeasNode(augeasConfigFileNode, resourceConfigRootNodePath);
- }
+ String resourceConfigRootPath = getResourceConfigurationRootPath();
+ if (resourceConfigRootPath.indexOf(AugeasNode.SEPARATOR_CHAR) != 0) {
+ // root path is relative - make it absolute
+ this.resourceConfigRootNode = new AugeasNode("/files/", resourceConfigRootPath);
} else {
- this.resourceConfigRootNode = augeasConfigFileNode;
+ // root path is already absolute
+ this.resourceConfigRootNode = new AugeasNode(resourceConfigRootPath);
}
+
}
}
@@ -107,24 +118,15 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
}
public AvailabilityType getAvailability() {
- if (!this.configFile.isAbsolute()) {
- throw new InvalidPluginConfigurationException("Location specified by '" + CONFIGURATION_FILE_PROP
- + "' connection property is not an absolute path.");
- }
- if (!this.configFile.exists()) {
- throw new InvalidPluginConfigurationException("Location specified by '" + CONFIGURATION_FILE_PROP
- + "' connection property does not exist.");
- }
- if (this.configFile.isDirectory()) {
- throw new InvalidPluginConfigurationException("Location specified by '" + CONFIGURATION_FILE_PROP
- + "' connection property is a directory, not a regular file.");
+ for (File f : getConfigurationFiles()) {
+ singleFileAvailabilityCheck(f);
}
- return this.configFile.exists() ? AvailabilityType.UP : AvailabilityType.DOWN;
+ return AvailabilityType.UP;
}
public Configuration loadResourceConfiguration() throws Exception {
// Load the config file from disk and build a tree representation of it.
- this.augeas.load();
+ loadConfigurationFiles(this.augeas);
ConfigurationDefinition resourceConfigDef = this.resourceContext.getResourceType()
.getResourceConfigurationDefinition();
@@ -142,28 +144,15 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
public void updateResourceConfiguration(ConfigurationUpdateReport report) {
if (!validateResourceConfiguration(report)) {
- log.debug("Validation of updated Resource configuration for "
- + this.getResourceContext().getResourceType() + " Resource with key '"
- + this.getResourceContext().getResourceKey() + "' failed with the following errors: "
- + report.getErrorMessage());
+ log.debug("Validation of updated Resource configuration for " + this.getResourceContext().getResourceType()
+ + " Resource with key '" + this.getResourceContext().getResourceKey()
+ + "' failed with the following errors: " + report.getErrorMessage());
report.setStatus(ConfigurationUpdateStatus.FAILURE);
return;
}
- if (!this.configFile.canWrite()) {
- report.setErrorMessage("Configuration file '" + this.configFile + "' is not writable.");
- return;
- }
-
- File configFileParentDir = this.configFile.getParentFile();
- if (!configFileParentDir.canWrite()) {
- report.setErrorMessage("Configuration file parent directory '" + configFileParentDir
- + "' is not writable.");
- return;
- }
-
- // Load the config file from disk and build a tree representation of it in memory.
- this.augeas.load();
+ // Load the config files from disk and build a tree representation of them in memory.
+ loadConfigurationFiles(this.augeas);
ConfigurationDefinition resourceConfigDef = this.resourceContext.getResourceType()
.getResourceConfigurationDefinition();
@@ -175,12 +164,50 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
}
// Write the updated tree out to the config file.
- saveConfigurationFile();
+ saveConfigurationFiles();
// If we got this far, we've succeeded in our mission.
report.setStatus(ConfigurationUpdateStatus.SUCCESS);
}
+ public CreateResourceReport createResource(CreateResourceReport report) {
+ Configuration resourceConfig = report.getResourceConfiguration();
+ ConfigurationDefinition resourceConfigDef = report.getResourceType().getResourceConfigurationDefinition();
+
+ // First insert the root node corresponding to the new child Resource.
+ String rootPath = getChildResourceConfigurationRootPath(report.getResourceType(), report
+ .getResourceConfiguration());
+ AugeasNode rootNode = new AugeasNode(rootPath);
+ if (this.augeas.exists(rootNode.getPath())) {
+ report.setStatus(CreateResourceStatus.FAILURE);
+ report.setErrorMessage("An Augeas node already exists with path " + rootPath);
+ return report;
+ }
+ String rootLabel = getChildResourceConfigurationRootLabel(report.getResourceType(), report
+ .getResourceConfiguration());
+ this.augeas.set(rootNode.getPath(), rootLabel);
+
+ // Then set all its child nodes.
+ Collection<PropertyDefinition> propDefs = resourceConfigDef.getPropertyDefinitions().values();
+ for (PropertyDefinition propDef : propDefs) {
+ setNode(propDef, resourceConfig, this.augeas, rootNode);
+ }
+
+ // Write the updated tree out to the config file.
+ saveConfigurationFiles();
+
+ // If we got this far, we've succeeded in our mission.
+ report.setStatus(CreateResourceStatus.SUCCESS);
+ return report;
+ }
+
+ public void deleteResource() throws Exception {
+ String rootPath = getResourceConfigurationRootPath();
+ Augeas augeas = getAugeas();
+ augeas.remove(rootPath);
+ augeas.save();
+ }
+
/**
* Subclasses should override this method in order to perform any validation that is not encapsulated
* in the Configuration metadata.
@@ -205,12 +232,54 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
}
}
- public ResourceContext getResourceContext() {
+ @NotNull
+ protected String getResourceConfigurationRootPath() {
+ Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
+ String rootPath = pluginConfig.getSimpleValue(RESOURCE_CONFIGURATION_ROOT_NODE_PROP, null);
+ if (rootPath == null) {
+ String includeGlobs = pluginConfig.getSimple(INCLUDE_GLOBS_PROP).getStringValue();
+ if (includeGlobs.indexOf('|') != -1) {
+ throw new IllegalStateException("Unable to determine resource configuration root Augeas path.");
+ }
+ rootPath = "/files" + includeGlobs;
+ }
+ return rootPath;
+ }
+
+ /**
+ * Subclasses that wish to support child Resource creation must override this method.
+ *
+ * @param resourceType the type of child Resource being created
+ * @param resourceConfig the Resource configuration for the child Resource being created
+ *
+ * @return the path of the Augeas node that should be created for the child Resource being created
+ */
+ protected String getChildResourceConfigurationRootPath(ResourceType resourceType, Configuration resourceConfig) {
+ throw new IllegalStateException("Class " + getClass().getName()
+ + " does not override getChildResourceConfigurationRootPath() for " + resourceType + ".");
+ }
+
+ /**
+ * Subclasses that wish to support child Resource creation must override this method.
+ *
+ * @param resourceType the type of child Resource being created
+ * @param resourceConfig the Resource configuration for the child Resource being created
+ *
+ * @return the value of the Augeas node that should be created for the child Resource being created
+ */
+ protected String getChildResourceConfigurationRootLabel(ResourceType resourceType, Configuration resourceConfig) {
+ throw new IllegalStateException("Class " + getClass().getName()
+ + " does not override getChildResourceConfigurationRootLabel() for " + resourceType + ".");
+ }
+
+ public ResourceContext<T> getResourceContext() {
return resourceContext;
}
- public File getConfigurationFile() {
- return this.configFile;
+ public List<File> getConfigurationFiles() {
+ List<File> files = Glob.matchAll(new File(this.augeasRootPath), includeGlobs);
+ Glob.excludeAll(files, excludeGlobs);
+ return files;
}
public Augeas getAugeas() {
@@ -230,9 +299,18 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
Augeas augeas;
try {
- augeas = new Augeas(AUGEAS_ROOT_PATH, AUGEAS_LOAD_PATH, Augeas.NO_MODL_AUTOLOAD);
+ augeas = new Augeas(this.augeasRootPath, AUGEAS_LOAD_PATH, Augeas.NO_MODL_AUTOLOAD);
augeas.set("/augeas/load/" + augeasModuleName + "/lens", augeasModuleName + ".lns");
- augeas.set("/augeas/load/" + augeasModuleName + "/incl", this.configFile.getPath());
+
+ int idx = 1;
+ for (String incl : this.includeGlobs) {
+ augeas.set("/augeas/load/" + augeasModuleName + "/incl[" + (idx++) + "]", incl);
+ }
+ idx = 1;
+ for (String excl : this.excludeGlobs) {
+ augeas.set("/augeas/load/" + augeasModuleName + "/excl[" + (idx++) + "]", excl);
+ }
+ loadConfigurationFiles(augeas);
} catch (RuntimeException e) {
augeas = null;
log.warn("Failed to initialize Augeas Java API.", e);
@@ -256,9 +334,13 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
return true;
}
- private void loadProperty(PropertyDefinition propDef, AbstractPropertyMap parentPropMap, Augeas augeas,
+ protected String getAugeasPathRelativeToParent(PropertyDefinition propDef, AugeasNode parentNode, Augeas augeas) {
+ return propDef.getName();
+ }
+
+ protected void loadProperty(PropertyDefinition propDef, AbstractPropertyMap parentPropMap, Augeas augeas,
AugeasNode parentNode) {
- String propName = propDef.getName();
+ String propName = getAugeasPathRelativeToParent(propDef, parentNode, augeas);
AugeasNode node = (propName.equals(".")) ? parentNode : new AugeasNode(parentNode, propName);
Property prop;
if (propDef instanceof PropertyDefinitionSimple) {
@@ -270,11 +352,17 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
} else {
throw new IllegalStateException("Unsupported PropertyDefinition subclass: " + propDef.getClass().getName());
}
- parentPropMap.put(prop);
+ if (prop != null) {
+ parentPropMap.put(prop);
+ }
+ }
+
+ protected Object toPropertyValue(PropertyDefinitionSimple propDefSimple, Augeas augeas, AugeasNode node) {
+ return augeas.get(node.getPath());
}
- private Property createPropertySimple(PropertyDefinitionSimple propDefSimple, Augeas augeas, AugeasNode node) {
- String value;
+ protected Property createPropertySimple(PropertyDefinitionSimple propDefSimple, Augeas augeas, AugeasNode node) {
+ Object value;
if (propDefSimple.getType() == PropertySimpleType.LONG_STRING) {
List<String> childPaths = augeas.match(node.getPath());
if (childPaths.isEmpty()) {
@@ -289,18 +377,18 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
propValue.deleteCharAt(propValue.length() - 1);
value = propValue.toString();
} else {
- value = augeas.get(node.getPath());
+ value = toPropertyValue(propDefSimple, augeas, node);
}
return new PropertySimple(propDefSimple.getName(), value);
}
- private PropertyMap createPropertyMap(PropertyDefinitionMap propDefMap, Augeas augeas, AugeasNode node) {
+ protected PropertyMap createPropertyMap(PropertyDefinitionMap propDefMap, Augeas augeas, AugeasNode node) {
PropertyMap propMap = new PropertyMap(propDefMap.getName());
populatePropertyMap(propDefMap, propMap, augeas, node);
return propMap;
}
- private Property createPropertyList(PropertyDefinitionList propDefList, Augeas augeas, AugeasNode node) {
+ protected Property createPropertyList(PropertyDefinitionList propDefList, Augeas augeas, AugeasNode node) {
PropertyDefinition listMemberPropDef = propDefList.getMemberDefinition();
if (!(listMemberPropDef instanceof PropertyDefinitionMap)) {
throw new IllegalArgumentException(
@@ -311,7 +399,8 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
PropertyList propList = new PropertyList(propDefList.getName());
String mapKey = getListMemberMapKey(propDefList);
- String listMemberPathsExpression = node.getPath() + AugeasNode.SEPARATOR_CHAR + listMemberPropDefMap.getName();
+ String mapPath = getAugeasPathRelativeToParent(listMemberPropDefMap, node, augeas);
+ String listMemberPathsExpression = node.getPath() + AugeasNode.SEPARATOR_CHAR + mapPath;
List<String> listMemberPaths = augeas.match(listMemberPathsExpression);
for (String listMemberPath : listMemberPaths) {
AugeasNode listMemberNode = new AugeasNode(listMemberPath);
@@ -331,16 +420,16 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
return propList;
}
- private void populatePropertyMap(PropertyDefinitionMap propDefMap, PropertyMap propMap, Augeas augeas,
+ protected void populatePropertyMap(PropertyDefinitionMap propDefMap, PropertyMap propMap, Augeas augeas,
AugeasNode mapNode) {
for (PropertyDefinition mapEntryPropDef : propDefMap.getPropertyDefinitions().values()) {
loadProperty(mapEntryPropDef, propMap, augeas, mapNode);
}
}
- private void setNode(PropertyDefinition propDef, AbstractPropertyMap parentPropMap, Augeas augeas,
+ protected void setNode(PropertyDefinition propDef, AbstractPropertyMap parentPropMap, Augeas augeas,
AugeasNode parentNode) {
- String propName = propDef.getName();
+ String propName = getAugeasPathRelativeToParent(propDef, parentNode, augeas);
AugeasNode node = (propName.equals(".")) ? parentNode : new AugeasNode(parentNode, propName);
if (isPropertyDefined(propDef, parentPropMap)) {
@@ -368,9 +457,14 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
}
}
- private void setNodeFromPropertySimple(Augeas augeas, AugeasNode node, PropertyDefinitionSimple propDefSimple,
+ protected String toNodeValue(Augeas augeas, AugeasNode node, PropertyDefinitionSimple propDefSimple,
+ PropertySimple propSimple) {
+ return propSimple.getStringValue();
+ }
+
+ protected void setNodeFromPropertySimple(Augeas augeas, AugeasNode node, PropertyDefinitionSimple propDefSimple,
PropertySimple propSimple) {
- String value = propSimple.getStringValue();
+ String value = toNodeValue(augeas, node, propDefSimple, propSimple);
if (propDefSimple.getType() == PropertySimpleType.LONG_STRING) {
// First remove the existing items.
List<String> childPaths = augeas.match(node.getPath());
@@ -391,16 +485,17 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
}
}
- private void setNodeFromPropertyMap(PropertyDefinitionMap propDefMap, PropertyMap propMap, Augeas augeas,
+ protected void setNodeFromPropertyMap(PropertyDefinitionMap propDefMap, PropertyMap propMap, Augeas augeas,
AugeasNode mapNode) {
for (PropertyDefinition mapEntryPropDef : propDefMap.getPropertyDefinitions().values()) {
setNode(mapEntryPropDef, propMap, augeas, mapNode);
}
}
- private void setNodeFromPropertyList(PropertyDefinitionList propDefList, PropertyList propList, Augeas augeas,
+ protected void setNodeFromPropertyList(PropertyDefinitionList propDefList, PropertyList propList, Augeas augeas,
AugeasNode listNode) {
PropertyDefinition listMemberPropDef = propDefList.getMemberDefinition();
+
if (!(listMemberPropDef instanceof PropertyDefinitionMap)) {
throw new IllegalArgumentException(
"Invalid Resource ConfigurationDefinition - only lists of maps are supported.");
@@ -408,8 +503,9 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
PropertyDefinitionMap listMemberPropDefMap = (PropertyDefinitionMap) listMemberPropDef;
int listIndex = 0;
+ String listMemberPropDefMapPath = getAugeasPathRelativeToParent(listMemberPropDefMap, listNode, augeas);
List<String> existingListMemberPaths = augeas.match(listNode.getPath() + AugeasNode.SEPARATOR_CHAR
- + listMemberPropDefMap.getName());
+ + listMemberPropDefMapPath);
List<AugeasNode> existingListMemberNodes = new ArrayList<AugeasNode>();
for (String existingListMemberPath : existingListMemberPaths) {
existingListMemberNodes.add(new AugeasNode(existingListMemberPath));
@@ -426,7 +522,11 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
} else {
// The maps in the list are non-keyed, or there is no map in the list with the same key as the map
// being added, so create a new node for the map to add to the list.
- memberNodeToUpdate = new AugeasNode(listNode, "0" + (listIndex++));
+ AugeasNode basePathNode = getNewListMemberNode(listNode, listMemberPropDefMap, listIndex);
+ String var = "prop" + listIndex;
+ augeas.defineNode(var, basePathNode.getPath(), null);
+ memberNodeToUpdate = new AugeasNode("$" + var);
+ listIndex++;
}
// Update the node's children.
@@ -441,6 +541,12 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
}
}
+ protected AugeasNode getNewListMemberNode(AugeasNode listNode, PropertyDefinitionMap listMemberPropDefMap,
+ int listIndex) {
+ return new AugeasNode(listNode, getAugeasPathRelativeToParent(listMemberPropDefMap, listNode, getAugeas())
+ + "[" + listIndex + "]");
+ }
+
private boolean isPropertyDefined(PropertyDefinition propDef, AbstractPropertyMap parentPropMap) {
Property prop = parentPropMap.get(propDef.getName());
if (prop == null) {
@@ -468,23 +574,66 @@ public class AugeasConfigurationComponent implements ResourceComponent<PlatformC
return mapKeyNames.getSimpleValue(listName, null);
}
- private void saveConfigurationFile() {
+ private void loadConfigurationFiles(Augeas augeas) {
+ try {
+ augeas.load();
+ } catch (AugeasException e) {
+ throw new RuntimeException(summarizeAugeasError(augeas), e);
+ }
+ }
+
+ private void saveConfigurationFiles() {
// TODO: Backup original file.
try {
this.augeas.save();
} catch (AugeasException e) {
- StringBuilder buffer = new StringBuilder("Failed to save " + this.configFile + ".");
- AugeasNode errorNode = new AugeasNode(this.augeasConfigFileMetadataNode, "error");
- String error = this.augeas.get(errorNode.getPath());
- if (error != null) {
- buffer.append(" Cause: ").append(error);
- AugeasNode errorMessageNode = new AugeasNode(errorNode, "message");
- String errorMessage = this.augeas.get(errorMessageNode.getPath());
- if (errorMessage != null) {
- buffer.append(": ").append(errorMessage);
- }
+ throw new RuntimeException(summarizeAugeasError(this.augeas), e);
+ }
+ }
+
+ private void initGlobs(Configuration pluginConfiguration) {
+ PropertySimple includes = pluginConfiguration.getSimple(INCLUDE_GLOBS_PROP);
+ PropertySimple excludes = pluginConfiguration.getSimple(EXCLUDE_GLOBS_PROP);
+
+ includeGlobs = new ArrayList<String>();
+ excludeGlobs = new ArrayList<String>();
+
+ includeGlobs.addAll(Arrays.asList(includes.getStringValue().split("\\s*\\|\\s*")));
+ if (excludes != null && excludes.getStringValue() != null) {
+ excludeGlobs.addAll(Arrays.asList(excludes.getStringValue().split("\\s*\\|\\s*")));
+ }
+ }
+
+ private void singleFileAvailabilityCheck(File f) {
+ if (!f.isAbsolute()) {
+ throw new InvalidPluginConfigurationException("Path '" + f.getPath() + "' is not an absolute path.");
+ }
+ if (!f.exists()) {
+ throw new InvalidPluginConfigurationException("File '" + f.getPath() + "' does not exist.");
+ }
+ if (f.isDirectory()) {
+ throw new InvalidPluginConfigurationException("Path '" + f.getPath()
+ + "' is a directory, not a regular file.");
+ }
+ }
+
+ protected String summarizeAugeasError(Augeas augeas) {
+ StringBuilder summary = new StringBuilder();
+ String metadataNodePrefix = "/augeas/files";
+ for (String glob : this.includeGlobs) {
+ if (glob.startsWith(AugeasNode.SEPARATOR)) {
+ glob = glob.substring(1);
+ }
+ AugeasNode metadataNode = new AugeasNode(metadataNodePrefix, glob);
+ AugeasNode errorNode = new AugeasNode(metadataNode, "error");
+ List<String> nodePaths = augeas.match(errorNode.getPath() + "/*");
+ for (String path : nodePaths) {
+ String error = augeas.get(path);
+ summary.append("File \"").append(path.substring(metadataNodePrefix.length(), path.length())).append(
+ "\":\n").append(error).append("\n");
}
- throw new RuntimeException(buffer.toString(), e);
}
+
+ return summary.toString();
}
}
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
index e0e8afa..8d533a4 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
@@ -19,7 +19,10 @@
package org.rhq.plugins.augeas;
import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
@@ -31,33 +34,34 @@ 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;
+import org.rhq.plugins.augeas.helper.Glob;
/**
* @author Ian Springer
+ * @author Lukas Krejci
*/
-public class AugeasConfigurationDiscoveryComponent implements ResourceDiscoveryComponent, ManualAddFacet {
+public class AugeasConfigurationDiscoveryComponent<T extends ResourceComponent> implements
+ ResourceDiscoveryComponent<T>, ManualAddFacet<T> {
private final Log log = LogFactory.getLog(this.getClass());
- public Set discoverResources(ResourceDiscoveryContext discoveryContext) throws InvalidPluginConfigurationException,
- Exception {
+ public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<T> discoveryContext)
+ throws InvalidPluginConfigurationException, Exception {
Set<DiscoveredResourceDetails> discoveredResources = new HashSet<DiscoveredResourceDetails>(1);
- File configFile = getConfigurationFile(discoveryContext);
- if (!configFile.isAbsolute()) {
- throw new IllegalStateException("getConfigurationFile() returned a non-absolute file.");
- }
- if (!configFile.exists()) {
- throw new IllegalStateException("getConfigurationFile() returned a non-existent file.");
- }
- if (configFile.isDirectory()) {
- throw new IllegalStateException("getConfigurationFile() returned a directory.");
- }
+ List<String> includes = determineIncludeGlobs(discoveryContext);
+ List<String> excludes = determineExcludeGlobs(discoveryContext);
Configuration pluginConfig = discoveryContext.getDefaultPluginConfiguration();
- pluginConfig
- .put(new PropertySimple(AugeasConfigurationComponent.CONFIGURATION_FILE_PROP, configFile.getPath()));
+ PropertySimple includeProps = getGlobList(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP, includes);
+ PropertySimple excludeProps = getGlobList(AugeasConfigurationComponent.EXCLUDE_GLOBS_PROP, excludes);
+ pluginConfig.put(includeProps);
+ pluginConfig.put(excludeProps);
+
+ checkFiles(pluginConfig);
+
DiscoveredResourceDetails resource = createResourceDetails(discoveryContext, pluginConfig);
discoveredResources.add(resource);
log.debug("Discovered " + discoveryContext.getResourceType().getName() + " Resource with key ["
@@ -67,43 +71,118 @@ public class AugeasConfigurationDiscoveryComponent implements ResourceDiscoveryC
}
public DiscoveredResourceDetails discoverResource(Configuration pluginConfig,
- ResourceDiscoveryContext discoveryContext) throws InvalidPluginConfigurationException {
- String configFilePath = pluginConfig.getSimple(AugeasConfigurationComponent.CONFIGURATION_FILE_PROP)
- .getStringValue();
-
- File configFile = new File(configFilePath);
- if (!configFile.isAbsolute()) {
- throw new InvalidPluginConfigurationException("Location specified by '"
- + AugeasConfigurationComponent.CONFIGURATION_FILE_PROP
- + "' connection property is not an absolute path.");
- }
- if (!configFile.exists()) {
- throw new InvalidPluginConfigurationException("Location specified by '"
- + AugeasConfigurationComponent.CONFIGURATION_FILE_PROP + "' connection property does not exist.");
- }
- if (configFile.isDirectory()) {
- throw new InvalidPluginConfigurationException("Location specified by '"
- + AugeasConfigurationComponent.CONFIGURATION_FILE_PROP
- + "' connection property is a directory, not a regular file.");
- }
+ ResourceDiscoveryContext<T> discoveryContext) throws InvalidPluginConfigurationException {
+
+ checkFiles(pluginConfig);
DiscoveredResourceDetails resource = createResourceDetails(discoveryContext, pluginConfig);
return resource;
}
- protected File getConfigurationFile(ResourceDiscoveryContext discoveryContext) {
- Configuration defaultPluginConfig = discoveryContext.getDefaultPluginConfiguration();
- String configFilePath = defaultPluginConfig.getSimple(AugeasConfigurationComponent.CONFIGURATION_FILE_PROP)
- .getStringValue();
- return new File(configFilePath);
- }
-
- protected DiscoveredResourceDetails createResourceDetails(ResourceDiscoveryContext discoveryContext,
+ protected DiscoveredResourceDetails createResourceDetails(ResourceDiscoveryContext<T> discoveryContext,
Configuration pluginConfig) {
ResourceType resourceType = discoveryContext.getResourceType();
- String resourceKey = getConfigurationFile(discoveryContext).getPath();
+ String resourceKey = composeResourceKey(pluginConfig);
DiscoveredResourceDetails resource = new DiscoveredResourceDetails(resourceType, resourceKey, resourceType
.getName(), null, resourceType.getDescription(), pluginConfig, null);
return resource;
}
+
+ protected List<String> determineIncludeGlobs(ResourceDiscoveryContext<T> discoveryContext) {
+ Configuration pluginConfiguration = discoveryContext.getDefaultPluginConfiguration();
+ PropertySimple includeGlobsProp = pluginConfiguration
+ .getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP);
+
+ List<String> ret = getGlobList(includeGlobsProp);
+ if (ret == null || ret.size() == 0) {
+ throw new IllegalStateException("Expecting at least once inclusion pattern for configuration files.");
+ }
+
+ return ret;
+ }
+
+ protected List<String> determineExcludeGlobs(ResourceDiscoveryContext<T> discoveryContext) {
+ Configuration pluginConfiguration = discoveryContext.getDefaultPluginConfiguration();
+ PropertySimple excludeGlobsProp = pluginConfiguration
+ .getSimple(AugeasConfigurationComponent.EXCLUDE_GLOBS_PROP);
+
+ List<String> ret = getGlobList(excludeGlobsProp);
+
+ return ret;
+ }
+
+ private void checkFiles(Configuration pluginConfiguration) {
+ PropertySimple includeGlobsProp = pluginConfiguration
+ .getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP);
+ PropertySimple excludeGlobsProp = pluginConfiguration
+ .getSimple(AugeasConfigurationComponent.EXCLUDE_GLOBS_PROP);
+
+ String augeasRootPath = pluginConfiguration.getSimpleValue(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP,
+ AugeasConfigurationComponent.DEFAULT_AUGEAS_ROOT_PATH);
+ File root = new File(augeasRootPath);
+
+ List<String> includeGlobs = getGlobList(includeGlobsProp);
+
+ if (includeGlobsProp == null) {
+ throw new IllegalStateException("Expecting at least one inclusion pattern for configuration files.");
+ }
+
+ List<File> files = Glob.matchAll(root, includeGlobs);
+
+ if (excludeGlobsProp != null) {
+ List<String> excludeGlobs = getGlobList(excludeGlobsProp);
+ Glob.excludeAll(files, excludeGlobs);
+ }
+
+ for (File configFile : files) {
+ if (!configFile.isAbsolute()) {
+ throw new IllegalStateException("Configuration files inclusion patterns contain a non-absolute file.");
+ }
+ if (!configFile.exists()) {
+ throw new IllegalStateException("Configuration files inclusion patterns refer to a non-existent file.");
+ }
+ if (configFile.isDirectory()) {
+ throw new IllegalStateException("Configuration files inclusion patterns refer to a directory.");
+ }
+ }
+ }
+
+ private String composeResourceKey(Configuration pluginConfiguration) {
+ PropertySimple includeGlobsProp = pluginConfiguration
+ .getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP);
+ PropertySimple excludeGlobsProp = pluginConfiguration
+ .getSimple(AugeasConfigurationComponent.EXCLUDE_GLOBS_PROP);
+
+ StringBuilder bld = new StringBuilder();
+
+ bld.append(includeGlobsProp.getStringValue());
+
+ if (excludeGlobsProp != null && excludeGlobsProp.getStringValue().length() > 0) {
+ bld.append("---");
+ bld.append(excludeGlobsProp.getStringValue());
+ }
+
+ return bld.toString();
+ }
+
+ public static PropertySimple getGlobList(String name, List<String> simples) {
+ StringBuilder bld = new StringBuilder();
+ if (simples != null) {
+ for (String s : simples) {
+ bld.append(s).append("|");
+ }
+ }
+ if (bld.length() > 0) {
+ bld.deleteCharAt(bld.length() - 1);
+ }
+ return new PropertySimple(name, bld);
+ }
+
+ public static List<String> getGlobList(PropertySimple list) {
+ if (list != null) {
+ return Arrays.asList(list.getStringValue().split("\\s*\\|\\s*"));
+ } else {
+ return Collections.emptyList();
+ }
+ }
}
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/AugeasNode.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/AugeasNode.java
index 6bff878..f3cfc4d 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/AugeasNode.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/AugeasNode.java
@@ -18,7 +18,6 @@
*/
package org.rhq.plugins.augeas.helper;
-
/**
* An abstract representation of a node in an Augeas configuration tree (e.g. /files/etc/hosts/3/canonical).
*
@@ -26,20 +25,55 @@ package org.rhq.plugins.augeas.helper;
*/
public class AugeasNode {
public static final char SEPARATOR_CHAR = '/';
+ public static final char VARIABLE_CHAR = '$';
public static final String SEPARATOR = new String(new char[] { SEPARATOR_CHAR });
private String path;
+ public static String patchNodeName(String name) {
+ //first split by /
+ StringBuilder bld = new StringBuilder();
+ int start = 0;
+ do {
+ int nextSlash = name.indexOf(SEPARATOR, start);
+ int nextOpenBracket = name.indexOf('[', start);
+ int nextCloseBracket = name.indexOf(']', start);
+
+ if (nextSlash > nextCloseBracket) {
+ if (nextOpenBracket == -1) {
+ bld.append(name.substring(start, nextSlash + 1).replaceAll(" ", "\\\\ "));
+ } else {
+ bld.append(name.substring(start, nextOpenBracket).replaceAll(" ", "\\\\ "))
+ .append(name, nextOpenBracket, nextCloseBracket + 1);
+ }
+ } else {
+ if (nextSlash == -1) nextSlash = name.length();
+ if (nextOpenBracket != -1) {
+ bld.append(name.substring(start, nextOpenBracket).replaceAll(" ", "\\\\ "))
+ .append(name, nextOpenBracket, nextCloseBracket + 1);
+ nextSlash = nextCloseBracket;
+ } else {
+ bld.append(name.substring(start).replaceAll(" ", "\\\\ "));
+ }
+ }
+
+ start = nextSlash + 1;
+ } while (start > 0 && start < name.length());
+
+ return bld.toString();
+ }
+
public AugeasNode(String path) {
if (path == null) {
throw new IllegalArgumentException("'path' parameter must not be null.");
}
- if (path.charAt(0) != SEPARATOR_CHAR) {
+ if (path.charAt(0) != SEPARATOR_CHAR && path.charAt(0) != VARIABLE_CHAR) {
throw new IllegalArgumentException("Specified path (" + path + ") is not absolute.");
}
// Remove redundant "." and ".." components and redundant slashes.
- this.path = path;
+ // TODO: This is temporary until augeas-java fixes a bug.
+ this.path = patchNodeName(path);
}
public AugeasNode(AugeasNode parent, String name) {
@@ -49,32 +83,19 @@ public class AugeasNode {
if (name == null) {
throw new IllegalArgumentException("'name' parameter must not be null.");
}
+ /*
if (name.charAt(0) == SEPARATOR_CHAR) {
throw new IllegalArgumentException("Specified path (" + path + ") is not relative.");
- }
+ }*/
- this.path = parent.getPath() + SEPARATOR_CHAR + name;
+ // TODO: This is temporary until augeas-java fixes a bug.
+ this.path = parent.getPath() + SEPARATOR_CHAR + patchNodeName(name);
}
public AugeasNode(String parentPath, String name) {
this(new AugeasNode(parentPath), name);
}
- private AugeasNode(AugeasNode child) {
- String path = child.getPath();
- if (path.equals(SEPARATOR)) {
- // special case - parent of "/" is "/".
- this.path = path;
- } else {
- char lastChar = path.charAt(path.length() - 1);
- if (lastChar == SEPARATOR_CHAR) {
- path = path.substring(0, path.length() - 1);
- }
- int lastSlashIndex = path.lastIndexOf(SEPARATOR_CHAR);
- this.path = path.substring(0, lastSlashIndex);
- }
- }
-
public String getName() {
int lastSlashIndex = this.path.lastIndexOf(SEPARATOR_CHAR);
return (lastSlashIndex == 0) ? this.path : this.path.substring(lastSlashIndex + 1);
@@ -85,7 +106,12 @@ public class AugeasNode {
}
public AugeasNode getParent() {
- return new AugeasNode(this);
+ String parentPath = getParentPath();
+ if (parentPath.indexOf(SEPARATOR_CHAR) == -1 && parentPath.startsWith(AugeasVariable.VARIABLE_NAME_PREFIX)) {
+ return new AugeasVariable(parentPath.substring(AugeasVariable.VARIABLE_NAME_PREFIX.length()));
+ } else {
+ return new AugeasNode(parentPath);
+ }
}
@Override
@@ -112,4 +138,19 @@ public class AugeasNode {
public String toString() {
return this.path;
}
+
+ protected String getParentPath() {
+ String path = getPath();
+ if (path.equals(SEPARATOR)) {
+ // special case - parent of "/" is "/".
+ return path;
+ } else {
+ char lastChar = path.charAt(path.length() - 1);
+ if (lastChar == SEPARATOR_CHAR) {
+ path = path.substring(0, path.length() - 1);
+ }
+ int lastSlashIndex = path.lastIndexOf(SEPARATOR_CHAR);
+ return path.substring(0, lastSlashIndex);
+ }
+ }
}
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/AugeasVariable.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/AugeasVariable.java
new file mode 100644
index 0000000..e25e128
--- /dev/null
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/AugeasVariable.java
@@ -0,0 +1,41 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.augeas.helper;
+
+/**
+ * A specialization of {@link AugeasNode} that represents an Augeas variable.
+ *
+ * @author Lukas Krejci
+ */
+public class AugeasVariable extends AugeasNode {
+
+ public static final String VARIABLE_NAME_PREFIX = "$";
+
+ /**
+ * @param path
+ */
+ public AugeasVariable(String name) {
+ super(VARIABLE_NAME_PREFIX + name);
+ }
+}
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java
new file mode 100644
index 0000000..0a2fc52
--- /dev/null
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/Glob.java
@@ -0,0 +1,138 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.augeas.helper;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A helper class for easy work with glob patterns.
+ *
+ * @author Lukas Krejci
+ */
+public class Glob {
+
+ private Glob() {
+
+ }
+
+ public static boolean isWildcard(String globPattern) {
+ for(char specialChar : GlobFilter.WILDCARD_CHARS) {
+ if (globPattern.indexOf(specialChar) >= 0) return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns a fixed size list of matches.
+ *
+ * The parent path specifies the "root" from which the glob pattern applies.
+ * The glob pattern can span several directories with wildcards present only
+ * on the lowest level.
+ * The glob pattern is always relative to the specified parent path, even if it denotes
+ * an absolute path. In that case, the leading root path is chopped off and the rest is
+ * appended to the parent path.
+ *
+ * @param parentPath the parent path to start the pattern search
+ * @param globPattern the glob pattern to match against
+ * @return the list of matches
+ */
+ public static List<File> match(File parentPath, String globPattern) {
+ String rootPortion = rootPortion(globPattern);
+ globPattern = globPattern.substring(rootPortion.length());
+
+ //now search for the first special character in the patterns
+ int specialCharIdx = globPattern.length();
+ for(char specialChar : GlobFilter.WILDCARD_CHARS) {
+ int idx = globPattern.indexOf(specialChar);
+ if (idx >= 0 && specialCharIdx > idx) {
+ specialCharIdx = idx;
+ }
+ }
+
+ if (specialCharIdx > 0) {
+ //now search for the first path separator preceeding the special char
+ int globParentIdx = globPattern.lastIndexOf(File.separatorChar, specialCharIdx);
+ if (globParentIdx > 0) {
+ //move the parent path down to the nearest parent of the wildcard part of the
+ //glob pattern
+ parentPath = new File(parentPath, globPattern.substring(0, globParentIdx));
+ globPattern = parentPath.getAbsolutePath() + globPattern.substring(globParentIdx);
+ } else {
+ globPattern = parentPath.getAbsolutePath() + globPattern;
+ }
+ } else {
+ globPattern = parentPath.getAbsolutePath() + globPattern;
+ }
+
+ return Arrays.asList(parentPath.listFiles(new GlobFilter(globPattern)));
+ }
+
+ public static List<File> matchAll(File parentPath, String... globPattern) {
+ return matchAll(parentPath, Arrays.asList(globPattern));
+ }
+
+ public static List<File> matchAll(File parentPath, List<String> globPatterns) {
+ ArrayList<File> matches = new ArrayList<File>();
+ for(String p : globPatterns) {
+ matches.addAll(match(parentPath, p));
+ }
+
+ return matches;
+ }
+
+ public static void exclude(List<File> matches, String globPattern) {
+ GlobFilter filter = new GlobFilter(globPattern);
+
+ Iterator<File> it = matches.iterator();
+ while (it.hasNext()) {
+ if (filter.accept(it.next())) {
+ it.remove();
+ }
+ }
+ }
+
+ public static void excludeAll(List<File> matches, String... globPattern) {
+ excludeAll(matches, Arrays.asList(globPattern));
+ }
+
+ public static void excludeAll(List<File> matches, List<String> globPatterns) {
+ for(String p : globPatterns) {
+ exclude(matches, p);
+ }
+ }
+
+ private static String rootPortion(String path) {
+ for (File root : File.listRoots()) {
+ if (path.startsWith(root.getPath())) {
+ return root.getPath();
+ }
+ }
+
+ return "";
+ }
+}
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/GlobFilter.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/GlobFilter.java
new file mode 100644
index 0000000..e17276b
--- /dev/null
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/helper/GlobFilter.java
@@ -0,0 +1,112 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.augeas.helper;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.regex.Pattern;
+
+/**
+ * A filter implementing a glob pattern match.
+ *
+ * @author Lukas Krejci
+ */
+public class GlobFilter implements FileFilter {
+
+ private String globPattern;
+ private Pattern regexPattern;
+
+ public static final char[] WILDCARD_CHARS;
+
+ static {
+ if (File.separatorChar == '\\') {
+ WILDCARD_CHARS = new char[] { '*', '?' };
+ } else {
+ WILDCARD_CHARS = new char[] { '*', '?', '[', ']'};
+ }
+ }
+
+ public GlobFilter(String globPattern) {
+ if (globPattern == null) {
+ throw new IllegalArgumentException("The glob pattern cannot be null.");
+ }
+
+ this.globPattern = globPattern;
+ this.regexPattern = convert(globPattern);
+ }
+
+
+ public String getGlobPattern() {
+ return globPattern;
+ }
+
+ /* (non-Javadoc)
+ * @see java.io.FileFilter#accept(java.io.File)
+ */
+ public boolean accept(File pathname) {
+ return regexPattern.matcher(pathname.getAbsolutePath()).matches();
+ }
+
+ private static Pattern convert(String globPattern) {
+ StringBuilder regexPattern = new StringBuilder("^");
+ int i = 0;
+ while (i < globPattern.length()) {
+ switch (globPattern.charAt(i)) {
+ case '\\' :
+ if (File.separatorChar == '\\') {
+ //we're on windows, \ is a separator
+ regexPattern.append("\\\\");
+ } else {
+ //anywhere else, \ is a escape sequence
+ if (i == globPattern.length() - 1) {
+ throw new IllegalArgumentException("Illegal glob pattern: " + globPattern);
+ }
+ regexPattern.append("\\").append(globPattern.charAt(i + 1));
+ i += 1; //just skip the next character
+ }
+ break;
+ case '*':
+ regexPattern.append(".*");
+ break;
+ case '?':
+ regexPattern.append(".?");
+ break;
+ case '.':
+ regexPattern.append("\\.");
+ break;
+ case '/':
+ regexPattern.append("\\/");
+ break;
+ default:
+ regexPattern.append(globPattern.charAt(i));
+ break;
+ }
+ i++;
+ }
+
+ regexPattern.append("$");
+
+ return Pattern.compile(regexPattern.toString());
+ }
+}
diff --git a/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java
new file mode 100644
index 0000000..423ac15
--- /dev/null
+++ b/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java
@@ -0,0 +1,200 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2009 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.augeas;
+
+import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
+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.configuration.ConfigurationManager;
+import org.rhq.core.pc.inventory.InventoryManager;
+import org.rhq.core.pc.plugin.FileSystemPluginFinder;
+import org.rhq.core.pc.plugin.PluginManager;
+import org.rhq.core.util.file.FileUtil;
+import org.testng.annotations.AfterSuite;
+import org.testng.annotations.BeforeSuite;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+import static org.testng.Assert.fail;
+
+/**
+ * An base class for integration tests for instances of {@link AugeasConfigurationComponent}.
+ *
+ * @author Ian Springer
+ */
+public abstract class AbstractAugeasConfigurationComponentTest {
+ public static final String TEST_GROUP = "linux-config";
+ private static final File ITEST_DIR = new File("target/itest");
+ private static final long ONE_WEEK_IN_SECONDS = 60L * 60 * 24;
+
+ @BeforeSuite(groups = TEST_GROUP)
+ public void start() {
+ try {
+ PluginContainerConfiguration pcConfig = new PluginContainerConfiguration();
+ File pluginsDir = new File(ITEST_DIR, "plugins");
+ pcConfig.setPluginFinder(new FileSystemPluginFinder(pluginsDir));
+ pcConfig.setPluginDirectory(pluginsDir);
+ pcConfig.setInsideAgent(false);
+ pcConfig.setCreateResourceClassloaders(true);
+
+ // Set initial delays for all scheduled scans to one week to effectively disable them.
+ pcConfig.setServerDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setServiceDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setAvailabilityScanInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setConfigurationDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+ pcConfig.setContentDiscoveryInitialDelay(ONE_WEEK_IN_SECONDS);
+
+ File tmpDir = new File(ITEST_DIR, "tmp");
+ tmpDir.mkdirs();
+ if (!tmpDir.isDirectory() || !tmpDir.canWrite()) {
+ throw new IOException("Failed to create temporary directory (" + tmpDir + ").");
+ }
+ pcConfig.setTemporaryDirectory(tmpDir);
+ PluginContainer.getInstance().setConfiguration(pcConfig);
+ System.out.println("Starting PC...");
+ PluginContainer.getInstance().initialize();
+ Set<String> pluginNames = PluginContainer.getInstance().getPluginManager().getMetadataManager()
+ .getPluginNames();
+ System.out.println("PC started with the following plugins: " + pluginNames);
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Failed to start the plugin container.", e);
+ }
+ }
+
+ @BeforeSuite(dependsOnMethods = "start", groups = TEST_GROUP)
+ public void updatePluginConfiguration() {
+ try {
+ System.out.println("Updating Augeas root in plugin configuration...");
+
+ // We need to have the Resource inventoried in order to update its plugin config.
+ InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
+ ResourceType resourceType = getResourceType();
+ switch (resourceType.getCategory()) {
+ case SERVICE:
+ System.out.println("Executing platform service scan to discover " + resourceType + " Resource...");
+ inventoryManager.performServiceScan(inventoryManager.getPlatform().getId());
+ break;
+ case SERVER:
+ System.out.println("Executing server scan to discover " + resourceType + " Resource...");
+ inventoryManager.executeServerScanImmediately();
+ break;
+ case PLATFORM:
+ throw new IllegalStateException("Huh? Using Augeas to configure a platform?");
+ }
+ Resource resource = getResource();
+ Configuration pluginConfig = resource.getPluginConfiguration();
+
+ String tmpDirPath = System.getProperty("java.io.tmpdir");
+ File tmpDir = new File(tmpDirPath);
+ File augeasRootPath = new File(tmpDir, "rhq-itest-augeas-root-path");
+ augeasRootPath.mkdirs();
+
+ pluginConfig.put(new PropertySimple(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP, augeasRootPath));
+
+ PropertySimple includes = pluginConfig.getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP);
+ List<String> includeGlobs = new ArrayList<String>();
+ includeGlobs.addAll(Arrays.asList(includes.getStringValue().split("\\s*\\|\\s*")));
+ for (String includeGlob : includeGlobs) {
+ InputStream inputStream = this.getClass().getResourceAsStream(includeGlob);
+ if (inputStream != null) {
+ File outputFile = new File(augeasRootPath, includeGlob);
+ outputFile.getParentFile().mkdirs();
+ FileUtil.writeFile(inputStream, outputFile);
+ }
+ }
+
+ inventoryManager.updatePluginConfiguration(resource.getId(), pluginConfig);
+ } catch (Exception e) {
+ fail("Failed to update Augeas root in plugin configuration.", e);
+ }
+ }
+
+ @BeforeSuite(dependsOnMethods = "updatePluginConfiguration", groups = TEST_GROUP)
+ public void scanInventory() {
+ /*try {
+ System.out.println("Executing full discovery scan...");
+ PluginContainer.getInstance().getInventoryManager().executeServerScanImmediately();
+ PluginContainer.getInstance().getInventoryManager().executeServiceScanImmediately();
+ } catch (Exception e) {
+ fail("Failed to execute full discovery scan.", e);
+ }*/
+ }
+
+ @AfterSuite(groups = TEST_GROUP)
+ public void stop() {
+ System.out.println("Stopping PC...");
+ PluginContainer.getInstance().shutdown();
+ System.out.println("PC stopped.");
+ }
+
+ @Test(groups = TEST_GROUP)
+ public void testResourceConfigLoad() throws Exception {
+ if (getResourceType().getResourceConfigurationDefinition() != null) {
+ ConfigurationManager configurationManager = PluginContainer.getInstance().getConfigurationManager();
+ Resource resource = getResource();
+ Configuration resourceConfig = configurationManager.loadResourceConfiguration(resource.getId());
+ Configuration expectedResourceConfig = getExpectedResourceConfig();
+ assert resourceConfig.equals(expectedResourceConfig) :
+ "Unexpected Resource configuration - \nExpected:\n\t"
+ + expectedResourceConfig.toString(true) + "\nActual:\n\t"
+ + resourceConfig.toString(true);
+ }
+ }
+
+ protected abstract Configuration getExpectedResourceConfig();
+
+ protected static ResourceType getResourceType(String resourceTypeName, String pluginName) {
+ PluginManager pluginManager = PluginContainer.getInstance().getPluginManager();
+ PluginMetadataManager pluginMetadataManager = pluginManager.getMetadataManager();
+ return pluginMetadataManager.getType(resourceTypeName, pluginName);
+ }
+
+ protected final ResourceType getResourceType() {
+ return getResourceType(getResourceTypeName(), getPluginName());
+ }
+
+ protected abstract String getPluginName();
+ protected abstract String getResourceTypeName();
+
+ protected Resource getResource() {
+ InventoryManager inventoryManager = PluginContainer.getInstance().getInventoryManager();
+ ResourceType resourceType = getResourceType();
+ Set<Resource> resources = inventoryManager.getResourcesWithType(resourceType);
+ if (resources.isEmpty()) {
+ return null;
+ }
+ if (resources.size() > 1) {
+ throw new IllegalStateException("Found more than one " + resourceType.getName()
+ + " Resource - expected there to be exactly one - resources: " + resources);
+ }
+ return resources.iterator().next();
+ }
+}
diff --git a/modules/plugins/cron/pom.xml b/modules/plugins/cron/pom.xml
new file mode 100644
index 0000000..5992726
--- /dev/null
+++ b/modules/plugins/cron/pom.xml
@@ -0,0 +1,217 @@
+<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-plugins-parent</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-cron-plugin</artifactId>
+ <packaging>jar</packaging>
+
+ <name>RHQ Augeas-based Cron Plugin</name>
+ <description>A plugin for managing the *nix cron file</description>
+
+ <scm>
+ <connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/plugins/cron</connection>
+ <developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/plugins/cron</developerConnection>
+ </scm>
+
+ <properties>
+ <scm.module.path>modules/plugins/cron/</scm.module.path>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-platform-plugin</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-augeas-plugin</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <profiles>
+ <profile>
+ <id>integration-tests</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>!true</value>
+ </property>
+ </activation>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>pre-integration-test</phase>
+ <configuration>
+ <tasks>
+ <echo>Setting up plugin dependencies for ${project.artifactId}-${project.version}.jar...
+ </echo>
+ <property name="settings.localRepository" location="${user.home}/.m2/repository" />
+ <mkdir dir="target/itest" />
+ <mkdir dir="target/itest/plugins" />
+ <mkdir dir="target/itest/lib" />
+ <copy toDir="target/itest/plugins" flatten="true">
+ <fileset dir="${settings.localRepository}/">
+ <include name="org/rhq/rhq-platform-plugin/${project.version}/rhq-platform-plugin-${project.version}.jar" />
+ </fileset>
+ <fileset dir="${project.build.directory}">
+ <include name="${project.artifactId}-${project.version}.jar" />
+ </fileset>
+ </copy>
+ <unzip dest="target/itest/lib">
+ <fileset dir="${settings.localRepository}/org/hyperic/sigar-dist/${sigar.version}" includes="*.zip" />
+ <patternset>
+ <include name="**/lib/sigar.jar" />
+ <include name="**/lib/bcel*.jar" />
+ <include name="**/lib/*.so" />
+ <include name="**/lib/*.sl" />
+ <include name="**/lib/*.dll" />
+ <include name="**/lib/*.dylib" />
+ </patternset>
+ </unzip>
+ <move todir="target/itest/lib" flatten="true">
+ <fileset dir="target/itest/lib">
+ <include name="**/lib/*" />
+ </fileset>
+ </move>
+ <delete dir="target/itest/lib/hyperic-sigar-${sigar.version}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- Integration testing voodoo to load and test this plugin with its plugin dependencies -->
+ <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>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
+ <systemProperties>
+ <property>
+ <name>project.artifactId</name>
+ <value>${project.artifactId}</value>
+ </property>
+ <property>
+ <name>project.version</name>
+ <value>${project.version}</value>
+ </property>
+ </systemProperties>
+ </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.deploymentDir>
+ ${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/rhq-downloads/rhq-plugins
+ </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>deploy-jar-meta-inf</id>
+ <phase>package</phase>
+ <configuration>
+ <tasks>
+ <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>
+ </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>
+
+ </profiles>
+
+</project>
diff --git a/modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronComponent.java b/modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronComponent.java
new file mode 100644
index 0000000..2cc5f8a
--- /dev/null
+++ b/modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronComponent.java
@@ -0,0 +1,207 @@
+/*
+ * 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.cron;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import net.augeas.Augeas;
+import net.augeas.AugeasException;
+
+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.definition.ConfigurationDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
+import org.rhq.core.domain.resource.CreateResourceStatus;
+import org.rhq.core.pluginapi.inventory.CreateChildResourceFacet;
+import org.rhq.core.pluginapi.inventory.CreateResourceReport;
+import org.rhq.plugins.augeas.AugeasConfigurationComponent;
+import org.rhq.plugins.augeas.AugeasConfigurationDiscoveryComponent;
+import org.rhq.plugins.augeas.helper.AugeasNode;
+import org.rhq.plugins.augeas.helper.GlobFilter;
+import org.rhq.plugins.platform.PlatformComponent;
+
+/**
+ * Provides an overview of all entries in the crontabs split into hourly/daily/weekly/monthly entries.
+ * Is able to create new cron tabs.
+ *
+ * @author Lukas Krejci
+ */
+public class CronComponent extends AugeasConfigurationComponent<PlatformComponent> implements CreateChildResourceFacet {
+
+ private static final String HOURLY_JOBS_PROP = "hourlyJobs";
+ private static final String HOURLY_JOBS_NODE = "entry[time/minute != \"*\" and time/hour = \"*\" and time/dayofmonth = \"*\" and time/month = \"*\" and time/dayofweek = \"*\"]";
+ private static final String DAILY_JOBS_PROP = "dailyJobs";
+ private static final String DAILY_JOBS_NODE = "entry[time/minute != \"*\" and time/hour != \"*\" and time/dayofmonth = \"*\" and time/month = \"*\" and time/dayofweek = \"*\"]";
+ private static final String WEEKLY_JOBS_PROP = "weeklyJobs";
+ private static final String WEEKLY_JOBS_NODE = "entry[time/minute != \"*\" and time/hour != \"*\" and time/dayofmonth = \"*\" and time/month = \"*\" and time/dayofweek != \"*\"]";
+ private static final String MONTHLY_JOBS_PROP = "monthlyJobs";
+ private static final String MONTHLY_JOBS_NODE = "entry[time/minute != \"*\" and time/hour != \"*\" and time/dayofmonth != \"*\" and time/month = \"*\" and time/dayofweek = \"*\"]";
+ private static final String YEARLY_JOBS_PROP = "yearlyJobs";
+ private static final String YEARLY_JOBS_NODE = "entry[time/minute != \"*\" and time/hour != \"*\" and time/dayofmonth != \"*\" and time/month != \"*\" and time/dayofweek = \"*\"]";
+ private static final String CRONTAB_PROP = "crontab";
+ private static final String CRONTAB_NODE = "..";
+ private static final String AUGEAS_FILES_PREFIX = "/files";
+ private static final int AUGEAS_FILES_PREFIX_LENGTH = AUGEAS_FILES_PREFIX.length();
+ private static final String CRONTAB_RESOURCE_TYPE_NAME = "Cron Tab";
+
+ @Override
+ protected String getResourceConfigurationRootPath() {
+ return "/files/"; //the trailing slash is intentional so that we can get the
+ // /files//blah paths...
+ }
+
+ public CreateResourceReport createResource(CreateResourceReport report) {
+ if (CRONTAB_RESOURCE_TYPE_NAME.equals(report.getResourceType().getName())) {
+ try {
+ String resourceKey = createCrontab(report.getUserSpecifiedResourceName(), report.getResourceType().getResourceConfigurationDefinition(), report.getResourceConfiguration());
+ report.setResourceName(resourceKey);
+ report.setResourceKey(resourceKey);
+ report.setStatus(CreateResourceStatus.SUCCESS);
+ } catch (Exception e) {
+ report.setException(e);
+ report.setStatus(CreateResourceStatus.FAILURE);
+ }
+ } else {
+ report.setErrorMessage("Don't know how to create resource of type " + report.getResourceType().getName());
+ report.setStatus(CreateResourceStatus.FAILURE);
+ }
+ return report;
+ }
+
+ @Override
+ protected String getAugeasPathRelativeToParent(PropertyDefinition propDef, AugeasNode parentNode, Augeas augeas) {
+ String name = propDef.getName();
+ if (CRONTAB_PROP.equals(name)) {
+ return CRONTAB_NODE;
+ } else if (HOURLY_JOBS_PROP.equals(name)) {
+ return HOURLY_JOBS_NODE;
+ } else if (DAILY_JOBS_PROP.equals(name)) {
+ return DAILY_JOBS_NODE;
+ } else if (WEEKLY_JOBS_PROP.equals(name)) {
+ return WEEKLY_JOBS_NODE;
+ } else if (MONTHLY_JOBS_PROP.equals(name)) {
+ return MONTHLY_JOBS_NODE;
+ } else if (YEARLY_JOBS_PROP.equals(name)) {
+ return YEARLY_JOBS_NODE;
+ } else {
+ return super.getAugeasPathRelativeToParent(propDef, parentNode, augeas);
+ }
+ }
+
+ @Override
+ protected Object toPropertyValue(PropertyDefinitionSimple propDefSimple, Augeas augeas, AugeasNode node) {
+ if (CRONTAB_PROP.equals(propDefSimple.getName())) {
+ return getEntryCrontabPath(node);
+ } else {
+ return super.toPropertyValue(propDefSimple, augeas, node);
+ }
+ }
+
+ private String getEntryCrontabPath(AugeasNode crontabNode) {
+ //the node's path is /files/blah/blah/entry/..
+ //we want the /blah/blah part
+ return crontabNode.getParent().getParent().getPath().substring(AUGEAS_FILES_PREFIX_LENGTH);
+ }
+
+ /**
+ * Creates a new crontab resource based on the provided configuration.
+ *
+ * @param resourceConfiguration
+ * @return the resource key of the crontab
+ */
+ private String createCrontab(String resourceName, ConfigurationDefinition configurationDefinition, Configuration resourceConfiguration) {
+ File crontabFile = new File(resourceName);
+
+ try {
+ if (!crontabFile.createNewFile()) {
+ throw new RuntimeException("File " + resourceName + " already exists. Creating the crontab would overwrite it.");
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to create the crontab file named: " + resourceName);
+ }
+
+ //check that the crontab's name passes the glob filters
+ Configuration pluginConfiguration = getResourceContext().getPluginConfiguration();
+
+ List<String> includeGlobs = AugeasConfigurationDiscoveryComponent.getGlobList(pluginConfiguration.getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP));
+ List<String> excludeGlobs = AugeasConfigurationDiscoveryComponent.getGlobList(pluginConfiguration.getSimple(AugeasConfigurationComponent.EXCLUDE_GLOBS_PROP));
+
+ boolean isIncluded = false;
+
+ for(String include : includeGlobs) {
+ if (new GlobFilter(include).accept(crontabFile)) {
+ isIncluded = true;
+ break;
+ }
+ }
+
+ String errorText = "Given Cron tab file name would be created outside of mapped filters. See the Cron resource connection properties for the inclusion and exclusion filters set up.";
+ if (!isIncluded) {
+ throw new IllegalArgumentException(errorText);
+ }
+
+ for(String exclude : excludeGlobs) {
+ if (new GlobFilter(exclude).accept(crontabFile)) {
+ throw new IllegalArgumentException(errorText);
+ }
+ }
+
+ updateCrontab(resourceName, configurationDefinition, resourceConfiguration);
+
+ return resourceName;
+ }
+
+ protected void updateCrontab(String crontabPath, ConfigurationDefinition crontabConfigurationDefinition, Configuration crontabConfiguration) {
+ Augeas augeas = getAugeas();
+ try {
+ augeas.load();
+
+ File crontabFile = new File(crontabPath);
+ String basePath = AUGEAS_FILES_PREFIX + crontabFile.getAbsolutePath();
+ AugeasNode baseNode = new AugeasNode(basePath);
+
+ PropertyList entries = crontabConfiguration.getList(CronTabComponent.ENTRIES_PROP);
+ PropertyDefinitionList entriesDef = crontabConfigurationDefinition.getPropertyDefinitionList(CronTabComponent.ENTRIES_PROP);
+ setNodeFromPropertyList(entriesDef, entries, augeas, baseNode);
+
+ PropertyList settings = crontabConfiguration.getList(CronTabComponent.ENVIRONMENT_SETTINGS_PROP);
+ if (settings != null) {
+ for(Property p : settings.getList()) {
+ PropertyMap setting = (PropertyMap)p;
+ String name = setting.getSimpleValue(CronTabComponent.NAME_PROP, null);
+ String value = setting.getSimpleValue(CronTabComponent.VALUE_PROP, "");
+ if (name != null) {
+ String settingPath = basePath + AugeasNode.SEPARATOR + name;
+ augeas.set(settingPath, value);
+ }
+ }
+ }
+
+ augeas.save();
+ } catch (AugeasException e) {
+ throw new RuntimeException(summarizeAugeasError(augeas), e);
+ }
+ }
+}
diff --git a/modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronDiscoveryComponent.java b/modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronDiscoveryComponent.java
new file mode 100644
index 0000000..676921c
--- /dev/null
+++ b/modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronDiscoveryComponent.java
@@ -0,0 +1,29 @@
+/*
+ * 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.cron;
+
+import org.rhq.plugins.augeas.AugeasConfigurationDiscoveryComponent;
+import org.rhq.plugins.platform.PlatformComponent;
+
+/**
+ * @author Lukas Krejci
+ */
+public class CronDiscoveryComponent extends AugeasConfigurationDiscoveryComponent<PlatformComponent> {
+ //the super class provides everything we need...
+}
diff --git a/modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronTabComponent.java b/modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronTabComponent.java
new file mode 100644
index 0000000..954605f
--- /dev/null
+++ b/modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronTabComponent.java
@@ -0,0 +1,149 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.cron;
+
+import java.io.File;
+import java.util.List;
+
+import net.augeas.Augeas;
+
+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.PropertyDefinition;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.plugins.augeas.AugeasConfigurationComponent;
+import org.rhq.plugins.augeas.helper.AugeasNode;
+
+/**
+ * A component representing a single crontab file.
+ *
+ * @author Lukas Krejci
+ */
+public class CronTabComponent extends AugeasConfigurationComponent<CronComponent> {
+
+ public static final String ENVIRONMENT_SETTINGS_PROP = "environmentSettings";
+ public static final String ENVIRONMENT_SETTINGS_NODE = ".";
+ public static final String VAR_PROP = "var";
+ public static final String ENTRIES_PROP = "entries";
+ public static final String ENTRIES_NODE = ".";
+ public static final String NAME_PROP = "name";
+ public static final String VALUE_PROP = "value";
+
+ private File crontabFile;
+ private String rootPath;
+
+ public void start(ResourceContext<CronComponent> context) throws InvalidPluginConfigurationException, Exception {
+ crontabFile = new File(context.getResourceKey());
+ rootPath = AugeasNode.SEPARATOR + "files" + crontabFile.getAbsolutePath();
+ super.start(context);
+ }
+
+ public AvailabilityType getAvailability() {
+ return crontabFile.exists() ? AvailabilityType.UP : AvailabilityType.DOWN;
+ }
+
+ @Override
+ protected String getResourceConfigurationRootPath() {
+ return rootPath;
+ }
+
+ @Override
+ protected String getAugeasPathRelativeToParent(PropertyDefinition propDef, AugeasNode parentNode, Augeas augeas) {
+ String name = propDef.getName();
+ if (ENVIRONMENT_SETTINGS_PROP.equals(name)) {
+ return ENVIRONMENT_SETTINGS_NODE;
+ } else if (ENTRIES_PROP.equals(name)) {
+ return ENTRIES_NODE;
+ } else {
+ return super.getAugeasPathRelativeToParent(propDef, parentNode, augeas);
+ }
+ }
+
+ @Override
+ protected Property createPropertyList(PropertyDefinitionList propDefList, Augeas augeas, AugeasNode node) {
+ if (ENVIRONMENT_SETTINGS_PROP.equals(propDefList.getName())) {
+ List<String> envSettings = augeas.match(node.getPath() + "/*[label() != \"entry\" and label() != \"#comment\"]");
+ PropertyList ret = new PropertyList(propDefList.getName());
+
+ for(String path : envSettings) {
+ PropertyMap map = new PropertyMap(VAR_PROP);
+ ret.add(map);
+ String name = new AugeasNode(path).getName();
+ String value = augeas.get(path);
+ map.put(new PropertySimple(NAME_PROP, name));
+ map.put(new PropertySimple(VALUE_PROP, value));
+ }
+
+ return ret;
+ } else {
+ return super.createPropertyList(propDefList, augeas, node);
+ }
+ }
+
+ @Override
+ protected void setNodeFromPropertyList(PropertyDefinitionList propDefList, PropertyList propList, Augeas augeas,
+ AugeasNode listNode) {
+ if (ENVIRONMENT_SETTINGS_PROP.equals(propDefList.getName())) {
+ List<String> currentVars = augeas.match(listNode.getPath() + "/*[label() != \"entry\" and label() != \"#comment\"]");
+ for(Property p : propList.getList()) {
+ PropertyMap map = (PropertyMap)p;
+ String name = map.getSimpleValue(NAME_PROP, null);
+ String value = map.getSimpleValue(VALUE_PROP, null);
+ String path = listNode.getPath() + AugeasNode.SEPARATOR + name;
+ augeas.set(path, value);
+ currentVars.remove(path);
+ }
+
+ //delete the leftovers
+ for(String path : currentVars) {
+ augeas.remove(path);
+ }
+ } else if (ENTRIES_PROP.equals(propDefList.getName())) {
+ super.setNodeFromPropertyList(propDefList, propList, augeas, listNode);
+ }
+ }
+
+ @Override
+ protected AugeasNode getExistingChildNodeForListMemberPropertyMap(AugeasNode parentNode,
+ PropertyDefinitionList propDefList, PropertyMap propMap) {
+ if (ENTRIES_PROP.equals(propDefList.getName())) {
+ int idx = propMap.getParentList().getList().indexOf(propMap);
+ int matchesCnt = getAugeas().match(parentNode.getPath() + AugeasNode.SEPARATOR + "entry").size();
+ boolean useIndex = idx != 0 || matchesCnt > 1;
+
+ if (idx < matchesCnt) {
+ return new AugeasNode(parentNode, propMap.getName() + (useIndex ? "[" + (idx + 1) + "]" : ""));
+ } else {
+ return null;
+ }
+ } else {
+ return super.getExistingChildNodeForListMemberPropertyMap(parentNode, propDefList, propMap);
+ }
+ }
+}
diff --git a/modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronTabDiscoveryComponent.java b/modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronTabDiscoveryComponent.java
new file mode 100644
index 0000000..fca42db
--- /dev/null
+++ b/modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronTabDiscoveryComponent.java
@@ -0,0 +1,78 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.cron;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+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.ResourceDiscoveryComponent;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+import org.rhq.plugins.augeas.AugeasConfigurationComponent;
+import org.rhq.plugins.augeas.AugeasConfigurationDiscoveryComponent;
+import org.rhq.plugins.augeas.helper.Glob;
+
+/**
+ * Discovery for cron tabs.
+ *
+ * @author Lukas Krejci
+ */
+public class CronTabDiscoveryComponent implements ResourceDiscoveryComponent<CronComponent> {
+
+ public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<CronComponent> context)
+ throws InvalidPluginConfigurationException, Exception {
+
+ Configuration cronConfiguration = context.getParentResourceContext().getPluginConfiguration();
+
+ List<String> includes = AugeasConfigurationDiscoveryComponent.getGlobList(
+ cronConfiguration.getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP));
+ List<String> excludes = AugeasConfigurationDiscoveryComponent.getGlobList(
+ cronConfiguration.getSimple(AugeasConfigurationComponent.EXCLUDE_GLOBS_PROP));
+
+ List<File> files = Glob.matchAll(new File(AugeasConfigurationComponent.DEFAULT_AUGEAS_ROOT_PATH), includes);
+ Glob.excludeAll(files, excludes);
+
+ HashSet<DiscoveredResourceDetails> results = new HashSet<DiscoveredResourceDetails>();
+
+ ResourceType resourceType = context.getResourceType();
+
+ for (File f : files) {
+ String resourceKey = f.getAbsolutePath();
+ Configuration defaultConfiguration = context.getDefaultPluginConfiguration();
+ defaultConfiguration.put(AugeasConfigurationDiscoveryComponent.getGlobList(
+ AugeasConfigurationComponent.INCLUDE_GLOBS_PROP, Collections.singletonList(resourceKey)));
+
+ DiscoveredResourceDetails result = new DiscoveredResourceDetails(resourceType, resourceKey, resourceKey,
+ null, null, defaultConfiguration, null);
+ results.add(result);
+ }
+ return results;
+ }
+}
diff --git a/modules/plugins/cron/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/cron/src/main/resources/META-INF/rhq-plugin.xml
new file mode 100644
index 0000000..483c28e
--- /dev/null
+++ b/modules/plugins/cron/src/main/resources/META-INF/rhq-plugin.xml
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE plugin [
+
+<!ENTITY cronEntry '
+ <c:simple-property name="time/minute" displayName="Minute" type="string" required="true" activationPolicy="immediate"
+ default="*" description="The minute in an hour at which the cron job should be run (0-59).">
+ </c:simple-property>
+ <c:simple-property name="time/hour" displayName="Hour" type="string" required="true" activationPolicy="immediate"
+ default="*" description="The hour at which the cron job should be run (0-23).">
+ </c:simple-property>
+ <c:simple-property name="time/dayofmonth" displayName="Day of Month" type="string" required="true" activationPolicy="immediate"
+ default="*" description="The day in a month on which the cron job should be run (1-31).">
+ </c:simple-property>
+ <c:simple-property name="time/month" displayName="Month" type="string" required="true" activationPolicy="immediate"
+ default="*" description="The month in a year in which the cron job should be run (1-12 or 3-letter names).">
+ </c:simple-property>
+ <c:simple-property name="time/dayofweek" displayName="Day of Week" type="string" required="true" activationPolicy="immediate"
+ default="*" description="The day in a week on which the cron job should be run (0-7 (Sunday is 0 or 7) or 3-letter names).">
+ </c:simple-property>
+ <c:simple-property name="user" displayName="Executing user" required="true" description="The user that cron should execute the job as."/>
+ <c:simple-property name="." displayName="Command" required="true" description="The actual command to execute when the cron job is run."/>
+'>
+
+<!ENTITY readOnlyCronEntry '
+ <c:simple-property name="time/minute" displayName="Minute" type="string" readOnly="true" required="true" activationPolicy="immediate"
+ default="*" description="The minute in an hour at which the cron job should be run (0-59).">
+ </c:simple-property>
+ <c:simple-property name="time/hour" displayName="Hour" type="string" readOnly="true" required="true" activationPolicy="immediate"
+ default="*" description="The hour at which the cron job should be run (0-23).">
+ </c:simple-property>
+ <c:simple-property name="time/dayofmonth" displayName="Day of Month" type="string" readOnly="true" required="true" activationPolicy="immediate"
+ default="*" description="The day in a month on which the cron job should be run (1-31).">
+ </c:simple-property>
+ <c:simple-property name="time/month" displayName="Month" type="string" readOnly="true" required="true" activationPolicy="immediate"
+ default="*" description="The month in a year in which the cron job should be run (1-12 or 3-letter names).">
+ </c:simple-property>
+ <c:simple-property name="time/dayofweek" displayName="Day of Week" type="string" readOnly="true" required="true" activationPolicy="immediate"
+ default="*" description="The day in a week on which the cron job should be run (0-7 (Sunday is 0 or 7) or 3-letter names).">
+ </c:simple-property>
+ <c:simple-property name="user" displayName="Executing user" readOnly="true" required="true" description="The user that cron should execute the job as."/>
+ <c:simple-property name="." displayName="Command" readOnly="true" required="true" description="The actual command to execute when the cron job is run."/>
+'>
+<!ENTITY cronEntriesDescription '
+ <c:description>
+ Ranges of numbers are allowed. Ranges are two numbers separated with a hyphen. The specified range is inclusive. For example, 8-11 for an "hours" entry
+ specifies execution at hours 8, 9, 10 and 11.
+
+ Lists are allowed. A list is a set of numbers (or ranges) separated by commas. Examples: "1,2,5,9", "0-4,8-12".
+
+ Step values can be used in conjunction with ranges. Following a range with "<number>" specifies skips of the numberâs value through the range. For example,
+ "0-23/2" can be used in the hours field to specify command execution every other hour (the alternative in the V7 standard is "0,2,4,6,8,10,12,14,16,18,20,22").
+ Steps are also permitted after an asterisk, so if you want to say "every two hours", just use "*/2".
+ </c:description>
+'>
+
+<!ENTITY cronTabRef '
+ <c:simple-property name="crontab" displayName="Cron Tab" type="string" readOnly="true" required="true" description="The crontab file in which this job is defined."/>
+'>
+
+]>
+<plugin name="Cron"
+ displayName="Cron"
+ description="Configuration of cron"
+ package="org.rhq.plugins.cron"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <depends plugin="Augeas"/>
+
+ <service name="Cron"
+ description="The cron configuration"
+ discovery="CronDiscoveryComponent"
+ class="CronComponent"
+ singleton="true">
+
+ <runs-inside>
+ <parent-resource-type name="Linux" plugin="Platforms"/>
+ <parent-resource-type name="Solaris" plugin="Platforms"/>
+ <parent-resource-type name="HP-UX" plugin="Platforms"/>
+ <parent-resource-type name="AIX" plugin="Platforms"/>
+ <parent-resource-type name="FreeBSD" plugin="Platforms"/>
+ <parent-resource-type name="Mac OS X" plugin="Platforms"/>
+ <parent-resource-type name="Java" plugin="Platforms"/>
+ </runs-inside>
+
+ <plugin-configuration>
+ <c:simple-property name="augeasModuleName" displayName="Augeas Module Name" default="Cron" required="true" readOnly="true"
+ description="the name of the Augeas module/lens to use for loading and updating this resource's configuration"/>
+ <c:simple-property name="configurationFilesInclusionPatterns" required="true" readOnly="true"
+ default="/etc/crontab|/etc/cron.d/*">
+ <c:description>A | delimited list of patterns of files to configure.</c:description>
+ </c:simple-property>
+ <c:simple-property name="configurationFilesExclusionPatterns" required="true" readOnly="true"
+ default="*.augnew|*.augsave|*.rpmsave|*.rpmnew|*~">
+ <c:description>A | delimited list of patterns of files to exclude from configuration.</c:description>
+ </c:simple-property>
+ </plugin-configuration>
+
+ <resource-configuration>
+ <c:list-property displayName="Hourly Jobs" readOnly="true"
+ name='hourlyJobs'>
+ <c:description>The list of all the hourly jobs defined across all the system cron tab files.</c:description>
+ <c:map-property name="." readOnly="true">
+ &readOnlyCronEntry;
+ &cronTabRef;
+ </c:map-property>
+ </c:list-property>
+ <c:list-property displayName="Daily Jobs" readOnly="true"
+ name='dailyJobs'>
+ <c:description>The list of all the daily jobs defined across all the system cron tab files.</c:description>
+ <c:map-property name="." readOnly="true">
+ &readOnlyCronEntry;
+ &cronTabRef;
+ </c:map-property>
+ </c:list-property>
+ <c:list-property displayName="Weekly Jobs" readOnly="true"
+ name='weeklyJobs'>
+ <c:description>The list of all the weekly jobs defined across all the system cron tab files.</c:description>
+ <c:map-property name="." readOnly="true">
+ &readOnlyCronEntry;
+ &cronTabRef;
+ </c:map-property>
+ </c:list-property>
+ <c:list-property displayName="Monthly Jobs" readOnly="true"
+ name='monthlyJobs'>
+ <c:description>The list of all the monthly jobs defined across all the system cron tab files.</c:description>
+ <c:map-property name="." readOnly="true">
+ &readOnlyCronEntry;
+ &cronTabRef;
+ </c:map-property>
+ </c:list-property>
+ <c:list-property displayName="Yearly Jobs" readOnly="true"
+ name='yearlyJobs'>
+ <c:description>The list of all the yearly jobs defined across all the system cron tab files.</c:description>
+ <c:map-property name="." readOnly="true">
+ &readOnlyCronEntry;
+ &cronTabRef;
+ </c:map-property>
+ </c:list-property>
+ </resource-configuration>
+
+ <service name="Cron Tab"
+ description="A single cron tab file"
+ discovery="CronTabDiscoveryComponent"
+ class="CronTabComponent"
+ createDeletePolicy="both">
+ <plugin-configuration>
+ <c:simple-property name="augeasModuleName" displayName="Augeas Module Name" default="Cron" required="true" readOnly="true"
+ description="the name of the Augeas module/lens to use for loading and updating this resource's configuration"/>
+ <c:simple-property name="configurationFilesInclusionPatterns" required="true" readOnly="true">
+ <c:description>A | delimited list of patterns of files to configure.</c:description>
+ </c:simple-property>
+ <c:simple-property name="configurationFilesExclusionPatterns" required="true" readOnly="true">
+ <c:description>A | delimited list of patterns of files to exclude from configuration.</c:description>
+ </c:simple-property>
+ </plugin-configuration>
+ <resource-configuration>
+ <c:list-property name="environmentSettings" displayName="Environment Settings">
+ <c:description>
+Several environment variables are set up automatically by the cron(8) daemon. SHELL is set to /bin/sh, and LOGNAME and HOME are set from the /etc/passwd line
+of the crontabÂŽs owner. HOME and SHELL may be overridden by settings in the crontab; LOGNAME may not.
+If MAILTO is defined (and non-empty), mail is sent to the user so named. If MAILTO is defined but empty (MAILTO=""), no mail will be sent. Otherwise mail is sent
+to the owner of the crontab.
+The CRON_TZ specifies the time zone specific for the cron table. User type into the chosen table times in the time of the specified time zone. The time into log
+is taken from local time zone, where is the daemon running.
+The MLS_LEVEL environment variable provides support for multiple per-job SELinux security contexts in the same crontab. By default, cron jobs execute with the
+default SELinux security context of the user that created the crontab file.
+ </c:description>
+ <c:map-property name="var">
+ <c:simple-property name="name" required="true" />
+ <c:simple-property name="value" required="true"/>
+ </c:map-property>
+ </c:list-property>
+
+ <c:list-property name="entries" displayName="Cron Entries">
+ &cronEntriesDescription;
+ <c:map-property name="entry">
+ &cronEntry;
+ </c:map-property>
+ </c:list-property>
+
+ </resource-configuration>
+ </service>
+ </service>
+
+</plugin>
diff --git a/modules/plugins/cron/src/test/resources/log4j.xml b/modules/plugins/cron/src/test/resources/log4j.xml
new file mode 100644
index 0000000..ef41b92
--- /dev/null
+++ b/modules/plugins/cron/src/test/resources/log4j.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
+
+ <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out"/>
+ <param name="Threshold" value="DEBUG"/>
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <!-- The default pattern: Date Priority [Category] Messagen -->
+
+ <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
+ </layout>
+ </appender>
+
+ <appender name="FILE" class="org.apache.log4j.RollingFileAppender">
+ <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>
+
+ <root>
+ <appender-ref ref="CONSOLE"/>
+ <appender-ref ref="FILE"/>
+ </root>
+
+</log4j:configuration>
diff --git a/modules/plugins/hosts/pom.xml b/modules/plugins/hosts/pom.xml
index 923a9b9..6956c58 100644
--- a/modules/plugins/hosts/pom.xml
+++ b/modules/plugins/hosts/pom.xml
@@ -42,9 +42,28 @@
<artifactId>rhq-augeas-plugin</artifactId>
<version>${project.version}</version>
</dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-augeas-plugin</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
</dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
<profiles>
<profile>
<id>integration-tests</id>
@@ -70,14 +89,6 @@
<mkdir dir="target/itest" />
<mkdir dir="target/itest/plugins" />
<mkdir dir="target/itest/lib" />
- <copy toDir="target/itest/plugins" flatten="true">
- <fileset dir="${settings.localRepository}/">
- <include name="org/rhq/rhq-platform-plugin/${project.version}/rhq-platform-plugin-${project.version}.jar" />
- </fileset>
- <fileset dir="${project.build.directory}">
- <include name="${project.artifactId}-${project.version}.jar" />
- </fileset>
- </copy>
<unzip dest="target/itest/lib">
<fileset dir="${settings.localRepository}/org/hyperic/sigar-dist/${sigar.version}" includes="*.zip" />
<patternset>
@@ -104,6 +115,38 @@
</executions>
</plugin>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-platform-plugin</artifactId>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-augeas-plugin</artifactId>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+ <artifactId>${project.artifactId}</artifactId>
+ <version>${project.version}</version>
+ </artifactItem>
+ </artifactItems>
+ <outputDirectory>target/itest/plugins</outputDirectory>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
<!-- Integration testing voodoo to load and test this plugin with its plugin dependencies -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
@@ -120,7 +163,7 @@
<configuration>
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
- <useSystemClassLoader>false</useSystemClassLoader>
+ <useSystemClassLoader>true</useSystemClassLoader>
<argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
<!--<argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
<systemProperties>
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
index 8e944db..b68dd1f 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
@@ -21,6 +21,7 @@ package org.rhq.plugins.hosts;
import net.augeas.Augeas;
import org.rhq.core.domain.configuration.*;
import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
@@ -89,6 +90,11 @@ public class HostsComponent extends AugeasConfigurationComponent {
}
@Override
+ protected AugeasNode getNewListMemberNode(AugeasNode listNode, PropertyDefinitionMap listMemberPropDefMap, int listIndex) {
+ return new AugeasNode(listNode, "0" + listIndex);
+ }
+
+ @Override
protected boolean validateResourceConfiguration(ConfigurationUpdateReport report) {
Configuration resourceConfig = report.getConfiguration();
StringBuilder errorMessage = new StringBuilder();
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java
index b63230e..bfd82a1 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsDiscoveryComponent.java
@@ -19,6 +19,8 @@
package org.rhq.plugins.hosts;
import java.io.File;
+import java.util.Collections;
+import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
@@ -54,7 +56,7 @@ public class HostsDiscoveryComponent extends AugeasConfigurationDiscoveryCompone
}
@Override
- protected File getConfigurationFile(ResourceDiscoveryContext discoveryContext)
+ protected List<String> determineIncludeGlobs(ResourceDiscoveryContext discoveryContext)
{
File hostsFile;
if (IS_WINDOWS) {
@@ -63,7 +65,12 @@ public class HostsDiscoveryComponent extends AugeasConfigurationDiscoveryCompone
} else {
hostsFile = new File("/etc/hosts");
}
- return hostsFile;
+ return Collections.singletonList(hostsFile.getAbsolutePath());
+ }
+
+ @Override
+ protected List<String> determineExcludeGlobs(ResourceDiscoveryContext discoveryContext) {
+ return null;
}
private File getWindowsDir() {
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/HostsComponentHelper.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/HostsComponentHelper.java
index c3041fc..3bf0ba6 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/HostsComponentHelper.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/HostsComponentHelper.java
@@ -23,6 +23,7 @@
package org.rhq.plugins.hosts.helper;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.plugins.hosts.HostsComponent;
@@ -33,17 +34,17 @@ import java.io.File;
*/
public class HostsComponentHelper {
public static File getHostsFile(Configuration pluginConfig) {
- String hostsFilePath = pluginConfig.getSimple(HostsComponent.CONFIGURATION_FILE_PROP).getStringValue();
+ String hostsFilePath = ((PropertySimple)pluginConfig.getList(HostsComponent.INCLUDE_GLOBS_PROP).getList().get(0)).getStringValue();
return new File(hostsFilePath);
}
public static void validateHostFileExists(File hostsFile) throws InvalidPluginConfigurationException {
if (!hostsFile.exists()) {
- throw new InvalidPluginConfigurationException("Location specified by '" + HostsComponent.CONFIGURATION_FILE_PROP
+ throw new InvalidPluginConfigurationException("Location specified by '" + HostsComponent.INCLUDE_GLOBS_PROP
+ "' connection property does not exist.");
}
if (hostsFile.isDirectory()) {
- throw new InvalidPluginConfigurationException("Location specified by '" + HostsComponent.CONFIGURATION_FILE_PROP
+ throw new InvalidPluginConfigurationException("Location specified by '" + HostsComponent.INCLUDE_GLOBS_PROP
+ "' connection property is a directory, not a regular file.");
}
}
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java
index 38cf18e..8856938 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/helper/NonAugeasHostsConfigurationDelegate.java
@@ -51,7 +51,7 @@ public class NonAugeasHostsConfigurationDelegate implements ConfigurationFacet
public Configuration loadResourceConfiguration() throws Exception {
Configuration resourceConfig = new Configuration();
- File hostsFile = this.hostsComponent.getConfigurationFile();
+ File hostsFile = (File)this.hostsComponent.getConfigurationFiles().get(0);
Hosts hosts = Hosts.load(hostsFile);
resourceConfig.setNotes("Loaded at " + new Date());
@@ -135,7 +135,7 @@ public class NonAugeasHostsConfigurationDelegate implements ConfigurationFacet
return;
}
- File hostsFile = this.hostsComponent.getConfigurationFile();
+ File hostsFile = (File)this.hostsComponent.getConfigurationFiles().get(0);
try {
Hosts.store(newHosts, hostsFile);
}
diff --git a/modules/plugins/hosts/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/hosts/src/main/resources/META-INF/rhq-plugin.xml
index 326eec6..eeeb667 100644
--- a/modules/plugins/hosts/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/hosts/src/main/resources/META-INF/rhq-plugin.xml
@@ -31,13 +31,8 @@
<c:simple-property name="augeasModuleName" displayName="Augeas Module Name" default="Hosts" required="true" readOnly="true"
description="the name of the Augeas module/lens to use for loading and updating this resource's configuration"/>
- <c:simple-property name="configurationFile" displayName="Hosts File Path" type="file" required="true" readOnly="true"
- description="the absolute path of the hosts file (e.g. /etc/hosts on Unix systems or C:\windows\system32\drivers\etc\hosts)"/>
-<!--
- <c:map-property name="listMemberMapKeyNames">
- <c:simple-property name="." default="key" readOnly="true"/>
- </c:map-property>
--->
+ <c:simple-property name="configurationFilesInclusionPatterns" displayName="Configuration File Paths" required="true" readOnly="true"
+ description="the absolute paths of the configuration files, delimited with pipe characters"/>
</plugin-configuration>
<resource-configuration>
diff --git a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
index 875e0eb..9810248 100644
--- a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
+++ b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
@@ -18,69 +18,79 @@
*/
package org.rhq.plugins.hosts;
-import java.util.Collection;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.testng.annotations.BeforeSuite;
-import org.testng.annotations.Test;
-
+import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
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.pc.PluginContainer;
+import org.rhq.plugins.augeas.AbstractAugeasConfigurationComponentTest;
/**
- * @author Jason Dobies
+ * An integration test for {@link HostsComponent}.
+ *
+ * @author Ian Springer
*/
-public class HostsComponentTest {
-
- private HostsComponent component = new HostsComponent();
-
- private Configuration pluginConfiguration = new Configuration();
-
- private final Log log = LogFactory.getLog(this.getClass());
-
- @BeforeSuite
- public void initPluginConfiguration() throws Exception {
- pluginConfiguration.put(new PropertySimple("lenses-path", "/usr/local/share/augeas/lenses"));
- pluginConfiguration.put(new PropertySimple("root-path", "/"));
- pluginConfiguration.put(new PropertySimple("hosts-path", "/etc/hosts"));
- pluginConfiguration.put(new PropertySimple("augeas-hosts-path", "/files/etc/hosts/*"));
+public class HostsComponentTest extends AbstractAugeasConfigurationComponentTest {
+ @Override
+ protected String getPluginName() {
+ return "Hosts";
}
- @Test(enabled = false)
- public void loadResourceConfiguration() throws Exception {
- Configuration configuration;
- try {
- configuration = component.loadResourceConfiguration();
- } catch (UnsatisfiedLinkError ule) {
- // Skip tests if augeas not available
- return;
- }
-
- assert configuration != null : "Null configuration returned from load call";
-
- Collection<Property> allProperties = configuration.getProperties();
-
- assert allProperties.size() == 1 : "Incorrect number of properties found. Expected: 1, Found: "
- + allProperties.size();
-
- PropertyList entryList = (PropertyList) allProperties.iterator().next();
-
- for (Property property : entryList.getList()) {
- PropertyMap entry = (PropertyMap) property;
+ @Override
+ protected String getResourceTypeName() {
+ return "Hosts File";
+ }
- Property ipProperty = entry.get("ip");
- Property canonicalProperty = entry.get("canonical");
+ @Override
+ protected Configuration getExpectedResourceConfig() {
+ Configuration config = new Configuration();
+ PropertyList entries = new PropertyList(".");
+ config.put(entries);
+
+ PropertyMap entry;
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "127.0.0.1"));
+ entry.put(new PropertySimple("canonical", "localhost"));
+ entry.put(new PropertySimple("alias", "localhost.localdomain\nlocalhost4\nlocalhost4.localdomain4"));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "::1"));
+ entry.put(new PropertySimple("canonical", "localhost"));
+ entry.put(new PropertySimple("alias", "localhost.localdomain\nlocalhost6\nlocalhost6.localdomain6"));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "1.1.1.1"));
+ entry.put(new PropertySimple("canonical", "one-one-one-one.com"));
+ entry.put(new PropertySimple("alias", null));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "2.2.2.2"));
+ entry.put(new PropertySimple("canonical", "two-two-two-two.com"));
+ entry.put(new PropertySimple("alias", "alias"));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "3.3.3.3"));
+ entry.put(new PropertySimple("canonical", "three-three-three-three.com"));
+ entry.put(new PropertySimple("alias", "alias1\nalias2"));
+ entries.getList().add(entry);
+
+ return config;
+ }
- assert ipProperty != null : "IP was null in entry";
- assert canonicalProperty != null : "Canonical was null in entry";
+ private boolean supportsFacet(Class<?> facetInterface) {
+ PluginMetadataManager manager = PluginContainer.getInstance().getPluginManager().getMetadataManager();
+ String componentClass = manager.getComponentClass(getResourceType());
- log.info("IP: " + ((PropertySimple) ipProperty).getStringValue());
- log.info("Canonical: " + ((PropertySimple) canonicalProperty).getStringValue());
+ try {
+ return facetInterface.isAssignableFrom(Class.forName(componentClass));
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Could not find component class " + componentClass, e);
}
-
- }
+ }
}
diff --git a/modules/plugins/hosts/src/test/resources/etc/hosts b/modules/plugins/hosts/src/test/resources/etc/hosts
new file mode 100644
index 0000000..3a451c9
--- /dev/null
+++ b/modules/plugins/hosts/src/test/resources/etc/hosts
@@ -0,0 +1,11 @@
+#
+# Hosts File
+#
+127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
+::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
+
+# comment
+1.1.1.1 one-one-one-one.com # no aliases
+2.2.2.2 two-two-two-two.com alias # one alias
+3.3.3.3 three-three-three-three.com alias1 alias2 # two aliases
+#4.4.4.4 # no hostname (invalid)
diff --git a/modules/plugins/hosts/src/test/resources/log4j.xml b/modules/plugins/hosts/src/test/resources/log4j.xml
index ef41b92..65b7562 100644
--- a/modules/plugins/hosts/src/test/resources/log4j.xml
+++ b/modules/plugins/hosts/src/test/resources/log4j.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
+
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
-<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
- <param name="Threshold" value="DEBUG"/>
+ <param name="Threshold" value="ERROR"/>
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Messagen -->
diff --git a/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/MBeanResourceComponent.java b/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/MBeanResourceComponent.java
index 8b30bfd..0e93097 100644
--- a/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/MBeanResourceComponent.java
+++ b/modules/plugins/jmx/src/main/java/org/rhq/plugins/jmx/MBeanResourceComponent.java
@@ -524,7 +524,8 @@ public class MBeanResourceComponent<T extends JMXComponent> implements Measureme
Object[] parameterValues = new Object[operation.getParameters().size()];
int i = 0;
- for (EmsParameter param : operation.getParameters()) {
+ List<EmsParameter> params = operation.getParameters();
+ for (EmsParameter param : params) {
PropertySimple ps = parameters.getSimple(param.getName());
if (param.getType().equals(String.class.getName())) {
parameterValues[i] = (ps == null) ? null : ps.getStringValue();
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index da45f9b..6a51dbd 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -102,6 +102,7 @@
<!-- other, possibly experimental plugins -->
<module>augeas</module>
<module>apt</module>
+ <module>cron</module>
<module>script</module>
<module>grub</module>
<!-- not behaving <module>hardware</module> -->
diff --git a/modules/plugins/samba/pom.xml b/modules/plugins/samba/pom.xml
index bffb1a0..ca1b0af 100644
--- a/modules/plugins/samba/pom.xml
+++ b/modules/plugins/samba/pom.xml
@@ -25,21 +25,39 @@
</properties>
<dependencies>
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-platform-plugin</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-augeas-plugin</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-augeas-plugin</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
- <dependency>
- <groupId>net.augeas</groupId>
- <artifactId>augeas</artifactId>
- <version>0.0.1</version>
- </dependency>
-
- <dependency>
- <groupId>com.sun.jna</groupId>
- <artifactId>jna</artifactId>
- <version>3.0.9</version>
- </dependency>
</dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
<profiles>
<profile>
<id>integration-tests</id>
@@ -99,6 +117,39 @@
</executions>
</plugin>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-platform-plugin</artifactId>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-augeas-plugin</artifactId>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+ <artifactId>${project.artifactId}</artifactId>
+ <version>${project.version}</version>
+ </artifactItem>
+ </artifactItems>
+ <outputDirectory>target/itest/plugins</outputDirectory>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+
<!-- Integration testing voodoo to load and test this plugin with its plugin dependencies -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
@@ -115,7 +166,7 @@
<configuration>
<skip>${maven.test.skip}</skip>
<excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
- <useSystemClassLoader>false</useSystemClassLoader>
+ <useSystemClassLoader>true</useSystemClassLoader>
<argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
<!--<argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
<systemProperties>
diff --git a/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaServerComponent.java b/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaServerComponent.java
index 8f0fa2c..d26aceb 100644
--- a/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaServerComponent.java
+++ b/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaServerComponent.java
@@ -18,191 +18,65 @@
*/
package org.rhq.plugins.samba;
-import java.io.File;
-import java.util.Date;
-import java.util.List;
-
-import net.augeas.Augeas;
-
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.pluginapi.configuration.ConfigurationFacet;
+import org.rhq.core.domain.resource.ResourceType;
import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
-import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
-import org.rhq.core.pluginapi.inventory.ResourceComponent;
+import org.rhq.core.pluginapi.inventory.CreateResourceReport;
import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.plugins.augeas.AugeasConfigurationComponent;
/**
- * @author Greg Hinkle, shughes
+ * TODO
*/
-public class SambaServerComponent implements ResourceComponent, ConfigurationFacet {
-
- private ResourceContext resourceContext;
- private File smbConfFile;
- //private ProcessInfo processInfo;
- //private static final int PORT = 445;
-
- private static final String[] GLOBAL_PROPS = { "workgroup", "server string", "security", "encrypt passwords",
- "load printers", "cups options" };
-
- public void start(ResourceContext resourceContext) throws InvalidPluginConfigurationException, Exception {
- this.resourceContext = resourceContext;
-
- Configuration pluginConfiguration = resourceContext.getPluginConfiguration();
-
- PropertySimple smbConfPathProperty = pluginConfiguration.getSimple("smb-path");
-
- if (smbConfPathProperty == null) {
- throw new InvalidPluginConfigurationException(
- "Hosts path not found in the plugin configuration, cannot start resource component");
- }
-
- String smbConfPath = smbConfPathProperty.getStringValue();
-
- smbConfFile = new File(smbConfPath);
-
- if (!smbConfFile.exists()) {
- throw new InvalidPluginConfigurationException("smb.conf file not found at specified location: "
- + smbConfPath);
- }
+public class SambaServerComponent extends AugeasConfigurationComponent {
- //getProcess();
+ public void start(ResourceContext resourceContext) throws Exception {
+ super.start(resourceContext);
}
public void stop() {
+ super.stop();
}
public AvailabilityType getAvailability() {
- if (smbConfFile == null) {
- return AvailabilityType.DOWN;
- }
-
- return smbConfFile.exists() ? AvailabilityType.UP : AvailabilityType.DOWN;
+ return super.getAvailability();
}
public Configuration loadResourceConfiguration() throws Exception {
- Configuration pluginConfiguration = resourceContext.getPluginConfiguration();
-
- return loadResourceConfiguration(pluginConfiguration);
- }
-
- public Configuration loadResourceConfiguration(Configuration pluginConfiguration) throws Exception {
-
- Augeas augeas = getAugeas();
- String sambaAugPath = getAugeasPath();
-
- // Request data from augeas
- List<String> matches = augeas.match(sambaAugPath);
- if (matches.size() == 0) {
- throw new Exception("Unable to load hosts data from augeas:" + sambaAugPath);
- }
-
- String globalNode = matches.get(0);
-
- // Parse out the properties
- Configuration configuration = new Configuration();
- configuration.setNotes("Loaded from Augeas at " + new Date());
-
- for (String prop : GLOBAL_PROPS) {
- String value = augeas.get(globalNode + "/" + prop.replaceAll(" ", "\\\\ "));
- configuration.put(new PropertySimple(prop, value));
- }
-
- return configuration;
+ return super.loadResourceConfiguration();
}
- public String getAugeasPath() throws Exception {
- // Find out where to look for the hosts tree
- PropertySimple augeasTreeNodeProperty = this.resourceContext.getPluginConfiguration().getSimple(
- "augeas-smb-path");
-
- if (augeasTreeNodeProperty == null) {
- throw new Exception("Augeas tree node not specified for hosts, cannot retrive configuration");
- }
-
- String sambaAugPath = augeasTreeNodeProperty.getStringValue();
-
- return sambaAugPath;
+ public void updateResourceConfiguration(ConfigurationUpdateReport report) {
+ super.updateResourceConfiguration(report);
}
- public Augeas getAugeas() throws Exception {
- Configuration pluginConfiguration = this.resourceContext.getPluginConfiguration();
- // Gather data necessary to create the Augeas hook
- PropertySimple lensesPathProperty = pluginConfiguration.getSimple("lenses-path");
-
- if (lensesPathProperty == null) {
- throw new Exception("Lenses path not found in plugin configuration, cannot retrieve configuration");
- }
-
- PropertySimple rootPathProperty = pluginConfiguration.getSimple("root-path");
-
- if (rootPathProperty == null) {
- throw new Exception("Root path not found in plugin configuration, cannot retrieve configuration");
- }
-
- String lensesPath = lensesPathProperty.getStringValue();
- String rootPath = rootPathProperty.getStringValue();
-
- Augeas augeas = new Augeas(rootPath, lensesPath, Augeas.NONE);
- return augeas;
+ @Override
+ public CreateResourceReport createResource(CreateResourceReport reportIn) {
+ CreateResourceReport report = reportIn;
+ Configuration config = report.getResourceConfiguration();
+ String name = config.getSimple(SambaShareComponent.NAME_RESOURCE_CONFIG_PROP).getStringValue();
+ report.setResourceKey(name);
+ report.setResourceName(name);
+ return super.createResource(report);
}
- public void updateResourceConfiguration(ConfigurationUpdateReport report) {
- try {
- Augeas augeas = getAugeas();
- String sambaAugPath = getAugeasPath();
-
- // Request data from augeas
- List<String> matches = augeas.match(sambaAugPath);
- if (matches.size() == 0) {
- throw new Exception("Unable to load hosts data from augeas");
- }
-
- String globalNode = null;
-
- for (String entyNode : matches) {
- if ("global".equals(augeas.get(entyNode))) {
-
- globalNode = entyNode;
- }
- }
-
- Configuration configuration = report.getConfiguration();
-
- for (String prop : GLOBAL_PROPS) {
- augeas.set(globalNode + "/" + prop.replaceAll(" ", "\\\\ "), configuration.getSimpleValue(prop, ""));
- }
-
- } catch (Exception e) {
- throw new RuntimeException("Unable to save samba configuration", e);
+ @Override
+ protected String getChildResourceConfigurationRootPath(ResourceType resourceType, Configuration resourceConfig) {
+ if (resourceType.getName().equals(SambaShareComponent.RESOURCE_TYPE_NAME)) {
+ String targetName = resourceConfig.getSimple(SambaShareComponent.NAME_RESOURCE_CONFIG_PROP).getStringValue();
+ return "/files/etc/samba/smb.conf/target[.='" + targetName + "']";
+ } else {
+ throw new IllegalArgumentException("Unsupported child Resource type: " + resourceType);
}
}
- /*
- private void getProcess() {
-
- List<ProcessInfo> procs = resourceContext.getSystemInformation().getProcesses(
- "process|basename|match=smbd,process|basename|nomatch|parent=smbd");
- if (procs.size() == 1) {
- this.processInfo = procs.get(0).getAggregateProcessTree();
+ @Override
+ protected String getChildResourceConfigurationRootLabel(ResourceType resourceType, Configuration resourceConfig) {
+ if (resourceType.getName().equals(SambaShareComponent.RESOURCE_TYPE_NAME)) {
+ return resourceConfig.getSimple(SambaShareComponent.NAME_RESOURCE_CONFIG_PROP).getStringValue();
+ } else {
+ throw new IllegalArgumentException("Unsupported child Resource type: " + resourceType);
}
}
- */
- /*
- public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
- NetworkStats stats = resourceContext.getSystemInformation().getNetworkStats("localhost", PORT);
- processInfo.refresh();
- for (MeasurementScheduleRequest request : metrics) {
- if (request.getName().startsWith("NetworkStat.")) {
- int val = stats.getByName(request.getName().substring("NetworkStat.".length()));
- report.addData(new MeasurementDataNumeric(request, (double) val));
- } else if (request.getName().startsWith("Process.")) {
- Double value = ObjectUtil.lookupDeepNumericAttributeProperty(processInfo, request.getName().substring(
- "Process.".length()));
- report.addData(new MeasurementDataNumeric(request, value));
- }
- }
- }
- */
}
diff --git a/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaServerDiscoveryComponent.java b/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaServerDiscoveryComponent.java
index 9b42a4a..5c26ac2 100644
--- a/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaServerDiscoveryComponent.java
+++ b/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaServerDiscoveryComponent.java
@@ -18,43 +18,15 @@
*/
package org.rhq.plugins.samba;
-import java.io.File;
-import java.util.HashSet;
-import java.util.Set;
-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.core.system.ProcessExecution;
-import org.rhq.core.system.ProcessExecutionResults;
-
-/**
- * @author Greg Hinkle
- */
-public class SambaServerDiscoveryComponent implements ResourceDiscoveryComponent {
-
- public Set discoverResources(ResourceDiscoveryContext resourceDiscoveryContext) throws InvalidPluginConfigurationException, Exception {
+import org.rhq.plugins.augeas.AugeasConfigurationDiscoveryComponent;
- Set<DiscoveredResourceDetails> details = new HashSet<DiscoveredResourceDetails>();
-
- File confFile = new File("/etc/samba/smb.conf");
-
- ProcessExecution pe = new ProcessExecution("/usr/sbin/smbd");
- pe.setArguments(new String[]{"--version"});
- pe.setCaptureOutput(true);
- ProcessExecutionResults per =
- resourceDiscoveryContext.getSystemInformation().executeProcess(pe);
- String data = per.getCapturedOutput();
- String version = data.replace("Version","").trim();
-
- if (confFile.exists()) {
- DiscoveredResourceDetails resource =
- new DiscoveredResourceDetails(resourceDiscoveryContext.getResourceType(), "samba", "Samba Server",
- version, "Samba services", null, null);
+import java.util.Set;
- details.add(resource);
- }
+public class SambaServerDiscoveryComponent extends AugeasConfigurationDiscoveryComponent {
- return details;
+ public Set discoverResources(ResourceDiscoveryContext resourceDiscoveryContext) throws InvalidPluginConfigurationException, Exception {
+ return super.discoverResources(resourceDiscoveryContext);
}
}
diff --git a/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaShareComponent.java b/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaShareComponent.java
index 878b70d..c123e86 100644
--- a/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaShareComponent.java
+++ b/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaShareComponent.java
@@ -10,7 +10,7 @@
* 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.
+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
@@ -18,119 +18,67 @@
*/
package org.rhq.plugins.samba;
-import java.util.Date;
-import java.util.List;
-import java.util.Set;
-
import net.augeas.Augeas;
-
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.MeasurementReport;
-import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
-import org.rhq.core.pluginapi.configuration.ConfigurationFacet;
+import org.rhq.core.domain.resource.CreateResourceHistory;
import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
-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.system.ProcessExecution;
-import org.rhq.core.system.ProcessExecutionResults;
+import org.rhq.core.pluginapi.inventory.CreateResourceReport;
+import org.rhq.plugins.augeas.AugeasConfigurationComponent;
+import org.rhq.plugins.augeas.helper.AugeasNode;
+
+import java.util.List;
/**
- * @author Greg Hinkle
+ * TODO
*/
-public class SambaShareComponent implements ResourceComponent<SambaServerComponent>, ConfigurationFacet,
- MeasurementFacet {
+public class SambaShareComponent extends AugeasConfigurationComponent<SambaServerComponent> {
+ public static final String TARGET_NAME_PROP = "targetName";
- private ResourceContext<SambaServerComponent> resourceContext;
+ public static final String NAME_RESOURCE_CONFIG_PROP = "name";
- private static String[] PROPERTIES = { "path", "comment", "public", "browseable", "writable", "printable",
- "write list", "guest ok", "share modes", "printable", "valid users" };
+ static final String RESOURCE_TYPE_NAME = "Samba Share";
- public void start(ResourceContext<SambaServerComponent> sambaServerComponentResourceContext)
- throws InvalidPluginConfigurationException, Exception {
- this.resourceContext = sambaServerComponentResourceContext;
+ public void start(ResourceContext<SambaServerComponent> resourceContext) throws Exception {
+ super.start(resourceContext);
}
- public void stop() {
+ @Override
+ protected String getResourceConfigurationRootPath() {
+ Configuration pluginConfig = getResourceContext().getPluginConfiguration();
+ String targetName = pluginConfig.getSimple(TARGET_NAME_PROP).getStringValue();
+ String targetPath = "/files/etc/samba/smb.conf/target[.='" + targetName + "']";
+ AugeasNode targetNode = new AugeasNode(targetPath);
+ Augeas augeas = getAugeas();
+ augeas.load();
+ List<String> matches = augeas.match(targetNode.getPath());
+ return matches.get(0);
+ }
+ public void stop() {
+ super.stop();
}
public AvailabilityType getAvailability() {
- return null;
+ return super.getAvailability();
}
public Configuration loadResourceConfiguration() throws Exception {
- String path = getAugeasPath();
- Augeas augeas = this.resourceContext.getParentResourceComponent().getAugeas();
-
- List<String> matches = augeas.match(path);
-
- // Parse out the properties
- Configuration configuration = new Configuration();
- configuration.setNotes("Loaded from Augeas at " + new Date());
-
- for (String prop : PROPERTIES) {
- String value = augeas.get(path + "/" + prop.replaceAll(" ", "\\\\ "));
- configuration.put(new PropertySimple(prop, value));
- }
-
- return configuration;
+ Configuration resourceConfig = super.loadResourceConfiguration();
+ Configuration pluginConfig = getResourceContext().getPluginConfiguration();
+ String targetName = pluginConfig.getSimple(TARGET_NAME_PROP).getStringValue();
+ resourceConfig.put(new PropertySimple(NAME_RESOURCE_CONFIG_PROP, targetName));
+ return resourceConfig;
}
public void updateResourceConfiguration(ConfigurationUpdateReport report) {
- try {
- String path = getAugeasPath();
- Augeas augeas = this.resourceContext.getParentResourceComponent().getAugeas();
-
- // Parse out the properties
- Configuration configuration = report.getConfiguration();
- for (String prop : PROPERTIES) {
- augeas.set(path + "/" + prop.replaceAll(" ", "\\\\ "), configuration.getSimpleValue(prop, ""));
- }
- } catch (Exception e) {
- report.setErrorMessageFromThrowable(e);
- }
+ super.updateResourceConfiguration(report);
}
- private String getAugeasPath() throws Exception {
- SambaServerComponent serverComponent = this.resourceContext.getParentResourceComponent();
-
- Augeas augeas = serverComponent.getAugeas();
-
- String path = null;
- for (String p : augeas.match(serverComponent.getAugeasPath())) {
- if (this.resourceContext.getResourceKey().equals(augeas.get(p))) {
- path = p;
- }
- }
-
- return path;
+ public void deleteResource() throws Exception {
+ super.deleteResource();
}
- public void getValues(MeasurementReport report, Set<MeasurementScheduleRequest> metrics) throws Exception {
- ProcessExecution exec = new ProcessExecution("smbstatus");
- exec.setArguments(new String[] { "-S" });
- exec.setCaptureOutput(true);
-
- ProcessExecutionResults results = this.resourceContext.getSystemInformation().executeProcess(exec);
-
- String output = results.getCapturedOutput();
-
- String[] lines = output.split("\\n");
- boolean dataLines = false;
- int count = 0;
- for (String line : lines) {
- if (!dataLines && line.startsWith("--------------")) {
- dataLines = true;
- continue;
- }
- // String[] row = line.split("\\s", 4);
-
- count++;
- }
-
- }
}
diff --git a/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaShareDiscoveryComponent.java b/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaShareDiscoveryComponent.java
index 501eb2e..5fc3b4f 100644
--- a/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaShareDiscoveryComponent.java
+++ b/modules/plugins/samba/src/main/java/org/rhq/plugins/samba/SambaShareDiscoveryComponent.java
@@ -29,10 +29,8 @@ import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertySimple;
-/**
- * @author Greg Hinkle
- */
public class SambaShareDiscoveryComponent implements ResourceDiscoveryComponent<SambaServerComponent> {
@@ -44,28 +42,23 @@ public class SambaShareDiscoveryComponent implements ResourceDiscoveryComponent<
SambaServerComponent serverComponent = discoveryContext.getParentResourceComponent();
Augeas augeas = serverComponent.getAugeas();
- String augeasPath = serverComponent.getAugeasPath();
+ augeas.load();
- List<String> matches = augeas.match(augeasPath);
+ List<String> matches = augeas.match("/files/etc/samba/smb.conf/target[. != 'global']");
for (String match : matches) {
- if (match.startsWith("target")) {
- String name = augeas.get(match);
- if (!name.equals("global")) {
-
- Configuration config = discoveryContext.getDefaultPluginConfiguration();
-
- DiscoveredResourceDetails detail = new DiscoveredResourceDetails(
+ String name = augeas.get(match);
+ Configuration pluginConfig = discoveryContext.getDefaultPluginConfiguration();
+ pluginConfig.put(new PropertySimple("targetName", name));
+ DiscoveredResourceDetails detail = new DiscoveredResourceDetails(
discoveryContext.getResourceType(),
- name,
- name + " share",
- null,
- "Samba Share [" + name + "]",
- config,
- null
- );
- details.add(detail);
- }
- }
+ name,
+ name + " share",
+ null,
+ "Samba Share [" + name + "]",
+ pluginConfig,
+ null
+ );
+ details.add(detail);
}
return details;
diff --git a/modules/plugins/samba/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/samba/src/main/resources/META-INF/rhq-plugin.xml
index 72a2272..a98da65 100644
--- a/modules/plugins/samba/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/samba/src/main/resources/META-INF/rhq-plugin.xml
@@ -1,3 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
<plugin name="Samba"
displayName="Samba"
description="Support for RHEL Samba service"
@@ -9,49 +11,27 @@
<depends plugin="Augeas"/>
<server name="Samba Server"
- description="The static table lookup for host names"
+ description="Configuration for Samba Server"
discovery="SambaServerDiscoveryComponent"
class="SambaServerComponent">
- <plugin-configuration>
- <c:group name="augeas" displayName="Augeas Settings">
- <c:simple-property name="lenses-path" displayName="Augeas Lenses Path"
- default="/usr/share/augeas/lenses" required="true"
- description="Full path to the augeas lenses directory"/>
- <c:simple-property name="root-path" displayName="Augeas Root Path" default="/" required="true"
- description="Path from which augeas should begin to search for configuration files. Example: /"/>
- </c:group>
- <c:group name="samba" displayName="Samba Settings">
- <c:simple-property name="smb-path" displayName="Samba Config File Path" required="true"
- default="/etc/samba/smb.conf" description="Location of the samba file."/>
- <c:simple-property name="augeas-smb-path" displayName="Augeas Samba Tree Path" required="true"
- default="/files/etc/samba/smb.conf/target[.='global']" description="Augeas tree location of the samba configuration values."/>
- </c:group>
- </plugin-configuration>
-
- <metric property="NetworkStat.tcpInboundTotal" displayName="TCP Inbound Connections" displayType="summary"/>
- <metric property="NetworkStat.tcpOutboundTotal" displayName="TCP Outbound Connections" displayType="summary"/>
- <metric property="NetworkStat.allInboundTotal" displayName="All Inbound Connections" displayType="summary"/>
- <metric property="NetworkStat.allOutboundTotal" displayName="All Outbound Connections" displayType="summary"/>
- <metric property="NetworkStat.tcpEstablished" displayName="State ESTABLISHED"/>
- <metric property="NetworkStat.tcpSynSent" displayName="State SYN_SENT"/>
- <metric property="NetworkStat.tcpSynRecv" displayName="State SYN_RECV"/>
- <metric property="NetworkStat.tcpFinWait1" displayName="State FIN_WAIT1"/>
- <metric property="NetworkStat.tcpFinWait2" displayName="State FIN_WAIT2"/>
- <metric property="NetworkStat.tcpTimeWait" displayName="State TIME_WAIT"/>
- <metric property="NetworkStat.tcpClose" displayName="State CLOSE"/>
- <metric property="NetworkStat.tcpCloseWait" displayName="State CLOSE_WAIT"/>
- <metric property="NetworkStat.tcpLastAck" displayName="State LAST_ACK"/>
- <metric property="NetworkStat.tcpListen" displayName="State LISTEN"/>
- <metric property="NetworkStat.tcpClosing" displayName="State CLOSING"/>
- <metric property="NetworkStat.tcpIdle" displayName="State IDLE"/>
- <metric property="NetworkStat.tcpBound" displayName="State BOUND"/>
+ <plugin-configuration>
+ <c:simple-property name="augeasModuleName" displayName="Augeas Module Name" default="Samba" required="true" readOnly="true"
+ description="the name of the Augeas module/lens to use for loading and updating this resource's configuration"/>
+
+ <c:simple-property name="configurationFilesInclusionPatterns" displayName="File Path" type="file" required="true" readOnly="true"
+ default="/etc/samba/smb.conf"
+ description="the absolute path of the samba configuration"/>
+
+ <c:simple-property name="resourceConfigurationRootNode" required="true" readOnly="true"
+ default="/files/etc/samba/smb.conf/target[.='global']"/>
+ </plugin-configuration>
<resource-configuration>
<c:group name="Basic Configurations">
-
- <c:simple-property name="workgroup" description="The workgroup of this computer" required="false"/>
- <c:simple-property name="server string" description="A description of this computer" required="false"/>
+
+ <c:simple-property name="workgroup" description="The workgroup your server will appear to be in when queried by clients" required="false"/>
+ <c:simple-property name="server string" description="Value that will display in the printer comment box in print manager" required="false"/>
</c:group>
@@ -64,37 +44,46 @@
<c:option value="user"/>
</c:property-options>
</c:simple-property>
-
+
<c:simple-property name="encrypt passwords" type="boolean" required="false" description="This option must be enabled if the clients are connecting from a Windows 98, Windows NT 4.0 with Service Pack 3, or other more recent versions of Microsoft Windows. The passwords are transfered between the server and the client in an encrypted format instead of in as a plain-text word that can be intercepted."/>
-
+
</c:group>
-
+
<c:group name="Printing">
- <c:simple-property name="load printers" displayName="Printing Enabled" type="boolean"/>
- <c:simple-property name="cups options" required="false"/>
-
+ <c:simple-property name="load printers" required="false" displayName="Printing Enabled" type="boolean" description="Controls whether all printers in the printcap will be loaded for browsing by default"/>
+ <c:simple-property name="cups options" required="false" description="Free form string of options passed to cups library"/>
+
</c:group>
</resource-configuration>
-<!--
- <service name="SambaShare" description="Shares on Samba"
- discovery="SambaShareDiscoveryComponent" class="SambaShareComponent">
-
- <metric property="connections" description="The count of active connections to this share"/>
-
+
+ <service name="Samba Share" description="a Samba share"
+ discovery="SambaShareDiscoveryComponent" class="SambaShareComponent"
+ createDeletePolicy="both">
+
+ <plugin-configuration>
+ <c:simple-property name="augeasModuleName" displayName="Augeas Module Name" default="Samba" required="true" readOnly="true"
+ description="the name of the Augeas lens to use for loading and updating this resource's configuration"/>
+
+ <c:simple-property name="configurationFilesInclusionPatterns" displayName="File Path" type="file" required="true" readOnly="true"
+ default="/etc/samba/smb.conf"
+ description="the absolute path of the samba configuration"/>
+
+ <c:simple-property name="targetName" required="true" readOnly="true"/>
+ </plugin-configuration>
+
<resource-configuration>
- <c:simple-property name="path" required="true"/>
- <c:simple-property name="comment" required="false"/>
- <c:simple-property name="public" type="boolean" required="false"/>
- <c:simple-property name="browseable" type="boolean" required="false"/>
- <c:simple-property name="writable" type="boolean" required="false"/>
- <c:simple-property name="printable" type="boolean" required="false"/>
- <c:simple-property name="write list" required="false"/>
- <c:simple-property name="guest ok" type="boolean" required="false"/>
- <c:simple-property name="share modes" />
- <c:simple-property name="valid users" required="false"/>
+ <c:simple-property name="name" required="true" readOnly="true" description="Name of share"/>
+ <c:simple-property name="path" required="false" description="Directory to which the user of the service is to be given access"/>
+ <c:simple-property name="comment" required="false" description="Comment string to associate with the new share"/>
+ <c:simple-property name="browseable" type="boolean" required="false" description="Controls whether this share is seen in the list of available shares"/>
+ <c:simple-property name="read only" type="boolean" required="false" description="Users of service may not create or modify files"/>
+ <c:simple-property name="printable" type="boolean" required="false" description="Clients may open, write to and submit spool files on the service directory "/>
+ <c:simple-property name="write list" required="false" description="List of users that are given read-write access to the service"/>
+ <c:simple-property name="guest ok" type="boolean" required="false" description="No password is required to connect"/>
+ <c:simple-property name="share modes" required="false" description="Enables or disables the honoring of the share modes during a file open"/>
+ <c:simple-property name="valid users" required="false" description="List of users that should be allowed to login to this service"/>
</resource-configuration>
</service>
--->
</server>
</plugin>
diff --git a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
index 3291399..7e55df7 100644
--- a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
+++ b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
@@ -18,79 +18,34 @@
*/
package org.rhq.plugins.samba;
-import java.util.Collection;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.testng.annotations.BeforeSuite;
-import org.testng.annotations.Test;
-
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.plugins.augeas.AbstractAugeasConfigurationComponentTest;
-/**
- * @author Jason Dobies
- */
-public class SambaComponentTest {
+public class SambaComponentTest extends AbstractAugeasConfigurationComponentTest {
- private SambaServerComponent component = new SambaServerComponent();
- private Configuration pluginConfiguration = new Configuration();
+ @Override
+ protected Configuration getExpectedResourceConfig() {
+ Configuration config = new Configuration();
- private final Log log = LogFactory.getLog(this.getClass());
+ config.put(new PropertySimple("workgroup", "SCOOBY"));
+ config.put(new PropertySimple("server string", "MysteryMachine"));
+ config.put(new PropertySimple("security", "user"));
+ config.put(new PropertySimple("encrypt passwords", "yes"));
+ config.put(new PropertySimple("load printers", "yes"));
+ config.put(new PropertySimple("cups options", "raw"));
- @BeforeSuite
- public void initPluginConfiguration() throws Exception {
- pluginConfiguration.put(new PropertySimple("lenses-path", "/usr/share/augeas/lenses"));
- pluginConfiguration.put(new PropertySimple("root-path", "/"));
- pluginConfiguration.put(new PropertySimple("hosts-path", "/etc/hosts"));
- pluginConfiguration.put(new PropertySimple("augeas-hosts-path", "/files/etc/hosts/*"));
+ return config;
}
-
- @Test
- public void dummyTest() {
- // Fake test to get maven to be happy with no tests in here
- // Spearhead team is working on setting up an augeas based test framework
- // which will fix this test
+ @Override
+ protected String getPluginName() {
+ return "Samba";
}
- public void loadResourceConfiguration() throws Exception {
- // Just bail because this test wont work yet
- if (true) {
- return;
- }
- Configuration configuration;
- try {
- configuration = component.loadResourceConfiguration(pluginConfiguration);
- } catch (UnsatisfiedLinkError ule) {
- // Skip tests if augeas not available
- return;
- }
-
- assert configuration != null : "Null configuration returned from load call";
-
- Collection<Property> allProperties = configuration.getProperties();
-
- assert allProperties.size() == 1 : "Incorrect number of properties found. Expected: 1, Found: "
- + allProperties.size();
-
- PropertyList entryList = (PropertyList) allProperties.iterator().next();
-
- for (Property property : entryList.getList()) {
- PropertyMap entry = (PropertyMap) property;
-
- Property ipProperty = entry.get("ip");
- Property canonicalProperty = entry.get("canonical");
-
- assert ipProperty != null : "IP was null in entry";
- assert canonicalProperty != null : "Canonical was null in entry";
-
- log.info("IP: " + ((PropertySimple) ipProperty).getStringValue());
- log.info("Canonical: " + ((PropertySimple) canonicalProperty).getStringValue());
- }
-
+ @Override
+ protected String getResourceTypeName() {
+ return "Samba Server";
}
}
diff --git a/modules/plugins/samba/src/test/resources/etc/samba/smb.conf b/modules/plugins/samba/src/test/resources/etc/samba/smb.conf
new file mode 100644
index 0000000..376f6fd
--- /dev/null
+++ b/modules/plugins/samba/src/test/resources/etc/samba/smb.conf
@@ -0,0 +1,8 @@
+# integration test smb.conf for samba plugin
+[global]
+ workgroup = SCOOBY
+ server string = MysteryMachine
+ security = user
+ encrypt passwords = yes
+ load printers = yes
+ cups options = raw
diff --git a/modules/plugins/sudoers/pom.xml b/modules/plugins/sudoers/pom.xml
index db87c64..d8a677f 100644
--- a/modules/plugins/sudoers/pom.xml
+++ b/modules/plugins/sudoers/pom.xml
@@ -37,6 +37,13 @@
<artifactId>rhq-augeas-plugin</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-augeas-plugin</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<profiles>
@@ -64,14 +71,6 @@
<mkdir dir="target/itest" />
<mkdir dir="target/itest/plugins" />
<mkdir dir="target/itest/lib" />
- <copy toDir="target/itest/plugins" flatten="true">
- <fileset dir="${settings.localRepository}/">
- <include name="org/rhq/rhq-platform-plugin/${project.version}/rhq-platform-plugin-${project.version}.jar" />
- </fileset>
- <fileset dir="${project.build.directory}">
- <include name="${project.artifactId}-${project.version}.jar" />
- </fileset>
- </copy>
<unzip dest="target/itest/lib">
<fileset dir="${settings.localRepository}/org/hyperic/sigar-dist/${sigar.version}" includes="*.zip" />
<patternset>
@@ -97,6 +96,37 @@
</execution>
</executions>
</plugin>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-platform-plugin</artifactId>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-augeas-plugin</artifactId>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+ <artifactId>${project.artifactId}</artifactId>
+ <version>${project.version}</version>
+ </artifactItem>
+ </artifactItems>
+ <outputDirectory>target/itest/plugins</outputDirectory>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
<!-- Integration testing voodoo to load and test this plugin with its plugin dependencies -->
<plugin>
diff --git a/modules/plugins/sudoers/src/main/java/org/rhq/plugins/sudoers/SudoersComponent.java b/modules/plugins/sudoers/src/main/java/org/rhq/plugins/sudoers/SudoersComponent.java
index 94bd969..88f9faf 100644
--- a/modules/plugins/sudoers/src/main/java/org/rhq/plugins/sudoers/SudoersComponent.java
+++ b/modules/plugins/sudoers/src/main/java/org/rhq/plugins/sudoers/SudoersComponent.java
@@ -18,10 +18,54 @@
*/
package org.rhq.plugins.sudoers;
+import java.util.List;
+
+import net.augeas.Augeas;
+
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
import org.rhq.plugins.augeas.AugeasConfigurationComponent;
+import org.rhq.plugins.augeas.helper.AugeasNode;
/**
* @author Partha Aji
*/
public class SudoersComponent extends AugeasConfigurationComponent {
+ @Override
+ protected Object toPropertyValue(PropertyDefinitionSimple propDefSimple, Augeas augeas, AugeasNode node) {
+ if ("tag".equals(node.getName())) {
+ return !"NOPASSWD".equals(augeas.get(node.getPath()));
+ }
+ return super.toPropertyValue(propDefSimple, augeas, node);
+ }
+
+ @Override
+ protected String toNodeValue(Augeas augeas, AugeasNode node, PropertyDefinitionSimple propDefSimple,
+ PropertySimple propSimple) {
+ if ("tag".equals(node.getName())) {
+ if (propSimple.getBooleanValue()) {
+ return "PASSWD";
+ }
+ return "NOPASSWD";
+ }
+
+ return super.toNodeValue(augeas, node, propDefSimple, propSimple);
+ }
+
+ protected AugeasNode getExistingChildNodeForListMemberPropertyMap(AugeasNode parentNode,
+ PropertyDefinitionList propDefList, PropertyMap propMap) {
+ // First find all child nodes with the same 'spec' value as the PropertyMap.
+ Augeas augeas = getAugeas();
+
+ String userName = propMap.getSimple("user").getStringValue();
+ String specFilter = parentNode.getPath() + "/spec";
+ List<String> userPaths = augeas.match(String.format(specFilter + "/user[.='%s']", userName));
+ if (userPaths == null || userPaths.isEmpty()) {
+ return null;
+ }
+ AugeasNode node = new AugeasNode(userPaths.get(0));
+ return node.getParent();
+ }
}
diff --git a/modules/plugins/sudoers/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/sudoers/src/main/resources/META-INF/rhq-plugin.xml
index c72d01d..27b36d4 100644
--- a/modules/plugins/sudoers/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/sudoers/src/main/resources/META-INF/rhq-plugin.xml
@@ -29,14 +29,16 @@
<plugin-configuration>
<c:simple-property name="augeasModuleName" displayName="Augeas Module Name" default="Sudoers" required="true" readOnly="true"
description="the name of the Augeas module/lens to use for loading and updating this resource's configuration"/>
- <c:simple-property name="configurationFile" displayName="Sudoers File Path" required="true" readOnly="true"
- default="/etc/sudoers" description="Location of the sudoers file."/>
+ <c:simple-property name="configurationFilesInclusionPatterns" displayName="Sudoers File Path" required="true" readOnly="true"
+ default="/etc/sudoers" description="Location of the sudoers file."/>
+ <c:simple-property name="resourceConfigurationRootNode" required="true" readOnly="true"
+ default="/files/etc/sudoers"/>
</plugin-configuration>
<resource-configuration>
<c:list-property name="." displayName="Entries">
- <c:map-property name="spec[*]">
- <c:simple-property name="user" displayName="User/Group" type="string" required="true" activationPolicy="immediate"
+ <c:map-property name="spec">
+ <c:simple-property name="user" displayName="User/Group" type="string" required="true" readOnly="true" activationPolicy="immediate"
description="The User/User Alias/Group/Group Alias who needs to be given access to run a command. Alternatively you can specify aliases defined using User_Alias. Eg: if you had this defined previously User_Alias OPERATORS = joe, mike, jude - You could enter OPERATORS for the user"/>
<c:simple-property name="host_group/host" displayName="Host Alias" type="string" required="true" activationPolicy="immediate"
description="The Host alias of the terminal from which the above user can run the given command. Set it to ALL if the user is allowed to execute from any host. Alternatively if you have a Host_Alias defined you can use that here. Eg: if you defined Host_Alias OFNET = 10.1.2.0/255.255.255.0 - you could use "OFNET'" here"/>
@@ -44,7 +46,7 @@
description="The Command/Command Alias that the specified user is allowed to execute from the specified hosts. Set it to ALL if the user is allowed to execute any command. Alternatively if you have a Cmnd_Alias defined you can use that here. Eg:if you defined Cmnd_Alias NETWORKING = /sbin/route, /sbin/ifconfig, /bin/ping, /sbin/dhclient, /usr/bin/net, /sbin/iptables - in /etc/sudoers you can specify NETWORKING here."/>
<c:simple-property name="host_group/command/runas_user" displayName="Run as User" type="string" required="false" activationPolicy="immediate"
description="The User name/Run Alias of the user the specified command will be run as. For example if you wanted the command to be run as user 'foo' you would specify foo here. Set it to ALL if the user is allowed to execute the command as any user. Alternatively if you have a Run_Alias defined you can use that here. Eg:if you defined Runas_Alias OP = root, operator - in /etc/sudoers you can specify OP here."/>
- <c:simple-property name="host_group/command/tag" displayName="Require Password" type="string" required="false" activationPolicy="immediate"
+ <c:simple-property name="host_group/command/tag" displayName="Tag Specification" type="boolean" required="false" activationPolicy="immediate"
description="True if password is required to execute the command. False otherwise."/>
</c:map-property>
</c:list-property>
diff --git a/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java b/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
index 211a7ed..f27ac40 100644
--- a/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
+++ b/modules/plugins/sudoers/src/test/java/org/rhq/plugins/sudoers/SudoersComponentTest.java
@@ -18,71 +18,64 @@
*/
package org.rhq.plugins.sudoers;
-import java.util.Collection;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.testng.annotations.BeforeSuite;
-import org.testng.annotations.Test;
-
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.plugins.augeas.AbstractAugeasConfigurationComponentTest;
/**
* @author Partha Aji
*/
-public class SudoersComponentTest {
-
- private SudoersComponent component = new SudoersComponent();
-
- private Configuration pluginConfiguration = new Configuration();
-
- private final Log log = LogFactory.getLog(this.getClass());
-
- @BeforeSuite
- public void initPluginConfiguration() throws Exception {
- pluginConfiguration.put(new PropertySimple("lenses-path", "/usr/local/share/augeas/lenses"));
- pluginConfiguration.put(new PropertySimple("root-path", "/tmp"));
- pluginConfiguration.put(new PropertySimple("sudoers-path", "/etc/sudoers"));
- pluginConfiguration.put(new PropertySimple("augeas-sudoers-path", "/files/etc/sudoers/spec[*]"));
+public class SudoersComponentTest extends AbstractAugeasConfigurationComponentTest {
+
+ @Override
+ protected Configuration getExpectedResourceConfig() {
+ Configuration config = new Configuration();
+ PropertyList entries = new PropertyList(".");
+ config.put(entries);
+ PropertyMap entry;
+ entry = new PropertyMap("spec");
+ entry.put(new PropertySimple("user", "root"));
+ entry.put(new PropertySimple("host_group/host", "ALL"));
+ entry.put(new PropertySimple("host_group/command", "ALL"));
+ entry.put(new PropertySimple("host_group/command/runas_user", "ALL"));
+ entry.put(new PropertySimple("host_group/command/tag", true));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("spec");
+ entry.put(new PropertySimple("user", "%wheel"));
+ entry.put(new PropertySimple("host_group/host", "ALL"));
+ entry.put(new PropertySimple("host_group/command", "ALL"));
+ entry.put(new PropertySimple("host_group/command/runas_user", "ALL"));
+ entry.put(new PropertySimple("host_group/command/tag", false));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("spec");
+ entry.put(new PropertySimple("user", "apache"));
+ entry.put(new PropertySimple("host_group/host", "ALL"));
+ entry.put(new PropertySimple("host_group/command", "/bin/env"));
+ entry.put(new PropertySimple("host_group/command/runas_user", "root"));
+ entry.put(new PropertySimple("host_group/command/tag", false));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("spec");
+ entry.put(new PropertySimple("user", "foo"));
+ entry.put(new PropertySimple("host_group/host", "ALL"));
+ entry.put(new PropertySimple("host_group/command", "NETWORKING"));
+ entry.put(new PropertySimple("host_group/command/runas_user", "root"));
+ entry.put(new PropertySimple("host_group/command/tag", true));
+ entries.getList().add(entry);
+ return config;
}
- @Test(enabled = false)
- public void loadResourceConfiguration() throws Exception {
- Configuration configuration;
- try {
- configuration = component.loadResourceConfiguration();
- } catch (UnsatisfiedLinkError ule) {
- // Skip tests if augeas not available
- return;
- }
-
- assert configuration != null : "Null configuration returned from load call";
-
- Collection<Property> allProperties = configuration.getProperties();
-
- assert allProperties.size() == 1 : "Incorrect number of properties found. Expected: 1, Found: "
- + allProperties.size();
-
- PropertyList entryList = (PropertyList) allProperties.iterator().next();
-
- for (Property property : entryList.getList()) {
- PropertyMap entry = (PropertyMap) property;
-
- Property user = entry.get("user");
- Property host = entry.get("host");
-
- assert user != null : "IP was null in entry";
- assert host != null : "Canonical was null in entry";
-
- System.out.println(entry);
-
- log.info("USER: " + ((PropertySimple) user).getStringValue());
- log.info("host: " + ((PropertySimple) host).getStringValue());
- }
+ @Override
+ protected String getPluginName() {
+ return "Sudoers";
+ }
+ @Override
+ protected String getResourceTypeName() {
+ return "Sudoers";
}
}
diff --git a/modules/plugins/sudoers/src/test/resources/etc/sudoers b/modules/plugins/sudoers/src/test/resources/etc/sudoers
new file mode 100644
index 0000000..58581de
--- /dev/null
+++ b/modules/plugins/sudoers/src/test/resources/etc/sudoers
@@ -0,0 +1,11 @@
+## Sudoers allows particular users to run various commands as
+## the root user, without needing the root password.
+## Command Aliases
+## These are groups of related commands...
+## Networking
+Cmnd_Alias NETWORKING = /sbin/route, /sbin/ifconfig, /bin/ping, /sbin/dhclient, /usr/bin/net, /sbin/iptables, /usr/bin/rfcomm, /usr/bin/wvdial, /sbin/iwconfig, /sbin/mii-tool
+root ALL=(ALL) PASSWD : ALL
+%wheel ALL=(ALL) NOPASSWD: ALL
+apache ALL=(root) NOPASSWD: /bin/env
+foo ALL=(root) NETWORKING
+
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
index d38d48b..f6fa791 100644
--- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
+++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/TomcatWarDiscoveryComponent.java
@@ -36,6 +36,7 @@ import org.apache.commons.logging.LogFactory;
import org.jboss.on.plugins.tomcat.helper.CreateResourceHelper;
import org.mc4j.ems.connection.EmsConnection;
import org.mc4j.ems.connection.bean.EmsBean;
+import org.mc4j.ems.connection.bean.attribute.EmsAttribute;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.resource.ResourceType;
@@ -90,8 +91,10 @@ public class TomcatWarDiscoveryComponent extends MBeanResourceDiscoveryComponent
EmsBean warBean = connection.getBean(resource.getResourceKey());
// this refresh is important in case EMS is caching a stale version of this object. It can happen if
// a user deletes and then recreates the same object.
- String contextRoot = (String) warBean.refreshAttributes(EMS_ATTRIBUTE_PATH).get(0).getValue();
- String docBase = (String) warBean.refreshAttributes(EMS_ATTRIBUTE_DOC_BASE).get(0).getValue();
+ List<EmsAttribute> contextRootAttribs = warBean.refreshAttributes(EMS_ATTRIBUTE_PATH);
+ String contextRoot = (String) contextRootAttribs.get(0).getValue();
+ List<EmsAttribute> docBaseAttribs = warBean.refreshAttributes(EMS_ATTRIBUTE_DOC_BASE);
+ String docBase = (String) docBaseAttribs.get(0).getValue();
File docBaseFile = new File(docBase);
String filename = (docBaseFile.isAbsolute()) ? docBase
: (deployDirectoryPath + File.separator + docBase);
@@ -217,7 +220,7 @@ public class TomcatWarDiscoveryComponent extends MBeanResourceDiscoveryComponent
* JMX discovered applications.
*
* @param defaultConfiguration default plugin configuration for the application's resource type
- * @param contextRoot contextRoot of the web app
+ * @param name name of the web app
*
* @return resource key to use for the indicated application file
*/
diff --git a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/helper/TomcatApplicationDeployer.java b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/helper/TomcatApplicationDeployer.java
index fde0933..2421969 100644
--- a/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/helper/TomcatApplicationDeployer.java
+++ b/modules/plugins/tomcat/src/main/java/org/jboss/on/plugins/tomcat/helper/TomcatApplicationDeployer.java
@@ -22,10 +22,6 @@
*/
package org.jboss.on.plugins.tomcat.helper;
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mc4j.ems.connection.EmsConnection;
@@ -59,7 +55,7 @@ public class TomcatApplicationDeployer {
public void deploy(String contextPath) throws DeployerException {
log.debug("Servicing " + contextPath + "...");
try {
- this.deployOperation.invoke(contextPath);
+ this.deployOperation.invoke(new Object[] {contextPath});
} catch (RuntimeException e) {
throw new DeployerException("Failed to service " + contextPath, e);
}
@@ -68,7 +64,7 @@ public class TomcatApplicationDeployer {
public void undeploy(String contextPath) throws DeployerException {
log.debug("Undeploying " + contextPath + "...");
try {
- this.undeployOperation.invoke(contextPath);
+ this.undeployOperation.invoke(new Object[] {contextPath});
} catch (RuntimeException e) {
throw new DeployerException("Failed to undeploy " + contextPath, e);
}
commit c2ea9fb491ae6cc84895e1eb0cfbd35fcfb4dd9c
Author: Pradeep Kilambi <pkilambi(a)redhat.com>
Date: Fri Nov 6 12:43:51 2009 -0500
create delete distro tests
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java
index 08ce133..f2d51ab 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java
@@ -75,11 +75,9 @@ public class DistributionManagerBean implements DistributionManagerLocal, Distri
throws DistributionException {
Distribution kstree = new Distribution(kslabel, basepath, disttype);
- System.out.println("NEW DISTRO CREATED" + kstree);
- validateDistTree(kstree);
+ validateDistTree(kstree);
entityManager.persist(kstree);
- System.out.println("persisted" + kstree);
return kstree;
}
@@ -104,7 +102,6 @@ public class DistributionManagerBean implements DistributionManagerLocal, Distri
}
- @RequiredPermission(Permission.MANAGE_INVENTORY)
public void deleteDistributionByDistId(Subject user, int distId) {
log.debug("User [" + user + "] is deleting distribution tree [" + distId + "]");
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java
new file mode 100644
index 0000000..cb06066
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/DistributionManagerBeanTest.java
@@ -0,0 +1,60 @@
+package org.rhq.enterprise.server.content.test;
+
+import javax.transaction.TransactionManager;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.content.Distribution;
+import org.rhq.core.domain.content.DistributionType;
+import org.rhq.enterprise.server.content.DistributionManagerLocal;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * @author Pradeep Kilambi
+ */
+public class DistributionManagerBeanTest extends AbstractEJB3Test {
+ private final static boolean ENABLED = true;
+ private DistributionManagerLocal distManager;
+ private DistributionType distType;
+ private Subject overlord;
+
+ @BeforeMethod
+ public void setupBeforeMethod() throws Exception {
+ TransactionManager tx = getTransactionManager();
+ tx.begin();
+
+ distManager = LookupUtil.getDistributionManagerLocal();
+ distType = new DistributionType("kickstart");
+
+ overlord = LookupUtil.getSubjectManager().getOverlord();
+ }
+
+ @AfterMethod
+ public void tearDownAfterMethod() throws Exception {
+ TransactionManager tx = getTransactionManager();
+ if (tx != null) {
+ tx.rollback();
+ }
+ }
+
+ @Test(enabled = ENABLED)
+ public void createDeleteDistribution() throws Exception {
+
+ String kslabel = "testCreateDeleteRepo";
+ String kspath = "/tmp";
+ int id = distManager.createDistribution(overlord, kslabel, kspath, distType).getId();
+ Distribution distro = distManager.getDistributionByLabel(kslabel);
+
+ assert distro != null;
+
+ assert id == distro.getId();
+
+ distManager.deleteDistributionByDistId(overlord, id);
+ distro = distManager.getDistributionByLabel(kslabel);
+ assert distro == null;
+ }
+}
commit 64930ddd4c1e51715518c2f2d9e8dc9545b43e45
Author: Sayli Karmarkar <skarmark(a)redhat.com>
Date: Fri Nov 6 12:24:06 2009 -0500
temporarily fixing domain objects to make sure the content branch build successfully until I figure out the problem
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
index c518455..74ad58f 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
@@ -49,8 +49,6 @@ import javax.persistence.PreUpdate;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
-import org.rhq.core.domain.common.Tag;
-import org.rhq.core.domain.common.Taggable;
import org.rhq.core.domain.configuration.Configuration;
/**
@@ -80,7 +78,7 @@ import org.rhq.core.domain.configuration.Configuration;
+ " WHERE ccs.repo.id = :repoId ) ") })
@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_CONTENT_SOURCE_ID_SEQ")
@Table(name = "RHQ_CONTENT_SOURCE")
-public class ContentSource implements Serializable, Taggable {
+public class ContentSource implements Serializable {
public static final String QUERY_FIND_ALL = "ContentSource.findAll";
public static final String QUERY_FIND_ALL_WITH_CONFIG = "ContentSource.findAllWithConfig";
public static final String QUERY_FIND_BY_NAME_AND_TYPENAME = "ContentSource.findByNameAndTypeName";
@@ -140,7 +138,7 @@ public class ContentSource implements Serializable, Taggable {
@OneToMany(mappedBy = "contentSource", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private Set<RepoContentSource> repoContentSources;
- private Set<Tag> tags;
+ //private Set<Tag> tags;
// Constructor
@@ -447,51 +445,51 @@ public class ContentSource implements Serializable, Taggable {
return true;
}
- @Override
- public Set<Tag> getTags() {
- return tags;
- }
-
- @Override
- public void setTags(Set<Tag> tags) {
- this.tags = tags;
- }
-
- @Override
- public boolean hasTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
- return false;
- }
-
- if (name == null) {
- if (tag.getName() != null) {
- return false;
- }
- } else if (!name.equals(tag.getName())) {
- return false;
- }
-
- return true;
-
- }
-
- @Override
- public void addTag(Tag tag) {
- if (this.tags == null) {
- this.tags = new HashSet<Tag>();
- }
-
- this.tags.add(tag);
- }
-
- @Override
- public void removeTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
- return;
- }
-
- if (tags.contains(tag)) {
- tags.remove(tag);
- }
- }
+ // @Override
+ // public Set<Tag> getTags() {
+ // return tags;
+ // }
+ //
+ // @Override
+ // public void setTags(Set<Tag> tags) {
+ // this.tags = tags;
+ // }
+ //
+ // @Override
+ // public boolean hasTag(Tag tag) {
+ // if ((this.tags == null) || (tag == null)) {
+ // return false;
+ // }
+ //
+ // if (name == null) {
+ // if (tag.getName() != null) {
+ // return false;
+ // }
+ // } else if (!name.equals(tag.getName())) {
+ // return false;
+ // }
+ //
+ // return true;
+ //
+ // }
+ //
+ // @Override
+ // public void addTag(Tag tag) {
+ // if (this.tags == null) {
+ // this.tags = new HashSet<Tag>();
+ // }
+ //
+ // this.tags.add(tag);
+ // }
+ //
+ // @Override
+ // public void removeTag(Tag tag) {
+ // if ((this.tags == null) || (tag == null)) {
+ // return;
+ // }
+ //
+ // if (tags.contains(tag)) {
+ // tags.remove(tag);
+ // }
+ // }
}
\ No newline at end of file
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
index 2eeb2ba..a8629fd 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
@@ -24,9 +24,7 @@ package org.rhq.core.domain.content;
import java.io.Serializable;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
@@ -44,9 +42,6 @@ import javax.persistence.Table;
import org.hibernate.annotations.NamedQueries;
import org.hibernate.annotations.NamedQuery;
-import org.rhq.core.domain.common.Tag;
-import org.rhq.core.domain.common.Taggable;
-
/**
* Represents a package inventoried in the system. A package can be created by either a {@link ContentSource} (on the
* server side) or via a plugin discovery (on the agent side). A package has no knowledge of how it was created (i.e. it
@@ -69,7 +64,7 @@ import org.rhq.core.domain.common.Taggable;
+ "AND p.packageType.resourceType.id = :resourceTypeId") })
@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_PACKAGE_ID_SEQ")
@Table(name = "RHQ_PACKAGE")
-public class Package implements Serializable, Taggable {
+public class Package implements Serializable {
// Constants --------------------------------------------
private static final long serialVersionUID = 1L;
@@ -98,7 +93,7 @@ public class Package implements Serializable, Taggable {
@OneToMany(mappedBy = "generalPackage", fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
private List<PackageVersion> versions;
- private Set<Tag> tags;
+ //private Set<Tag> tags;
// Constructor ----------------------------------------
@@ -220,52 +215,52 @@ public class Package implements Serializable, Taggable {
return result;
}
- @Override
- public Set<Tag> getTags() {
- return tags;
- }
-
- @Override
- public void setTags(Set<Tag> tags) {
- this.tags = tags;
- }
-
- @Override
- public boolean hasTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
- return false;
- }
-
- if (name == null) {
- if (tag.getName() != null) {
- return false;
- }
- } else if (!name.equals(tag.getName())) {
- return false;
- }
-
- return true;
-
- }
-
- @Override
- public void addTag(Tag tag) {
- if (this.tags == null) {
- this.tags = new HashSet<Tag>();
- }
-
- this.tags.add(tag);
- }
-
- @Override
- public void removeTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
- return;
- }
-
- if (tags.contains(tag)) {
- tags.remove(tag);
- }
- }
+ // @Override
+ // public Set<Tag> getTags() {
+ // return tags;
+ // }
+ //
+ // @Override
+ // public void setTags(Set<Tag> tags) {
+ // this.tags = tags;
+ // }
+ //
+ // @Override
+ // public boolean hasTag(Tag tag) {
+ // if ((this.tags == null) || (tag == null)) {
+ // return false;
+ // }
+ //
+ // if (name == null) {
+ // if (tag.getName() != null) {
+ // return false;
+ // }
+ // } else if (!name.equals(tag.getName())) {
+ // return false;
+ // }
+ //
+ // return true;
+ //
+ // }
+ //
+ // @Override
+ // public void addTag(Tag tag) {
+ // if (this.tags == null) {
+ // this.tags = new HashSet<Tag>();
+ // }
+ //
+ // this.tags.add(tag);
+ // }
+ //
+ // @Override
+ // public void removeTag(Tag tag) {
+ // if ((this.tags == null) || (tag == null)) {
+ // return;
+ // }
+ //
+ // if (tags.contains(tag)) {
+ // tags.remove(tag);
+ // }
+ // }
}
\ No newline at end of file
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
index a2f9d70..f09faea 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
@@ -41,8 +41,6 @@ import javax.persistence.PreUpdate;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
-import org.rhq.core.domain.common.Tag;
-import org.rhq.core.domain.common.Taggable;
import org.rhq.core.domain.resource.Resource;
/**
@@ -87,7 +85,7 @@ import org.rhq.core.domain.resource.Resource;
+ "AND c.candidate = false ") })
@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_REPO_ID_SEQ")
@Table(name = "RHQ_REPO")
-public class Repo implements Serializable, Taggable {
+public class Repo implements Serializable {
// Constants --------------------------------------------
public static final String QUERY_FIND_ALL_IMPORTED_REPOS = "Repo.findAll";
@@ -141,7 +139,7 @@ public class Repo implements Serializable, Taggable {
@OneToMany(mappedBy = "repo", fetch = FetchType.LAZY)
private Set<RepoRepoRelationship> repoRepoRelationships;
- private Set<Tag> tags;
+ //private Set<Tag> tags;
// Constructor ----------------------------------------
@@ -658,52 +656,52 @@ public class Repo implements Serializable, Taggable {
this.lastModifiedDate = System.currentTimeMillis();
}
- @Override
- public Set<Tag> getTags() {
- return tags;
- }
-
- @Override
- public void setTags(Set<Tag> tags) {
- this.tags = tags;
- }
-
- @Override
- public boolean hasTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
- return false;
- }
-
- if (name == null) {
- if (tag.getName() != null) {
- return false;
- }
- } else if (!name.equals(tag.getName())) {
- return false;
- }
-
- return true;
-
- }
-
- @Override
- public void addTag(Tag tag) {
- if (this.tags == null) {
- this.tags = new HashSet<Tag>();
- }
-
- this.tags.add(tag);
- }
-
- @Override
- public void removeTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
- return;
- }
-
- if (tags.contains(tag)) {
- tags.remove(tag);
- }
- }
-
+ // @Override
+ // public Set<Tag> getTags() {
+ // return tags;
+ // }
+ //
+ // @Override
+ // public void setTags(Set<Tag> tags) {
+ // this.tags = tags;
+ // }
+ //
+ // @Override
+ // public boolean hasTag(Tag tag) {
+ // if ((this.tags == null) || (tag == null)) {
+ // return false;
+ // }
+ //
+ // if (name == null) {
+ // if (tag.getName() != null) {
+ // return false;
+ // }
+ // } else if (!name.equals(tag.getName())) {
+ // return false;
+ // }
+ //
+ // return true;
+ //
+ // }
+ //
+ // @Override
+ // public void addTag(Tag tag) {
+ // if (this.tags == null) {
+ // this.tags = new HashSet<Tag>();
+ // }
+ //
+ // this.tags.add(tag);
+ // }
+ //
+ // @Override
+ // public void removeTag(Tag tag) {
+ // if ((this.tags == null) || (tag == null)) {
+ // return;
+ // }
+ //
+ // if (tags.contains(tag)) {
+ // tags.remove(tag);
+ // }
+ // }
+ //
}
\ No newline at end of file
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
index 56a1499..4b90561 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
@@ -66,8 +66,6 @@ import org.jetbrains.annotations.Nullable;
import org.rhq.core.domain.alert.AlertDefinition;
import org.rhq.core.domain.auth.Subject;
-import org.rhq.core.domain.common.Tag;
-import org.rhq.core.domain.common.Taggable;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PluginConfigurationUpdate;
import org.rhq.core.domain.configuration.ResourceConfigurationUpdate;
@@ -731,7 +729,7 @@ import org.rhq.core.domain.util.serial.ExternalizableStrategy;
@Table(name = "RHQ_RESOURCE")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
-public class Resource implements Comparable<Resource>, Externalizable, Taggable {
+public class Resource implements Comparable<Resource>, Externalizable {
public static final String QUERY_FIND_PROBLEM_RESOURCES_ALERT = "Resource.findProblemResourcesAlert";
public static final String QUERY_FIND_PROBLEM_RESOURCES_ALERT_ADMIN = "Resource.findProblemResourcesAlert_admin";
public static final String QUERY_FIND_PROBLEM_RESOURCES_ALERT_COUNT = "Resource.findProblemResourcesAlertCount";
@@ -1019,7 +1017,7 @@ public class Resource implements Comparable<Resource>, Externalizable, Taggable
@ManyToOne(fetch = FetchType.LAZY)
private ProductVersion productVersion;
- private Set<Tag> tags;
+ //private Set<Tag> tags;
public Resource() {
this.uuid = UUID.randomUUID().toString();
@@ -1812,52 +1810,52 @@ public class Resource implements Comparable<Resource>, Externalizable, Taggable
this.currentAvailability = new ResourceAvailability(this, null);
}
- @Override
- public Set<Tag> getTags() {
- return tags;
- }
-
- @Override
- public void setTags(Set<Tag> tags) {
- this.tags = tags;
- }
-
- @Override
- public boolean hasTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
- return false;
- }
-
- if (name == null) {
- if (tag.getName() != null) {
- return false;
- }
- } else if (!name.equals(tag.getName())) {
- return false;
- }
-
- return true;
-
- }
-
- @Override
- public void addTag(Tag tag) {
- if (this.tags == null) {
- this.tags = new HashSet<Tag>();
- }
-
- this.tags.add(tag);
- }
-
- @Override
- public void removeTag(Tag tag) {
- if ((this.tags == null) || (tag == null)) {
- return;
- }
-
- if (tags.contains(tag)) {
- tags.remove(tag);
- }
- }
-
+ // @Override
+ // public Set<Tag> getTags() {
+ // return tags;
+ // }
+ //
+ // @Override
+ // public void setTags(Set<Tag> tags) {
+ // this.tags = tags;
+ // }
+ //
+ // @Override
+ // public boolean hasTag(Tag tag) {
+ // if ((this.tags == null) || (tag == null)) {
+ // return false;
+ // }
+ //
+ // if (name == null) {
+ // if (tag.getName() != null) {
+ // return false;
+ // }
+ // } else if (!name.equals(tag.getName())) {
+ // return false;
+ // }
+ //
+ // return true;
+ //
+ // }
+ //
+ // @Override
+ // public void addTag(Tag tag) {
+ // if (this.tags == null) {
+ // this.tags = new HashSet<Tag>();
+ // }
+ //
+ // this.tags.add(tag);
+ // }
+ //
+ // @Override
+ // public void removeTag(Tag tag) {
+ // if ((this.tags == null) || (tag == null)) {
+ // return;
+ // }
+ //
+ // if (tags.contains(tag)) {
+ // tags.remove(tag);
+ // }
+ // }
+ //
}
commit 74ccaaf9ba2dcd588eb8fdc440cf01b357a229a3
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Fri Nov 6 12:05:27 2009 -0500
always display the Custom tab, rather than requiring the debug=true request param
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml
index 4420565..eac2995 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml
@@ -31,7 +31,7 @@
<script type="text/javascript" src="/js/popup.js"></script>
<script type="text/javascript" src="/js/iframeSSI.js">
/***********************************************
- * IFrame SSI script II- © Dynamic Drive DHTML code library (http://www.dynamicdrive.com)
+ * IFrame SSI script II- © Dynamic Drive DHTML code library (http://www.dynamicdrive.com)
* Visit DynamicDrive.com for hundreds of original DHTML scripts
* This notice must stay intact for legal use
***********************************************/
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/layout/main.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/layout/main.xhtml
index 6b5d39d..3f5f94e 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/layout/main.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/layout/main.xhtml
@@ -120,9 +120,7 @@ REQUEST PARAMETERS:
</onc:tab>
<onc:tab name="Custom" image="/images/icons/Subcategory_16.png"
- url="/rhq/resource/perspective/index.xhtml"
- rendered="#{param.debug}">
- <f:param name="debug" value="#{param.debug}" />
+ url="/rhq/resource/perspective/index.xhtml">
</onc:tab>
</onc:tabBar>
commit ce57d4e0a7b261b309f0f1020e88eef35f69dde2
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 6 09:48:52 2009 -0500
fix test so we don't really deploy any actual jars
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
index 16a8aea..22cc264 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
@@ -20,8 +20,10 @@ package org.rhq.enterprise.server.test;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
+import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -39,6 +41,7 @@ import org.rhq.enterprise.server.plugin.pc.content.ContentProviderPluginManager;
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.PackageSyncReport;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
* Used as a mock service for the content source plugin container.
@@ -68,6 +71,16 @@ public class TestServerPluginService extends ServerPluginService implements Test
pcs.add(new TestContentServerPluginContainer(this));
return pcs;
}
+
+ @Override
+ protected ClassLoader createRootServerPluginClassLoader() {
+ return this.getClass().getClassLoader();
+ }
+
+ @Override
+ protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
+ return new HashMap<URL, ServerPluginDescriptorType>();
+ }
}
/**
commit 806e366c1ee03df6900c57507cf2b1dee7e8431f
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 6 01:42:53 2009 -0500
fix some minor things the tests flushed out
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index b92d2b8..c477897 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -149,8 +149,10 @@ public class MasterServerPluginContainer {
}
// now shutdown the classloader manager, destroying the classloaders it created
- this.classLoaderManager.shutdown();
- log.debug("Shutdown classloader manager: " + this.classLoaderManager);
+ if (this.classLoaderManager != null) {
+ this.classLoaderManager.shutdown();
+ log.debug("Shutdown classloader manager: " + this.classLoaderManager);
+ }
this.pluginContainers.clear();
this.classLoaderManager = null;
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
index c42c479..16a8aea 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
@@ -88,7 +88,6 @@ public class TestServerPluginService extends ServerPluginService implements Test
@Override
protected ContentProviderPluginManager createPluginManager() {
TestContentProviderPluginManager pm = new TestContentProviderPluginManager(this);
- pm.initialize();
return pm;
}
}
@@ -100,14 +99,6 @@ public class TestServerPluginService extends ServerPluginService implements Test
public TestContentProviderPluginManager(ContentServerPluginContainer pc) {
super(pc);
}
-
- @Override
- public void initialize() {
- }
-
- @Override
- public void shutdown() {
- }
}
/**
commit b50aedfb583d91586ea5441f0e42d5027a33526e
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 6 01:13:19 2009 -0500
it all compiles now, just have to test content plugins to make sure they didn't break
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index 8d9c8ab..ef1085c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -19,6 +19,8 @@
package org.rhq.enterprise.server.plugin.pc;
+import java.util.Collection;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -32,7 +34,7 @@ public abstract class AbstractTypeServerPluginContainer {
private final Log log = LogFactory.getLog(this.getClass());
private final MasterServerPluginContainer master;
- private final PluginManager pluginManager;
+ private PluginManager pluginManager;
/**
* Instantiates the plugin container. All subclasses must support this and only this
@@ -42,41 +44,70 @@ public abstract class AbstractTypeServerPluginContainer {
*/
public AbstractTypeServerPluginContainer(MasterServerPluginContainer master) {
this.master = master;
- this.pluginManager = createPluginManager();
}
/**
+ * Each plugin container will tell the master which plugins it can support via this method; this
+ * method returns the type of plugin that the plugin container can process. Only one
+ * plugin container can support a plugin type.
+ *
+ * @return the type of plugin that this plugin container instance can support
+ */
+ public abstract ServerPluginType getSupportedServerPluginType();
+
+ /**
* Returns the master plugin container that is responsible for managing this instance.
*
* @return this plugin container's master
*/
public MasterServerPluginContainer getMasterServerPluginContainer() {
-
return this.master;
}
/**
- * The initialize method that all plugin container subclasses must implement in order to initialize
- * themselves.
+ * Returns the object that manages the plugins.
*
- * @throws Exception if the plugin container failed to initialize for some reason
+ * @return the plugin manager for this container
*/
- public abstract void initialize() throws Exception;
+ public PluginManager getPluginManager() {
+ return this.pluginManager;
+ }
/**
- * The shutdown method that all plugin container subclasses must implement in order to shutdown
- * themselves.
+ * The initialize method that prepares the plugin container.
+ *
+ * Subclasses are free to perform additional tasks by overriding this method.
+ *
+ * @throws Exception if the plugin container failed to initialize for some reason
*/
- public abstract void shutdown();
+ public void initialize() throws Exception {
+ this.pluginManager = createPluginManager();
+ this.pluginManager.initialize();
+ }
/**
- * Each plugin container will tell the master which plugins it can support via this method; this
- * method returns the type of plugin that the plugin container can process. Only one
- * plugin container can support a plugin type.
+ * The shutdown method that will stop and unload all plugins.
*
- * @return the type of plugin that this plugin container instance can support
+ * Subclasses are free to perform additional tasks by overriding this method.
*/
- public abstract ServerPluginType getSupportedServerPluginType();
+ public void shutdown() {
+ Collection<ServerPluginEnvironment> envs = this.pluginManager.getPluginEnvironments();
+ for (ServerPluginEnvironment env : envs) {
+ try {
+ unloadPlugin(env);
+ } catch (Exception e) {
+ this.log.warn("Failed to unload plugin [" + env.getPluginName() + "].", e);
+ }
+ }
+
+ try {
+ this.pluginManager.shutdown();
+ } finally {
+ this.pluginManager = null;
+ }
+
+ return;
+ }
/**
* Informs the plugin container that it has a plugin that it must being to start managing.
@@ -90,6 +121,18 @@ public abstract class AbstractTypeServerPluginContainer {
}
/**
+ * Informs the plugin container that a plugin should be unloaded and any of its resources
+ * should be released.
+ *
+ * @param env the plugin environment, including the plugin jar and its descriptor
+ *
+ * @throws Exception if failed to unload the plugin
+ */
+ public void unloadPlugin(ServerPluginEnvironment env) throws Exception {
+ this.pluginManager.unloadPlugin(env);
+ }
+
+ /**
* This will be called when its time for this plugin container to create its plugin manager.
* Subclasses are free to override this if they need their own specialized plugin manager.
*
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ClassLoaderManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ClassLoaderManager.java
index aec20ce..7c543b3 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ClassLoaderManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ClassLoaderManager.java
@@ -95,7 +95,11 @@ public class ClassLoaderManager {
public void shutdown() {
for (ClassLoader doomedCL : getUniqueServerPluginClassLoaders()) {
if (doomedCL instanceof ServerPluginClassLoader) {
- ((ServerPluginClassLoader) doomedCL).destroy();
+ try {
+ ((ServerPluginClassLoader) doomedCL).destroy();
+ } catch (Exception e) {
+ log.warn("Failed to destroy classloader: " + doomedCL, e);
+ }
}
}
this.serverPluginClassLoaders.clear();
@@ -107,8 +111,10 @@ public class ClassLoaderManager {
Set<ClassLoader> classLoaders;
StringBuilder str = new StringBuilder(this.getClass().getSimpleName());
+ str.append(" tmp-dir=[").append(this.tmpDir).append(']');
+
classLoaders = getUniqueServerPluginClassLoaders();
- str.append(" [#plugin CLs=").append(classLoaders.size());
+ str.append(", #plugin CLs=[").append(classLoaders.size());
classLoaders.clear(); // help out the GC, clear out the shallow copy container
str.append(']');
@@ -137,12 +143,12 @@ public class ClassLoaderManager {
if (cl == null) {
URL pluginJarUrl = this.pluginNamesUrls.get(pluginName);
- ClassLoader parentClassLoader = this.rootClassLoader;
if (log.isDebugEnabled()) {
log.debug("Creating classloader for plugin [" + pluginName + "] from URL [" + pluginJarUrl + ']');
}
+ ClassLoader parentClassLoader = this.rootClassLoader;
cl = createClassLoader(pluginJarUrl, null, parentClassLoader);
this.serverPluginClassLoaders.put(pluginName, cl);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index c4ced0e..b92d2b8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -22,6 +22,7 @@ import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -55,7 +56,7 @@ public class MasterServerPluginContainer {
*/
public void initialize(MasterServerPluginContainerConfiguration config) {
try {
- log.debug("Master server plugin container has been initialized with config: " + config);
+ log.debug("Master server plugin container is being initialized with config: " + config);
this.configuration = config;
@@ -66,41 +67,59 @@ public class MasterServerPluginContainer {
ClassLoader rootClassLoader = createRootServerPluginClassLoader();
File tmpDir = this.configuration.getTemporaryDirectory();
this.classLoaderManager = createClassLoaderManager(plugins, rootClassLoader, tmpDir);
+ log.debug("Created classloader manager: " + this.classLoaderManager);
// create all known child plugin containers and map them to their supported plugin types
List<AbstractTypeServerPluginContainer> pcs = createPluginContainers();
for (AbstractTypeServerPluginContainer pc : pcs) {
this.pluginContainers.put(pc.getSupportedServerPluginType(), pc);
}
+ log.debug("Created server plugin containers: " + this.pluginContainers.keySet());
// initialize all the plugin containers
- for (Map.Entry<ServerPluginType, AbstractTypeServerPluginContainer> entry : this.pluginContainers
- .entrySet()) {
- log.info("Master PC is initializing plugin container for plugin type [" + entry.getKey() + "]");
+ Iterator<Map.Entry<ServerPluginType, AbstractTypeServerPluginContainer>> iterator;
+ iterator = this.pluginContainers.entrySet().iterator();
+
+ while (iterator.hasNext()) {
+ Map.Entry<ServerPluginType, AbstractTypeServerPluginContainer> entry = iterator.next();
+
+ ServerPluginType pluginType = entry.getKey();
+ AbstractTypeServerPluginContainer pc = entry.getValue();
+
+ log.debug("Master PC is initializing server plugin container for plugin type [" + pluginType + "]");
try {
- entry.getValue().initialize();
+ pc.initialize();
+ log.info("Master PC initialized server plugin container for plugin type [" + pluginType + "]");
} catch (Exception e) {
- log.warn("Failed to initialize plugin container for plugin type [" + entry.getKey() + "]", e);
+ log.warn("Failed to initialize server plugin container for plugin type [" + pluginType + "]", e);
+ iterator.remove();
}
}
- // create classloaders for all plugins and load plugins into their plugin containers
- // Note that we do not care what order we load plugins - in the future we may want dependencies
+ // Create classloaders/environments for all plugins and load plugins into their plugin containers.
+ // Note that we do not care what order we load plugins - in the future we may want dependencies.
for (Map.Entry<URL, ? extends ServerPluginDescriptorType> entry : plugins.entrySet()) {
URL pluginUrl = entry.getKey();
ServerPluginDescriptorType descriptor = entry.getValue();
- String pluginName = entry.getValue().getName();
- ClassLoader parentCL = this.classLoaderManager.obtainServerPluginClassLoader(pluginName);
- ServerPluginEnvironment env = new ServerPluginEnvironment(pluginUrl, parentCL, tmpDir, descriptor);
+ String pluginName = descriptor.getName();
+ ClassLoader classLoader = this.classLoaderManager.obtainServerPluginClassLoader(pluginName);
AbstractTypeServerPluginContainer pc = getPluginContainerByDescriptor(descriptor);
if (pc != null) {
- log.debug("Loading plugin [" + pluginUrl + "] into its plugin container");
- pc.loadPlugin(env);
+ log.debug("Loading server plugin [" + pluginUrl + "] into its plugin container");
+ try {
+ ServerPluginEnvironment env = new ServerPluginEnvironment(pluginUrl, classLoader, descriptor);
+ pc.loadPlugin(env);
+ log.info("Loaded server plugin [" + pluginUrl + "]");
+ } catch (Exception e) {
+ log.warn("Failed to load server plugin [" + pluginUrl + "]", e);
+ }
} else {
- log.warn("Failed to get a plugin container for plugin: " + pluginUrl);
+ log.warn("There is no server plugin container to support plugin: " + pluginUrl);
}
}
+ log.info("Master server plugin container has been initialized");
+
} catch (Throwable t) {
shutdown();
log.error("Failed to initialize master plugin container! Server side plugins will not start.", t);
@@ -115,22 +134,29 @@ public class MasterServerPluginContainer {
public void shutdown() {
log.debug("Master server plugin container is being shutdown");
- // shutdown all the plugin containers which in turn shuts down all their plugins
+ // Shutdown all the plugin containers which in turn shuts down all their plugins.
for (Map.Entry<ServerPluginType, AbstractTypeServerPluginContainer> entry : this.pluginContainers.entrySet()) {
- log.info("Master PC is shutting down plugin container for plugin type [" + entry.getKey() + "]");
+ ServerPluginType pluginType = entry.getKey();
+ AbstractTypeServerPluginContainer pc = entry.getValue();
+
+ log.debug("Master PC is shutting down server plugin container for plugin type [" + pluginType + "]");
try {
- entry.getValue().shutdown();
+ pc.shutdown();
+ log.info("Master PC shutdown server plugin container for plugin type [" + pluginType + "]");
} catch (Exception e) {
- log.error("Failed to shutdown plugin container for plugin type [" + entry.getKey() + "]", e);
+ log.error("Failed to shutdown server plugin container for plugin type [" + pluginType + "]", e);
}
}
// now shutdown the classloader manager, destroying the classloaders it created
this.classLoaderManager.shutdown();
+ log.debug("Shutdown classloader manager: " + this.classLoaderManager);
this.pluginContainers.clear();
this.classLoaderManager = null;
this.configuration = null;
+
+ log.info("Master server plugin container has been shutdown");
}
/**
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
index 97a4585..08c2251 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
@@ -51,6 +51,29 @@ public class PluginManager {
}
/**
+ * Initializes the plugin manager to prepare it to start loading plugins.
+ *
+ * @throws Exception if failed to initialize
+ */
+ public void initialize() throws Exception {
+ return; // no-op
+ }
+
+ /**
+ * Shuts down this manager. This should be called only after all of its plugins
+ * have been {@link #unloadPlugin(ServerPluginEnvironment) unloaded}.
+ */
+ public void shutdown() {
+ if (this.loadedPlugins.size() > 0) {
+ log.warn("Server plugin manager is being shutdown while some plugins are still loaded: "
+ + this.loadedPlugins);
+ }
+
+ this.loadedPlugins.clear();
+ return;
+ }
+
+ /**
* Informs the plugin manager that a plugin with the given environment needs to be loaded.
* Once this method returns, the plugin's components are ready to be created and used.
*
@@ -59,10 +82,7 @@ public class PluginManager {
* @throws Exception if the plugin manager cannot load the plugin or deems the plugin invalid
*/
public void loadPlugin(ServerPluginEnvironment env) throws Exception {
- if (log.isDebugEnabled()) {
- log.debug("Loading server plugin [" + env.getPluginName() + "] from: " + env.getPluginUrl());
- }
-
+ log.debug("Loading server plugin [" + env.getPluginName() + "] from: " + env.getPluginUrl());
this.loadedPlugins.put(env.getPluginName(), env);
return;
}
@@ -76,10 +96,7 @@ public class PluginManager {
* @throws Exception if the plugin manager cannot unload the plugin
*/
public void unloadPlugin(ServerPluginEnvironment env) throws Exception {
- if (log.isDebugEnabled()) {
- log.debug("Unloading server plugin [" + env.getPluginName() + "]");
- }
-
+ log.debug("Unloading server plugin [" + env.getPluginName() + "]");
this.loadedPlugins.remove(env.getPluginName());
return;
}
@@ -93,6 +110,19 @@ public class PluginManager {
return this.loadedPlugins.values();
}
+ /**
+ * Given a plugin name, this returns that plugin's environment.
+ *
+ * <p>The plugin's name is defined in its plugin descriptor - specifically the XML root node's "name" attribute
+ * (e.g. <server-plugin name="thePluginName").</p>
+ *
+ * @param pluginName the plugin whose environment is to be returned
+ * @return given plugin's environment
+ */
+ public ServerPluginEnvironment getPluginEnvironment(String pluginName) {
+ return this.loadedPlugins.get(pluginName);
+ }
+
public AbstractTypeServerPluginContainer getParentPluginContainer() {
return this.parentPluginContainer;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java
index 202d0a8..093c017 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java
@@ -18,90 +18,35 @@
*/
package org.rhq.enterprise.server.plugin.pc;
-import java.io.File;
import java.net.URL;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
* Manages the context of a loaded plugin.
*
- * @author Greg Hinkle
* @author John Mazzitelli
*/
public class ServerPluginEnvironment {
- private final Log log = LogFactory.getLog(ServerPluginEnvironment.class);
-
- private URL pluginUrl;
- private String pluginName;
- private ClassLoader pluginClassLoader;
- private ServerPluginDescriptorType pluginDescriptor;
+ private final URL pluginUrl;
+ private final String pluginName;
+ private final ClassLoader pluginClassLoader;
+ private final ServerPluginDescriptorType pluginDescriptor;
/**
* Creates a new plugin environment.
*
- * @param pluginUrl where the plugin jar is located (may be <code>null</code>, mainly to support tests)
- * @param parentClassLoader the parent classloader to be assigned to the plugin's new classloader
- * @param tmpdir a directory where the jars are placed when unpacked
- * @param descriptor the plugin descriptor that was found and parsed in the plugin jar at the given URL
- *
- * @throws Exception
- */
- public ServerPluginEnvironment(URL pluginUrl, ClassLoader parentClassLoader, File tmpdir,
- ServerPluginDescriptorType descriptor) throws Exception {
- initialize(pluginUrl, null, parentClassLoader, true, tmpdir, descriptor);
- }
-
- public void destroy() {
- // if its our own plugin classloader, let's tell it to clean up its directory where the jars were unpacked
- if (this.pluginClassLoader instanceof ServerPluginClassLoader) {
- log.debug("Destroying classloader: " + this.toString());
- ((ServerPluginClassLoader) this.pluginClassLoader).destroy();
- }
- }
-
- /**
- * This will create the plugin's {@link #getClassLoader() classloader}.
- * If <code>classLoader</code> is specified, it will be used as the environment's
- * classloader and <code>parentClassLoader</code> will be ignored.
- * If <code>classLoader</code> is <code>null</code>, then a {@link ServerPluginClassLoader}
- * will be created with the given parent classloader and it will
- * unpack all embedded jars found in the given plugin URL's <code>/lib</code> directory.
- *
- * @param pluginJarUrl where the plugin jar is located (may be <code>null</code>, mainly to support tests)
- * @param classLoader the classloader used by this environment
- * @param parentClassLoader the parent classloader, if <code>null</code>, will use this class's classloader - this
- * is ignored if <code>classloader</code> is not <code>null</code>
- * @param unpackJars if <code>true</code> and plugin jar has embedded jars, they will be unpacked - this is
- * ignored if <code>classloader</code> is not <code>null</code>
- * @param tmpDirectory a directory where the jars are placed if they are to be unpacked; only meaningful when
- * <code>unpackJars</code> is <code>true</code>
- * @param descriptor the plugin descriptor that was found and parsed in the plugin jar at the given URL
+ * @param pluginUrl where the plugin jar is located (may be <code>null</code>, mainly to support tests)
+ * @param classLoader the plugin's new classloader
+ * @param descriptor the plugin descriptor that was found and parsed in the plugin jar at the given URL
*
* @throws Exception
*/
- protected void initialize(URL pluginJarUrl, ClassLoader classLoader, ClassLoader parentClassLoader,
- boolean unpackJars, File tmpDirectory, ServerPluginDescriptorType descriptor) throws Exception {
- if (classLoader == null) {
- if (parentClassLoader == null) {
- parentClassLoader = this.getClass().getClassLoader();
- }
-
- if (pluginJarUrl != null) {
- classLoader = ServerPluginClassLoader.create(new File(pluginJarUrl.getPath()).getName(), pluginJarUrl,
- unpackJars, parentClassLoader, tmpDirectory);
- } else {
- // this is mainly to support tests
- classLoader = parentClassLoader;
- }
- }
-
- this.pluginUrl = pluginJarUrl;
- this.pluginDescriptor = descriptor;
+ public ServerPluginEnvironment(URL pluginUrl, ClassLoader classLoader, ServerPluginDescriptorType descriptor)
+ throws Exception {
+ this.pluginUrl = pluginUrl;
this.pluginClassLoader = classLoader;
+ this.pluginDescriptor = descriptor;
this.pluginName = this.pluginDescriptor.getName();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertServerPluginContainer.java
index 60a228f..2c3068f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertServerPluginContainer.java
@@ -36,14 +36,6 @@ public class AlertServerPluginContainer extends AbstractTypeServerPluginContaine
}
@Override
- public void initialize() throws Exception {
- }
-
- @Override
- public void shutdown() {
- }
-
- @Override
public ServerPluginType getSupportedServerPluginType() {
return new ServerPluginType(AlertPluginDescriptorType.class);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
index da42dca..ff7d1e7 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderManager.java
@@ -575,7 +575,7 @@ public class ContentProviderManager {
apiClassName = type.getContentSourceApiClass();
pluginName = this.pluginManager.getMetadataManager().getPluginNameFromContentSourceType(type);
- ServerPluginEnvironment pluginEnv = this.pluginManager.getPlugin(pluginName);
+ ServerPluginEnvironment pluginEnv = this.pluginManager.getPluginEnvironment(pluginName);
ClassLoader pluginClassloader = pluginEnv.getClassLoader();
ClassLoader startingClassLoader = Thread.currentThread().getContextClassLoader();
@@ -649,7 +649,7 @@ public class ContentProviderManager {
throw new RuntimeException("There is no adapter for content source [" + adapter + "]");
}
- ServerPluginEnvironment env = this.pluginManager.getPlugin(contentSource.getContentSourceType());
+ ServerPluginEnvironment env = this.pluginManager.getPluginEnvironment(contentSource.getContentSourceType());
if (env == null) {
throw new RuntimeException("There is no plugin env. for content source [" + contentSource + "]");
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderPluginManager.java
index 14c2d62..f3b0e3d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderPluginManager.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentProviderPluginManager.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2009 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -18,21 +18,12 @@
*/
package org.rhq.enterprise.server.plugin.pc.content;
-import java.io.File;
-import java.net.URL;
import java.util.Collection;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.Map;
import java.util.Set;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jetbrains.annotations.Nullable;
-
import org.rhq.core.domain.content.ContentSourceType;
-import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
-import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
+import org.rhq.enterprise.server.plugin.pc.PluginManager;
import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
import org.rhq.enterprise.server.plugin.pc.content.metadata.ContentSourcePluginMetadataManager;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.content.ContentPluginDescriptorType;
@@ -41,96 +32,28 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.content.Conten
* This loads in all content source server plugins that can be found and will maintain the complete set of
* {@link #getMetadataManager() metadata} found in all plugin descriptors from all loaded plugins. You can obtain a
* loaded plugin's {@link ServerPluginEnvironment environment}, including its classloader, from this object as
- * well - see {@link #getPlugin(String)}.
+ * well.
*
* @author John Mazzitelli
*/
-public class ContentProviderPluginManager {
- private final Log log = LogFactory.getLog(ContentProviderPluginManager.class);
+public class ContentProviderPluginManager extends PluginManager {
- /**
- * The map of all plugins keyed on plugin name.
- */
- private Map<String, ServerPluginEnvironment> loadedPlugins = new HashMap<String, ServerPluginEnvironment>();
- private ContentSourcePluginMetadataManager metadataManager = new ContentSourcePluginMetadataManager();
- private ContentServerPluginContainer parentPluginContainer;
+ private ContentSourcePluginMetadataManager metadataManager;
public ContentProviderPluginManager(ContentServerPluginContainer pc) {
- this.parentPluginContainer = pc;
- }
-
- /**
- * Finds all plugins and {@link #loadPlugin(URL, ClassLoader) loads} each plugin found.
- *
- * @throws RuntimeException if failed catastrophically; will not happen if a plugin failed to load - it will just be
- * ignored
- */
- public void initialize() {
-
- try {
- MasterServerPluginContainer master = this.parentPluginContainer.getMasterServerPluginContainer();
- MasterServerPluginContainerConfiguration config = master.getConfiguration();
- File[] pluginFiles = config.getPluginDirectory().listFiles();
-
- for (File pluginFile : pluginFiles) {
- if (pluginFile.getName().endsWith(".jar")) {
- URL pluginUrl = pluginFile.toURI().toURL();
-
- try {
- log.debug("Loading content source server plugin from URL: " + pluginUrl);
- loadPlugin(pluginUrl, null);
- } catch (Throwable t) {
- // for some reason, the plugin failed to load - it will be ignored
- log.error("Plugin at [" + pluginUrl + "] could not be loaded", t);
- continue;
- }
- }
- }
- } catch (Exception e) {
- shutdown(); // have to clean up the environments (e.g. unpacked jars) we might have already created
- log.error("Error initializing content provider plugin manager", e);
- throw new RuntimeException("Cannot initialize content provider plugin manager", e);
- }
+ super(pc);
}
- /**
- * Ensures that all the plugin classloaders clean up.
- */
- public void shutdown() {
- for (ServerPluginEnvironment pluginEnvironment : loadedPlugins.values()) {
- log.debug("Cleaning up plugin environment for [" + pluginEnvironment.getPluginName() + "]");
- pluginEnvironment.destroy();
- }
-
- loadedPlugins.clear();
+ @Override
+ public void initialize() throws Exception {
+ super.initialize();
metadataManager = new ContentSourcePluginMetadataManager();
-
- return;
}
- /**
- * Returns the {@link ServerPluginEnvironment}s for every plugin this manager found and loaded.
- *
- * @return environments for all the plugins
- */
- public Collection<ServerPluginEnvironment> getPlugins() {
- return this.loadedPlugins.values();
- }
-
- /**
- * Returns the {@link ServerPluginEnvironment} for the specific plugin with the given name.
- *
- * <p>The plugin's name is defined in its plugin descriptor - specifically the XML root node's "name" attribute
- * (e.g. <plugin name="thePluginName").</p>
- *
- * @param pluginName plugin name as defined in the plugin's descriptor
- *
- * @return the environment of the loaded plugin with the given name (<code>null</code> if there is no loaded plugin
- * with the given name)
- */
- @Nullable
- public ServerPluginEnvironment getPlugin(String pluginName) {
- return this.loadedPlugins.get(pluginName);
+ @Override
+ public void shutdown() {
+ super.shutdown();
+ metadataManager = null;
}
/**
@@ -140,14 +63,14 @@ public class ContentProviderPluginManager {
*
* @return plugin environment
*/
- public ServerPluginEnvironment getPlugin(ContentSourceType type) {
+ public ServerPluginEnvironment getPluginEnvironment(ContentSourceType type) {
String pluginName = this.metadataManager.getPluginNameFromContentSourceType(type);
- return this.loadedPlugins.get(pluginName);
+ return getPluginEnvironment(pluginName);
}
/**
- * An object that can be used to process and store all metadata from all plugins. This object will contain all the
- * metadata found in all loaded plugins.
+ * An object that can be used to process and store all metadata from all content plugins. This object will contain all the
+ * metadata found in all loaded content plugins.
*
* @return object to retrieve plugin metadata from
*/
@@ -155,35 +78,20 @@ public class ContentProviderPluginManager {
return metadataManager;
}
- /**
- * This will create a {@link ServerPluginEnvironment} for the plugin at the given URL. What this means is a
- * classloader is created for the plugin (if <code>classLoader</code> is <code>null</code>) and the plugin's
- * descriptor is parsed. Once this method returns, the plugin's components are ready to be created and used.
- *
- * @param pluginUrl the new plugin's jar location
- * @param classLoader the new plugin's classloader - if <code>null</code>, one will be created for it
- *
- * @throws Exception
- */
- private void loadPlugin(URL pluginUrl, ClassLoader classLoader) throws Exception {
- log.info("Loading content server plugin from: " + pluginUrl);
-
- ServerPluginEnvironment pluginEnvironment;
+ @Override
+ public void loadPlugin(ServerPluginEnvironment env) throws Exception {
- MasterServerPluginContainer master = this.parentPluginContainer.getMasterServerPluginContainer();
- MasterServerPluginContainerConfiguration config = master.getConfiguration();
- pluginEnvironment = new ServerPluginEnvironment(pluginUrl, classLoader, null, config.getTemporaryDirectory());
+ super.loadPlugin(env);
- loadedPlugins.put(pluginEnvironment.getPluginName(), pluginEnvironment);
- Collection<ContentSourceType> newTypes = metadataManager
- .loadPlugin((ContentPluginDescriptorType) pluginEnvironment.getPluginDescriptor());
+ Collection<ContentSourceType> newTypes;
+ newTypes = this.metadataManager.loadPlugin((ContentPluginDescriptorType) env.getPluginDescriptor());
// double check that the api classes are loadable, if not, very bad
Set<ContentSourceType> newTypesCopy = new HashSet<ContentSourceType>(newTypes);
for (ContentSourceType newType : newTypesCopy) {
try {
String className = newType.getContentSourceApiClass();
- Class<?> apiClass = Class.forName(className, false, pluginEnvironment.getClassLoader());
+ Class<?> apiClass = Class.forName(className, false, env.getClassLoader());
if (!ContentProvider.class.isAssignableFrom(apiClass)) {
throw new Exception("The API class [" + className + "] should implement ["
@@ -191,13 +99,20 @@ public class ContentProviderPluginManager {
}
} catch (Exception e) {
// do not deploy this plugin - its stinky
- metadataManager.unloadPlugin(pluginEnvironment.getPluginName());
- loadedPlugins.remove(pluginEnvironment.getPluginName());
- pluginEnvironment.destroy();
+ try {
+ unloadPlugin(env);
+ } catch (Exception ignore) {
+ }
throw e;
}
}
return;
}
+
+ @Override
+ public void unloadPlugin(ServerPluginEnvironment env) throws Exception {
+ metadataManager.unloadPlugin(env.getPluginName());
+ super.unloadPlugin(env);
+ };
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
index acf2638..d66b6b4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
@@ -28,6 +28,7 @@ import org.rhq.core.domain.content.ContentSource;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.PluginManager;
import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.scheduler.SchedulerLocal;
import org.rhq.enterprise.server.scheduler.jobs.ContentSourceSyncJob;
@@ -43,7 +44,6 @@ public class ContentServerPluginContainer extends AbstractTypeServerPluginContai
private static final String SYNC_JOB_GROUP_NAME = "syncContentSource";
- private ContentProviderPluginManager pluginManager;
private ContentProviderManager adapterManager;
public ContentServerPluginContainer(MasterServerPluginContainer master) {
@@ -52,20 +52,18 @@ public class ContentServerPluginContainer extends AbstractTypeServerPluginContai
@Override
public void initialize() throws Exception {
- getLog().debug("Content server plugin container has been initialized");
-
- this.pluginManager = createPluginManager();
- this.adapterManager = createAdapterManager(this.pluginManager);
-
- return;
+ getLog().debug("Content server plugin container initializing");
+ super.initialize();
+ this.adapterManager = createAdapterManager((ContentProviderPluginManager) getPluginManager()); // initializes, too
+ getLog().debug("Content server plugin container initialized");
}
@Override
public void shutdown() {
- getLog().debug("Content server plugin container is being shutdown");
-
+ getLog().debug("Content server plugin container is shutting down");
this.adapterManager.shutdown();
- this.pluginManager.shutdown();
+ super.shutdown();
+ getLog().debug("Content server plugin container is shutdown");
}
@Override
@@ -84,18 +82,6 @@ public class ContentServerPluginContainer extends AbstractTypeServerPluginContai
}
/**
- * Returns the object that is responsible for managing all plugins and their metadata.
- *
- * <p>This is protected to only allow subclasses access to this - external clients to this PC should never have
- * direct access to this plugin manager.</p>
- *
- * @return plugin manager
- */
- protected ContentProviderPluginManager getPluginManager() {
- return this.pluginManager;
- }
-
- /**
* This will syncronize the given content source, meaning its {@link PackageVersion}s will be updated and, if not
* lazy-loading, will load the package versions that are not loaded yet.
*
@@ -188,18 +174,9 @@ public class ContentServerPluginContainer extends AbstractTypeServerPluginContai
return;
}
- /**
- * Creates, configures and initializes the plugin manager that the PC will use.
- *
- * <p>This is protected scope so subclasses can define their own plugin manager to use. This is mainly to support
- * tests.</p>
- *
- * @return the new plugin manager
- */
- protected ContentProviderPluginManager createPluginManager() {
- ContentProviderPluginManager pm = new ContentProviderPluginManager(this);
- pm.initialize();
- return pm;
+ @Override
+ protected PluginManager createPluginManager() {
+ return new ContentProviderPluginManager(this);
}
/**
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginContainer.java
index 204cfc0..70e9a8f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginContainer.java
@@ -37,14 +37,6 @@ public class GenericServerPluginContainer extends AbstractTypeServerPluginContai
}
@Override
- public void initialize() throws Exception {
- }
-
- @Override
- public void shutdown() {
- }
-
- @Override
public ServerPluginType getSupportedServerPluginType() {
return new ServerPluginType(GenericPluginDescriptorType.class);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/perspective/PerspectiveServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/perspective/PerspectiveServerPluginContainer.java
index 202ab03..e6929cc 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/perspective/PerspectiveServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/perspective/PerspectiveServerPluginContainer.java
@@ -36,14 +36,6 @@ public class PerspectiveServerPluginContainer extends AbstractTypeServerPluginCo
}
@Override
- public void initialize() throws Exception {
- }
-
- @Override
- public void shutdown() {
- }
-
- @Override
public ServerPluginType getSupportedServerPluginType() {
return new ServerPluginType(PerspectivePluginDescriptorType.class);
}
commit 064e177b9bf7b69881d8beeac1d81b144bf09571
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 5 20:45:48 2009 -0500
the start of getting plugin classloading to work
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index 98783fe..8d9c8ab 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -32,6 +32,7 @@ public abstract class AbstractTypeServerPluginContainer {
private final Log log = LogFactory.getLog(this.getClass());
private final MasterServerPluginContainer master;
+ private final PluginManager pluginManager;
/**
* Instantiates the plugin container. All subclasses must support this and only this
@@ -41,6 +42,7 @@ public abstract class AbstractTypeServerPluginContainer {
*/
public AbstractTypeServerPluginContainer(MasterServerPluginContainer master) {
this.master = master;
+ this.pluginManager = createPluginManager();
}
/**
@@ -68,6 +70,36 @@ public abstract class AbstractTypeServerPluginContainer {
public abstract void shutdown();
/**
+ * Each plugin container will tell the master which plugins it can support via this method; this
+ * method returns the type of plugin that the plugin container can process. Only one
+ * plugin container can support a plugin type.
+ *
+ * @return the type of plugin that this plugin container instance can support
+ */
+ public abstract ServerPluginType getSupportedServerPluginType();
+
+ /**
+ * Informs the plugin container that it has a plugin that it must being to start managing.
+ *
+ * @param env the plugin environment, including the plugin jar and its descriptor
+ *
+ * @throws Exception if failed to load the plugin
+ */
+ public void loadPlugin(ServerPluginEnvironment env) throws Exception {
+ this.pluginManager.loadPlugin(env);
+ }
+
+ /**
+ * This will be called when its time for this plugin container to create its plugin manager.
+ * Subclasses are free to override this if they need their own specialized plugin manager.
+ *
+ * @return the plugin manager for use by this plugin container
+ */
+ protected PluginManager createPluginManager() {
+ return new PluginManager(this);
+ }
+
+ /**
* Returns the logger that can be used to log messages. A convienence object so all
* subclasses don't have to explicitly declare and create their own.
*
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ClassLoaderManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ClassLoaderManager.java
new file mode 100644
index 0000000..aec20ce
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ClassLoaderManager.java
@@ -0,0 +1,216 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 Red Hat, Inc.
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation, and/or the GNU Lesser
+ * General Public License, version 2.1, also as published by the Free
+ * Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License and the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.rhq.enterprise.server.plugin.pc;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
+
+/**
+ * Manages the classloaders created and used by the master plugin container and all plugins.
+ *
+ * @author John Mazzitelli
+ */
+public class ClassLoaderManager {
+ private final Log log = LogFactory.getLog(ClassLoaderManager.class);
+
+ /**
+ * Directory where temporary files can be stored. Used to extract jars embedded in plugin jars.
+ */
+ private final File tmpDir;
+
+ /**
+ * Provides a map keyed on plugin name whose values are the URLs to those plugin jars.
+ */
+ private final Map<String, URL> pluginNamesUrls;
+
+ /**
+ * The parent classloader for those classloaders at the top of the classloader hierarchy.
+ */
+ private final ClassLoader rootClassLoader;
+
+ /**
+ * These are the classloaders that are built for each plugin.
+ * This map is keyed on plugin name.
+ *
+ * @see #obtainServerPluginClassLoader(String)
+ */
+ private final Map<String, ClassLoader> serverPluginClassLoaders;
+
+ /**
+ * Creates the object that will manage all classloaders for the plugins deployed in the server.
+ *
+ * @param plugins maps a plugin URL to that plugin's descriptor
+ * @param rootClassLoader the classloader at the top of the classloader hierarchy
+ * @param tmpDir where the classloaders can write out the jars that are embedded in the plugin jars
+ */
+ public ClassLoaderManager(Map<URL, ? extends ServerPluginDescriptorType> plugins, ClassLoader rootClassLoader,
+ File tmpDir) {
+
+ this.rootClassLoader = rootClassLoader;
+ this.tmpDir = tmpDir;
+ this.serverPluginClassLoaders = new HashMap<String, ClassLoader>();
+
+ this.pluginNamesUrls = new HashMap<String, URL>(plugins.size());
+ for (Map.Entry<URL, ? extends ServerPluginDescriptorType> entry : plugins.entrySet()) {
+ this.pluginNamesUrls.put(entry.getValue().getName(), entry.getKey());
+ }
+
+ return;
+ }
+
+ /**
+ * Cleans up this object and all classloaders it has created.
+ */
+ public void shutdown() {
+ for (ClassLoader doomedCL : getUniqueServerPluginClassLoaders()) {
+ if (doomedCL instanceof ServerPluginClassLoader) {
+ ((ServerPluginClassLoader) doomedCL).destroy();
+ }
+ }
+ this.serverPluginClassLoaders.clear();
+ return;
+ }
+
+ @Override
+ public String toString() {
+ Set<ClassLoader> classLoaders;
+ StringBuilder str = new StringBuilder(this.getClass().getSimpleName());
+
+ classLoaders = getUniqueServerPluginClassLoaders();
+ str.append(" [#plugin CLs=").append(classLoaders.size());
+ classLoaders.clear(); // help out the GC, clear out the shallow copy container
+
+ str.append(']');
+ return str.toString();
+ }
+
+ /**
+ * Returns the classloader that should be the ancestor (i.e. top most parent) of all plugin classloaders.
+ *
+ * @return the root plugin classloader for all plugins
+ */
+ public ClassLoader getRootClassLoader() {
+ return this.rootClassLoader;
+ }
+
+ /**
+ * Returns a plugin classloader (creating it if necessary).
+ *
+ * @param pluginName the plugin whose classloader is to be created
+ * @return the plugin classloader
+ * @throws Exception
+ */
+ public synchronized ClassLoader obtainServerPluginClassLoader(String pluginName) throws Exception {
+
+ ClassLoader cl = this.serverPluginClassLoaders.get(pluginName);
+
+ if (cl == null) {
+ URL pluginJarUrl = this.pluginNamesUrls.get(pluginName);
+ ClassLoader parentClassLoader = this.rootClassLoader;
+
+ if (log.isDebugEnabled()) {
+ log.debug("Creating classloader for plugin [" + pluginName + "] from URL [" + pluginJarUrl + ']');
+ }
+
+ cl = createClassLoader(pluginJarUrl, null, parentClassLoader);
+ this.serverPluginClassLoaders.put(pluginName, cl);
+ }
+
+ return cl;
+ }
+
+ /**
+ * Returns the total number of plugin classloaders that have been created and managed.
+ * This method is here just to support a plugin container management MBean.
+ *
+ * @return number of plugin classloaders that are currently created and being used
+ */
+ public synchronized int getNumberOfServerPluginClassLoaders() {
+ return this.serverPluginClassLoaders.size();
+ }
+
+ /**
+ * Returns a shallow copy of the plugin classloaders keyed on plugin name. This method is here
+ * just to support a plugin container management MBean.
+ *
+ * Do not use this method to obtain a plugin's classloader, instead, you want to use
+ * {@link #obtainServerPluginClassLoader(String)}.
+ *
+ * @return all plugin classloaders currently assigned to plugins (will never be <code>null</code>)
+ */
+ public synchronized Map<String, ClassLoader> getServerPluginClassLoaders() {
+ return new HashMap<String, ClassLoader>(this.serverPluginClassLoaders);
+ }
+
+ private Set<ClassLoader> getUniqueServerPluginClassLoaders() {
+ HashSet<ClassLoader> uniqueClassLoaders = new HashSet<ClassLoader>(this.serverPluginClassLoaders.values());
+ return uniqueClassLoaders;
+ }
+
+ private ClassLoader createClassLoader(URL mainJarUrl, List<URL> additionalJars, ClassLoader parentClassLoader)
+ throws Exception {
+
+ ClassLoader classLoader;
+ if (parentClassLoader == null) {
+ parentClassLoader = this.getClass().getClassLoader();
+ }
+
+ if (mainJarUrl != null) {
+ // Note that we don't really care if the URL uses "file:" or not,
+ // we just use File to parse the name from the path.
+ String pluginJarName = new File(mainJarUrl.getPath()).getName();
+
+ if (additionalJars == null || additionalJars.size() == 0) {
+ classLoader = ServerPluginClassLoader.create(pluginJarName, mainJarUrl, true, parentClassLoader,
+ this.tmpDir);
+ } else {
+ List<URL> allJars = new ArrayList<URL>(additionalJars.size() + 1);
+ allJars.add(mainJarUrl);
+ allJars.addAll(additionalJars);
+ classLoader = ServerPluginClassLoader.create(pluginJarName, allJars.toArray(new URL[allJars.size()]),
+ true, parentClassLoader, this.tmpDir);
+ }
+
+ if (log.isDebugEnabled()) {
+ log.debug("Created classloader for plugin jar [" + mainJarUrl + "] with additional jars ["
+ + additionalJars + "]");
+ }
+ } else {
+ // this is mainly to support tests
+ classLoader = parentClassLoader;
+ }
+
+ return classLoader;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index d46de59..c4ced0e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2009 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -18,7 +18,11 @@
*/
package org.rhq.enterprise.server.plugin.pc;
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
@@ -28,6 +32,8 @@ import org.rhq.enterprise.server.plugin.pc.alert.AlertServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.content.ContentServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.generic.GenericServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.perspective.PerspectiveServerPluginContainer;
+import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
* The container responsible for managing all the plugin containers for all the
@@ -40,54 +46,76 @@ public class MasterServerPluginContainer {
private MasterServerPluginContainerConfiguration configuration;
private Map<ServerPluginType, AbstractTypeServerPluginContainer> pluginContainers = new HashMap<ServerPluginType, AbstractTypeServerPluginContainer>();
+ private ClassLoaderManager classLoaderManager;
/**
* Starts the master plugin container, which will load all plugins and begin managing them.
*
- * @param config
+ * @param config the master configuration
*/
public void initialize(MasterServerPluginContainerConfiguration config) {
- log.debug("Master server plugin container has been initialized with config: " + config);
+ try {
+ log.debug("Master server plugin container has been initialized with config: " + config);
- this.configuration = config;
+ this.configuration = config;
- // create all known child plugin containers
- createPluginContainers(this.pluginContainers);
+ // load all server-side plugins - this just parses their descriptors and confirms they are valid server plugins
+ Map<URL, ? extends ServerPluginDescriptorType> plugins = preloadAllPlugins();
- // initialize all the plugin containers
- for (Map.Entry<ServerPluginType, AbstractTypeServerPluginContainer> entry : this.pluginContainers.entrySet()) {
- log.info("Master PC is initializing plugin container for plugin type [" + entry.getKey() + "]");
- try {
- entry.getValue().initialize();
- } catch (Exception e) {
- log.error("Failed to initialize plugin container for plugin type [" + entry.getKey() + "]", e);
+ // create the root classloader to be used as the top classloader for all plugins
+ ClassLoader rootClassLoader = createRootServerPluginClassLoader();
+ File tmpDir = this.configuration.getTemporaryDirectory();
+ this.classLoaderManager = createClassLoaderManager(plugins, rootClassLoader, tmpDir);
+
+ // create all known child plugin containers and map them to their supported plugin types
+ List<AbstractTypeServerPluginContainer> pcs = createPluginContainers();
+ for (AbstractTypeServerPluginContainer pc : pcs) {
+ this.pluginContainers.put(pc.getSupportedServerPluginType(), pc);
+ }
+
+ // initialize all the plugin containers
+ for (Map.Entry<ServerPluginType, AbstractTypeServerPluginContainer> entry : this.pluginContainers
+ .entrySet()) {
+ log.info("Master PC is initializing plugin container for plugin type [" + entry.getKey() + "]");
+ try {
+ entry.getValue().initialize();
+ } catch (Exception e) {
+ log.warn("Failed to initialize plugin container for plugin type [" + entry.getKey() + "]", e);
+ }
+ }
+
+ // create classloaders for all plugins and load plugins into their plugin containers
+ // Note that we do not care what order we load plugins - in the future we may want dependencies
+ for (Map.Entry<URL, ? extends ServerPluginDescriptorType> entry : plugins.entrySet()) {
+ URL pluginUrl = entry.getKey();
+ ServerPluginDescriptorType descriptor = entry.getValue();
+ String pluginName = entry.getValue().getName();
+ ClassLoader parentCL = this.classLoaderManager.obtainServerPluginClassLoader(pluginName);
+ ServerPluginEnvironment env = new ServerPluginEnvironment(pluginUrl, parentCL, tmpDir, descriptor);
+ AbstractTypeServerPluginContainer pc = getPluginContainerByDescriptor(descriptor);
+ if (pc != null) {
+ log.debug("Loading plugin [" + pluginUrl + "] into its plugin container");
+ pc.loadPlugin(env);
+ } else {
+ log.warn("Failed to get a plugin container for plugin: " + pluginUrl);
+ }
}
+
+ } catch (Throwable t) {
+ shutdown();
+ log.error("Failed to initialize master plugin container! Server side plugins will not start.", t);
}
return;
}
/**
- * Create the individual plugin containers that can be used to deploy different plugin types.
- *
- * <p>This is protected to allow subclasses to override the PCs that are created by this service (mainly to support tests).</p>
- *
- * @param pcs the map to store references to the new plugin containers created by this method
- */
- protected void createPluginContainers(Map<ServerPluginType, AbstractTypeServerPluginContainer> pcs) {
- pcs.put(ServerPluginType.GENERIC, new GenericServerPluginContainer(this));
- pcs.put(ServerPluginType.CONTENT, new ContentServerPluginContainer(this));
- pcs.put(ServerPluginType.PERSPECTIVE, new PerspectiveServerPluginContainer(this));
- pcs.put(ServerPluginType.ALERT, new AlertServerPluginContainer(this));
- }
-
- /**
* Stops all plugins and cleans up after them.
*/
public void shutdown() {
log.debug("Master server plugin container is being shutdown");
- // shutdown all the plugin containers
+ // shutdown all the plugin containers which in turn shuts down all their plugins
for (Map.Entry<ServerPluginType, AbstractTypeServerPluginContainer> entry : this.pluginContainers.entrySet()) {
log.info("Master PC is shutting down plugin container for plugin type [" + entry.getKey() + "]");
try {
@@ -97,7 +125,11 @@ public class MasterServerPluginContainer {
}
}
+ // now shutdown the classloader manager, destroying the classloaders it created
+ this.classLoaderManager.shutdown();
+
this.pluginContainers.clear();
+ this.classLoaderManager = null;
this.configuration = null;
}
@@ -113,23 +145,13 @@ public class MasterServerPluginContainer {
}
/**
- * Get the plugin container that supports the given type of plugins.
- *
- * @param serverPluginType the type of plugin whose plugin container is to be returned
- * @return the plugin container that manages plugins of the given type (<code>null</code> if none found)
- */
- public AbstractTypeServerPluginContainer getPluginContainer(ServerPluginType serverPluginType) {
- return this.pluginContainers.get(serverPluginType);
- }
-
- /**
* Get the plugin container of the given class. This method provides a strongly typed return value,
* based on the type of plugin container the caller wants returned.
*
* @param clazz the class name of the plugin container that the caller wants
* @return the plugin container of the given class (<code>null</code> if none found)
*/
- public <T> T getPluginContainer(Class<T> clazz) {
+ public <T extends AbstractTypeServerPluginContainer> T getPluginContainer(Class<T> clazz) {
for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
if (clazz.isInstance(pc)) {
return (T) pc;
@@ -137,4 +159,103 @@ public class MasterServerPluginContainer {
}
return null;
}
+
+ /**
+ * Returns the manager that is responsible for created classloaders for plugins.
+ *
+ * @return classloader manager
+ */
+ public ClassLoaderManager getClassLoaderManager() {
+ return this.classLoaderManager;
+ }
+
+ /**
+ * Given a plugin's descriptor, this will return the plugin container that can manage the plugin.
+ *
+ * @param descriptor descriptor to identify a plugin whose container is to be returned
+ * @return a plugin container that can handle the plugin with the given descriptor
+ */
+ protected AbstractTypeServerPluginContainer getPluginContainerByDescriptor(ServerPluginDescriptorType descriptor) {
+ ServerPluginType pluginType = new ServerPluginType(descriptor.getClass());
+ AbstractTypeServerPluginContainer pc = this.pluginContainers.get(pluginType);
+ return pc;
+ }
+
+ /**
+ * Finds all plugins and parses their descriptors.
+ *
+ * If a plugin fails to load, it will be ignored - other plugins will still load.
+ *
+ * @return a map of plugins, keyed on the plugin jar URL whose values are the parsed descriptors
+ *
+ * @throws Exception on catastrophic failure. Note that if a plugin failed to load,
+ * that plugin will simply be ignored and no exception will be thrown
+ */
+ protected Map<URL, ? extends ServerPluginDescriptorType> preloadAllPlugins() throws Exception {
+ Map<URL, ServerPluginDescriptorType> plugins;
+
+ plugins = new HashMap<URL, ServerPluginDescriptorType>();
+
+ File[] pluginFiles = this.configuration.getPluginDirectory().listFiles();
+ for (File pluginFile : pluginFiles) {
+ if (pluginFile.getName().endsWith(".jar")) {
+ URL pluginUrl = pluginFile.toURI().toURL();
+
+ try {
+ ServerPluginDescriptorType descriptor;
+ descriptor = ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginUrl);
+ if (descriptor != null) {
+ log.debug("pre-loaded server plugin from URL: " + pluginUrl);
+ plugins.put(pluginUrl, descriptor);
+ }
+ } catch (Throwable t) {
+ // for some reason, the plugin failed to load - it will be ignored
+ log.error("Plugin at [" + pluginUrl + "] could not be pre-loaded. Ignoring it.", t);
+ }
+ }
+ }
+
+ return plugins;
+ }
+
+ /**
+ * Creates the individual plugin containers that can be used to deploy different plugin types.
+ *
+ * <p>This is protected to allow subclasses to override the PCs that are created by this service (mainly to support tests).</p>
+ *
+ * @return the new plugin containers created by this method
+ */
+ protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
+ ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(4);
+ pcs.add(new GenericServerPluginContainer(this));
+ pcs.add(new ContentServerPluginContainer(this));
+ pcs.add(new PerspectiveServerPluginContainer(this));
+ pcs.add(new AlertServerPluginContainer(this));
+ return pcs;
+ }
+
+ /**
+ * Create the root classloader that will be the ancester to all plugin classloaders.
+ *
+ * @return the root server plugin classloader
+ */
+ protected ClassLoader createRootServerPluginClassLoader() {
+ ClassLoader thisClassLoader = this.getClass().getClassLoader();
+ String classesToHideRegexStr = this.configuration.getRootServerPluginClassLoaderRegex();
+ RootServerPluginClassLoader root = new RootServerPluginClassLoader(null, thisClassLoader, classesToHideRegexStr);
+ return root;
+ }
+
+ /**
+ * Creates the manager that will be responsible for instantiating plugin classloaders.
+ * @param plugins maps plugin URLs with their parsed descriptors
+ * @param rootClassLoader the classloader at the top of the classloader hierarchy
+ * @param tmpDir where the classloaders can write out the jars that are embedded in the plugin jars
+ *
+ * @return the classloader manager instance
+ */
+ protected ClassLoaderManager createClassLoaderManager(Map<URL, ? extends ServerPluginDescriptorType> plugins,
+ ClassLoader rootClassLoader, File tmpDir) {
+ return new ClassLoaderManager(plugins, rootClassLoader, tmpDir);
+ }
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
new file mode 100644
index 0000000..97a4585
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/PluginManager.java
@@ -0,0 +1,103 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Provides functionality to manage plugins for a plugin container. Plugin containers
+ * can install their own plugin managers that are extensions to this class if they need to.
+ *
+ * @author John Mazzitelli
+ */
+public class PluginManager {
+ private final Log log = LogFactory.getLog(this.getClass());
+
+ /**
+ * The map of all plugins keyed on plugin name.
+ */
+ private Map<String, ServerPluginEnvironment> loadedPlugins = new HashMap<String, ServerPluginEnvironment>();
+ private AbstractTypeServerPluginContainer parentPluginContainer;
+
+ /**
+ * Creates a plugin manager for the given plugin container.
+ *
+ * @param pc the plugin manager's owning plugin container
+ */
+ public PluginManager(AbstractTypeServerPluginContainer pc) {
+ this.parentPluginContainer = pc;
+ }
+
+ /**
+ * Informs the plugin manager that a plugin with the given environment needs to be loaded.
+ * Once this method returns, the plugin's components are ready to be created and used.
+ *
+ * @param env the environment of the plugin to be loaded
+ *
+ * @throws Exception if the plugin manager cannot load the plugin or deems the plugin invalid
+ */
+ public void loadPlugin(ServerPluginEnvironment env) throws Exception {
+ if (log.isDebugEnabled()) {
+ log.debug("Loading server plugin [" + env.getPluginName() + "] from: " + env.getPluginUrl());
+ }
+
+ this.loadedPlugins.put(env.getPluginName(), env);
+ return;
+ }
+
+ /**
+ * Informs the plugin manager that a plugin with the given environment is to be unloaded.
+ * Once this method returns, the plugin's components are should no longer be created or used.
+ *
+ * @param env the environment of the plugin to be unloaded
+ *
+ * @throws Exception if the plugin manager cannot unload the plugin
+ */
+ public void unloadPlugin(ServerPluginEnvironment env) throws Exception {
+ if (log.isDebugEnabled()) {
+ log.debug("Unloading server plugin [" + env.getPluginName() + "]");
+ }
+
+ this.loadedPlugins.remove(env.getPluginName());
+ return;
+ }
+
+ /**
+ * Returns the {@link ServerPluginEnvironment}s for every plugin this manager has loaded.
+ *
+ * @return environments for all the plugins
+ */
+ public Collection<ServerPluginEnvironment> getPluginEnvironments() {
+ return this.loadedPlugins.values();
+ }
+
+ public AbstractTypeServerPluginContainer getParentPluginContainer() {
+ return this.parentPluginContainer;
+ }
+
+ protected Log getLog() {
+ return this.log;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java
index a80e0a6..202d0a8 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginEnvironment.java
@@ -1,6 +1,6 @@
/*
* RHQ Management Platform
- * Copyright (C) 2005-2008 Red Hat, Inc.
+ * Copyright (C) 2005-2009 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -24,72 +24,35 @@ import java.net.URL;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
- * Manages the context of a loaded plugin. This includes a classloader created specifically for the plugin and access to
- * its XML descriptor file.
+ * Manages the context of a loaded plugin.
*
- * This is an abstract superclass that all plugin types must extend to provide the access to the proper type
- * of descriptor.
- *
* @author Greg Hinkle
* @author John Mazzitelli
*/
public class ServerPluginEnvironment {
private final Log log = LogFactory.getLog(ServerPluginEnvironment.class);
- // make these protected mainly to allow unit tests to extend this class to customize these
- protected URL pluginUrl;
- protected String pluginName;
- protected ClassLoader pluginClassLoader;
- protected ServerPluginDescriptorType pluginDescriptor;
-
- /**
- * Creates a new plugin environment. If <code>classLoader</code> is specified, it will be used as the environment's
- * classloader and <code>parentClassLoader</code> will be ignored. If <code>classLoader</code> is <code>null</code>,
- * then a {@link ServerPluginClassLoader} will be created with the given parent classloader and it will
- * unpack all embedded jars found in the given plugin URL's <code>/lib</code> directory.
- *
- * @param pluginUrl where the plugin jar is located (may be <code>null</code>, mainly to support tests)
- * @param classLoader the classloader used by this environment
- * @param parentClassLoader the parent classloader, if <code>null</code>, will use this class's classloader - this
- * is ignored if <code>classloader</code> is not <code>null</code>
- * @param tmpdir a directory where the jars are placed when unpacked
- *
- * @throws Exception
- */
- public ServerPluginEnvironment(URL pluginUrl, ClassLoader classLoader, ClassLoader parentClassLoader, File tmpdir)
- throws Exception {
- initialize(pluginUrl, classLoader, parentClassLoader, true, tmpdir);
- }
+ private URL pluginUrl;
+ private String pluginName;
+ private ClassLoader pluginClassLoader;
+ private ServerPluginDescriptorType pluginDescriptor;
/**
- * This creates a {@link ServerPluginEnvironment} that will allow you to specify the plugin's new class
- * loader to not unpack its embedded jars, if they exist. You normally only pass in <code>false</code> for <code>
- * unpackJars</code> if you only want to process/parse the plugin descriptor but do not plan on using this
- * environment instance for actual runtime of the plugin (because it won't work since you haven't unpacked the
- * jars).
+ * Creates a new plugin environment.
*
- * <p>If you pass in a non-<code>null</code> <code>classLoader</code>, then both <code>parentClassLoader</code> and
- * <code>unpackJars</code> is ignored since you are saying you already know how to find the classes for this
- * environment.</p>
- *
- * @param pluginUrl where the plugin jar is located (may be <code>null</code>, mainly to support tests)
- * @param classLoader the classloader used by this environment
- * @param parentClassLoader the parent classloader, if <code>null</code>, will use this class's classloader - this
- * is ignored if <code>classloader</code> is not <code>null</code>
- * @param unpackJars if <code>true</code> and plugin jar has embedded jars, they will be unpacked - this is
- * ignored if <code>classloader</code> is not <code>null</code>
- * @param tmpdir a directory where the jars are placed if they are to be unpacked; only meaningful when
- * <code>unpackJars</code> is <code>true</code>
+ * @param pluginUrl where the plugin jar is located (may be <code>null</code>, mainly to support tests)
+ * @param parentClassLoader the parent classloader to be assigned to the plugin's new classloader
+ * @param tmpdir a directory where the jars are placed when unpacked
+ * @param descriptor the plugin descriptor that was found and parsed in the plugin jar at the given URL
*
* @throws Exception
*/
- public ServerPluginEnvironment(URL pluginUrl, ClassLoader classLoader, ClassLoader parentClassLoader,
- boolean unpackJars, File tmpdir) throws Exception {
- initialize(pluginUrl, classLoader, parentClassLoader, unpackJars, tmpdir);
+ public ServerPluginEnvironment(URL pluginUrl, ClassLoader parentClassLoader, File tmpdir,
+ ServerPluginDescriptorType descriptor) throws Exception {
+ initialize(pluginUrl, null, parentClassLoader, true, tmpdir, descriptor);
}
public void destroy() {
@@ -101,21 +64,27 @@ public class ServerPluginEnvironment {
}
/**
- * This will create the plugin's {@link #getClassLoader() classloader}, then read and parse the descriptor to make sure its valid.
- *
- * @param pluginJarUrl where the plugin jar is located (may be <code>null</code>, mainly to support tests)
- * @param classLoader the classloader used by this environment
- * @param parentClassLoader the parent classloader, if <code>null</code>, will use this class's classloader - this
- * is ignored if <code>classloader</code> is not <code>null</code>
- * @param unpackJars if <code>true</code> and plugin jar has embedded jars, they will be unpacked - this is
- * ignored if <code>classloader</code> is not <code>null</code>
- * @param tmpDirectory a directory where the jars are placed if they are to be unpacked; only meaningful when
- * <code>unpackJars</code> is <code>true</code>
+ * This will create the plugin's {@link #getClassLoader() classloader}.
+ * If <code>classLoader</code> is specified, it will be used as the environment's
+ * classloader and <code>parentClassLoader</code> will be ignored.
+ * If <code>classLoader</code> is <code>null</code>, then a {@link ServerPluginClassLoader}
+ * will be created with the given parent classloader and it will
+ * unpack all embedded jars found in the given plugin URL's <code>/lib</code> directory.
+ *
+ * @param pluginJarUrl where the plugin jar is located (may be <code>null</code>, mainly to support tests)
+ * @param classLoader the classloader used by this environment
+ * @param parentClassLoader the parent classloader, if <code>null</code>, will use this class's classloader - this
+ * is ignored if <code>classloader</code> is not <code>null</code>
+ * @param unpackJars if <code>true</code> and plugin jar has embedded jars, they will be unpacked - this is
+ * ignored if <code>classloader</code> is not <code>null</code>
+ * @param tmpDirectory a directory where the jars are placed if they are to be unpacked; only meaningful when
+ * <code>unpackJars</code> is <code>true</code>
+ * @param descriptor the plugin descriptor that was found and parsed in the plugin jar at the given URL
*
* @throws Exception
*/
protected void initialize(URL pluginJarUrl, ClassLoader classLoader, ClassLoader parentClassLoader,
- boolean unpackJars, File tmpDirectory) throws Exception {
+ boolean unpackJars, File tmpDirectory, ServerPluginDescriptorType descriptor) throws Exception {
if (classLoader == null) {
if (parentClassLoader == null) {
parentClassLoader = this.getClass().getClassLoader();
@@ -130,24 +99,12 @@ public class ServerPluginEnvironment {
}
}
- initializeDescriptor(classLoader, pluginJarUrl);
-
this.pluginUrl = pluginJarUrl;
+ this.pluginDescriptor = descriptor;
this.pluginClassLoader = classLoader;
this.pluginName = this.pluginDescriptor.getName();
}
- private void initializeDescriptor(ClassLoader classloader, URL pluginJarUrl) throws Exception {
-
- if (pluginJarUrl == null) {
- throw new Exception("A valid plugin JAR URL must be supplied in order to initialize the descriptor");
- }
-
- log.debug("Initializing descriptor from plugin URL [" + pluginJarUrl + ']');
- this.pluginDescriptor = ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginJarUrl);
- return;
- }
-
public String getPluginName() {
return this.pluginName;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
index ec868bc..f9fe313 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
@@ -18,30 +18,45 @@
*/
package org.rhq.enterprise.server.plugin.pc;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
+
/**
* Defines the types of server-side plugins that are currently supported.
*
* @author John Mazzitelli
*/
-public enum ServerPluginType {
- /**
- * Generic plugins need only be started and stopped by the plugin container, but otherwise has no
- * dependencies or needs that are provided to it by the plugin container.
- */
- GENERIC,
+public class ServerPluginType {
+ private final Class<? extends ServerPluginDescriptorType> descriptorType;
+
+ public ServerPluginType(Class<? extends ServerPluginDescriptorType> descriptorType) {
+ if (descriptorType == null) {
+ throw new NullPointerException("descriptorType must not be null");
+ }
+ this.descriptorType = descriptorType;
+ }
+
+ public Class<? extends ServerPluginDescriptorType> getDescriptorType() {
+ return descriptorType;
+ }
- /**
- * Content plugins obtain repos and packages from remote locations.
- */
- CONTENT,
+ @Override
+ public String toString() {
+ return this.descriptorType.getSimpleName().replace("DescriptorType", "");
+ }
- /**
- * Perspective plugins allow customization of the management interface.
- */
- PERSPECTIVE,
+ @Override
+ public int hashCode() {
+ return this.descriptorType.getName().hashCode();
+ }
- /**
- * Alert plugins allow alerts to be sent to custom endpoints.
- */
- ALERT
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof ServerPluginType)) {
+ return false;
+ }
+ return this.descriptorType.getName().equals(((ServerPluginType) obj).descriptorType.getName());
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertServerPluginContainer.java
index 63d3b4e..60a228f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertServerPluginContainer.java
@@ -21,6 +21,8 @@ package org.rhq.enterprise.server.plugin.pc.alert;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.alert.AlertPluginDescriptorType;
/**
* Manages alert plugins.
@@ -41,4 +43,8 @@ public class AlertServerPluginContainer extends AbstractTypeServerPluginContaine
public void shutdown() {
}
+ @Override
+ public ServerPluginType getSupportedServerPluginType() {
+ return new ServerPluginType(AlertPluginDescriptorType.class);
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
index ed229e2..acf2638 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/ContentServerPluginContainer.java
@@ -28,9 +28,11 @@ import org.rhq.core.domain.content.ContentSource;
import org.rhq.core.domain.content.PackageVersion;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.scheduler.SchedulerLocal;
import org.rhq.enterprise.server.scheduler.jobs.ContentSourceSyncJob;
import org.rhq.enterprise.server.util.LookupUtil;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.content.ContentPluginDescriptorType;
/**
* The container responsible for managing the lifecycle of content server-side plugins.
@@ -66,6 +68,11 @@ public class ContentServerPluginContainer extends AbstractTypeServerPluginContai
this.pluginManager.shutdown();
}
+ @Override
+ public ServerPluginType getSupportedServerPluginType() {
+ return new ServerPluginType(ContentPluginDescriptorType.class);
+ }
+
/**
* Returns the object that is responsible for managing all {@link ContentProvider adapters} which are the
* things that know how to download content from a specific {@link ContentSource}.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginContainer.java
index 4a089c3..204cfc0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginContainer.java
@@ -21,6 +21,8 @@ package org.rhq.enterprise.server.plugin.pc.generic;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.generic.GenericPluginDescriptorType;
/**
* Manages generic plugins. This plugin container is very simple because it provides
@@ -42,4 +44,8 @@ public class GenericServerPluginContainer extends AbstractTypeServerPluginContai
public void shutdown() {
}
+ @Override
+ public ServerPluginType getSupportedServerPluginType() {
+ return new ServerPluginType(GenericPluginDescriptorType.class);
+ }
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/perspective/PerspectiveServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/perspective/PerspectiveServerPluginContainer.java
index af4b847..202ab03 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/perspective/PerspectiveServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/perspective/PerspectiveServerPluginContainer.java
@@ -21,6 +21,8 @@ package org.rhq.enterprise.server.plugin.pc.perspective;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.perspective.PerspectivePluginDescriptorType;
/**
* Manages perspective plugins.
@@ -41,4 +43,8 @@ public class PerspectiveServerPluginContainer extends AbstractTypeServerPluginCo
public void shutdown() {
}
+ @Override
+ public ServerPluginType getSupportedServerPluginType() {
+ return new ServerPluginType(PerspectivePluginDescriptorType.class);
+ }
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
index 3780c90..c42c479 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/test/TestServerPluginService.java
@@ -20,8 +20,10 @@ package org.rhq.enterprise.server.test;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -30,7 +32,6 @@ import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainerConfiguration;
import org.rhq.enterprise.server.plugin.pc.ServerPluginService;
-import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
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.ContentProviderPackageDetails;
@@ -62,8 +63,10 @@ public class TestServerPluginService extends ServerPluginService implements Test
*/
class TestMasterServerPluginContainer extends MasterServerPluginContainer {
@Override
- protected void createPluginContainers(Map<ServerPluginType, AbstractTypeServerPluginContainer> pcs) {
- pcs.put(ServerPluginType.CONTENT, new TestContentServerPluginContainer(this));
+ protected List<AbstractTypeServerPluginContainer> createPluginContainers() {
+ ArrayList<AbstractTypeServerPluginContainer> pcs = new ArrayList<AbstractTypeServerPluginContainer>(1);
+ pcs.add(new TestContentServerPluginContainer(this));
+ return pcs;
}
}
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 44cbadf..ac89223 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
@@ -153,6 +153,9 @@ public abstract class ServerPluginDescriptorUtil {
if (descriptor == null) {
descriptor = loadPluginDescriptorFromUrl(pluginFile.toURI().toURL());
+ if (descriptor == null) {
+ throw new Exception("Plugin is missing a descriptor: " + pluginFile);
+ }
}
String version = descriptor.getVersion();
@@ -177,13 +180,14 @@ public abstract class ServerPluginDescriptorUtil {
}
/**
- * Loads a plugin descriptor from the given plugin jar and returns it.
- *
- * This is a static method to provide a convienence method for others to be able to use.
+ * Loads a plugin descriptor from the given plugin jar and returns it. If the given jar does not
+ * have a server plugin descriptor, <code>null</code> will be returned, meaning this is not
+ * a server plugin jar.
*
* @param pluginJarFileUrl URL to a plugin jar file
- * @return the plugin descriptor found in the given plugin jar file
- * @throws Exception if failed to find or parse a descriptor file in the plugin jar
+ * @return the plugin descriptor found in the given plugin jar file, or <code>null</code> if there
+ * is no plugin descriptor in the jar file
+ * @throws Exception if failed to parse the descriptor file found in the plugin jar
*/
public static ServerPluginDescriptorType loadPluginDescriptorFromUrl(URL pluginJarFileUrl) throws Exception {
@@ -192,7 +196,10 @@ public abstract class ServerPluginDescriptorUtil {
if (pluginJarFileUrl == null) {
throw new Exception("A valid plugin JAR URL must be supplied.");
}
- logger.debug("Loading plugin descriptor from plugin jar at [" + pluginJarFileUrl + "]...");
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Loading plugin descriptor from plugin jar at [" + pluginJarFileUrl + "]...");
+ }
testPluginJarIsReadable(pluginJarFileUrl);
@@ -211,27 +218,28 @@ public abstract class ServerPluginDescriptorUtil {
}
}
- if (descriptorEntry == null) {
- throw new Exception("The plugin descriptor does not exist");
- }
-
- Unmarshaller unmarshaller = null;
ServerPluginDescriptorType pluginDescriptor = null;
- try {
- unmarshaller = getServerPluginDescriptorUnmarshaller();
- pluginDescriptor = ((JAXBElement<? extends ServerPluginDescriptorType>) unmarshaller.unmarshal(jis))
- .getValue();
- } finally {
- if (unmarshaller != null) {
- for (ValidationEvent ev : ((ValidationEventCollector) unmarshaller.getEventHandler()).getEvents()) {
- logger.debug("Plugin [" + pluginJarFileUrl + "] descriptor event {Severity: "
- + ev.getSeverity() + ", Message: " + ev.getMessage() + ", Exception: "
- + ev.getLinkedException() + "}");
+
+ if (descriptorEntry != null) {
+ Unmarshaller unmarshaller = null;
+ try {
+ unmarshaller = getServerPluginDescriptorUnmarshaller();
+ Object jaxbElement = unmarshaller.unmarshal(jis);
+ pluginDescriptor = ((JAXBElement<? extends ServerPluginDescriptorType>) jaxbElement).getValue();
+ } finally {
+ if (unmarshaller != null) {
+ for (ValidationEvent ev : ((ValidationEventCollector) unmarshaller.getEventHandler())
+ .getEvents()) {
+ logger.debug("Plugin [" + pluginJarFileUrl + "] descriptor event {Severity: "
+ + ev.getSeverity() + ", Message: " + ev.getMessage() + ", Exception: "
+ + ev.getLinkedException() + "}");
+ }
}
}
}
return pluginDescriptor;
+
} catch (Exception e) {
throw new Exception("Could not successfully parse the plugin descriptor [" + PLUGIN_DESCRIPTOR_PATH
+ "] found in plugin jar at [" + pluginJarFileUrl + "]", e);
diff --git a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-perspective.xsd b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-perspective.xsd
index 4a85c0e..85aa20b 100644
--- a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-perspective.xsd
+++ b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-perspective.xsd
@@ -22,7 +22,6 @@
</xs:appinfo>
</xs:annotation>
- <!--
<xs:element name="perspective-plugin" type="perspective:PerspectivePluginDescriptorType" substitutionGroup="serverplugin:server-plugin">
<xs:annotation>
<xs:documentation>
@@ -41,151 +40,10 @@
<xs:complexContent>
<xs:extension base="serverplugin:ServerPluginDescriptorType">
<xs:sequence>
- ...put specific perspective schema definitions here...
+ <!--...put specific perspective schema definitions here...-->
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
- -->
- <xs:element name="perspective">
- <xs:annotation>
- <xs:documentation>
-Perspective is a collection of user interface screens and defined URL access points to
-get to high level functionality within the Perspective.
-
- Fields:
-
- name: Name of the Perspective.
-
- url: Root URL of the Perspective.
-
- description: Description of Perspective
-
- tasks: The set of Tasks this Perspective 'owns' and shares as available for users to
- navigate to.
-
- navigation: The List of NavigationItem objects associated with this Perspective.
- NavigationItems are name/path pairs that represent high level navigation links this
- Perspective desires to show. Examples would for an Administration Perspective:
-
- Name , Path
- Users , /admin/users
- Systems , /admin/systems
- Configuration, /admin/configuration
-
- </xs:documentation>
- <xs:appinfo>
- <jaxb:class name="Perspective"/>
- </xs:appinfo>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element ref="perspective:task" minOccurs="0" maxOccurs="unbounded">
- <xs:annotation>
- <xs:documentation>
- Defines child server types that can be embedded in this server type.
- </xs:documentation>
- <xs:appinfo>
- <jaxb:property name="tasks" />
- </xs:appinfo>
- </xs:annotation>
- </xs:element>
- <xs:element ref="perspective:navigationitem" minOccurs="0" maxOccurs="unbounded">
- <xs:annotation>
- <xs:documentation>
- Defines child server types that can be embedded in this server type.
- </xs:documentation>
- <xs:appinfo>
- <jaxb:property name="navigationItems" />
- </xs:appinfo>
- </xs:annotation>
- </xs:element>
- </xs:sequence>
- <xs:attribute name="name" use="required" type="xs:string"/>
- <xs:attribute name="path" type="xs:string"/>
- <xs:attribute name="description" type="xs:string"/>
-
- </xs:complexType>
- </xs:element>
-
-
- <xs:element name="task">
- <xs:annotation>
- <xs:documentation>
-Tasks are high level UI concepts that a Perspectives are responsible for. The Task will
-provide a URL that allows the user to access the starting point for that Task.
-
-For example, common tasks in most web applications involve creation and management of
-Users of the system. A common task in managing users is the step of actually creating a
-User. In order to designate the starting point for creating a user you would create a
-Task object:
-
-Task.name = "user create"
-Task.url = "/users/create"
-Task.display = "Create a new User in the system"
-Task.urlmatches = "/users/*"
-
-Fields:
-
-The name field is a progmatically referenceable name that isn't intended to change. Code
-will reference Tasks by name.
-
-The url field will allow UIs to build a link to the Task's starting point.
-
-The display can be used when linking to the Task to show a display value describing what
-the Task does
-
-The urlmatches is used to indicate a list of URLs that this Task should be visible to.
-This can allow GUI developers a way to specify the relationship of this Task to specific
-pages or a tree of URLs. The above example indicates that urlmatches is "/users/*" which
-is an indication that the task is relative to all the pages in the /users tree of URLs.
-This can be used by a page rendering to show a link to the 'user create' Task if the user
-was looking at a page with a path starting with /users/
- </xs:documentation>
- <xs:appinfo>
- <jaxb:class name="Task"/>
- </xs:appinfo>
- </xs:annotation>
- <xs:complexType>
- <xs:sequence>
- <xs:element name="pathmatches" type="xs:string" minOccurs="0" maxOccurs="unbounded">
- <xs:annotation>
- <xs:documentation>
- The pathMatches is used to indicate a list of rooted paths that this Task should be visible to.
- This can allow GUI developers a way to specify the relationship of this Task to specific
- pages or a tree of URLs. The above example indicates that urlmatches is "/users/*" which
- is an indication that the task is relative to all the pages in the /users tree of URLs.
- This can be used by a page rendering to show a link to the 'user create' Task if the user
- was looking at a page with a path starting with /users/
- </xs:documentation>
- </xs:annotation>
- </xs:element>
- </xs:sequence>
-
- <xs:attribute name="name" use="required" type="xs:string"/>
- <xs:attribute name="path" use="required" type="xs:string"/>
- <xs:attribute name="description" type="xs:string"/>
- <xs:attribute name="context" type="xs:string"/>
- </xs:complexType>
- </xs:element>
-
- <xs:element name="navigationitem">
- <xs:annotation>
- <xs:documentation>
-NavigationItem is a class that represents named paths that a Perspective can show in a
-GUI to get to high-level areas of a Perspective's pages. An example would be: Typical web
-applications include a Top Level navigation bar. You could represent a Perspective's top
-nav with a set of NavigationItems
- </xs:documentation>
- <xs:appinfo>
- <jaxb:class name="NavigationItem"/>
- </xs:appinfo>
- </xs:annotation>
- <xs:complexType>
- <xs:attribute name="name" use="required" type="xs:string"/>
- <xs:attribute name="path" type="xs:string"/>
- </xs:complexType>
- </xs:element>
-
</xs:schema>
commit 4012ef2d87105666daedc4362e39761497883a5c
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 6 09:57:22 2009 -0500
fix the build - we should not be creating modules/dev-container,
everything goes in /dev-container
diff --git a/.gitignore b/.gitignore
index 21d58ab..55de495 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,7 +13,6 @@ logs
*.ipr
*.iws
dev-container
-modules/dev-container
dev-agent
antlr-generated/
*.tokens
diff --git a/modules/enterprise/remoting/cli/pom.xml b/modules/enterprise/remoting/cli/pom.xml
index 68b4b96..06cee76 100644
--- a/modules/enterprise/remoting/cli/pom.xml
+++ b/modules/enterprise/remoting/cli/pom.xml
@@ -336,7 +336,7 @@
<id>dev</id>
<properties>
<rhq.client.build.include.client.jar>true</rhq.client.build.include.client.jar>
- <rhq.rootDir>../../..</rhq.rootDir>
+ <rhq.rootDir>../../../..</rhq.rootDir>
<rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir>
<rhq.projectJar>${project.build.finalName}.zip</rhq.projectJar>
<rhq.deploymentZip>rhq-remoting-cli-${project.version}.zip</rhq.deploymentZip>
diff --git a/modules/enterprise/server/xml-schemas/pom.xml b/modules/enterprise/server/xml-schemas/pom.xml
index c5c1b62..07962d2 100644
--- a/modules/enterprise/server/xml-schemas/pom.xml
+++ b/modules/enterprise/server/xml-schemas/pom.xml
@@ -171,7 +171,7 @@
<id>dev</id>
<properties>
- <rhq.rootDir>../../..</rhq.rootDir>
+ <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>
commit 32c861d0f49ac2e117dd963ad360d1d7b452256d
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Fri Nov 6 09:41:22 2009 -0500
prototype of custom tab containing page-within-a-page implemented via IFRAME (for perspective service)
diff --git a/modules/enterprise/gui/perspectives/pom.xml b/modules/enterprise/gui/perspectives/pom.xml
new file mode 100644
index 0000000..3ff4835
--- /dev/null
+++ b/modules/enterprise/gui/perspectives/pom.xml
@@ -0,0 +1,33 @@
+<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>1.4.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-gui-perspectives-parent</artifactId>
+ <packaging>pom</packaging>
+
+ <name>RHQ Enterprise GUI Perspectives</name>
+ <description>parent POM for perspective modules for the RHQ enterprise GUI</description>
+
+ <scm>
+ <connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/enterprise/gui/per...</connection>
+ <developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/enterprise/gui/per...</developerConnection>
+ </scm>
+
+ <properties>
+ <scm.module.path>modules/enterprise/gui/perspectives/</scm.module.path>
+ </properties>
+
+ <modules>
+ <module>sample-perspective-war</module>
+ </modules>
+
+</project>
diff --git a/modules/enterprise/gui/perspectives/sample-perspective-war/pom.xml b/modules/enterprise/gui/perspectives/sample-perspective-war/pom.xml
new file mode 100644
index 0000000..c653fef
--- /dev/null
+++ b/modules/enterprise/gui/perspectives/sample-perspective-war/pom.xml
@@ -0,0 +1,143 @@
+<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>1.4.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-sample-perspective</artifactId>
+ <packaging>war</packaging>
+
+ <name>Sample RHQ Perspective War</name>
+
+ <scm>
+ <connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/enterprise/gui/per...</connection>
+ <developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/enterprise/gui/per...</developerConnection>
+ </scm>
+
+ <properties>
+ <scm.module.path>modules/enterprise/gui/perspectives/sample-perspective-war/</scm.module.path>
+ <war.dir>${basedir}/target/${final.name}</war.dir>
+ </properties>
+
+ <dependencies>
+
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+
+ <plugins>
+
+ <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>true</filtering>
+ <directory>${basedir}/src/main/webapp</directory>
+ <includes>
+ <include>**/*.properties</include>
+ </includes>
+ </resource>
+ </webResources>
+ </configuration>
+ </plugin>
+
+ </plugins>
+
+ </build>
+
+ <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.deploymentName}</rhq.deploymentDir>
+ </properties>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.1</version>
+ <executions>
+
+ <execution>
+ <id>deploy-classes</id>
+ <phase>compile</phase>
+ <configuration>
+ <tasks>
+ <property name="classes.dir" location="${rhq.deploymentDir}/WEB-INF/classes" />
+ <echo>*** Copying updated files from target/classes to ${classes.dir}...</echo>
+ <copy todir="${classes.dir}" failonerror="false" verbose="${rhq.verbose}">
+ <fileset dir="target/classes" />
+ </copy>
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>deploy</id>
+ <phase>package</phase>
+ <configuration>
+ <tasks>
+ <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>
+ <delete dir="${deployment.dir}.rej" /> <!-- need to remove any residual backups -->
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ <execution>
+ <id>undeploy</id>
+ <phase>clean</phase>
+ <configuration>
+ <tasks>
+ <property name="deployment.dir" location="${rhq.deploymentDir}" />
+ <echo>*** Deleting ${deployment.dir}${file.separator}...</echo>
+ <delete dir="${deployment.dir}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+ </profile>
+
+ </profiles>
+
+</project>
\ No newline at end of file
diff --git a/modules/enterprise/gui/perspectives/sample-perspective-war/src/main/webapp/WEB-INF/web.xml b/modules/enterprise/gui/perspectives/sample-perspective-war/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..a1968e1
--- /dev/null
+++ b/modules/enterprise/gui/perspectives/sample-perspective-war/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE web-app
+ PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<web-app>
+ <display-name>Welcome to Foo!</display-name>
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+</web-app>
diff --git a/modules/enterprise/gui/perspectives/sample-perspective-war/src/main/webapp/index.html b/modules/enterprise/gui/perspectives/sample-perspective-war/src/main/webapp/index.html
new file mode 100644
index 0000000..8bc586a
--- /dev/null
+++ b/modules/enterprise/gui/perspectives/sample-perspective-war/src/main/webapp/index.html
@@ -0,0 +1,14 @@
+<script type="text/javascript">
+ //document.domain = "redhat.com";
+</script>
+
+<!-- Force the page to be taller than the height of the browser
+ to test that a vertical scrollbar is not added to the
+ enclosing iframe. -->
+<div style="padding: 10px; background-color: #DDF; height: 1000px;">
+ <h4>It's always good to see something from another perspective.</h4>
+
+ <p>The blue portion of this page is an IFRAME whose content was
+ loaded from rhq-sample-perspective.war, a WAR deployed to the
+ RHQ Server, as a sibling of rhq.ear.</p>
+</div>
diff --git a/modules/enterprise/gui/pom.xml b/modules/enterprise/gui/pom.xml
index 39eb1f6..40076d8 100644
--- a/modules/enterprise/gui/pom.xml
+++ b/modules/enterprise/gui/pom.xml
@@ -35,6 +35,7 @@
<module>portal-war</module>
<module>installer-war</module>
<module>webdav-war</module>
+ <module>perspectives</module>
</modules>
</profile>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/css/win.css b/modules/enterprise/gui/portal-war/src/main/webapp/css/win.css
index 60dcbc6..0cccd4d 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/css/win.css
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/css/win.css
@@ -1,4 +1,5 @@
/* GLOBAL RULES */
+
HTML {
overflow: auto;
}
@@ -7,6 +8,9 @@ BODY {
background-color: #FFF;
margin: 0;
padding: 0;
+ min-height: 100%;
+ height: auto !important;
+ height: 100%;
}
BODY,P,TD,TH,OPTION,INPUT,TEXTAREA,SELECT {
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/js/iframeSSI.js b/modules/enterprise/gui/portal-war/src/main/webapp/js/iframeSSI.js
new file mode 100644
index 0000000..32f26d6
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/js/iframeSSI.js
@@ -0,0 +1,77 @@
+/***********************************************
+* IFrame SSI script II- © Dynamic Drive DHTML code library (http://www.dynamicdrive.com)
+* Visit DynamicDrive.com for hundreds of original DHTML scripts
+* This notice must stay intact for legal use
+***********************************************/
+
+//Input the IDs of the IFRAMES you wish to dynamically resize to match its content height:
+//Separate each ID with a comma. Examples: ["myframe1", "myframe2"] or ["myframe"] or [] for none:
+var iframeids = ["perspective"];
+
+//Should script hide iframe from browsers that don't support this script (non IE5+/NS6+ browsers. Recommended):
+var iframehide = "no";
+
+var isFirefox = (navigator.userAgent.indexOf("Firefox/") != -1);
+// NOTE (ips): Original script had 16px, but 40px was what I needed to make it work on FF 3.5.3.
+var extraHeight = isFirefox ? 40 : 0; // extra height in px to add to iframe in Firefox
+
+function resizeCaller()
+{
+ var dyniframe = new Array();
+ for (i = 0; i < iframeids.length; i++)
+ {
+ if (document.getElementById) {
+ resizeIframe(iframeids[i]);
+ }
+ //reveal iframe for lower end browsers? (see var above):
+ if ((document.all || document.getElementById) && iframehide == "no")
+ {
+ var tempobj = document.all ? document.all[iframeids[i]] : document.getElementById(iframeids[i]);
+ tempobj.style.display = "block";
+ }
+ }
+}
+
+function resizeIframe(frameid)
+{
+ var currentfr = document.getElementById(frameid);
+ if (currentfr && !window.opera)
+ {
+ currentfr.style.display = "block";
+ if (currentfr.contentDocument && currentfr.contentDocument.body.offsetHeight) { // NS6+ syntax
+ currentfr.height = currentfr.contentDocument.body.offsetHeight + extraHeight;
+ } else if (currentfr.Document && currentfr.Document.body.scrollHeight) { // IE5+ syntax
+ currentfr.height = currentfr.Document.body.scrollHeight;
+ }
+ if (currentfr.addEventListener) {
+ currentfr.addEventListener("load", readjustIframe, false);
+ } else if (currentfr.attachEvent) {
+ currentfr.detachEvent("onload", readjustIframe); // Bug fix line
+ currentfr.attachEvent("onload", readjustIframe);
+ }
+ }
+}
+
+function readjustIframe(loadevt)
+{
+ var crossevt = (window.event) ? event : loadevt;
+ var iframeroot = (crossevt.currentTarget) ? crossevt.currentTarget : crossevt.srcElement;
+ if (iframeroot) {
+ resizeIframe(iframeroot.id);
+ }
+}
+
+function loadintoIframe(iframeid, url)
+{
+ if (document.getElementById) {
+ document.getElementById(iframeid).src = url;
+ }
+}
+
+if (window.addEventListener) {
+ window.addEventListener("load", resizeCaller, false);
+} else if (window.attachEvent) {
+ window.attachEvent("onload", resizeCaller);
+} else {
+ window.onload = resizeCaller;
+}
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/js/rhq.js b/modules/enterprise/gui/portal-war/src/main/webapp/js/rhq.js
index 1f6a69f..074890b 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/js/rhq.js
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/js/rhq.js
@@ -715,5 +715,5 @@ var WindowResizeTracker = {
}
};
-// initalize the resize tracker
+// initialize the resize tracker
Event.observe(window, "load", WindowResizeTracker.init);
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/entity/layout/main.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/entity/layout/main.xhtml
index 4c08b0d..e314620 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/entity/layout/main.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/entity/layout/main.xhtml
@@ -49,10 +49,8 @@ id - the id of the Resource being accessed
</div>
</div>
<div id="centerContent" class="column" style="width: #{100 - UserPreferencesUIBean.leftResourceNavState}%;">
-
<div id="centerContentWrapper" class="content-right">
-
- <div style="left: 0; right: 0;">
+ <div style="left: 0; right: 0; height: 100%;">
<ui:insert name="summary"><p>Default Entity Summary</p></ui:insert>
<ui:insert name="tabBar"><p>Default Entity TabBar</p></ui:insert>
<ui:insert name="content"><p>Default Entity Content</p></ui:insert>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml
index dd83460..4420565 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/layout/main-layout.xhtml
@@ -29,6 +29,13 @@
<script type="text/javascript" src="/js/formValues.js"></script>
<script type="text/javascript" src="/js/rhq.js"></script>
<script type="text/javascript" src="/js/popup.js"></script>
+ <script type="text/javascript" src="/js/iframeSSI.js">
+ /***********************************************
+ * IFrame SSI script II- © Dynamic Drive DHTML code library (http://www.dynamicdrive.com)
+ * Visit DynamicDrive.com for hundreds of original DHTML scripts
+ * This notice must stay intact for legal use
+ ***********************************************/
+ </script>
<link href="/css/theme/default.css" rel="stylesheet" type="text/css"/>
<link href="/css/theme/alphacube.css" rel="stylesheet" type="text/css"/>
@@ -43,7 +50,7 @@
padding-top: 3px;
padding-bottom: 3px;
}
- HTML, BODY { overflow: hidden; }
+ HTML, BODY { overflow: hidden; }
</style>
<link rel="stylesheet" type="text/css" media="screen" href="/css/tabular.css"/>
@@ -68,7 +75,7 @@ Firefox and other Gecko-based browsers to render the page in "Almost Standards"
<!-- =================== PAGE HEADER =================== -->
- <script language="javascript" type="text/javascript">
+ <script language="javascript" type="text/javascript">
//this has to be defined before the resize trackers inside
//the PageBody element because they depend on the values
//computed inside this tracker function.
@@ -78,7 +85,7 @@ Firefox and other Gecko-based browsers to render the page in "Almost Standards"
if (Prototype.Browser.IE) {
header.style.height = WindowResizeTracker.currentSizes.windowHeight + 'px';
- } else {
+ } else {
header.style.height = (WindowResizeTracker.currentSizes.windowHeight - borderHeight) + 'px';
}
header.style.width = WindowResizeTracker.currentSizes.windowWidth + 'px';
@@ -87,7 +94,7 @@ Firefox and other Gecko-based browsers to render the page in "Almost Standards"
//27 = menu height (and the top position of PageBody)
body.style.height = (WindowResizeTracker.currentSizes.windowHeight - 27 - borderHeight) + 'px';
body.style.width = header.style.width;
-
+
document.body.style.height = WindowResizeTracker.currentSizes.windowHeight + 'px';
});
</script>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/layout/main.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/layout/main.xhtml
index 05eb2f3..6b5d39d 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/layout/main.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/layout/main.xhtml
@@ -119,6 +119,12 @@ REQUEST PARAMETERS:
<onc:subtab name="History" url="/rhq/resource/content/history.xhtml" />
</onc:tab>
+ <onc:tab name="Custom" image="/images/icons/Subcategory_16.png"
+ url="/rhq/resource/perspective/index.xhtml"
+ rendered="#{param.debug}">
+ <f:param name="debug" value="#{param.debug}" />
+ </onc:tab>
+
</onc:tabBar>
<!-- Shows the results of the last action executed. -->
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/perspective/index.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/perspective/index.xhtml
new file mode 100644
index 0000000..fe32cbd
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/perspective/index.xhtml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+
+<!DOCTYPE html
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets">
+
+THIS TEXT WILL BE REMOVED.
+
+<ui:composition template="/rhq/resource/layout/main.xhtml">
+
+ THIS TEXT WILL BE REMOVED AS WELL.
+
+ <ui:param name="pageTitle"
+ value="#{ResourceUIBean.resourceType.name} '#{ResourceUIBean.name}' - Custom Perspective-Defined Tab"/>
+
+ <ui:param name="selectedTabName" value="Custom"/>
+
+ <ui:define name="content">
+
+ <iframe id="perspective" src="/rhq-sample-perspective/"
+ scrolling="no" marginwidth="0" marginheight="0" frameborder="0"
+ style="overflow: visible; display: none; width: 100%;">
+ ERROR: Perspective-defined page could not be embedded. Please make sure you're using IE6+ or FF2+.
+ </iframe>
+
+ </ui:define>
+
+</ui:composition>
+
+THIS TEXT WILL BE REMOVED AS WELL.
+
+</html>
diff --git a/modules/enterprise/server/container/pom.xml b/modules/enterprise/server/container/pom.xml
index 5953428..7eb6635 100644
--- a/modules/enterprise/server/container/pom.xml
+++ b/modules/enterprise/server/container/pom.xml
@@ -45,6 +45,13 @@
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-sample-perspective</artifactId>
+ <version>${project.version}</version>
+ <type>war</type>
+ </dependency>
+
<!-- 3rd Party Deps -->
<dependency>
diff --git a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
index 9b458d7..1c04382 100644
--- a/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
+++ b/modules/enterprise/server/container/src/main/scripts/rhq-container.build.xml
@@ -406,7 +406,12 @@
<include name="jaxb-impl.jar" />
</fileset>
</move>
-
+
+ <echo>Deploying perspective WARs ...</echo>
+ <mkdir dir="${jboss.deploy.dir}/rhq-sample-perspective.war" />
+ <unwar src="${settings.localRepository}/org/rhq/rhq-sample-perspective/${rhq.version}/rhq-sample-perspective-${rhq.version}.war"
+ dest="${jboss.deploy.dir}/rhq-sample-perspective.war" />
+
</target>
<target name="package-connectors" if="package-connectors">
commit dbb063634e4472b07d228995363e7a973cf293a0
Author: Shannon Hughes <shughes(a)fred.hughes.lan>
Date: Fri Nov 6 09:04:44 2009 -0500
logic for aliases platform service discovery and load resources
diff --git a/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesComponent.java b/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesComponent.java
index ff37eab..53d1ac5 100644
--- a/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesComponent.java
+++ b/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesComponent.java
@@ -43,12 +43,14 @@ public class AliasesComponent extends AugeasConfigurationComponent {
}
public AvailabilityType getAvailability() {
- return super.getAvailability();
+ AvailabilityType aType = super.getAvailability();
+ return aType;
}
@Override
public Configuration loadResourceConfiguration() throws Exception {
- return super.loadResourceConfiguration();
+ Configuration config = super.loadResourceConfiguration();
+ return config;
}
@Override
@@ -58,7 +60,9 @@ public class AliasesComponent extends AugeasConfigurationComponent {
@Override
protected AugeasNode getNewListMemberNode(AugeasNode listNode, PropertyDefinitionMap listMemberPropDefMap, int listIndex) {
- return new AugeasNode(listNode, "0" + listIndex);
+ PropertyDefinitionMap member = listMemberPropDefMap;
+ AugeasNode node = new AugeasNode(listNode, "0" + listIndex);
+ return node;
}
protected AugeasNode getExistingChildNodeForListMemberPropertyMap(AugeasNode parentNode,
diff --git a/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesDiscoveryComponent.java b/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesDiscoveryComponent.java
index ebb16a2..d876c3c 100644
--- a/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesDiscoveryComponent.java
+++ b/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesDiscoveryComponent.java
@@ -33,19 +33,17 @@ import java.util.Set;
*/
public class AliasesDiscoveryComponent extends AugeasConfigurationDiscoveryComponent {
- private final Log log = LogFactory.getLog(this.getClass());
-
@Override
public Set discoverResources(ResourceDiscoveryContext discoveryContext) throws InvalidPluginConfigurationException,
Exception {
- return super.discoverResources(discoveryContext);
+ Set discoverResources = super.discoverResources(discoveryContext);
+ return discoverResources;
}
@Override
public DiscoveredResourceDetails discoverResource(Configuration pluginConfig,
ResourceDiscoveryContext discoveryContext) throws InvalidPluginConfigurationException {
- return super.discoverResource(pluginConfig, discoveryContext);
+ DiscoveredResourceDetails details = super.discoverResource(pluginConfig, discoveryContext);
+ return details;
}
-
-
}
diff --git a/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml
index 8c6a638..a937098 100644
--- a/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml
@@ -15,7 +15,11 @@
discovery="AliasesDiscoveryComponent"
class="AliasesComponent"
supportsManualAdd="true">
-
+
+ <runs-inside>
+ <parent-resource-type name="Linux" plugin="Platforms"/>
+ </runs-inside>
+
<plugin-configuration>
<c:simple-property name="augeasModuleName" displayName="Augeas Module Name" default="Aliases" required="true" readOnly="true"
description="the name of the Augeas module/lens to use for loading and updating this resource's configuration"/>
@@ -24,7 +28,7 @@
default="/etc/aliases"
description="the absolute paths of the configuration files, delimited with pipe characters"/>
<c:simple-property name="resourceConfigurationRootNode" required="true" readOnly="true"
- default="/files/etc/aliases"/>
+ default="/files/etc/aliases/*"/>
</plugin-configuration>
<resource-configuration>
@@ -35,7 +39,6 @@
<c:simple-property name="value" displayName="Value" type="string" required="true"
description="Username or Alias name value"/>
-
</c:map-property>
</c:list-property>
</resource-configuration>
commit 06f58d5ac74be0550810cbe270e74d712cc1b0c4
Author: Pradeep Kilambi <pkilambi(a)redhat.com>
Date: Thu Nov 5 21:40:31 2009 -0500
some fixes based on unit test failures
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Distribution.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Distribution.java
index 233ad60..a7507fc 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Distribution.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Distribution.java
@@ -22,20 +22,23 @@
*/
package org.rhq.core.domain.content;
-import org.hibernate.annotations.NamedQueries;
-import org.hibernate.annotations.NamedQuery;
+import java.io.Serializable;
-import javax.persistence.Entity;
-import javax.persistence.SequenceGenerator;
-import javax.persistence.Table;
+import javax.persistence.CascadeType;
import javax.persistence.Column;
+import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
-import java.io.Serializable;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import javax.persistence.SequenceGenerator;
+import javax.persistence.Table;
+import org.hibernate.annotations.NamedQueries;
+import org.hibernate.annotations.NamedQuery;
/**
*
@@ -43,23 +46,22 @@ import java.io.Serializable;
*/
@Entity
@NamedQueries( {
- @NamedQuery(name = Distribution.QUERY_FIND_ALL,
- query = "SELECT dt FROM Distribution dt"),
+ @NamedQuery(name = Distribution.QUERY_FIND_ALL, query = "SELECT dt FROM Distribution dt"),
@NamedQuery(name = Distribution.QUERY_FIND_PATH_BY_DIST_TYPE, query = "SELECT dt " + " FROM Distribution dt "
+ " WHERE dt.label = :label AND dt.distributionType.name = :typeName "),
- @NamedQuery(name = Distribution.QUERY_FIND_PATH_BY_DIST_LABEL,
- query = "SELECT dt.base_path FROM Distribution AS dt WHERE dt.label = :label"),
- @NamedQuery(name = Distribution.QUERY_FIND_PATH_BY_DIST_PATH,
- query = "SELECT dt.base_path FROM Distribution AS dt WHERE dt.base_path = :path")})
+ @NamedQuery(name = Distribution.QUERY_FIND_BY_DIST_LABEL, query = "SELECT dt FROM Distribution dt WHERE dt.label = :label"),
+ @NamedQuery(name = Distribution.QUERY_FIND_BY_DIST_PATH, query = "SELECT dt FROM Distribution dt WHERE dt.base_path = :path"),
+ @NamedQuery(name = Distribution.QUERY_DELETE_BY_DIST_ID, query = "DELETE Distribution dt WHERE dt.id = :distid") })
@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_DISTRIBUTION_ID_SEQ")
@Table(name = "RHQ_DISTRIBUTION")
public class Distribution implements Serializable {
-
+
private static final long serialVersionUID = 1L;
public static final String QUERY_FIND_ALL = "Distribution.findAll";
- public static final String QUERY_FIND_PATH_BY_DIST_LABEL = "Distribution.findPathByDistLabel";
- public static final String QUERY_FIND_PATH_BY_DIST_PATH = "Distribution.findPathByDistPath";
- public static final String QUERY_FIND_PATH_BY_DIST_TYPE = "Distribution.findPathByDistType";
+ public static final String QUERY_FIND_BY_DIST_LABEL = "Distribution.findByDistLabel";
+ public static final String QUERY_FIND_BY_DIST_PATH = "Distribution.findByDistPath";
+ public static final String QUERY_FIND_PATH_BY_DIST_TYPE = "Distribution.findPathByDistType";
+ public static final String QUERY_DELETE_BY_DIST_ID = "Distribution.deleteByDistId";
// Attributes --------------------------------------------
@@ -69,7 +71,7 @@ public class Distribution implements Serializable {
private int id;
@JoinColumn(name = "DISTRIBUTION_TYPE_ID", referencedColumnName = "ID", nullable = false)
- @ManyToOne
+ @ManyToOne(cascade = CascadeType.PERSIST)
private DistributionType distributionType;
/**
@@ -77,20 +79,22 @@ public class Distribution implements Serializable {
*/
@Column(name = "LABEL", nullable = false)
private String label;
-
+
/**
* Base path where the kickstart tree is located
*/
@Column(name = "BASE_PATH", nullable = false)
private String base_path;
+ @Column(name = "LAST_MODIFIED", nullable = false)
+ private long lastModifiedDate;
// Constructor ----------------------------------------
public Distribution() {
}
- public Distribution(String label, String basepathIn, DistributionType distributionType ) {
+ public Distribution(String label, String basepathIn, DistributionType distributionType) {
setLabel(label);
setBasePath(basepathIn);
setDistributionType(distributionType);
@@ -112,6 +116,14 @@ public class Distribution implements Serializable {
this.base_path = basepathIn;
}
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
/**
* Describes the capabilities of this distribution.
*/
@@ -123,6 +135,14 @@ public class Distribution implements Serializable {
this.distributionType = distributionType;
}
+ public void setLastModifiedDate(long lastModifiedDate) {
+ this.lastModifiedDate = lastModifiedDate;
+ }
+
+ public long getLastModifiedDate() {
+ return lastModifiedDate;
+ }
+
// Object Overridden Methods --------------------------------------------
@Override
@@ -153,6 +173,16 @@ public class Distribution implements Serializable {
return true;
}
+ @PrePersist
+ void onPersist() {
+ this.setLastModifiedDate(System.currentTimeMillis());
+ }
+
+ @PreUpdate
+ void onUpdate() {
+ this.setLastModifiedDate(System.currentTimeMillis());
+ }
+
@Override
public int hashCode() {
final int prime = 31;
@@ -160,4 +190,5 @@ public class Distribution implements Serializable {
result = (prime * result) + ((label == null) ? 0 : label.hashCode());
return result;
}
+
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
index 4e05045..522cbc2 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/RepoDistribution.java
@@ -29,12 +29,12 @@ import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.PrePersist;
import javax.persistence.Table;
-import javax.persistence.ManyToOne;
-import javax.persistence.JoinColumn;
/**
* This is the many-to-many entity that correlates a repo with a content source that will fill the repo with
@@ -45,7 +45,7 @@ import javax.persistence.JoinColumn;
@Entity
@IdClass(RepoDistributionPK.class)
@NamedQueries( {
- @NamedQuery(name = RepoDistribution.DELETE_BY_KICKSTART_TREE_ID, query = "DELETE RepoDistribution rkt WHERE rkt.dist.id = :KsTreeId"),
+ @NamedQuery(name = RepoDistribution.DELETE_BY_KICKSTART_TREE_ID, query = "DELETE RepoDistribution rkt WHERE rkt.dist.id = :distId"),
@NamedQuery(name = RepoDistribution.DELETE_BY_REPO_ID, query = "DELETE RepoDistribution rkt WHERE rkt.repo.id = :repoId") })
@Table(name = "RHQ_REPO_DIST_MAP_KEY")
public class RepoDistribution implements Serializable {
@@ -69,7 +69,6 @@ public class RepoDistribution implements Serializable {
@JoinColumn(name = "DISTRIBUTION_ID", referencedColumnName = "ID", nullable = false, insertable = false, updatable = false)
private Distribution dist;
-
@Column(name = "LAST_MODIFIED", nullable = false)
private long last_modified;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java
index b61ce87..08ce133 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerBean.java
@@ -19,26 +19,28 @@
package org.rhq.enterprise.server.content;
+import java.util.List;
+
+import javax.ejb.EJB;
+import javax.ejb.Stateless;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import javax.sql.DataSource;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.content.Distribution;
+import org.rhq.core.domain.content.DistributionType;
+import org.rhq.core.domain.content.RepoDistribution;
import org.rhq.enterprise.server.RHQConstants;
-import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
import org.rhq.enterprise.server.authz.AuthorizationManagerLocal;
import org.rhq.enterprise.server.authz.RequiredPermission;
import org.rhq.enterprise.server.core.AgentManagerLocal;
-import org.rhq.core.domain.content.Distribution;
-import org.rhq.core.domain.content.RepoDistribution;
-import org.rhq.core.domain.content.DistributionType;
-import org.rhq.core.domain.auth.Subject;
-import org.rhq.core.domain.authz.Permission;
-
-import javax.ejb.Stateless;
-import javax.ejb.EJB;
-import javax.persistence.PersistenceContext;
-import javax.persistence.EntityManager;
-import javax.persistence.Query;
-import javax.sql.DataSource;
-import java.util.List;
+import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal;
/**
* @author Pradeep Kilambi
@@ -69,23 +71,28 @@ public class DistributionManagerBean implements DistributionManagerLocal, Distri
private ResourceTypeManagerLocal resourceTypeManager;
@RequiredPermission(Permission.MANAGE_INVENTORY)
- public Distribution createDistribution(Subject user, String kslabel, String basepath, DistributionType disttype)
- throws DistributionException {
+ public Distribution createDistribution(Subject user, String kslabel, String basepath, DistributionType disttype)
+ throws DistributionException {
+
Distribution kstree = new Distribution(kslabel, basepath, disttype);
+ System.out.println("NEW DISTRO CREATED" + kstree);
validateDistTree(kstree);
entityManager.persist(kstree);
+ System.out.println("persisted" + kstree);
return kstree;
}
+
@RequiredPermission(Permission.MANAGE_INVENTORY)
- public void deleteDistributionByRepo(Subject user, int repoId ) {
+ public void deleteDistributionByRepo(Subject user, int repoId) {
log.debug("User [" + user + "] is deleting distribution tree from repo [" + repoId + "]");
entityManager.flush();
entityManager.clear();
- entityManager.createNamedQuery(RepoDistribution.DELETE_BY_REPO_ID).setParameter("repoId", repoId).executeUpdate();
+ entityManager.createNamedQuery(RepoDistribution.DELETE_BY_REPO_ID).setParameter("repoId", repoId)
+ .executeUpdate();
RepoDistribution kstree = entityManager.find(RepoDistribution.class, repoId);
if (kstree != null) {
@@ -98,20 +105,21 @@ public class DistributionManagerBean implements DistributionManagerLocal, Distri
}
@RequiredPermission(Permission.MANAGE_INVENTORY)
- public void deleteDistributionByKSTreeId(Subject user, int kstreeId ) {
- log.debug("User [" + user + "] is deleting distribution tree [" + kstreeId + "]");
+ public void deleteDistributionByDistId(Subject user, int distId) {
+ log.debug("User [" + user + "] is deleting distribution tree [" + distId + "]");
entityManager.flush();
entityManager.clear();
- entityManager.createNamedQuery(RepoDistribution.DELETE_BY_KICKSTART_TREE_ID).setParameter("repoId", kstreeId).executeUpdate();
+ entityManager.createNamedQuery(Distribution.QUERY_DELETE_BY_DIST_ID).setParameter("distid", distId)
+ .executeUpdate();
- RepoDistribution kstree = entityManager.find(RepoDistribution.class, kstreeId);
+ Distribution kstree = entityManager.find(Distribution.class, distId);
if (kstree != null) {
entityManager.remove(kstree);
log.debug("User [" + user + "] deleted kstree [" + kstree + "]");
} else {
- log.debug("Distribution tree ID [" + kstreeId + "] doesn't exist - nothing to delete");
+ log.debug("Distribution tree ID [" + distId + "] doesn't exist - nothing to delete");
}
}
@@ -121,9 +129,9 @@ public class DistributionManagerBean implements DistributionManagerLocal, Distri
//TODO: Implement the ks tree bit downloads
}
- @RequiredPermission(Permission.MANAGE_INVENTORY)
+ @SuppressWarnings("unchecked")
public Distribution getDistributionByLabel(String kslabel) {
- Query query = entityManager.createNamedQuery(Distribution.QUERY_FIND_PATH_BY_DIST_LABEL);
+ Query query = entityManager.createNamedQuery(Distribution.QUERY_FIND_BY_DIST_LABEL);
query.setParameter("label", kslabel);
List<Distribution> results = query.getResultList();
@@ -141,8 +149,9 @@ public class DistributionManagerBean implements DistributionManagerLocal, Distri
* @param basepath location on filesystem
* @return kickstarttree object from db
*/
+ @SuppressWarnings("unchecked")
public Distribution getDistributionByPath(String basepath) {
- Query query = entityManager.createNamedQuery(Distribution.QUERY_FIND_PATH_BY_DIST_PATH);
+ Query query = entityManager.createNamedQuery(Distribution.QUERY_FIND_BY_DIST_PATH);
query.setParameter("base_path", basepath);
List<Distribution> results = query.getResultList();
@@ -161,6 +170,7 @@ public class DistributionManagerBean implements DistributionManagerLocal, Distri
* @throws DistributionException
*/
public void validateDistTree(Distribution kstree) throws DistributionException {
+
if (kstree.getLabel() == null || kstree.getLabel().trim().equals("")) {
throw new DistributionException("A valid Distribution tree is required");
}
@@ -169,6 +179,7 @@ public class DistributionManagerBean implements DistributionManagerLocal, Distri
if (kstreeobj != null) {
throw new DistributionException("There is already a kstree with the name of [" + kstree.getLabel() + "]");
}
+
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerLocal.java
index 83035a3..3867085 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerLocal.java
@@ -25,7 +25,6 @@ import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.content.Distribution;
import org.rhq.core.domain.content.DistributionType;
-
/**
* @author Pradeep Kilambi
*/
@@ -41,7 +40,7 @@ public interface DistributionManagerLocal {
* @return newly created distribution tree object
*/
Distribution createDistribution(Subject subject, String kslabel, String basepath, DistributionType disttype)
- throws DistributionException;
+ throws DistributionException;
/**
* Deletes a given instance of distribution object. If the object does not exist
@@ -53,9 +52,9 @@ public interface DistributionManagerLocal {
/**
* Deletes a given instance of distribution object. If the object does not exist
* @param subject
- * @param kstreeId
+ * @param distId
*/
- void deleteDistributionByKSTreeId(Subject subject, int kstreeId);
+ void deleteDistributionByDistId(Subject subject, int distId);
/**
* get the kickstart tree bits either from database or filesystem based on kickstart label
@@ -79,7 +78,4 @@ public interface DistributionManagerLocal {
*/
Distribution getDistributionByPath(String basepath);
-
-
-
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerRemote.java
index 0aea346..6787017 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerRemote.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/DistributionManagerRemote.java
@@ -18,17 +18,17 @@
*/
package org.rhq.enterprise.server.content;
+import javax.ejb.Remote;
+import javax.jws.WebMethod;
+import javax.jws.WebParam;
+import javax.jws.WebService;
+import javax.jws.soap.SOAPBinding;
+
+import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.content.Distribution;
import org.rhq.core.domain.content.DistributionType;
-import org.rhq.core.domain.auth.Subject;
import org.rhq.enterprise.server.system.ServerVersion;
-import javax.jws.soap.SOAPBinding;
-import javax.jws.WebService;
-import javax.jws.WebMethod;
-import javax.jws.WebParam;
-import javax.ejb.Remote;
-
/**
* @author Pradeep Kilambi
*/
@@ -47,10 +47,10 @@ public interface DistributionManagerRemote {
*/
@WebMethod
Distribution createDistribution( //
- @WebParam(name = "subject") Subject subject, //
- @WebParam(name = "kslabel") String kslabel, //
- @WebParam(name = "basepath") String basepath, //
- @WebParam(name = "disttype") DistributionType disttype) throws DistributionException;
+ @WebParam(name = "subject") Subject subject, //
+ @WebParam(name = "kslabel") String kslabel, //
+ @WebParam(name = "basepath") String basepath, //
+ @WebParam(name = "disttype") DistributionType disttype) throws DistributionException;
/**
* Deletes a given instance of kickstart tree object. If the object does not exist
@@ -60,19 +60,19 @@ public interface DistributionManagerRemote {
*/
@WebMethod
void deleteDistributionByRepo( //
- @WebParam(name = "subject") Subject subject, //
- @WebParam(name = "repoId") int repoId) throws Exception;
+ @WebParam(name = "subject") Subject subject, //
+ @WebParam(name = "repoId") int repoId) throws Exception;
/**
* Deletes a given instance of kickstart tree object. If the object does not exist
* @param subject
- * @param kstreeId
+ * @param distId
*
*/
@WebMethod
- void deleteDistributionByKSTreeId( //
- @WebParam(name = "subject") Subject subject, //
- @WebParam(name = "kstreeId") int kstreeId) throws Exception;
+ void deleteDistributionByDistId( //
+ @WebParam(name = "subject") Subject subject, //
+ @WebParam(name = "distId") int distId) throws Exception;
/**
* get the kickstart tree bits either from database or filesystem based on kickstart label
@@ -81,9 +81,8 @@ public interface DistributionManagerRemote {
* @return
*/
@WebMethod
- void getDistributionBits(
- @WebParam(name = "subject") Subject subject, //
- @WebParam(name = "kslabel") String kslabel) throws Exception;
+ void getDistributionBits(@WebParam(name = "subject") Subject subject, //
+ @WebParam(name = "kslabel") String kslabel) throws Exception;
/**
* get kickstart tree based on a given label
@@ -91,8 +90,7 @@ public interface DistributionManagerRemote {
* @return kickstart tree object
*/
@WebMethod
- Distribution getDistributionByLabel(
- @WebParam(name = "kslabel") String kslabel);
+ Distribution getDistributionByLabel(@WebParam(name = "kslabel") String kslabel);
/**
* get kickstart tree based on base path
@@ -100,10 +98,5 @@ public interface DistributionManagerRemote {
* @return kstree object
*/
@WebMethod
- Distribution getDistributionByPath(
- @WebParam(name = "basepath") String basepath);
+ Distribution getDistributionByPath(@WebParam(name = "basepath") String basepath);
}
-
-
-
-
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
index 4503776..1f3325f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java
@@ -83,6 +83,8 @@ import org.rhq.enterprise.server.content.ContentUIManagerBean;
import org.rhq.enterprise.server.content.ContentUIManagerLocal;
import org.rhq.enterprise.server.content.RepoManagerBean;
import org.rhq.enterprise.server.content.RepoManagerLocal;
+import org.rhq.enterprise.server.content.DistributionManagerLocal;
+import org.rhq.enterprise.server.content.DistributionManagerBean;
import org.rhq.enterprise.server.content.metadata.ContentSourceMetadataManagerBean;
import org.rhq.enterprise.server.content.metadata.ContentSourceMetadataManagerLocal;
import org.rhq.enterprise.server.core.AgentManagerBean;
@@ -412,6 +414,11 @@ public final class LookupUtil {
return lookupLocal(RepoManagerBean.class);
}
+ public static DistributionManagerLocal getDistributionManagerLocal() {
+ return lookupLocal(DistributionManagerBean.class);
+ }
+
+
public static AffinityGroupManagerLocal getAffinityGroupManager() {
return lookupLocal(AffinityGroupManagerBean.class);
}
commit dd4d8667c9b12fbba43626d6fafe96b3dd36defe
Author: Shannon Hughes <shughes(a)fred.hughes.lan>
Date: Thu Nov 5 21:32:25 2009 -0500
intial stubs for Aliases service (platform)
diff --git a/modules/plugins/aliases/pom.xml b/modules/plugins/aliases/pom.xml
new file mode 100644
index 0000000..e2f5ee4
--- /dev/null
+++ b/modules/plugins/aliases/pom.xml
@@ -0,0 +1,238 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<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-plugins-parent</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-aliases-plugin</artifactId>
+ <packaging>jar</packaging>
+
+ <name>RHQ Aliases File Plugin</name>
+ <description>A plugin for managing the system aliases file</description>
+
+ <scm>
+ <connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/plugins/aliases</connection>
+ <developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/plugins/aliases</developerConnection>
+ </scm>
+
+ <properties>
+ <scm.module.path>modules/plugins/aliases/</scm.module.path>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-augeas-plugin</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-augeas-plugin</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>integration-tests</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>!true</value>
+ </property>
+ </activation>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>pre-integration-test</phase>
+ <configuration>
+ <tasks>
+ <echo>Setting up integration test plugin container environment under target/itest/...</echo>
+
+ <property name="settings.localRepository" location="${user.home}/.m2/repository" />
+
+ <mkdir dir="target/itest/plugins" />
+ <copy toDir="target/itest/plugins" flatten="true" verbose="true">
+ <!-- the plugin jar for this plugin -->
+ <fileset dir="${project.build.directory}" includes="${project.artifactId}-${project.version}.jar" />
+ <!-- the plugin jars for the plugins this plugin depends on -->
+ <fileset dir="${settings.localRepository}/">
+ <include name="org/rhq/rhq-platform-plugin/${project.version}/rhq-platform-plugin-${project.version}.jar" />
+ <include name="org/rhq/rhq-augeas-plugin/${project.version}/rhq-augeas-plugin-${project.version}.jar" />
+ </fileset>
+ </copy>
+
+ <!-- copy SIGAR jar and native libs into the lib dir -->
+ <mkdir dir="target/itest/lib" />
+ <unzip dest="target/itest/lib">
+ <fileset dir="${settings.localRepository}/org/hyperic/sigar-dist/${sigar.version}" includes="*.zip" />
+ <patternset>
+ <include name="**/lib/sigar.jar" />
+ <include name="**/lib/bcel*.jar" />
+ <include name="**/lib/*.so" />
+ <include name="**/lib/*.sl" />
+ <include name="**/lib/*.dll" />
+ <include name="**/lib/*.dylib" />
+ </patternset>
+ </unzip>
+ <move todir="target/itest/lib" flatten="true">
+ <fileset dir="target/itest/lib">
+ <include name="**/lib/*" />
+ </fileset>
+ </move>
+ <delete dir="target/itest/lib/hyperic-sigar-${sigar.version}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- Integration testing voodoo to load and test this plugin with its plugin dependencies -->
+ <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>true</useSystemClassLoader>
+ <argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
+ <systemProperties>
+ <property>
+ <name>project.artifactId</name>
+ <value>${project.artifactId}</value>
+ </property>
+ <property>
+ <name>project.version</name>
+ <value>${project.version}</value>
+ </property>
+ </systemProperties>
+ </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.deploymentDir>
+ ${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/rhq-downloads/rhq-plugins
+ </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>deploy-jar-meta-inf</id>
+ <phase>package</phase>
+ <configuration>
+ <tasks>
+ <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>
+ </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>
+
+ </profiles>
+
+</project>
diff --git a/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesComponent.java b/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesComponent.java
new file mode 100644
index 0000000..ff37eab
--- /dev/null
+++ b/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesComponent.java
@@ -0,0 +1,78 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.aliases;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionList;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
+import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.plugins.augeas.AugeasConfigurationComponent;
+import org.rhq.plugins.augeas.helper.AugeasNode;
+import net.augeas.Augeas;
+
+import java.util.List;
+
+public class AliasesComponent extends AugeasConfigurationComponent {
+
+ public void start(ResourceContext resourceContext) throws InvalidPluginConfigurationException, Exception {
+ super.start(resourceContext);
+ }
+
+ public void stop() {
+ return;
+ }
+
+ public AvailabilityType getAvailability() {
+ return super.getAvailability();
+ }
+
+ @Override
+ public Configuration loadResourceConfiguration() throws Exception {
+ return super.loadResourceConfiguration();
+ }
+
+ @Override
+ public void updateResourceConfiguration(ConfigurationUpdateReport report) {
+ super.updateResourceConfiguration(report);
+ }
+
+ @Override
+ protected AugeasNode getNewListMemberNode(AugeasNode listNode, PropertyDefinitionMap listMemberPropDefMap, int listIndex) {
+ return new AugeasNode(listNode, "0" + listIndex);
+ }
+
+ protected AugeasNode getExistingChildNodeForListMemberPropertyMap(AugeasNode parentNode,
+ PropertyDefinitionList propDefList, PropertyMap propMap) {
+ // First find all child nodes with the same 'name' value as the PropertyMap.
+ Augeas augeas = getAugeas();
+
+ String name = propMap.getSimple("name").getStringValue();
+ String nameFilter = parentNode.getPath() + "/name";
+ List<String> namePaths = augeas.match(String.format(nameFilter + "/name[.='%s']", name));
+ if (namePaths == null || namePaths.isEmpty()) {
+ return null;
+ }
+ AugeasNode node = new AugeasNode(namePaths.get(0));
+ return node.getParent();
+ }
+}
diff --git a/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesDiscoveryComponent.java b/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesDiscoveryComponent.java
new file mode 100644
index 0000000..ebb16a2
--- /dev/null
+++ b/modules/plugins/aliases/src/main/java/org/rhq/plugins/aliases/AliasesDiscoveryComponent.java
@@ -0,0 +1,51 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.aliases;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+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.ResourceDiscoveryContext;
+import org.rhq.plugins.augeas.AugeasConfigurationDiscoveryComponent;
+
+import java.util.Set;
+
+/**
+ * The ResourceDiscoveryComponent for the "Aliases File" ResourceType.
+ */
+public class AliasesDiscoveryComponent extends AugeasConfigurationDiscoveryComponent {
+
+ private final Log log = LogFactory.getLog(this.getClass());
+
+ @Override
+ public Set discoverResources(ResourceDiscoveryContext discoveryContext) throws InvalidPluginConfigurationException,
+ Exception {
+ return super.discoverResources(discoveryContext);
+ }
+
+ @Override
+ public DiscoveredResourceDetails discoverResource(Configuration pluginConfig,
+ ResourceDiscoveryContext discoveryContext) throws InvalidPluginConfigurationException {
+ return super.discoverResource(pluginConfig, discoveryContext);
+ }
+
+
+}
diff --git a/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml
new file mode 100644
index 0000000..8c6a638
--- /dev/null
+++ b/modules/plugins/aliases/src/main/resources/META-INF/rhq-plugin.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<plugin name="Aliases"
+ displayName="Aliases"
+ description="Support for aliases file"
+ package="org.rhq.plugins.aliases"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <depends plugin="Augeas"/>
+
+ <service name="Aliases File"
+ description="the local file used for mapping aliases to usernames"
+ discovery="AliasesDiscoveryComponent"
+ class="AliasesComponent"
+ supportsManualAdd="true">
+
+ <plugin-configuration>
+ <c:simple-property name="augeasModuleName" displayName="Augeas Module Name" default="Aliases" required="true" readOnly="true"
+ description="the name of the Augeas module/lens to use for loading and updating this resource's configuration"/>
+
+ <c:simple-property name="configurationFilesInclusionPatterns" displayName="Configuration File Paths" required="true" readOnly="true"
+ default="/etc/aliases"
+ description="the absolute paths of the configuration files, delimited with pipe characters"/>
+ <c:simple-property name="resourceConfigurationRootNode" required="true" readOnly="true"
+ default="/files/etc/aliases"/>
+ </plugin-configuration>
+
+ <resource-configuration>
+ <c:list-property name="." displayName="Entries">
+ <c:map-property name="*[name]">
+ <c:simple-property name="name" displayName="Name" type="string" required="true"
+ description="Name of the alias"/>
+
+ <c:simple-property name="value" displayName="Value" type="string" required="true"
+ description="Username or Alias name value"/>
+
+ </c:map-property>
+ </c:list-property>
+ </resource-configuration>
+
+ </service>
+
+</plugin>
diff --git a/modules/plugins/aliases/src/test/java/org/rhq/plugins/aliases/AliasesComponentTest.java b/modules/plugins/aliases/src/test/java/org/rhq/plugins/aliases/AliasesComponentTest.java
new file mode 100644
index 0000000..4071fb4
--- /dev/null
+++ b/modules/plugins/aliases/src/test/java/org/rhq/plugins/aliases/AliasesComponentTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.aliases;
+
+import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
+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.pc.PluginContainer;
+import org.rhq.plugins.augeas.AbstractAugeasConfigurationComponentTest;
+
+/**
+ * An integration test for {@link AliasesComponent}.
+ */
+public class AliasesComponentTest extends AbstractAugeasConfigurationComponentTest {
+ @Override
+ protected String getPluginName() {
+ return "Hosts";
+ }
+
+ @Override
+ protected String getResourceTypeName() {
+ return "Hosts File";
+ }
+
+ @Override
+ protected Configuration getExpectedResourceConfig() {
+ Configuration config = new Configuration();
+ PropertyList entries = new PropertyList(".");
+ config.put(entries);
+
+ PropertyMap entry;
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "127.0.0.1"));
+ entry.put(new PropertySimple("canonical", "localhost"));
+ entry.put(new PropertySimple("alias", "localhost.localdomain\nlocalhost4\nlocalhost4.localdomain4"));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "::1"));
+ entry.put(new PropertySimple("canonical", "localhost"));
+ entry.put(new PropertySimple("alias", "localhost.localdomain\nlocalhost6\nlocalhost6.localdomain6"));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "1.1.1.1"));
+ entry.put(new PropertySimple("canonical", "one-one-one-one.com"));
+ entry.put(new PropertySimple("alias", null));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "2.2.2.2"));
+ entry.put(new PropertySimple("canonical", "two-two-two-two.com"));
+ entry.put(new PropertySimple("alias", "alias"));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "3.3.3.3"));
+ entry.put(new PropertySimple("canonical", "three-three-three-three.com"));
+ entry.put(new PropertySimple("alias", "alias1\nalias2"));
+ entries.getList().add(entry);
+
+ return config;
+ }
+
+ private boolean supportsFacet(Class<?> facetInterface) {
+ PluginMetadataManager manager = PluginContainer.getInstance().getPluginManager().getMetadataManager();
+ String componentClass = manager.getComponentClass(getResourceType());
+
+ try {
+ return facetInterface.isAssignableFrom(Class.forName(componentClass));
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Could not find component class " + componentClass, e);
+ }
+ }
+
+ @Override
+ protected Configuration getChangedResourceConfig() {
+ // TODO Auto-generated method stub
+ //TODO NEED TO FIX THIS
+ return null;
+ }
+}
diff --git a/modules/plugins/aliases/src/test/resources/etc/aliases b/modules/plugins/aliases/src/test/resources/etc/aliases
new file mode 100644
index 0000000..82c495f
--- /dev/null
+++ b/modules/plugins/aliases/src/test/resources/etc/aliases
@@ -0,0 +1,7 @@
+# General redirections for pseudo accounts.
+bin: root
+daemon: root
+adm: root
+lp: root
+sync: root
+shutdown: root
diff --git a/modules/plugins/aliases/src/test/resources/log4j.xml b/modules/plugins/aliases/src/test/resources/log4j.xml
new file mode 100644
index 0000000..65b7562
--- /dev/null
+++ b/modules/plugins/aliases/src/test/resources/log4j.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+ <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out"/>
+ <param name="Threshold" value="ERROR"/>
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <!-- The default pattern: Date Priority [Category] Messagen -->
+
+ <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
+ </layout>
+ </appender>
+
+ <appender name="FILE" class="org.apache.log4j.RollingFileAppender">
+ <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>
+
+ <root>
+ <appender-ref ref="CONSOLE"/>
+ <appender-ref ref="FILE"/>
+ </root>
+
+</log4j:configuration>
commit 2610763ee19102ffb68e13f5c022bff58ae67483
Author: Sayli Karmarkar <skarmark(a)redhat.com>
Date: Thu Nov 5 21:22:16 2009 -0500
552 - Adding generic tag object, taggable interface and implementation
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
index d787962..c518455 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/ContentSource.java
@@ -49,6 +49,8 @@ import javax.persistence.PreUpdate;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
+import org.rhq.core.domain.common.Tag;
+import org.rhq.core.domain.common.Taggable;
import org.rhq.core.domain.configuration.Configuration;
/**
@@ -78,7 +80,7 @@ import org.rhq.core.domain.configuration.Configuration;
+ " WHERE ccs.repo.id = :repoId ) ") })
@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_CONTENT_SOURCE_ID_SEQ")
@Table(name = "RHQ_CONTENT_SOURCE")
-public class ContentSource implements Serializable {
+public class ContentSource implements Serializable, Taggable {
public static final String QUERY_FIND_ALL = "ContentSource.findAll";
public static final String QUERY_FIND_ALL_WITH_CONFIG = "ContentSource.findAllWithConfig";
public static final String QUERY_FIND_BY_NAME_AND_TYPENAME = "ContentSource.findByNameAndTypeName";
@@ -138,6 +140,8 @@ public class ContentSource implements Serializable {
@OneToMany(mappedBy = "contentSource", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private Set<RepoContentSource> repoContentSources;
+ private Set<Tag> tags;
+
// Constructor
public ContentSource() {
@@ -442,4 +446,52 @@ public class ContentSource implements Serializable {
return true;
}
+
+ @Override
+ public Set<Tag> getTags() {
+ return tags;
+ }
+
+ @Override
+ public void setTags(Set<Tag> tags) {
+ this.tags = tags;
+ }
+
+ @Override
+ public boolean hasTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return false;
+ }
+
+ if (name == null) {
+ if (tag.getName() != null) {
+ return false;
+ }
+ } else if (!name.equals(tag.getName())) {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ @Override
+ public void addTag(Tag tag) {
+ if (this.tags == null) {
+ this.tags = new HashSet<Tag>();
+ }
+
+ this.tags.add(tag);
+ }
+
+ @Override
+ public void removeTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return;
+ }
+
+ if (tags.contains(tag)) {
+ tags.remove(tag);
+ }
+ }
}
\ No newline at end of file
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
index 416112e..2eeb2ba 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Package.java
@@ -24,7 +24,9 @@ package org.rhq.core.domain.content;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.Column;
@@ -42,6 +44,9 @@ import javax.persistence.Table;
import org.hibernate.annotations.NamedQueries;
import org.hibernate.annotations.NamedQuery;
+import org.rhq.core.domain.common.Tag;
+import org.rhq.core.domain.common.Taggable;
+
/**
* Represents a package inventoried in the system. A package can be created by either a {@link ContentSource} (on the
* server side) or via a plugin discovery (on the agent side). A package has no knowledge of how it was created (i.e. it
@@ -64,7 +69,7 @@ import org.hibernate.annotations.NamedQuery;
+ "AND p.packageType.resourceType.id = :resourceTypeId") })
@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_PACKAGE_ID_SEQ")
@Table(name = "RHQ_PACKAGE")
-public class Package implements Serializable {
+public class Package implements Serializable, Taggable {
// Constants --------------------------------------------
private static final long serialVersionUID = 1L;
@@ -93,6 +98,8 @@ public class Package implements Serializable {
@OneToMany(mappedBy = "generalPackage", fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
private List<PackageVersion> versions;
+ private Set<Tag> tags;
+
// Constructor ----------------------------------------
public Package() {
@@ -212,4 +219,53 @@ public class Package implements Serializable {
result = (prime * result) + ((packageType == null) ? 0 : packageType.hashCode());
return result;
}
+
+ @Override
+ public Set<Tag> getTags() {
+ return tags;
+ }
+
+ @Override
+ public void setTags(Set<Tag> tags) {
+ this.tags = tags;
+ }
+
+ @Override
+ public boolean hasTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return false;
+ }
+
+ if (name == null) {
+ if (tag.getName() != null) {
+ return false;
+ }
+ } else if (!name.equals(tag.getName())) {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ @Override
+ public void addTag(Tag tag) {
+ if (this.tags == null) {
+ this.tags = new HashSet<Tag>();
+ }
+
+ this.tags.add(tag);
+ }
+
+ @Override
+ public void removeTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return;
+ }
+
+ if (tags.contains(tag)) {
+ tags.remove(tag);
+ }
+ }
+
}
\ No newline at end of file
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
index 6441c06..a2f9d70 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/content/Repo.java
@@ -26,6 +26,7 @@ import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;
+import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
@@ -39,8 +40,9 @@ import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
-import javax.persistence.CascadeType;
+import org.rhq.core.domain.common.Tag;
+import org.rhq.core.domain.common.Taggable;
import org.rhq.core.domain.resource.Resource;
/**
@@ -78,15 +80,14 @@ import org.rhq.core.domain.resource.Resource;
+ ") "
+ "FROM Repo AS c "
+ "WHERE c.id NOT IN ( SELECT rc.repo.id FROM ResourceRepo rc WHERE rc.resource.id = :resourceId ) "
- + "AND c.candidate is false "
- + "GROUP BY c, c.name, c.description, c.creationDate, c.lastModifiedDate"),
+ + "AND c.candidate is false " + "GROUP BY c, c.name, c.description, c.creationDate, c.lastModifiedDate"),
@NamedQuery(name = Repo.QUERY_FIND_AVAILABLE_REPO_COMPOSITES_BY_RESOURCE_ID_COUNT, query = "SELECT COUNT( c ) "
+ "FROM Repo AS c "
+ "WHERE c.id NOT IN ( SELECT rc.repo.id FROM ResourceRepo rc WHERE rc.resource.id = :resourceId ) "
+ "AND c.candidate = false ") })
@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_REPO_ID_SEQ")
@Table(name = "RHQ_REPO")
-public class Repo implements Serializable {
+public class Repo implements Serializable, Taggable {
// Constants --------------------------------------------
public static final String QUERY_FIND_ALL_IMPORTED_REPOS = "Repo.findAll";
@@ -136,10 +137,12 @@ public class Repo implements Serializable {
@OneToMany(mappedBy = "repo", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
private Set<RepoRepoGroup> repoRepoGroups;
-
+
@OneToMany(mappedBy = "repo", fetch = FetchType.LAZY)
private Set<RepoRepoRelationship> repoRepoRelationships;
+ private Set<Tag> tags;
+
// Constructor ----------------------------------------
public Repo() {
@@ -532,8 +535,6 @@ public class Repo implements Serializable {
return doomed;
}
-
-
/**
* Returns the explicit mapping entities.
*
@@ -612,8 +613,6 @@ public class Repo implements Serializable {
return doomed;
}
-
-
@Override
public String toString() {
return "Repo: id=[" + this.id + "], name=[" + this.name + "]";
@@ -658,4 +657,53 @@ public class Repo implements Serializable {
void onUpdate() {
this.lastModifiedDate = System.currentTimeMillis();
}
+
+ @Override
+ public Set<Tag> getTags() {
+ return tags;
+ }
+
+ @Override
+ public void setTags(Set<Tag> tags) {
+ this.tags = tags;
+ }
+
+ @Override
+ public boolean hasTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return false;
+ }
+
+ if (name == null) {
+ if (tag.getName() != null) {
+ return false;
+ }
+ } else if (!name.equals(tag.getName())) {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ @Override
+ public void addTag(Tag tag) {
+ if (this.tags == null) {
+ this.tags = new HashSet<Tag>();
+ }
+
+ this.tags.add(tag);
+ }
+
+ @Override
+ public void removeTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return;
+ }
+
+ if (tags.contains(tag)) {
+ tags.remove(tag);
+ }
+ }
+
}
\ No newline at end of file
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
index ede0f73..56a1499 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/Resource.java
@@ -66,13 +66,15 @@ import org.jetbrains.annotations.Nullable;
import org.rhq.core.domain.alert.AlertDefinition;
import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.common.Tag;
+import org.rhq.core.domain.common.Taggable;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PluginConfigurationUpdate;
import org.rhq.core.domain.configuration.ResourceConfigurationUpdate;
-import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.content.ContentServiceRequest;
import org.rhq.core.domain.content.InstalledPackage;
import org.rhq.core.domain.content.InstalledPackageHistory;
+import org.rhq.core.domain.content.Repo;
import org.rhq.core.domain.content.ResourceRepo;
import org.rhq.core.domain.event.EventSource;
import org.rhq.core.domain.measurement.Availability;
@@ -729,7 +731,7 @@ import org.rhq.core.domain.util.serial.ExternalizableStrategy;
@Table(name = "RHQ_RESOURCE")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement
-public class Resource implements Comparable<Resource>, Externalizable {
+public class Resource implements Comparable<Resource>, Externalizable, Taggable {
public static final String QUERY_FIND_PROBLEM_RESOURCES_ALERT = "Resource.findProblemResourcesAlert";
public static final String QUERY_FIND_PROBLEM_RESOURCES_ALERT_ADMIN = "Resource.findProblemResourcesAlert_admin";
public static final String QUERY_FIND_PROBLEM_RESOURCES_ALERT_COUNT = "Resource.findProblemResourcesAlertCount";
@@ -1017,6 +1019,8 @@ public class Resource implements Comparable<Resource>, Externalizable {
@ManyToOne(fetch = FetchType.LAZY)
private ProductVersion productVersion;
+ private Set<Tag> tags;
+
public Resource() {
this.uuid = UUID.randomUUID().toString();
}
@@ -1807,4 +1811,53 @@ public class Resource implements Comparable<Resource>, Externalizable {
public void initCurrentAvailability() {
this.currentAvailability = new ResourceAvailability(this, null);
}
+
+ @Override
+ public Set<Tag> getTags() {
+ return tags;
+ }
+
+ @Override
+ public void setTags(Set<Tag> tags) {
+ this.tags = tags;
+ }
+
+ @Override
+ public boolean hasTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return false;
+ }
+
+ if (name == null) {
+ if (tag.getName() != null) {
+ return false;
+ }
+ } else if (!name.equals(tag.getName())) {
+ return false;
+ }
+
+ return true;
+
+ }
+
+ @Override
+ public void addTag(Tag tag) {
+ if (this.tags == null) {
+ this.tags = new HashSet<Tag>();
+ }
+
+ this.tags.add(tag);
+ }
+
+ @Override
+ public void removeTag(Tag tag) {
+ if ((this.tags == null) || (tag == null)) {
+ return;
+ }
+
+ if (tags.contains(tag)) {
+ tags.remove(tag);
+ }
+ }
+
}
commit de0475535bd259a4248d463131220445cca0f323
Merge: c206d5c... 7930790...
Author: Sayli Karmarkar <skarmark(a)redhat.com>
Date: Thu Nov 5 21:20:21 2009 -0500
Merge branch 'content' of git+ssh://git.fedorahosted.org/git/rhq/rhq into mycontent
commit c206d5cab0f4f91bcfc986475e5b989af5db5dd3
Author: Sayli Karmarkar <skarmark(a)redhat.com>
Date: Thu Nov 5 21:19:28 2009 -0500
552 - Adding generic tag object, taggable interface and implementation
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/common/Tag.java b/modules/core/domain/src/main/java/org/rhq/core/domain/common/Tag.java
new file mode 100644
index 0000000..843d3c2
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/common/Tag.java
@@ -0,0 +1,105 @@
+/*
+ * 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.common;
+
+import java.io.Serializable;
+
+/**
+ * A generic tag that can be associated with domain objects such as
+ * Repository, Content Provider, Resource, Package etc.
+ * @author Sayli Karmarkar
+ */
+
+//@Entity
+//@SequenceGenerator(name = "SEQ", sequenceName = "RHQ_TAG_ID_SEQ")
+//@Table(name = "RHQ_TAG")
+public class Tag implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ //@Column(name = "ID", nullable = false)
+ //@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ")
+ //@Id
+ //private int id;
+
+ //@Column(name = "NAME", nullable = false)
+ private String name;
+
+ //@Column(name = "DESCRIPTION", nullable = true)
+ private String description;
+
+ public Tag() {
+ }
+
+ /**
+ * String representation of tag
+ */
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Description of tag
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ @Override
+ public String toString() {
+ return "Tag: [name=" + this.name + " , description=" + this.description + "]";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+
+ if ((o == null) || (!(o instanceof Tag))) {
+ return false;
+ }
+
+ Tag other = (Tag) o;
+
+ if (!name.equals(other.name)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/common/Taggable.java b/modules/core/domain/src/main/java/org/rhq/core/domain/common/Taggable.java
new file mode 100644
index 0000000..fce4f88
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/common/Taggable.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, 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.common;
+
+import java.util.Set;
+
+public interface Taggable {
+
+ public Set<Tag> getTags();
+
+ void setTags(Set<Tag> tags);
+
+ public boolean hasTag(Tag tag);
+
+ public void addTag(Tag tag);
+
+ public void removeTag(Tag tag);
+}
commit 79307902adb105db312b43941621a5b93debb148
Merge: ab6f5f9... 867bb8e...
Author: John Sanda <john(a)localhost.localdomain>
Date: Thu Nov 5 20:53:13 2009 -0500
Merge branch 'master' into content
commit 867bb8ed5d412bfc85048a788208b964c322bb41
Author: John Sanda <john(a)localhost.localdomain>
Date: Thu Nov 5 20:52:21 2009 -0500
Fixing typo in property names
diff --git a/etc/m2/settings-content.xml b/etc/m2/settings-content.xml
index a2354bf..806006b 100644
--- a/etc/m2/settings-content.xml
+++ b/etc/m2/settings-content.xml
@@ -37,8 +37,8 @@
<DatabaseTest.nofail>true</DatabaseTest.nofail>
<!-- comm and agent config properties -->
- <rhq.comm.test.connectorBindport>89898</rhq.comm.test.connectorBindPort>
- <rhq.comm.test.connector2Bindport>62627</rhq.comm.test.connector2BindPort>
+ <rhq.comm.test.connectorBindPort>89898</rhq.comm.test.connectorBindPort>
+ <rhq.comm.test.connector2BindPort>62627</rhq.comm.test.connector2BindPort>
<agent1.cfg.file>test-agent1-cfg-mvn.xml</agent1.cfg.file>
<agent2.cfg.file>test-agent2-cfg-mvn.xml</agent2.cfg.file>
<agent1.server.bind-port>77777</agent1.server.bind-port>
commit 70a72d6f653da898fe0363089e4f82c1a7a1d0bc
Author: Partha Aji <paji(a)redhat.com>
Date: Thu Nov 5 20:50:45 2009 -0500
Important bug fixes on various issues with the /etc/hosts plugin and augeas plugin in general
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
index 32fde55..c03f7b2 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
@@ -93,7 +93,10 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
this.resourceContext = resourceContext;
Configuration pluginConfig = this.resourceContext.getPluginConfiguration();
- this.augeasRootPath = pluginConfig.getSimpleValue(AUGEAS_ROOT_PATH_PROP, DEFAULT_AUGEAS_ROOT_PATH);
+ this.augeasRootPath = DEFAULT_AUGEAS_ROOT_PATH;
+ if (System.getProperty(AUGEAS_ROOT_PATH_PROP) != null) {
+ this.augeasRootPath = System.getProperty(AUGEAS_ROOT_PATH_PROP);
+ }
log.debug("Augeas Root Path = \"" + this.augeasRootPath + "\"");
initGlobs(pluginConfig);
@@ -462,22 +465,30 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
return propSimple.getStringValue();
}
+ protected String getNodeInsertionPoint(Augeas augeas, AugeasNode node, PropertyDefinitionSimple propDefSimple,
+ PropertySimple propSimple) {
+ return String.format("%s/*[following-sibling::*[1]=%s[1]]", node.getParent().getPath(), node.getPath());
+ }
+
protected void setNodeFromPropertySimple(Augeas augeas, AugeasNode node, PropertyDefinitionSimple propDefSimple,
PropertySimple propSimple) {
String value = toNodeValue(augeas, node, propDefSimple, propSimple);
if (propDefSimple.getType() == PropertySimpleType.LONG_STRING) {
// First remove the existing items.
- List<String> childPaths = augeas.match(node.getPath());
- for (String childPath : childPaths) {
- augeas.remove(childPath);
- }
-
+ //get the node position first, needed to say insert after node x
+ String varName = "path";
+ String nodeExpression = getNodeInsertionPoint(augeas, node, propDefSimple, propSimple);
+ augeas.defineNode(varName, nodeExpression, null);
+ augeas.remove(node.getPath());
// Now add the updated items.
String[] tokens = value.trim().split("\\s+");
- for (int i = 0, tokensLength = tokens.length; i < tokensLength; i++) {
- String itemPath = node.getPath() + "[" + (i + 1) + "]";
- String itemValue = tokens[i];
- augeas.set(itemPath, itemValue);
+ for (int i = tokens.length; i > 0; i--) {
+ String itemValue = tokens[i - 1];
+ if (itemValue != null && itemValue.trim().length() != 0) {
+ augeas.insert("$" + varName, node.getName(), false);
+ augeas.set(node.getPath() + "[1]", itemValue);
+ }
+
}
} else {
// Update the value of the existing node.
diff --git a/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java b/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java
index 381ff4d..dee0b0d 100644
--- a/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java
+++ b/modules/plugins/augeas/src/test/java/org/rhq/plugins/augeas/AbstractAugeasConfigurationComponentTest.java
@@ -111,26 +111,25 @@ public abstract class AbstractAugeasConfigurationComponentTest {
case PLATFORM:
throw new IllegalStateException("Huh? Using Augeas to configure a platform?");
}
+ resetAugeasConfigs();
Resource resource = getResource();
Configuration pluginConfig = resource.getPluginConfiguration();
-
- resetAugeasConfigs(pluginConfig);
-
inventoryManager.updatePluginConfiguration(resource.getId(), pluginConfig);
} catch (Exception e) {
fail("Failed to update Augeas root in plugin configuration.", e);
}
}
- public void resetAugeasConfigs(Configuration pluginConfig) throws IOException {
+ public void resetAugeasConfigs() throws IOException {
String tmpDirPath = System.getProperty("java.io.tmpdir");
File tmpDir = new File(tmpDirPath);
File augeasRootPath = new File(tmpDir, "rhq-itest-augeas-root-path");
if (!augeasRootPath.exists()) {
augeasRootPath.mkdirs();
}
-
- pluginConfig.put(new PropertySimple(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP, augeasRootPath));
+ System.setProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP, augeasRootPath.getAbsolutePath());
+ Resource resource = getResource();
+ Configuration pluginConfig = resource.getPluginConfiguration();
PropertySimple includes = pluginConfig.getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP);
List<String> includeGlobs = new ArrayList<String>();
@@ -149,6 +148,7 @@ public abstract class AbstractAugeasConfigurationComponentTest {
@AfterSuite(groups = TEST_GROUP)
public void stop() {
+ System.clearProperty(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP);
System.out.println("Stopping PC...");
PluginContainer.getInstance().shutdown();
System.out.println("PC stopped.");
@@ -215,7 +215,7 @@ public abstract class AbstractAugeasConfigurationComponentTest {
assert resourceConfig.equals(updatedResourceConfig) : "Unexpected Resource configuration - \nExpected:\n\t"
+ updatedResourceConfig.toString(true) + "\nActual:\n\t" + resourceConfig.toString(true);
} finally {
- resetAugeasConfigs(getResource().getPluginConfiguration());
+ resetAugeasConfigs();
}
}
}
diff --git a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
index b68dd1f..15374f4 100644
--- a/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
+++ b/modules/plugins/hosts/src/main/java/org/rhq/plugins/hosts/HostsComponent.java
@@ -18,10 +18,22 @@
*/
package org.rhq.plugins.hosts;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
import net.augeas.Augeas;
-import org.rhq.core.domain.configuration.*;
+
+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.PropertyDefinitionList;
import org.rhq.core.domain.configuration.definition.PropertyDefinitionMap;
+import org.rhq.core.domain.configuration.definition.PropertyDefinitionSimple;
import org.rhq.core.domain.measurement.AvailabilityType;
import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
@@ -31,28 +43,19 @@ import org.rhq.plugins.augeas.helper.AugeasNode;
import org.rhq.plugins.augeas.helper.AugeasUtility;
import org.rhq.plugins.hosts.helper.NonAugeasHostsConfigurationDelegate;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
/**
* The ResourceComponent for the "Hosts File" ResourceType.
*
* @author Ian Springer
*/
public class HostsComponent extends AugeasConfigurationComponent {
- private static final String IPV4_ADDRESS_REGEX =
- "((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)";
+ private static final String IPV4_ADDRESS_REGEX = "((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)\\.){3}(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]\\d|\\d)";
private static final Pattern IPV4_ADDRESS_PATTERN = Pattern.compile(IPV4_ADDRESS_REGEX);
- private static final String IPV6_ADDRESS_REGEX =
- "((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}(:|((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})|(:[0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){5}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4}){0,4}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})))(%.+)?";
+ private static final String IPV6_ADDRESS_REGEX = "((([0-9A-Fa-f]{1,4}:){7}(([0-9A-Fa-f]{1,4})|:))|(([0-9A-Fa-f]{1,4}:){6}(:|((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})|(:[0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){5}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(([0-9A-Fa-f]{1,4}:)(:[0-9A-Fa-f]{1,4}){0,4}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(:(:[0-9A-Fa-f]{1,4}){0,5}((:((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})?)|((:[0-9A-Fa-f]{1,4}){1,2})))|(((25[0-5]|2[0-4]\\d|[01]?\\d{1,2})(\\.(25[0-5]|2[0-4]\\d|[01]?\\d{1,2})){3})))(%.+)?";
private static final Pattern IPV6_ADDRESS_PATTERN = Pattern.compile(IPV6_ADDRESS_REGEX);
- private static final String DOMAIN_NAME_REGEX =
- "(([a-zA-Z\\d]|[a-zA-Z\\d][a-zA-Z\\d\\-]*[a-zA-Z\\d])\\.)*([A-Za-z]|[A-Za-z][A-Za-z\\d\\-]*[A-Za-z\\d])";
+ private static final String DOMAIN_NAME_REGEX = "(([a-zA-Z\\d]|[a-zA-Z\\d][a-zA-Z\\d\\-]*[a-zA-Z\\d])\\.)*([A-Za-z]|[A-Za-z][A-Za-z\\d\\-]*[A-Za-z\\d])";
private static final Pattern DOMAIN_NAME_PATTERN = Pattern.compile(DOMAIN_NAME_REGEX);
public void start(ResourceContext resourceContext) throws InvalidPluginConfigurationException, Exception {
@@ -68,8 +71,7 @@ public class HostsComponent extends AugeasConfigurationComponent {
}
@Override
- public Configuration loadResourceConfiguration() throws Exception
- {
+ public Configuration loadResourceConfiguration() throws Exception {
Configuration resourceConfig;
if (getAugeas() != null) {
resourceConfig = super.loadResourceConfiguration();
@@ -80,8 +82,7 @@ public class HostsComponent extends AugeasConfigurationComponent {
}
@Override
- public void updateResourceConfiguration(ConfigurationUpdateReport report)
- {
+ public void updateResourceConfiguration(ConfigurationUpdateReport report) {
if (getAugeas() != null) {
super.updateResourceConfiguration(report);
} else {
@@ -90,7 +91,17 @@ public class HostsComponent extends AugeasConfigurationComponent {
}
@Override
- protected AugeasNode getNewListMemberNode(AugeasNode listNode, PropertyDefinitionMap listMemberPropDefMap, int listIndex) {
+ protected String getNodeInsertionPoint(Augeas augeas, AugeasNode node, PropertyDefinitionSimple propDefSimple,
+ PropertySimple propSimple) {
+ if ("alias".equals(propSimple.getName())) {
+ return String.format("%s/canonical", node.getParent().getPath());
+ }
+ return super.getNodeInsertionPoint(augeas, node, propDefSimple, propSimple);
+ }
+
+ @Override
+ protected AugeasNode getNewListMemberNode(AugeasNode listNode, PropertyDefinitionMap listMemberPropDefMap,
+ int listIndex) {
return new AugeasNode(listNode, "0" + listIndex);
}
@@ -129,36 +140,26 @@ public class HostsComponent extends AugeasConfigurationComponent {
ipv4DuplicateCanonicalNames.add(canonical);
}
}
- PropertySimple aliasProp = entryPropMap.getSimple("alias");
- String aliasValue = (aliasProp != null) ? aliasProp.getStringValue() : null;
- if (aliasValue != null) {
- String[] aliases = aliasValue.trim().split("\\s+");
- Set<String> invalidAliases = new HashSet<String>();
- for (String alias : aliases) {
- if (!validateDomainName(alias)) {
- invalidAliasCanonicalNames.add(canonical);
- }
- }
- if (!invalidAliases.isEmpty()) {
- aliasProp.setErrorMessage("Invalid domain name" + ((invalidAliases.size() > 1) ? "s" : "") + ": "
- + invalidAliases);
- }
- }
}
if (!invalidDomainNameCanonicalNames.isEmpty()) {
- errorMessage.append("The entries with the following canonical names have invalid canonical names: ").append(invalidDomainNameCanonicalNames).append(".\n");
+ errorMessage.append("The entries with the following canonical names have invalid canonical names: ")
+ .append(invalidDomainNameCanonicalNames).append(".\n");
}
if (!invalidIpAddressCanonicalNames.isEmpty()) {
- errorMessage.append("The entries with the following canonical names have invalid IP addresses: ").append(invalidIpAddressCanonicalNames).append(".\n");
+ errorMessage.append("The entries with the following canonical names have invalid IP addresses: ").append(
+ invalidIpAddressCanonicalNames).append(".\n");
}
if (!invalidAliasCanonicalNames.isEmpty()) {
- errorMessage.append("The entries with the following canonical names have one or more invalid aliases: ").append(invalidAliasCanonicalNames).append(".\n");
+ errorMessage.append("The entries with the following canonical names have one or more invalid aliases: ")
+ .append(invalidAliasCanonicalNames).append(".\n");
}
if (!ipv4DuplicateCanonicalNames.isEmpty()) {
- errorMessage.append("More than one IPv4 address is defined for the following canonical names: ").append(ipv4DuplicateCanonicalNames).append(".\n");
+ errorMessage.append("More than one IPv4 address is defined for the following canonical names: ").append(
+ ipv4DuplicateCanonicalNames).append(".\n");
}
if (!ipv6DuplicateCanonicalNames.isEmpty()) {
- errorMessage.append("More than one IPv6 address is defined for the following canonical names: ").append(ipv6DuplicateCanonicalNames).append(".\n");
+ errorMessage.append("More than one IPv6 address is defined for the following canonical names: ").append(
+ ipv6DuplicateCanonicalNames).append(".\n");
}
boolean isValid;
if (errorMessage.length() != 0) {
@@ -171,8 +172,7 @@ public class HostsComponent extends AugeasConfigurationComponent {
}
protected AugeasNode getExistingChildNodeForListMemberPropertyMap(AugeasNode parentNode,
- PropertyDefinitionList propDefList,
- PropertyMap propMap) {
+ PropertyDefinitionList propDefList, PropertyMap propMap) {
// First find all child nodes with the same 'canonical' value as the PropertyMap.
Augeas augeas = getAugeas();
String canonicalFilter = parentNode.getPath() + "/*/canonical";
diff --git a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
index 051cc89..fcaaa7e 100644
--- a/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
+++ b/modules/plugins/hosts/src/test/java/org/rhq/plugins/hosts/HostsComponentTest.java
@@ -18,12 +18,10 @@
*/
package org.rhq.plugins.hosts;
-import org.rhq.core.clientapi.agent.metadata.PluginMetadataManager;
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.pc.PluginContainer;
import org.rhq.plugins.augeas.AbstractAugeasConfigurationComponentTest;
/**
@@ -83,21 +81,43 @@ public class HostsComponentTest extends AbstractAugeasConfigurationComponentTest
return config;
}
- private boolean supportsFacet(Class<?> facetInterface) {
- PluginMetadataManager manager = PluginContainer.getInstance().getPluginManager().getMetadataManager();
- String componentClass = manager.getComponentClass(getResourceType());
-
- try {
- return facetInterface.isAssignableFrom(Class.forName(componentClass));
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException("Could not find component class " + componentClass, e);
- }
- }
-
@Override
protected Configuration getChangedResourceConfig() {
- // TODO Auto-generated method stub
- //TODO NEED TO FIX THIS
- return null;
+ Configuration config = new Configuration();
+ PropertyList entries = new PropertyList(".");
+ config.put(entries);
+
+ PropertyMap entry;
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "127.0.0.1"));
+ entry.put(new PropertySimple("canonical", "localhost"));
+ entry.put(new PropertySimple("alias", "hehe\nlocalhost4\nlocalhost4.localdomain4"));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "::1"));
+ entry.put(new PropertySimple("canonical", "localhost"));
+ entry.put(new PropertySimple("alias", "localhost.localdomain\nlocalhost6\nlocalhost6.localdomain6"));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "1.1.1.1"));
+ entry.put(new PropertySimple("canonical", "one-one-one-one.com"));
+ entry.put(new PropertySimple("alias", ""));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "2.2.2.2"));
+ entry.put(new PropertySimple("canonical", "two-two-two-two.com"));
+ entry.put(new PropertySimple("alias", ""));
+ entries.getList().add(entry);
+
+ entry = new PropertyMap("*[canonical]");
+ entry.put(new PropertySimple("ipaddr", "3.3.3.3"));
+ entry.put(new PropertySimple("canonical", "three-three-three-three.com"));
+ entry.put(new PropertySimple("alias", "aliast1.org\nalias2.org"));
+ entries.getList().add(entry);
+ return config;
}
}
commit ab6f5f9cd5e45c54d93e7ab4ddcc36af2e4bff6e
Merge: df9ca9d... c66d4ca...
Author: John Sanda <john(a)localhost.localdomain>
Date: Thu Nov 5 20:31:50 2009 -0500
Merge branch 'master' into content
commit df9ca9da7877ede3441048dbeef7ea3808c41e95
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 5 11:20:13 2009 -0500
do not assume java is in /usr/lib/jvm/java and remove the additional
test opts
diff --git a/modules/enterprise/agent/src/etc/rhq-agent-env.sh b/modules/enterprise/agent/src/etc/rhq-agent-env.sh
index 847bb8f..bb679ef 100755
--- a/modules/enterprise/agent/src/etc/rhq-agent-env.sh
+++ b/modules/enterprise/agent/src/etc/rhq-agent-env.sh
@@ -30,8 +30,7 @@
# If this and RHQ_AGENT_JAVA_EXE_FILE_PATH are
# not set, the agent's embedded JRE will be used.
#
-#RHQ_AGENT_JAVA_HOME="/opt/java"
-RHQ_AGENT_JAVA_HOME="/usr/lib/jvm/java"
+#RHQ_AGENT_JAVA_HOME="/usr/lib/jvm/jre"
# RHQ_AGENT_JAVA_EXE_FILE_PATH - Defines the full path to the Java
# executable to use. If this is set,
@@ -53,7 +52,7 @@ RHQ_AGENT_JAVA_HOME="/usr/lib/jvm/java"
# use RHQ_AGENT_ADDITIONAL_JAVA_OPTS instead.
#
#RHQ_AGENT_JAVA_OPTS="-Xms64m -Xmx128m -Djava.net.preferIPv4Stack=true"
- RHQ_AGENT_JAVA_OPTS="-Don.perftest.scenario=configurable-1 -Don.perftest.server-a-count=1 -Don.perftest.service-a-count=2"
+
# RHQ_AGENT_JAVA_ENDORSED_DIRS - Java VM command line option to set the
# endorsed dirs for the agent's VM. If this
# is not defined this script will pass in a
commit 17debfb0ff8c9dae6182d780855d0ba1a55cda04
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 5 09:43:08 2009 -0500
remove eclipse tools that dealt with jopr things since there is no separate project anymore
diff --git a/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - Clean.launch b/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - Clean.launch
deleted file mode 100644
index 0106869..0000000
--- a/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - Clean.launch
+++ /dev/null
@@ -1,11 +0,0 @@
-<?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="${env_var:M2_HOME}/bin/${MAVEN_EXE}"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-o -Dmaven.test.skip=true clean"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/jopr}"/>
-</launchConfiguration>
diff --git a/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - Dev Profile Plugin.launch b/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - Dev Profile Plugin.launch
deleted file mode 100644
index 9f222f0..0000000
--- a/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - Dev Profile Plugin.launch
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
-<stringAttribute key="bad_container_name" value="\jop\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="${env_var:M2_HOME}/bin/${MAVEN_EXE}"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-Dmaven.test.skip=true -Pdev clean install"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/jopr/modules/plugins}/${string_prompt:Plugin Module Name}"/>
-</launchConfiguration>
diff --git a/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - Dev Profile.launch b/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - Dev Profile.launch
deleted file mode 100644
index 7d76547..0000000
--- a/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - Dev Profile.launch
+++ /dev/null
@@ -1,11 +0,0 @@
-<?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="${env_var:M2_HOME}/bin/${MAVEN_EXE}"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-Dmaven.test.skip=true -Pdev install"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/jopr}"/>
-</launchConfiguration>
diff --git a/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - Download Dependencies.launch b/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - Download Dependencies.launch
deleted file mode 100644
index 536e37b..0000000
--- a/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - Download Dependencies.launch
+++ /dev/null
@@ -1,11 +0,0 @@
-<?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="${env_var:M2_HOME}/bin/${MAVEN_EXE}"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="validate"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/jopr}"/>
-</launchConfiguration>
diff --git a/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - JBoss AS 5 Plugin Dev Profile.launch b/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - JBoss AS 5 Plugin Dev Profile.launch
deleted file mode 100644
index 3497389..0000000
--- a/modules/jopr/etc/eclipse-tools/maven/JOPR Maven Build - JBoss AS 5 Plugin Dev Profile.launch
+++ /dev/null
@@ -1,11 +0,0 @@
-<?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="${env_var:M2_HOME}/bin/${MAVEN_EXE}"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-o -Dmaven.test.skip=true -Pdev install"/>
-<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/jopr/modules/plugins/jboss-as-5}"/>
-</launchConfiguration>
commit 492dfa7d0928e5f687c6513be1b7f30855a9f6b3
Author: Pradeep Kilambi <pkilambi(a)redhat.com>
Date: Thu Nov 5 10:58:19 2009 -0500
Adding a distribution facet for the plugin to implement and process distro syncs
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionDetails.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionDetails.java
new file mode 100644
index 0000000..e58895f
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionDetails.java
@@ -0,0 +1,120 @@
+/*
+* 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.enterprise.server.plugin.pc.content;
+
+/**
+ * @author Pradeep Kilambi
+ */
+public class DistributionDetails {
+ private String label;
+ private String description;
+
+ private String distType;
+ private String distpath;
+
+ public DistributionDetails(String labelIn, String disttypeIn) {
+ setLabel(labelIn);
+ setDistributionType(disttypeIn);
+ }
+
+ public DistributionDetails(String labelIn, String distpathIn, String disttypeIn) {
+ setLabel(labelIn);
+ setDistributionPath(distpathIn);
+ setDistributionType(disttypeIn);
+ }
+
+ /**
+ * Returns the identifying name of the distribution.
+ *
+ * @return cannot be <code>null</code>
+ */
+ public String getLabel() {
+ return label;
+ }
+
+ /**
+ * Sets the name of the distribution being represented.
+ *
+ * @param label cannot be <code>null</code>
+ * @throws IllegalArgumentException is name is <code>null</code>
+ */
+ public void setLabel(String label) {
+ if (label == null) {
+ throw new IllegalArgumentException("label cannot be null");
+ }
+
+ this.label = label;
+ }
+
+ /**
+ * Returns the distribution type.
+ *
+ * @return may be <code>null</code>
+ */
+ public String getDistributionType() {
+ return distType;
+ }
+
+ /**
+ *
+ * @param distType may be <code>null</code>
+ */
+ public void setDistributionType(String distType) {
+ this.distType = distType;
+ }
+
+ /**
+ * Returns a user-readable description of what the distribution contains.
+ *
+ * @return may be <code>null</code>
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Sets the name of the user-readable description of the distribution.
+ *
+ * @param description may be <code>null</code>
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * Return the distribution path on filesystem
+ * @return
+ */
+ public String getDistributionPath() {
+ return distpath;
+ }
+
+ /**
+ * sets the distribution path value for a single distribution instance
+ * @param distpath distribution path
+ */
+ public void setDistributionPath(String distpath) {
+ this.distpath = distpath;
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java
new file mode 100644
index 0000000..b702645
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSource.java
@@ -0,0 +1,55 @@
+/*
+ * 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.enterprise.server.plugin.pc.content;
+
+import java.io.InputStream;
+
+/**
+ * Indicates a content provider has the capability to provide distributions into the server.
+ * Distribution synchronization will be done through the calls defined in this interface.
+ *
+ * @author Pradeep Kilambi
+ */
+public interface DistributionSource {
+
+ /**
+ * Requests that this distribution source perform a synchronization with its external repository.
+ *
+ * @param report used to accumulate the collection of distros
+ * @throws Exception if the source is unable to perform the synchronization, for instance if the external
+ * source cannot be connected to.
+ */
+ void synchronizeDistribution(DistributionSyncReport report)
+ throws Exception;
+
+ /**
+ * Get an input stream for the specified distribution.
+ *
+ * @param location The location of the distribution.
+ * @return An initialized input stream. <b>The caller is responsible for closing the stream.</b>
+ * @throws Exception if failed to obtain the stream to the remote distribution data
+ */
+ InputStream getInputStream(String location) throws Exception;
+
+}
+
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSyncReport.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSyncReport.java
new file mode 100644
index 0000000..0b68c1b
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/content/DistributionSyncReport.java
@@ -0,0 +1,53 @@
+/*
+* 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.enterprise.server.plugin.pc.content;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Accumulates all the synced distros into a collection
+ * @author Pradeep Kilambi
+ */
+public class DistributionSyncReport {
+ private List<DistributionDetails> distros = new ArrayList<DistributionDetails>();
+
+
+ public DistributionSyncReport() {
+ }
+
+ public List<DistributionDetails> getDistributions() {
+ return distros;
+ }
+
+ public void addRepo(DistributionDetails distro) {
+ distros.add(distro);
+ }
+
+ public void addDistros(Collection<DistributionDetails> distros) {
+ distros.addAll(distros);
+ }
+
+}
commit ebf69ece5e3168a76bc78cba5d7221bfcd0afd15
Merge: c37168b... b225391...
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Thu Nov 5 07:52:04 2009 -0500
Merge branch 'master' into content
commit c37168b6978e1f39317dcc45c941b36f2be9844c
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Thu Nov 5 07:45:46 2009 -0500
794 - Additons to support create/delete/retrieve for candidate repos
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/RepoCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/RepoCriteria.java
index a1c807e..188c955 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/RepoCriteria.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/RepoCriteria.java
@@ -43,6 +43,8 @@ public class RepoCriteria extends Criteria {
private String filterName;
private String filterDescription;
private List<Integer> filterResourceIds; // needs overrides
+ private Boolean filterCandidate;
+ private List<Integer> filterContentSourceIds; // needs overrides
private boolean fetchResourceRepos;
private boolean fetchRepoContentSources;
@@ -56,6 +58,10 @@ public class RepoCriteria extends Criteria {
super(Repo.class);
filterOverrides.put("resourceIds", "resourceRepos.resource.id IN ( ? )");
+ filterOverrides.put("contentSourceIds",
+ "id IN (SELECT innerRepo FROM Repo innerRepo " +
+ "JOIN innerRepo.repoContentSources rcs " +
+ "WHERE rcs.contentSource.id IN ( ? ))");
}
public void addFilterId(Integer filterId) {
@@ -74,6 +80,14 @@ public class RepoCriteria extends Criteria {
this.filterResourceIds = Arrays.asList(filterResourceIds);
}
+ public void addFilterCandidate(Boolean filterCandidate) {
+ this.filterCandidate = filterCandidate;
+ }
+
+ public void addFilterContentSourceIds(Integer... filterContentSourceIds) {
+ this.filterContentSourceIds = Arrays.asList(filterContentSourceIds);
+ }
+
public void fetchResourceRepos(boolean fetchResourceRepos) {
this.fetchResourceRepos = fetchResourceRepos;
}
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 96f856f..e6c9b8b 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
@@ -289,6 +289,8 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
public Repo createRepo(Subject subject, Repo repo) throws RepoException {
validateRepo(repo);
+ repo.setCandidate(false);
+
log.debug("User [" + subject + "] is creating repo [" + repo + "]");
entityManager.persist(repo);
log.debug("User [" + subject + "] created repo [" + repo + "]");
@@ -297,6 +299,17 @@ public class RepoManagerBean implements RepoManagerLocal, RepoManagerRemote {
}
@RequiredPermission(Permission.MANAGE_INVENTORY)
+ public Repo createCandidateRepo(Subject subject, Repo repo) throws RepoException {
+ validateRepo(repo);
+
+ repo.setCandidate(true);
+
+ entityManager.persist(repo);
+
+ return repo;
+ }
+
+ @RequiredPermission(Permission.MANAGE_INVENTORY)
public RepoGroup createRepoGroup(Subject subject, RepoGroup repoGroup) throws RepoException {
validateRepoGroup(repoGroup);
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 8044b8e..f837a7c 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
@@ -128,6 +128,18 @@ public interface RepoManagerLocal {
*/
void addRepoRelationship(Subject subject, int repoId, int relatedRepoId, String relationshipTypeName);
+ /**
+ * Functions similar to {@link RepoManagerRemote#createRepo(Subject, Repo)} except that it will ensure
+ * the candidate bit on the repo parameter is correctly set.
+ *
+ * @param subject user creating the repo
+ * @param repo repo data to create
+ * @return persisted repo (ID will be populated)
+ * @throws RepoException if the repo contains invalid data
+ */
+ Repo createCandidateRepo(Subject subject, Repo repo) throws RepoException;
+
+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// The following are shared with the Remote Interface
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
index a0c9376..4aaf6d1 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/content/test/RepoManagerBeanTest.java
@@ -31,27 +31,40 @@ import org.rhq.core.domain.content.RepoGroup;
import org.rhq.core.domain.content.RepoGroupType;
import org.rhq.core.domain.content.RepoRelationshipType;
import org.rhq.core.domain.content.RepoRepoRelationship;
+import org.rhq.core.domain.content.ContentSourceType;
+import org.rhq.core.domain.content.ContentSource;
import org.rhq.core.domain.criteria.RepoCriteria;
import org.rhq.core.domain.util.PageList;
+import org.rhq.core.domain.util.PageControl;
import org.rhq.enterprise.server.content.RepoManagerLocal;
import org.rhq.enterprise.server.content.RepoException;
+import org.rhq.enterprise.server.content.ContentSourceManagerLocal;
+import org.rhq.enterprise.server.content.metadata.ContentSourceMetadataManagerLocal;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
import org.rhq.enterprise.server.util.LookupUtil;
import java.util.Set;
+import java.util.HashSet;
public class RepoManagerBeanTest extends AbstractEJB3Test {
private final static boolean ENABLED = true;
private RepoManagerLocal repoManager;
+ private ContentSourceManagerLocal contentSourceManager;
+ private ContentSourceMetadataManagerLocal contentSourceMetadataManager;
+
private Subject overlord;
@BeforeMethod
public void setupBeforeMethod() throws Exception {
TransactionManager tx = getTransactionManager();
tx.begin();
+
repoManager = LookupUtil.getRepoManagerLocal();
+ contentSourceManager = LookupUtil.getContentSourceManager();
+ contentSourceMetadataManager = LookupUtil.getContentSourceMetadataManager();
+
overlord = LookupUtil.getSubjectManager().getOverlord();
}
@@ -112,6 +125,29 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
}
@Test(enabled = ENABLED)
+ public void createFindDeleteCandidateRepo() throws Exception {
+ // Setup
+ Repo repo = new Repo("test candidate repo");
+
+ // Test
+ repo = repoManager.createCandidateRepo(overlord, repo);
+
+ // Verify
+ try {
+ assert repo.isCandidate();
+
+ // Should not be returned from this call since its a candidate repo
+ PageList<Repo> importedRepos = repoManager.findRepos(overlord, new PageControl());
+ assert importedRepos.size() == 0;
+
+ assert repoManager.getRepo(overlord, repo.getId()) != null;
+ }
+ finally {
+ repoManager.deleteRepo(overlord, repo.getId());
+ }
+ }
+
+ @Test(enabled = ENABLED)
public void createDuplicateRepoGroup() throws Exception {
// Setup
EntityManager entityManager = getEntityManager();
@@ -216,4 +252,48 @@ public class RepoManagerBeanTest extends AbstractEJB3Test {
// Cleanup handled by rollback in tear down method
}
+
+ @Test(enabled = ENABLED)
+ public void findCandidatesByContentProvider() throws Exception {
+ // Setup
+ String candidateRepoName = "candidate with source";
+
+ // Create a content source type and a content source
+ ContentSourceType type = new ContentSourceType("testGetSyncResultsListCST");
+ Set<ContentSourceType> types = new HashSet<ContentSourceType>();
+ types.add(type);
+ contentSourceMetadataManager.registerTypes(types); // this blows away any previous existing types
+ ContentSource contentSource = new ContentSource("testGetSyncResultsListCS", type);
+ contentSource = contentSourceManager.simpleCreateContentSource(overlord, contentSource);
+
+ // Create an imported (non-candidate) repo associated with the source
+ Repo importedRepo = new Repo("imported repo");
+ importedRepo.addContentSource(contentSource);
+ importedRepo = repoManager.createRepo(overlord, importedRepo);
+
+ // Create a candidate repo associated with that source
+ Repo candidateRepo = new Repo(candidateRepoName);
+ candidateRepo.addContentSource(contentSource);
+ candidateRepo = repoManager.createCandidateRepo(overlord, candidateRepo);
+
+ // Test
+ RepoCriteria criteria = new RepoCriteria();
+ criteria.addFilterCandidate(true);
+ criteria.addFilterContentSourceIds(contentSource.getId());
+ criteria.fetchRepoContentSources(true);
+
+ PageList<Repo> foundRepos = repoManager.findReposByCriteria(overlord, criteria);
+
+ // Verify
+
+ // Make sure only one of the two repos from above came back
+ assert foundRepos.size() == 1;
+
+ Repo foundRepo = foundRepos.get(0);
+ assert foundRepo.getName().equals(candidateRepoName);
+ assert foundRepo.isCandidate();
+
+ // Cleanup handled by rollback in tear down method
+ }
+
}
\ No newline at end of file
commit c43c87ddd271feafff24cb0323eef26c032cd579
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 4 23:41:11 2009 -0500
Squashed commit of the following:
commit 1822f149fb993fd440027b375f1ff8e69e8ab757
Merge: 743702c f1b95fa
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 4 22:59:38 2009 -0500
Merge branch 'pc'
Conflicts:
modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNProvider.java
modules/enterprise/server/plugins/rhnhosted/src/test/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelperTest.java
modules/plugins/apt/src/test/java/org/rhq/plugins/apt/AptSourcesComponentTest.java
commit 743702cdf79f3365c32b34d4f6f2fad962ee36f6
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Wed Nov 4 19:25:46 2009 -0800
disabling these 2 tests in master so we have a clean build
commit 570a521681720901c89d0e17d46cccf938250336
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Wed Nov 4 19:24:57 2009 -0800
more unit test cleanup.
Conflicts:
modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNConstants.java
commit fde95e389058cc22bb003bee1fd9b7ccef8b1a3a
Author: Devan Goodwin <dgoodwin(a)redhat.com>
Date: Wed Nov 4 20:59:47 2009 -0400
Revert "Merge branch 'master' into linux-config"
This reverts commit befd9352107feb4b0d599a7e451a036941285a7b, reversing
changes made to 90522410865ee096ec1bab00e9dc002c77fd7639.
Linux config branch was accidentally merged into master, very soon after
the merge was performed in the opposite direction. Because no work was
happening in master, git allowed the push to complete without throwing
up any warnings.
This commit will need to be reverted before performing the later
(expected) merge of linux-config.
commit d9f656b50586750124a3d3bbecee95ade22c3885
Author: Devan Goodwin <dgoodwin(a)redhat.com>
Date: Wed Nov 4 20:58:31 2009 -0400
Revert "Added a generic augeas testResourceConfigUpdate method"
This reverts commit 0c01ac12240c1948d13ca943ead27b9586c2adeb.
Accidentally merged from linux-config branch.
commit 69f21f3d96f20b517f7c69b1f33b5dc5374d30e7
Author: Devan Goodwin <dgoodwin(a)redhat.com>
Date: Wed Nov 4 20:57:32 2009 -0400
Revert "Made the testResourceConfigUpdate to propertly clean up the mess it creates"
This reverts commit 82dac4e78bd0b4293ddf64bd10cc51ce9ff94215.
Accidentally merged from linux-config branch.
commit 064497721444f4c47bd87f2c121470f2e10e0285
Author: Devan Goodwin <dgoodwin(a)redhat.com>
Date: Wed Nov 4 20:57:18 2009 -0400
Revert "updated integration test for samba"
This reverts commit 5d6165e561037287f9976a21767ebba7e70831c7.
5d6165e561037287f9976a21767ebba7e70831c7
commit 59f8852ff1910fde1981fa9839156f01524d152f
Author: Devan Goodwin <dgoodwin(a)redhat.com>
Date: Wed Nov 4 20:56:49 2009 -0400
Revert "log4j.xml DTD file (useful for associating log4j doctype to DTD in IntelliJ/Eclipse)"
This reverts commit 98fc9d73582d5934662c540f6e7b0a3044cd5444.
Commit part of accidental merge of linux-config branch.
commit 8ac542cda213945e68faeeb652b414613815c92d
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 4 15:37:16 2009 -0500
set a default JAVA_HOME via which if not set already.
If java isn't in path, then try to guess a typical location
for some platforms. If the guess is wrong, the script will spit
out an error and will not start the agent, but that will only
happen if java isn't in the path and the user doesn't have any
environment variables set to help us guide where java is
commit 8b2cc2ef3cfa2f1edd4b076d6d1141bc97007655
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 4 13:31:08 2009 -0500
put the apt test in a testng group which will allow us to exclude it via
settings.xml
commit 98fc9d73582d5934662c540f6e7b0a3044cd5444
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Nov 4 09:41:33 2009 -0500
log4j.xml DTD file (useful for associating log4j doctype to DTD in IntelliJ/Eclipse)
commit 5d6165e561037287f9976a21767ebba7e70831c7
Author: Shannon Hughes <shughes(a)fred.hughes.lan>
Date: Tue Nov 3 17:27:02 2009 -0500
updated integration test for samba
commit 82dac4e78bd0b4293ddf64bd10cc51ce9ff94215
Author: Partha Aji <paji(a)redhat.com>
Date: Tue Nov 3 17:12:35 2009 -0500
Made the testResourceConfigUpdate to propertly clean up the mess it creates
commit 0c01ac12240c1948d13ca943ead27b9586c2adeb
Author: Partha Aji <paji(a)redhat.com>
Date: Tue Nov 3 16:42:39 2009 -0500
Added a generic augeas testResourceConfigUpdate method
commit befd9352107feb4b0d599a7e451a036941285a7b
Merge: 31cc8bc 9052241
Author: Partha Aji <paji(a)redhat.com>
Date: Tue Nov 3 14:12:49 2009 -0500
Merge branch 'master' into linux-config
commit 31cc8bc625a588ce6c2918f060a54682e1a72ca5
Author: Shannon Hughes <shughes(a)fred.hughes.lan>
Date: Tue Nov 3 12:29:49 2009 -0500
initial integration test for samba load resource config
commit d55020067da7254b83b7e7030ad06c6c6be78c7f
Author: Partha Aji <paji(a)redhat.com>
Date: Tue Nov 3 11:29:22 2009 -0500
Added Sudoers loadConfiguration unit test
commit 90522410865ee096ec1bab00e9dc002c77fd7639
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Tue Nov 3 10:23:31 2009 -0500
Attempts to make this test run more stable. This change worked when running it directly on the Hudson box, so hopefully it will work within Hudson as well.
The rationale is that the scheduler was picking it up and running it too quickly, which would cause the assertion to make sure it was scheduled to fail sometimes.
commit 682785d07ec187a775e16d88aa989e7445cf676b
Author: Jason Dobies <jason.dobies(a)redhat.com>
Date: Tue Nov 3 09:44:14 2009 -0500
Added pause between test methods to ensure the ports are released.
commit 730da4871173b5aae088de093ffe7255c515fc33
Merge: 3125b91 c35251f
Author: Partha Aji <paji(a)redhat.com>
Date: Mon Nov 2 15:56:19 2009 -0500
Merge branch 'master' into linux-config
commit 3125b91278503c358e6d8a1c08ba1fd7187000ef
Author: Partha Aji <paji(a)redhat.com>
Date: Mon Nov 2 15:55:46 2009 -0500
Updating eclipse classpath to include augeas tests
commit 7dfb6c8ff63d37bef8dcd1b06a1b2b4982666e09
Merge: 1bcc740 99ea8b4
Author: Ian P. Springer <ips(a)jetengine.springer.net>
Date: Mon Nov 2 15:15:00 2009 -0500
Merge branch 'linux-config' of ssh://git.fedorahosted.org/git/rhq/rhq into linux-config
Conflicts:
modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
modules/plugins/cron/src/main/java/org/rhq/plugins/cron/CronTabDiscoveryComponent.java
commit c35251f5f95133adb04b4f5273f7bccb2d44a007
Author: Pradeep Kilambi <pkilambi(a)redhat.com>
Date: Mon Nov 2 14:59:37 2009 -0500
if one of the packages is busted dont quit. Instead try to fetch as many package objects as we can
commit 99ea8b4397e6ca10d303bf3b68e9498dea77bc69
Author: Partha Aji <paji(a)redhat.com>
Date: Mon Nov 2 14:00:34 2009 -0500
Fixing a compile error that occured due to a refactor..
commit 1bcc740de47ac95984667e91c3794c2d9a0a1055
Author: Ian P. Springer <ips(a)jetengine.springer.net>
Date: Mon Nov 2 13:21:51 2009 -0500
add abstract base integration test class to augeas plugin and concrete subclass in hosts plugin
commit c3d0353629ffcd41cf0404253b31f9c191be4b5f
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sat Oct 31 14:23:02 2009 -0400
no longer use redstone xmlrpc lib
commit c2c76dd29e7592715432d0a563c87ac9878b3726
Author: Partha Aji <paji(a)redhat.com>
Date: Fri Oct 30 19:42:45 2009 -0400
Fixed a broken sudoers add configuration thanks to changes in Base component
commit d05920292d337406e77bff1caf17052f1d6b5ba3
Author: Partha Aji <paji(a)redhat.com>
Date: Fri Oct 30 19:06:54 2009 -0400
Fixed an accidental bug that occured because of choosing the wrong variable name...
commit 8f574acd781af4b6c9a71a53a88249017a7abefb
Author: Partha Aji <paji(a)redhat.com>
Date: Fri Oct 30 18:32:17 2009 -0400
Added a way to specify custom augeas root directories by adding the 'AUGEAS_ROOT' property
commit 79456f3955f284a13994dc436b1a10860ae957c0
Author: Partha Aji <paji(a)redhat.com>
Date: Fri Oct 30 16:05:28 2009 -0400
Updated spec file to point to latest db
commit ee3f2ac1ff45a7a92e2616270331dc742a38bc1d
Merge: dac03d9 91fc97f
Author: Partha Aji <paji(a)redhat.com>
Date: Fri Oct 30 15:09:16 2009 -0400
Fixed merge conflicts
commit dac03d9be5beba48f441189f240a7e4a8e22755f
Merge: 61680ed 7ff4ce1
Author: Ian P. Springer <ips(a)jetengine.springer.net>
Date: Fri Oct 30 14:38:19 2009 -0400
Merge branch 'linux-config' of ssh://git.fedorahosted.org/git/rhq/rhq into linux-config
commit 61680ed1ebd22325c0c77333cfca841fb652212d
Author: Ian P. Springer <ips(a)jetengine.springer.net>
Date: Fri Oct 30 14:34:22 2009 -0400
get hosts plugin working again
commit 7ff4ce16c71827faa6572859c516404690f590eb
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Fri Oct 30 18:19:11 2009 +0100
Adding the cron plugin to the default server build.
commit f2b87f27134cc074df4d19d81fedd7524c7c1fef
Author: Ian P. Springer <ips(a)jetengine.springer.net>
Date: Fri Oct 30 10:56:46 2009 -0400
comment out broken test
commit b5262dd418af5cb9743d897012d61ade18e07ba2
Merge: 99de8c1 ba2a3f1
Author: Partha Aji <paji(a)redhat.com>
Date: Thu Oct 29 15:43:38 2009 -0400
fixed a bunch of merge conflicts
commit 99de8c13a35c2c867fd9d17946766051c9b1ec0d
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Oct 29 12:00:23 2009 +0100
Removing newNodeExpression concept from sudoers.
commit 4cfa54e535fb9f14a84079cf1d039b15834a4660
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Oct 29 14:14:56 2009 +0100
added the descriptions to the cron plugin descriptor.
commit 9a56aa6c639d7def54a07f2103ec647488eb6404
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Oct 29 11:59:22 2009 +0100
Finishing up cron plugin.
commit 700cb61b4531815040cdb223d382481818fafc07
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Oct 29 11:58:51 2009 +0100
Making the workaround for whitespace escaping in the node names a little bit more robust (now can handle a node name with an [] expression with embedded spaces).
Still not perfect, but let's hope it will suffice before the bug gets fixed.
commit 1579f505a6cf41e258046e63444e68f9ecb85b82
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Oct 29 11:55:56 2009 +0100
Adding the ability for the subclasses to override how is an augeas node called based on the current property definition.
Removing the "newNodeExpression" concept because it is insufficient for handling multiple lists with different mappings and replaced it using the new ability to find out the proper name for the child resource.
Other minor fixes.
commit 6cb936b9ff24be71731fe09bf64e61c9423fd20c
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Oct 27 10:03:25 2009 +0100
throwing more descriptive errors, attempt at making the augeas paths well formed with the default "/files//" root.
commit 0a5d6a1e7fde9fffbef8cf17d15bf220426e6d40
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Tue Oct 27 10:01:47 2009 +0100
user is a mandatory in the cron entry
commit 8218fe227a305ec253384d2d65f2e27eb055609b
Author: Shannon Hughes <shughes(a)fred.hughes.lan>
Date: Tue Oct 27 15:12:46 2009 -0400
fixes to samba share create using augeas plugin. added report prop logic
commit 63254c634b7ea33ffaf259dbeb69e63b8ea868f7
Merge: 3145a64 dcc37be
Author: Partha Aji <paji(a)redhat.com>
Date: Tue Oct 27 14:57:37 2009 -0400
Merge branch 'master' into linux-config
commit 3145a6481b06ea4984212c5f89452c2cc28fe9c3
Author: Partha Aji <paji(a)redhat.com>
Date: Tue Oct 27 14:57:02 2009 -0400
Got the add functionality working with sudoers
commit 263b1271a574912df59548c3daf841560cfd9898
Author: Shannon Hughes <shughes(a)fred.hughes.lan>
Date: Tue Oct 27 08:31:01 2009 -0400
modifying support for resource creating using augeas set vs insert nodes
commit 988ddae459d868610e4e408ac4126523c6db70df
Author: Jay Shaughnessy <jshaughn(a)redhat.com>
Date: Mon Oct 26 23:20:30 2009 -0400
Add samba and sudoers plugins to rhq.ear for dist builds
commit b6b99e75c6353b684d3dceb70a69c504473c88be
Author: Shannon Hughes <shughes(a)scooby.rdu.redhat.com>
Date: Mon Oct 26 18:58:23 2009 -0400
adding support for samba share creation
commit 610e1ef8c3c4351a919313bda0dd92439d61335a
Author: Partha Aji <paji(a)redhat.com>
Date: Mon Oct 26 16:45:25 2009 -0400
Commiting a bare bones limited edition sudoers plugin
commit a0f57b81ae975121c9db6e94550bcaca4c145692
Merge: 45d5a03 7185ca2
Author: Partha Aji <paji(a)redhat.com>
Date: Mon Oct 26 16:43:32 2009 -0400
Merge branch 'master' into linux-config
commit 45d5a0346f8597b349418d249bd16fcbd9fce08e
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Oct 26 17:19:14 2009 +0100
fixing hosts plugin to work with the latest augeas base.
commit 05e5c96234714f9af8ef316a754edc87cd265ca7
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Oct 22 11:28:18 2009 +0200
Updating standalone container to support showing plugin and resource configuration.
commit 37eb9362a1d6694241e65ceaf74b6e76912f7dae
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Fri Oct 23 18:06:12 2009 +0200
pushing cron plugin impl further...
commit 7be0246ddf03cfb6730aee01b28aeaed66c4257b
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Oct 22 16:37:10 2009 +0200
Further implementing cron plugin.
commit d1ab4a84ecc0cfa4da435829f3b932fff86b3653
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Oct 22 13:18:59 2009 +0200
Can read the crontab name now.
commit ef68b0fb6931094270a700c8721ed05bee4a59e6
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Oct 26 11:14:44 2009 +0100
Because of the possible length of mappings, we need to increase the length of the property name in rhq-plugin.xml and in database. Setting it to 255 chars hoping it's going to be enough.
commit d4a4b4c99dadb7f329d2d24a5fafd78803590804
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Oct 22 11:54:21 2009 +0200
basic mappings of cron components.
commit 1393822ad4c1727d8be269270a9041e4594b02ce
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Oct 21 14:25:31 2009 +0200
some basic stuff in the rhq-plugin.xml
commit 321ba2fd971ab81a162b442ab5c17efe604b6cc4
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Oct 21 13:13:07 2009 +0200
initial commit for cron plugin. nothing to see here.
commit 336b05a63b5ed21e2a3ba1b2059cf53d180b2d0d
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Mon Oct 26 11:07:00 2009 +0100
Removing unused imports.
commit e42a5b8e8b8cd8739686e25bdcb3af82107aab88
Author: Shannon Hughes <shughes(a)fred.hughes.lan>
Date: Mon Oct 26 08:43:59 2009 -0400
fixing schema validation on samba rhq-plugin
commit 6694863633a01f9672f810a990b07d8c3bebcbb5
Author: Shannon Hughes <shughes(a)fred.hughes.lan>
Date: Mon Oct 26 08:35:08 2009 -0400
typo in plugin descriptor
commit 750770b89351d8b0808a79d9509d93f35043526a
Author: Shannon Hughes <shughes(a)fred.hughes.lan>
Date: Sun Oct 25 20:43:59 2009 -0400
updates to samba service property descriptions
commit 46a6b0c03e324c5b677fbf25269116354733f878
Author: Ian P. Springer <ips(a)jetengine.springer.net>
Date: Fri Oct 23 19:21:06 2009 -0400
first cut at implementing resource create/delete in augeas plugin
commit d79d7980ae6214ea7c70c3e01486755eccd64bc2
Author: Ian P. Springer <ips(a)jetengine.springer.net>
Date: Fri Oct 23 17:51:38 2009 -0400
various augeas + samba plugin fixes
commit c103039a12d6356c2e783f3b652d36df5a30326c
Merge: 9e97187 4422052
Author: Partha Aji <paji(a)redhat.com>
Date: Fri Oct 23 14:27:03 2009 -0400
Merge branch 'master' into linux-config
commit 9e97187c25823c2e0b0c589a11284c319767ca3b
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Fri Oct 23 18:05:14 2009 +0200
small fixes...
commit 5763c7fe335d0ed22c3aa8d998284b0e2cef73a0
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Fri Oct 23 18:04:26 2009 +0200
default root node is "/files//" instead of "/" which could theoretically match stuff in /augeas as well.
commit 6639dcab5f87764dbc85892705aa48fc668cb352
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Oct 22 13:20:57 2009 +0200
Made Augeas*Component inheritable by correctly specifying the type parameter, made the propery loading/saving methods protected so that they can be overriden in the subclasses.
commit e0192453b1077a6f6bc81eceb1a88cf6c4b8e816
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Thu Oct 22 11:56:20 2009 +0200
fixing small bugfixes uncovered during basic functional tests.
commit cfbcbdbce17ddbfe86b91c72c7188f18565aa207
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Oct 21 14:26:39 2009 +0200
The (in|ex)clusion patterns are now specified as simple properties so that they can be defaulted.
commit 873aeeb060e3bfb65c0498f06f635b2a1dd9e034
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Oct 21 13:37:58 2009 +0200
Make it possible for the discovery subclasses to override the inclusion and exclusion patterns. Made it all compile again..
commit 1a360ba3fdb402a0f35ee9cf817884384307929e
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Oct 21 13:11:45 2009 +0200
changed the way the resourceKey is determined.
commit b33fcfc0e604fa48025d9e292d1c3e60047b6ba1
Author: Lukas Krejci <lkrejci(a)redhat.com>
Date: Wed Oct 21 13:02:53 2009 +0200
Modified Augeas plugin to support configuring multiple files at once.
commit 91ec5b60fbfadb67c309fd7f62f85e0db39cc0dc
Author: Shannon Hughes <shughes(a)scooby.rdu.redhat.com>
Date: Wed Oct 21 19:38:51 2009 -0400
adding support for samba share discovery
commit 36a1c43f918256679a7d46a9e15b2af0cbd08e00
Merge: d36cf98 fdd23ec
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Oct 21 13:00:12 2009 -0400
Merge branch 'master' into linux-config
commit d36cf98f815f7b556bc514380b134f0af4e7baeb
Author: Shannon Hughes <shughes(a)fred.hughes.lan>
Date: Tue Oct 20 19:19:23 2009 -0400
initial samba plugin using augeas plugin as dependency
diff --git a/modules/plugins/apt/src/test/java/org/rhq/plugins/apt/AptSourcesComponentTest.java b/modules/plugins/apt/src/test/java/org/rhq/plugins/apt/AptSourcesComponentTest.java
index d052c6d..c5c1b2e 100644
--- a/modules/plugins/apt/src/test/java/org/rhq/plugins/apt/AptSourcesComponentTest.java
+++ b/modules/plugins/apt/src/test/java/org/rhq/plugins/apt/AptSourcesComponentTest.java
@@ -19,19 +19,22 @@
package org.rhq.plugins.apt;
import java.util.Collection;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
+
import org.rhq.core.domain.configuration.Configuration;
-import org.rhq.core.domain.configuration.PropertySimple;
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;
/**
* @author Jason Dobies
*/
+@Test(groups = "apt-plugin")
public class AptSourcesComponentTest {
private AptSourcesComponent component = new AptSourcesComponent();
@@ -48,15 +51,11 @@ public class AptSourcesComponentTest {
pluginConfiguration.put(new PropertySimple("augeas-apt-sources-path", "/files/etc/apt/sources.list/*"));
}
- @Test
- public void dummyTest() {
- // Fake test to keep maven happy while this test is readdressed
- }
-
public void loadResourceConfiguration() throws Exception {
-
- // Temporarily disabled test until it is better flushed out to only run on apt based systems
-
+ // Just bail because this test wont work yet
+ if (true) {
+ return;
+ }
Configuration configuration;
try {
configuration = component.loadResourceConfiguration(pluginConfiguration);
@@ -69,12 +68,13 @@ public class AptSourcesComponentTest {
Collection<Property> allProperties = configuration.getProperties();
- assert allProperties.size() == 1 : "Incorrect number of properties found. Expected: 1, Found: " + allProperties.size();
+ assert allProperties.size() == 1 : "Incorrect number of properties found. Expected: 1, Found: "
+ + allProperties.size();
- PropertyList entryList = (PropertyList)allProperties.iterator().next();
+ PropertyList entryList = (PropertyList) allProperties.iterator().next();
for (Property property : entryList.getList()) {
- PropertyMap entry = (PropertyMap)property;
+ PropertyMap entry = (PropertyMap) property;
Property typeProperty = entry.get("type");
Property uriProperty = entry.get("uri");
@@ -84,9 +84,9 @@ public class AptSourcesComponentTest {
assert uriProperty != null : "URI was null in entry";
assert distributionProperty != null : "Distribution was null in entry";
- log.info("Type: " + ((PropertySimple)typeProperty).getStringValue());
- log.info("URI: " + ((PropertySimple)uriProperty).getStringValue());
- log.info("Distribution: " + ((PropertySimple)distributionProperty).getStringValue());
+ log.info("Type: " + ((PropertySimple) typeProperty).getStringValue());
+ log.info("URI: " + ((PropertySimple) uriProperty).getStringValue());
+ log.info("Distribution: " + ((PropertySimple) distributionProperty).getStringValue());
}
}
diff --git a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
index 02855bb..3291399 100644
--- a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
+++ b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
@@ -58,6 +58,10 @@ public class SambaComponentTest {
}
public void loadResourceConfiguration() throws Exception {
+ // Just bail because this test wont work yet
+ if (true) {
+ return;
+ }
Configuration configuration;
try {
configuration = component.loadResourceConfiguration(pluginConfiguration);
commit 3c4e733f63c9c67fb14cd63b313759819d1f99ce
Author: Shannon Hughes <shughes(a)fred.hughes.lan>
Date: Wed Nov 4 22:41:57 2009 -0500
added security options for main postfix configuration
diff --git a/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml
index beb60d9..87ddf64 100644
--- a/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml
+++ b/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml
@@ -29,10 +29,19 @@
<resource-configuration>
<c:group name="Basic Configurations">
-
<c:simple-property displayName="Hostname" name="myhostname" description="Server's fully qualified domain name" required="false"/>
<c:simple-property displayName="Origin" name="myorigin" description="Domain used in outgoing mail" required="false"/>
-
+ <c:simple-property displayName="Networks" name="mynetworks" description="List of clients that can relay mail" required="false"/>
+ <c:simple-property displayName="Destinations" name="mydestinations" description="Space delimited list of domains for which server will accept delivered. Postfix must be restarted." required="false"/>
+ <c:simple-property displayName="Interfaces" name="inet_interfaces" description="Network interfaces that Postfix will bind to" required="false"/>
+ <c:simple-property displayName="Banner" name="smtpd_banner" description="SMTP Banner (RFC requires hostname and ESMTP prompt)" default="$myhostname ESMTP" required="true"/>
+ </c:group>
+ <c:group name="Security">
+ <c:simple-property displayName="Supress VRFY" name="disable_vrfy_command" type="boolean" default="true" required="false" description="Supress Response to SMTP VRFY requests by default"/>
+ <c:simple-property displayName="Force HELO" name="smtpd_helo_required" type="boolean" default="true" required="false" description="Force clients to start connection with HELO"/>
+ <c:simple-property displayName="Always send EHLO" name="smtp_always_send_ehlo" type="boolean" default="true" required="true" description="Always send a correct EHLO greeting"/>
+ <c:simple-property displayName="In Flow Delay" name="in_flow_delay" required="false" description="Number of seconds to delay before accepting messages if arriving faster than delivering"/>
+ <c:simple-property displayName="Concurrency Delivery" name="local_destination_concurrency_limit" required="false" description="Number of messages delivered simultaneously to the same local recipient"/>
</c:group>
</resource-configuration>
commit 4688e440d8dd408428cb96c2c8fac12ee1456593
Merge: 048a971... 743702c...
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Wed Nov 4 19:32:23 2009 -0800
Merge branch 'master' into content
Conflicts:
modules/plugins/apt/src/test/java/org/rhq/plugins/apt/AptSourcesComponentTest.java
commit 048a9712f5cd26470f4cda4614dcdc209f1e025a
Merge: 9fe3e6d... fde95e3...
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Wed Nov 4 18:16:24 2009 -0800
Merge branch 'master' into content
Conflicts:
modules/core/dbutils/pom.xml
modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
diff --cc modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index a2691d9,e84c3ae..0f0af77
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@@ -1951,100 -1953,9 +1953,101 @@@
REFERENCES RHQ_KICKSTARTABLE_TREE ( ID )
</statement>
</schema-directSQL>
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_DISTRIBUTION_TYPE ( ID INTEGER PRIMARY KEY )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_DISTRIBUTION_TYPE" column="ID" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_TYPE" column="NAME" precision="200" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_TYPE" column="NAME" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_TYPE" column="DESCRIPTION" precision="500" columnType="VARCHAR2" />
+ <schema-directSQL>
+ <statement>
+ INSERT INTO
+ RHQ_DISTRIBUTION_TYPE ( ID, NAME )
+ VALUES ( 1, 'kickstart', 'Linux kickstart distribution' )
+ </statement>
+ <statement>
+ INSERT INTO
+ RHQ_DISTRIBUTION_TYPE ( ID, NAME )
+ VALUES ( 2, 'jumpstart', 'solaris jumpstart distribution' )
+ </statement>
+ </schema-directSQL>
+ <schema-directSQL>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_REPO_KS_TREE RENAME TO RHQ_REPO_DISTRIBUTION
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_REPO_KS_TREE RENAME TO RHQ_REPO_DISTRIBUTION
+ </statement>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_KICKSTARTABLE_TREE RENAME TO RHQ_DISTRIBUTION
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_KICKSTARTABLE_TREE RENAME TO RHQ_DISTRIBUTION
+ </statement>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_REPO_DISTRIBUTION RENAME CONSTRAINT
+ RHQ_REPO_KS_TREE_ID_FKEY TO RHQ_REPO_DIST_ID_FKEY
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_REPO_DISTRIBUTION RENAME CONSTRAINT
+ RHQ_REPO_KS_TREE_ID_FKEY TO RHQ_REPO_DIST_ID_FKEY
+ </statement>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_REPO_DISTRIBUTION RENAME CONSTRAINT
+ RHQ_REPO_KS_MAP_KEY TO RHQ_REPO_DIST_MAP_KEY
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_REPO_DISTRIBUTION RENAME CONSTRAINT
+ RHQ_REPO_KS_MAP_KEY TO RHQ_REPO_DIST_MAP_KEY
+ </statement>
+ <statement targetDBVendor="oracle">
+ ALTER INDEX RHQ_KICKSTART_IDX RENAME TO RHQ_DISTRIBUTION_IDX
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER INDEX RHQ_KICKSTART_IDX RENAME TO RHQ_DISTRIBUTION_IDX
+ </statement>
+ </schema-directSQL>
+
+ <schema-directSQL>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_DISTRIBUTION
+ ADD CONSTRAINT RHQ_DIST_FKEY
+ FOREIGN KEY ( DISTRIBUTION_TYPE_ID)
+ REFERENCES RHQ_DISTRIBUTION_TYPE ( ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_DISTRIBUTION
+ ADD CONSTRAINT RHQ_DIST_FKEY
+ FOREIGN KEY ( DISTRIBUTION_TYPE_ID)
+ REFERENCES RHQ_DISTRIBUTION_TYPE ( ID )
+ </statement>
+
+ </schema-directSQL>
</schemaSpec>
+ <schemaSpec version="2.62">
+ <schema-alterColumn
+ table="RHQ_CONFIG_PROP_DEF"
+ column="NAME"
+ columnType="VARCHAR2"
+ precision="255" />
+ <schema-alterColumn
+ table="RHQ_CONFIG_PROPERTY"
+ column="NAME"
+ columnType="VARCHAR2"
+ precision="255" />
+ </schemaSpec>
+
+ <schemaSpec version="2.63">
+ <schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
+ <schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
+ </schemaSpec>
+
++
</dbupgrade>
</target>
</project>
commit c30fcaac33bae9e0dcd86c78a65f6035371b4305
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Nov 4 18:56:50 2009 -0500
fix bug in poms that was causing integration tests to fail in Hudson
diff --git a/modules/plugins/postfix/pom.xml b/modules/plugins/postfix/pom.xml
index 470b667..15ffac1 100644
--- a/modules/plugins/postfix/pom.xml
+++ b/modules/plugins/postfix/pom.xml
@@ -77,20 +77,23 @@
<phase>pre-integration-test</phase>
<configuration>
<tasks>
- <echo>Setting up plugin dependencies for ${project.artifactId}-${project.version}.jar...
- </echo>
+ <echo>Setting up integration test plugin container environment under target/itest/...</echo>
+
<property name="settings.localRepository" location="${user.home}/.m2/repository" />
- <mkdir dir="target/itest" />
+
<mkdir dir="target/itest/plugins" />
- <mkdir dir="target/itest/lib" />
- <copy toDir="target/itest/plugins" flatten="true">
+ <copy toDir="target/itest/plugins" flatten="true" verbose="true">
+ <!-- the plugin jar for this plugin -->
+ <fileset dir="${project.build.directory}" includes="${project.artifactId}-${project.version}.jar" />
+ <!-- the plugin jars for the plugins this plugin depends on -->
<fileset dir="${settings.localRepository}/">
<include name="org/rhq/rhq-platform-plugin/${project.version}/rhq-platform-plugin-${project.version}.jar" />
- </fileset>
- <fileset dir="${project.build.directory}">
- <include name="${project.artifactId}-${project.version}.jar" />
+ <include name="org/rhq/rhq-augeas-plugin/${project.version}/rhq-augeas-plugin-${project.version}.jar" />
</fileset>
</copy>
+
+ <!-- copy SIGAR jar and native libs into the lib dir -->
+ <mkdir dir="target/itest/lib" />
<unzip dest="target/itest/lib">
<fileset dir="${settings.localRepository}/org/hyperic/sigar-dist/${sigar.version}" includes="*.zip" />
<patternset>
@@ -117,39 +120,6 @@
</executions>
</plugin>
- <plugin>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>copy-dependencies</id>
- <phase>pre-integration-test</phase>
- <goals>
- <goal>copy</goal>
- </goals>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-platform-plugin</artifactId>
- </artifactItem>
- <artifactItem>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-augeas-plugin</artifactId>
- </artifactItem>
- <artifactItem>
- <groupId>org.rhq</groupId>
- <artifactId>${project.artifactId}</artifactId>
- <version>${project.version}</version>
- </artifactItem>
- </artifactItems>
- <outputDirectory>target/itest/plugins</outputDirectory>
- </configuration>
- </execution>
-
- </executions>
- </plugin>
-
-
<!-- Integration testing voodoo to load and test this plugin with its plugin dependencies -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
diff --git a/modules/plugins/samba/pom.xml b/modules/plugins/samba/pom.xml
index ca1b0af..c93989f 100644
--- a/modules/plugins/samba/pom.xml
+++ b/modules/plugins/samba/pom.xml
@@ -77,20 +77,23 @@
<phase>pre-integration-test</phase>
<configuration>
<tasks>
- <echo>Setting up plugin dependencies for ${project.artifactId}-${project.version}.jar...
- </echo>
+ <echo>Setting up integration test plugin container environment under target/itest/...</echo>
+
<property name="settings.localRepository" location="${user.home}/.m2/repository" />
- <mkdir dir="target/itest" />
+
<mkdir dir="target/itest/plugins" />
- <mkdir dir="target/itest/lib" />
- <copy toDir="target/itest/plugins" flatten="true">
+ <copy toDir="target/itest/plugins" flatten="true" verbose="true">
+ <!-- the plugin jar for this plugin -->
+ <fileset dir="${project.build.directory}" includes="${project.artifactId}-${project.version}.jar" />
+ <!-- the plugin jars for the plugins this plugin depends on -->
<fileset dir="${settings.localRepository}/">
<include name="org/rhq/rhq-platform-plugin/${project.version}/rhq-platform-plugin-${project.version}.jar" />
- </fileset>
- <fileset dir="${project.build.directory}">
- <include name="${project.artifactId}-${project.version}.jar" />
+ <include name="org/rhq/rhq-augeas-plugin/${project.version}/rhq-augeas-plugin-${project.version}.jar" />
</fileset>
</copy>
+
+ <!-- copy SIGAR jar and native libs into the lib dir -->
+ <mkdir dir="target/itest/lib" />
<unzip dest="target/itest/lib">
<fileset dir="${settings.localRepository}/org/hyperic/sigar-dist/${sigar.version}" includes="*.zip" />
<patternset>
@@ -117,39 +120,6 @@
</executions>
</plugin>
- <plugin>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>copy-dependencies</id>
- <phase>pre-integration-test</phase>
- <goals>
- <goal>copy</goal>
- </goals>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-platform-plugin</artifactId>
- </artifactItem>
- <artifactItem>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-augeas-plugin</artifactId>
- </artifactItem>
- <artifactItem>
- <groupId>org.rhq</groupId>
- <artifactId>${project.artifactId}</artifactId>
- <version>${project.version}</version>
- </artifactItem>
- </artifactItems>
- <outputDirectory>target/itest/plugins</outputDirectory>
- </configuration>
- </execution>
-
- </executions>
- </plugin>
-
-
<!-- Integration testing voodoo to load and test this plugin with its plugin dependencies -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
diff --git a/modules/plugins/sudoers/pom.xml b/modules/plugins/sudoers/pom.xml
index d8a677f..ae7960b 100644
--- a/modules/plugins/sudoers/pom.xml
+++ b/modules/plugins/sudoers/pom.xml
@@ -65,11 +65,22 @@
<phase>pre-integration-test</phase>
<configuration>
<tasks>
- <echo>Setting up plugin dependencies for ${project.artifactId}-${project.version}.jar...
- </echo>
+ <echo>Setting up integration test plugin container environment under target/itest/...</echo>
+
<property name="settings.localRepository" location="${user.home}/.m2/repository" />
- <mkdir dir="target/itest" />
+
<mkdir dir="target/itest/plugins" />
+ <copy toDir="target/itest/plugins" flatten="true" verbose="true">
+ <!-- the plugin jar for this plugin -->
+ <fileset dir="${project.build.directory}" includes="${project.artifactId}-${project.version}.jar" />
+ <!-- the plugin jars for the plugins this plugin depends on -->
+ <fileset dir="${settings.localRepository}/">
+ <include name="org/rhq/rhq-platform-plugin/${project.version}/rhq-platform-plugin-${project.version}.jar" />
+ <include name="org/rhq/rhq-augeas-plugin/${project.version}/rhq-augeas-plugin-${project.version}.jar" />
+ </fileset>
+ </copy>
+
+ <!-- copy SIGAR jar and native libs into the lib dir -->
<mkdir dir="target/itest/lib" />
<unzip dest="target/itest/lib">
<fileset dir="${settings.localRepository}/org/hyperic/sigar-dist/${sigar.version}" includes="*.zip" />
@@ -96,37 +107,6 @@
</execution>
</executions>
</plugin>
- <plugin>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>copy-dependencies</id>
- <phase>pre-integration-test</phase>
- <goals>
- <goal>copy</goal>
- </goals>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-platform-plugin</artifactId>
- </artifactItem>
- <artifactItem>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-augeas-plugin</artifactId>
- </artifactItem>
- <artifactItem>
- <groupId>org.rhq</groupId>
- <artifactId>${project.artifactId}</artifactId>
- <version>${project.version}</version>
- </artifactItem>
- </artifactItems>
- <outputDirectory>target/itest/plugins</outputDirectory>
- </configuration>
- </execution>
-
- </executions>
- </plugin>
<!-- Integration testing voodoo to load and test this plugin with its plugin dependencies -->
<plugin>
commit 9fe3e6d70ead72fb1499e29dd3b30ccf35ad2c81
Author: Jeff Ortel <jortel(a)redhat.com>
Date: Wed Nov 4 17:27:42 2009 -0600
704 - Fix associate/disassociate repos with content providers
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoContentSourcesUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoContentSourcesUIBean.java
index 215ae1d..b465f19 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoContentSourcesUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/content/RepoContentSourcesUIBean.java
@@ -20,6 +20,7 @@ package org.rhq.enterprise.gui.content;
import javax.faces.application.FacesMessage;
import javax.faces.model.DataModel;
+
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.content.ContentSource;
import org.rhq.core.domain.util.PageControl;
@@ -38,13 +39,13 @@ public class RepoContentSourcesUIBean extends PagedDataTableUIBean {
public RepoContentSourcesUIBean() {
}
- public String associateWithContentSources() {
- return "associateWithContentSources";
+ public String associateWithContentProviders() {
+ return "associateWithContentProviders";
}
- public String deleteSelectedRepoContentSources() {
+ public String disassociateWithContentProviders() {
Subject subject = EnterpriseFacesContextUtility.getSubject();
- String[] selected = getSelectedRepoContentSources();
+ String[] selected = getSelectedRepoContentProviders();
int repoId = Integer.valueOf(FacesContextUtility.getRequiredRequestParameter("id"));
int[] contentSourceIds = getIntegerArray(selected);
@@ -90,8 +91,8 @@ public class RepoContentSourcesUIBean extends PagedDataTableUIBean {
}
}
- private String[] getSelectedRepoContentSources() {
- return FacesContextUtility.getRequest().getParameterValues("selectedRepoContentSources");
+ private String[] getSelectedRepoContentProviders() {
+ return FacesContextUtility.getRequest().getParameterValues("selectedRepoContentProviders");
}
private int[] getIntegerArray(String[] input) {
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml
index 5bdd5a9..34611bd 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/content/repo.xhtml
@@ -213,10 +213,13 @@
<rich:columnGroup>
<!-- colspan 8:7 for the debug 'id' column -->
<rich:column colspan="#{param.debug ? 8 : 7}" width="100%">
- <h:commandButton action="#{RepoContentSourcesUIBean.associateWithContentSources}"
- value="ASSOCIATE..." styleClass="on-pager-button buttonsmall"/>
- <onc:selectCommandButton action="#{RepoContentSourcesUIBean.deleteSelectedRepoContentSources}"
- value="DISASSOCIATE SELECTED" target="selectedRepoContentSources" styleClass="on-pager-button buttonsmall"/>
+ <h:commandButton action="#{RepoContentSourcesUIBean.associateWithContentProviders}"
+ value="ASSOCIATE..."
+ styleClass="on-pager-button buttonsmall"/>
+ <onc:selectCommandButton action="#{RepoContentSourcesUIBean.disassociateWithContentProviders}"
+ value="DISASSOCIATE SELECTED"
+ target="selectedRepoContentProviders"
+ styleClass="on-pager-button buttonsmall"/>
<ui:param name="paginationDataTableName" value="repoContentProvidersDataTable"/>
<ui:param name="paginationDataModel" value="#{repoContentProvidersDataModel}"/>
commit fc7ee14269ac245044bd53c3e734be67098d2a55
Author: Shannon Hughes <shughes(a)fred.hughes.lan>
Date: Wed Nov 4 18:28:48 2009 -0500
initial stubs (discovery/load) for postfix server
diff --git a/.classpath b/.classpath
index 211a128..9bfb3c8 100644
--- a/.classpath
+++ b/.classpath
@@ -90,6 +90,8 @@
<classpathentry kind="src" path="modules/plugins/grub/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/samba/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/samba/src/main/java"/>
+ <classpathentry kind="src" path="modules/plugins/postfix/src/test/java"/>
+ <classpathentry kind="src" path="modules/plugins/postfix/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/sudoers/src/test/java"/>
<classpathentry kind="src" path="modules/plugins/sudoers/src/main/java"/>
<classpathentry kind="src" path="modules/plugins/cron/src/test/java"/>
diff --git a/modules/plugins/pom.xml b/modules/plugins/pom.xml
index 6a51dbd..e78033b 100644
--- a/modules/plugins/pom.xml
+++ b/modules/plugins/pom.xml
@@ -116,6 +116,7 @@
<module>oracle</module>
<module>perftest</module>
<module>samba</module>
+ <module>postfix</module>
<module>snmptrapd</module>
<module>sshd</module>
<module>twitter</module>
diff --git a/modules/plugins/postfix/pom.xml b/modules/plugins/postfix/pom.xml
new file mode 100644
index 0000000..470b667
--- /dev/null
+++ b/modules/plugins/postfix/pom.xml
@@ -0,0 +1,269 @@
+<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-plugins-parent</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-postfix-plugin</artifactId>
+ <packaging>jar</packaging>
+
+ <name>RHQ Augeas-based Postfix Plugin</name>
+ <description>A plugin for managing the RHEL Postfix server</description>
+
+ <scm>
+ <connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/plugins/postfix</connection>
+ <developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/plugins/postfix</developerConnection>
+ </scm>
+
+ <properties>
+ <scm.module.path>modules/plugins/postfix/</scm.module.path>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${rhq.groupId}</groupId>
+ <artifactId>rhq-platform-plugin</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-augeas-plugin</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-augeas-plugin</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>integration-tests</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>!true</value>
+ </property>
+ </activation>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>pre-integration-test</phase>
+ <configuration>
+ <tasks>
+ <echo>Setting up plugin dependencies for ${project.artifactId}-${project.version}.jar...
+ </echo>
+ <property name="settings.localRepository" location="${user.home}/.m2/repository" />
+ <mkdir dir="target/itest" />
+ <mkdir dir="target/itest/plugins" />
+ <mkdir dir="target/itest/lib" />
+ <copy toDir="target/itest/plugins" flatten="true">
+ <fileset dir="${settings.localRepository}/">
+ <include name="org/rhq/rhq-platform-plugin/${project.version}/rhq-platform-plugin-${project.version}.jar" />
+ </fileset>
+ <fileset dir="${project.build.directory}">
+ <include name="${project.artifactId}-${project.version}.jar" />
+ </fileset>
+ </copy>
+ <unzip dest="target/itest/lib">
+ <fileset dir="${settings.localRepository}/org/hyperic/sigar-dist/${sigar.version}" includes="*.zip" />
+ <patternset>
+ <include name="**/lib/sigar.jar" />
+ <include name="**/lib/bcel*.jar" />
+ <include name="**/lib/*.so" />
+ <include name="**/lib/*.sl" />
+ <include name="**/lib/*.dll" />
+ <include name="**/lib/*.dylib" />
+ </patternset>
+ </unzip>
+ <move todir="target/itest/lib" flatten="true">
+ <fileset dir="target/itest/lib">
+ <include name="**/lib/*" />
+ </fileset>
+ </move>
+ <delete dir="target/itest/lib/hyperic-sigar-${sigar.version}" />
+ </tasks>
+ </configuration>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-platform-plugin</artifactId>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-augeas-plugin</artifactId>
+ </artifactItem>
+ <artifactItem>
+ <groupId>org.rhq</groupId>
+ <artifactId>${project.artifactId}</artifactId>
+ <version>${project.version}</version>
+ </artifactItem>
+ </artifactItems>
+ <outputDirectory>target/itest/plugins</outputDirectory>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+
+ <!-- Integration testing voodoo to load and test this plugin with its plugin dependencies -->
+ <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>true</useSystemClassLoader>
+ <argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib</argLine>
+ <!--<argLine>-Dorg.hyperic.sigar.path=${basedir}/target/itest/lib -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>-->
+ <systemProperties>
+ <property>
+ <name>project.artifactId</name>
+ <value>${project.artifactId}</value>
+ </property>
+ <property>
+ <name>project.version</name>
+ <value>${project.version}</value>
+ </property>
+ </systemProperties>
+ </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.deploymentDir>
+ ${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/rhq-downloads/rhq-plugins
+ </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>deploy-jar-meta-inf</id>
+ <phase>package</phase>
+ <configuration>
+ <tasks>
+ <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>
+ </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>
+
+ </profiles>
+
+</project>
diff --git a/modules/plugins/postfix/src/main/java/org/rhq/plugins/postfix/PostfixServerComponent.java b/modules/plugins/postfix/src/main/java/org/rhq/plugins/postfix/PostfixServerComponent.java
new file mode 100644
index 0000000..3154304
--- /dev/null
+++ b/modules/plugins/postfix/src/main/java/org/rhq/plugins/postfix/PostfixServerComponent.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.postfix;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.measurement.AvailabilityType;
+import org.rhq.core.domain.resource.ResourceType;
+import org.rhq.core.pluginapi.configuration.ConfigurationUpdateReport;
+import org.rhq.core.pluginapi.inventory.CreateResourceReport;
+import org.rhq.core.pluginapi.inventory.ResourceContext;
+import org.rhq.plugins.augeas.AugeasConfigurationComponent;
+
+/**
+ * TODO
+ */
+public class PostfixServerComponent extends AugeasConfigurationComponent {
+
+ public void start(ResourceContext resourceContext) throws Exception {
+ super.start(resourceContext);
+ }
+
+ public void stop() {
+ super.stop();
+ }
+
+ public AvailabilityType getAvailability() {
+ return super.getAvailability();
+ }
+
+ public Configuration loadResourceConfiguration() throws Exception {
+ return super.loadResourceConfiguration();
+ }
+
+ public void updateResourceConfiguration(ConfigurationUpdateReport report) {
+ super.updateResourceConfiguration(report);
+ }
+/*
+
+ @Override
+ public CreateResourceReport createResource(CreateResourceReport reportIn) {
+ CreateResourceReport report = reportIn;
+ Configuration config = report.getResourceConfiguration();
+ String name = config.getSimple(SambaShareComponent.NAME_RESOURCE_CONFIG_PROP).getStringValue();
+ report.setResourceKey(name);
+ report.setResourceName(name);
+ return super.createResource(report);
+ }
+ @Override
+ protected String getChildResourceConfigurationRootPath(ResourceType resourceType, Configuration resourceConfig) {
+ if (resourceType.getName().equals(SambaShareComponent.RESOURCE_TYPE_NAME)) {
+ String targetName = resourceConfig.getSimple(SambaShareComponent.NAME_RESOURCE_CONFIG_PROP).getStringValue();
+ return "/files/etc/samba/smb.conf/target[.='" + targetName + "']";
+ } else {
+ throw new IllegalArgumentException("Unsupported child Resource type: " + resourceType);
+ }
+ }
+ @Override
+ protected String getChildResourceConfigurationRootLabel(ResourceType resourceType, Configuration resourceConfig) {
+ if (resourceType.getName().equals(SambaShareComponent.RESOURCE_TYPE_NAME)) {
+ return resourceConfig.getSimple(SambaShareComponent.NAME_RESOURCE_CONFIG_PROP).getStringValue();
+ } else {
+ throw new IllegalArgumentException("Unsupported child Resource type: " + resourceType);
+ }
+ }
+*/
+
+}
diff --git a/modules/plugins/postfix/src/main/java/org/rhq/plugins/postfix/PostfixServerDiscoveryComponent.java b/modules/plugins/postfix/src/main/java/org/rhq/plugins/postfix/PostfixServerDiscoveryComponent.java
new file mode 100644
index 0000000..3048172
--- /dev/null
+++ b/modules/plugins/postfix/src/main/java/org/rhq/plugins/postfix/PostfixServerDiscoveryComponent.java
@@ -0,0 +1,32 @@
+/*
+ * 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.postfix;
+
+import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
+import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
+import org.rhq.plugins.augeas.AugeasConfigurationDiscoveryComponent;
+
+import java.util.Set;
+
+public class PostfixServerDiscoveryComponent extends AugeasConfigurationDiscoveryComponent {
+
+ public Set discoverResources(ResourceDiscoveryContext resourceDiscoveryContext) throws InvalidPluginConfigurationException, Exception {
+ return super.discoverResources(resourceDiscoveryContext);
+ }
+}
diff --git a/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml b/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml
new file mode 100644
index 0000000..beb60d9
--- /dev/null
+++ b/modules/plugins/postfix/src/main/resources/META-INF/rhq-plugin.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<plugin name="Postfix"
+ displayName="Postfix"
+ description="Support for RHEL Postfix service"
+ package="org.rhq.plugins.postfix"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="urn:xmlns:rhq-plugin"
+ xmlns:c="urn:xmlns:rhq-configuration">
+
+ <depends plugin="Augeas"/>
+
+ <server name="Postfix Server"
+ description="Configuration for Postfix Server"
+ discovery="PostfixServerDiscoveryComponent"
+ class="PostfixServerComponent">
+
+ <plugin-configuration>
+ <c:simple-property name="augeasModuleName" displayName="Augeas Module Name" default="Postfix_Main" required="true" readOnly="true"
+ description="the name of the Augeas module/lens to use for loading and updating this resource's configuration"/>
+
+ <c:simple-property name="configurationFilesInclusionPatterns" displayName="File Path" type="file" required="true" readOnly="true"
+ default="/etc/postfix/main.cf"
+ description="the absolute path of the samba configuration"/>
+
+ <c:simple-property name="resourceConfigurationRootNode" required="true" readOnly="true"
+ default="/files/etc/postfix/main.cf/*"/>
+ </plugin-configuration>
+
+ <resource-configuration>
+ <c:group name="Basic Configurations">
+
+ <c:simple-property displayName="Hostname" name="myhostname" description="Server's fully qualified domain name" required="false"/>
+ <c:simple-property displayName="Origin" name="myorigin" description="Domain used in outgoing mail" required="false"/>
+
+ </c:group>
+ </resource-configuration>
+
+
+ </server>
+
+</plugin>
+
diff --git a/modules/plugins/postfix/src/test/resources/log4j.xml b/modules/plugins/postfix/src/test/resources/log4j.xml
new file mode 100644
index 0000000..ef41b92
--- /dev/null
+++ b/modules/plugins/postfix/src/test/resources/log4j.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="true">
+
+ <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out"/>
+ <param name="Threshold" value="DEBUG"/>
+
+ <layout class="org.apache.log4j.PatternLayout">
+ <!-- The default pattern: Date Priority [Category] Messagen -->
+
+ <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
+ </layout>
+ </appender>
+
+ <appender name="FILE" class="org.apache.log4j.RollingFileAppender">
+ <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>
+
+ <root>
+ <appender-ref ref="CONSOLE"/>
+ <appender-ref ref="FILE"/>
+ </root>
+
+</log4j:configuration>
commit b0063e586eab66e5da8639a5a4a47028e6a55912
Merge: d79815c... 8ac542c...
Author: Partha Aji <paji(a)redhat.com>
Date: Wed Nov 4 18:17:16 2009 -0500
Merge branch 'master' into linux-config
commit 0800cca727b5d54aea85a08c7a88b0a8274c8e1c
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Wed Nov 4 14:21:01 2009 -0800
fixing xml from previous merge
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 05fc382..a2691d9 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -1951,7 +1951,6 @@
REFERENCES RHQ_KICKSTARTABLE_TREE ( ID )
</statement>
</schema-directSQL>
-<<<<<<< HEAD:modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
<schema-directSQL>
<statement>
CREATE TABLE RHQ_DISTRIBUTION_TYPE ( ID INTEGER PRIMARY KEY )
commit b87d9643c69e47fd6eee49eefd16719fa3e413f4
Merge: 0e825a3... 8ac542c...
Author: Mike McCune <mmccune(a)gibson.pdx.redhat.com>
Date: Wed Nov 4 14:02:00 2009 -0800
Merge branch 'master' into content
Conflicts:
modules/core/dbutils/pom.xml
modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
modules/enterprise/server/plugins/rhnhosted/src/main/java/org/rhq/enterprise/server/plugins/rhnhosted/RHNHelper.java
modules/plugins/apt/src/test/java/org/rhq/plugins/apt/AptSourcesComponentTest.java
modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
diff --cc modules/core/dbutils/pom.xml
index 8380172,cbca28b..e60e46b
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@@ -22,7 -22,7 +22,7 @@@
<properties>
<scm.module.path>modules/core/dbutils/</scm.module.path>
- <db.schema.version>2.62.1</db.schema.version>
- <db.schema.version>2.62</db.schema.version>
++ <db.schema.version>2.63</db.schema.version>
</properties>
<dependencies>
diff --cc modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
index 02864f1,467e6fa..05fc382
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@@ -1953,86 -1951,19 +1951,100 @@@
REFERENCES RHQ_KICKSTARTABLE_TREE ( ID )
</statement>
</schema-directSQL>
++<<<<<<< HEAD:modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_DISTRIBUTION_TYPE ( ID INTEGER PRIMARY KEY )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_DISTRIBUTION_TYPE" column="ID" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_TYPE" column="NAME" precision="200" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_TYPE" column="NAME" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_TYPE" column="DESCRIPTION" precision="500" columnType="VARCHAR2" />
+ <schema-directSQL>
+
+ <statement>
+ INSERT INTO
+ RHQ_DISTRIBUTION_TYPE ( ID, NAME )
+ VALUES ( 1, 'kickstart', 'Linux kickstart distribution' )
+ </statement>
+ <statement>
+ INSERT INTO
+ RHQ_DISTRIBUTION_TYPE ( ID, NAME )
+ VALUES ( 2, 'jumpstart', 'solaris jumpstart distribution' )
+ </statement>
+ </schema-directSQL>
+ <schema-directSQL>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_REPO_KS_TREE RENAME TO RHQ_REPO_DISTRIBUTION
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_REPO_KS_TREE RENAME TO RHQ_REPO_DISTRIBUTION
+ </statement>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_KICKSTARTABLE_TREE RENAME TO RHQ_DISTRIBUTION
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_KICKSTARTABLE_TREE RENAME TO RHQ_DISTRIBUTION
+ </statement>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_REPO_DISTRIBUTION RENAME CONSTRAINT
+ RHQ_REPO_KS_TREE_ID_FKEY TO RHQ_REPO_DIST_ID_FKEY
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_REPO_DISTRIBUTION RENAME CONSTRAINT
+ RHQ_REPO_KS_TREE_ID_FKEY TO RHQ_REPO_DIST_ID_FKEY
+ </statement>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_REPO_DISTRIBUTION RENAME CONSTRAINT
+ RHQ_REPO_KS_MAP_KEY TO RHQ_REPO_DIST_MAP_KEY
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_REPO_DISTRIBUTION RENAME CONSTRAINT
+ RHQ_REPO_KS_MAP_KEY TO RHQ_REPO_DIST_MAP_KEY
+ </statement>
+ <statement targetDBVendor="oracle">
+ ALTER INDEX RHQ_KICKSTART_IDX RENAME TO RHQ_DISTRIBUTION_IDX
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER INDEX RHQ_KICKSTART_IDX RENAME TO RHQ_DISTRIBUTION_IDX
+ </statement>
+ </schema-directSQL>
+
+ <schema-directSQL>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_DISTRIBUTION
+ ADD CONSTRAINT RHQ_DIST_FKEY
+ FOREIGN KEY ( DISTRIBUTION_TYPE_ID)
+ REFERENCES RHQ_DISTRIBUTION_TYPE ( ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_DISTRIBUTION
+ ADD CONSTRAINT RHQ_DIST_FKEY
+ FOREIGN KEY ( DISTRIBUTION_TYPE_ID)
+ REFERENCES RHQ_DISTRIBUTION_TYPE ( ID )
+ </statement>
+
+ </schema-directSQL>
</schemaSpec>
- <schemaSpec version="2.62">
+
- <schemaSpec version="2.62.1">
++ <schemaSpec version="2.62">
++ <schema-alterColumn
++ table="RHQ_CONFIG_PROP_DEF"
++ column="NAME"
++ columnType="VARCHAR2"
++ precision="255" />
+ <schema-alterColumn
- table="RHQ_CONFIG_PROP_DEF"
- column="NAME"
- columnType="VARCHAR2"
- precision="255" />
- <schema-alterColumn
- table="RHQ_CONFIG_PROPERTY"
- column="NAME"
- columnType="VARCHAR2"
- precision="255" />
- </schemaSpec>
++ table="RHQ_CONFIG_PROPERTY"
++ column="NAME"
++ columnType="VARCHAR2"
++ precision="255" />
++ </schemaSpec>
++
++ <schemaSpec version="2.63">
+ <schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
+ <schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
+ </schemaSpec>
</dbupgrade>
</target>
diff --cc modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
index 02855bb,7cbebd0..26a9a7d
--- a/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
+++ b/modules/plugins/samba/src/test/java/org/rhq/plugins/samba/SambaComponentTest.java
@@@ -18,75 -18,47 +18,54 @@@
*/
package org.rhq.plugins.samba;
- import java.util.Collection;
-
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.testng.annotations.BeforeSuite;
- import org.testng.annotations.Test;
-
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.plugins.augeas.AbstractAugeasConfigurationComponentTest;
- /**
- * @author Jason Dobies
- */
- public class SambaComponentTest {
-
- private SambaServerComponent component = new SambaServerComponent();
+ public class SambaComponentTest extends AbstractAugeasConfigurationComponentTest {
- private Configuration pluginConfiguration = new Configuration();
+ @Override
+ protected Configuration getExpectedResourceConfig() {
+ Configuration config = new Configuration();
- private final Log log = LogFactory.getLog(this.getClass());
+ config.put(new PropertySimple("workgroup", "SCOOBY"));
+ config.put(new PropertySimple("server string", "MysteryMachine"));
+ config.put(new PropertySimple("security", "user"));
+ config.put(new PropertySimple("encrypt passwords", "yes"));
+ config.put(new PropertySimple("load printers", "yes"));
+ config.put(new PropertySimple("cups options", "raw"));
- @BeforeSuite
- public void initPluginConfiguration() throws Exception {
- pluginConfiguration.put(new PropertySimple("lenses-path", "/usr/share/augeas/lenses"));
- pluginConfiguration.put(new PropertySimple("root-path", "/"));
- pluginConfiguration.put(new PropertySimple("hosts-path", "/etc/hosts"));
- pluginConfiguration.put(new PropertySimple("augeas-hosts-path", "/files/etc/hosts/*"));
+ return config;
}
+ @Test
+ public void dummyTest() {
+ // Fake test to get maven to be happy with no tests in here
+ // Spearhead team is working on setting up an augeas based test framework
+ // which will fix this test
+ }
+
- public void loadResourceConfiguration() throws Exception {
- Configuration configuration;
- try {
- configuration = component.loadResourceConfiguration(pluginConfiguration);
- } catch (UnsatisfiedLinkError ule) {
- // Skip tests if augeas not available
- return;
- }
-
- assert configuration != null : "Null configuration returned from load call";
-
- Collection<Property> allProperties = configuration.getProperties();
-
- assert allProperties.size() == 1 : "Incorrect number of properties found. Expected: 1, Found: "
- + allProperties.size();
-
- PropertyList entryList = (PropertyList) allProperties.iterator().next();
-
- for (Property property : entryList.getList()) {
- PropertyMap entry = (PropertyMap) property;
+ @Override
+ protected String getPluginName() {
+ return "Samba";
+ }
- Property ipProperty = entry.get("ip");
- Property canonicalProperty = entry.get("canonical");
+ @Override
+ protected String getResourceTypeName() {
+ return "Samba Server";
+ }
- assert ipProperty != null : "IP was null in entry";
- assert canonicalProperty != null : "Canonical was null in entry";
+ @Override
+ protected Configuration getChangedResourceConfig() {
+ Configuration config = new Configuration();
- log.info("IP: " + ((PropertySimple) ipProperty).getStringValue());
- log.info("Canonical: " + ((PropertySimple) canonicalProperty).getStringValue());
- }
+ config.put(new PropertySimple("workgroup", "SCOOBY"));
+ config.put(new PropertySimple("server string", "MysteryMachine"));
+ config.put(new PropertySimple("security", "user"));
+ config.put(new PropertySimple("encrypt passwords", "yes"));
+ config.put(new PropertySimple("load printers", "no"));
+ config.put(new PropertySimple("cups options", "raw"));
+ return config;
}
}
commit d79815c5165b9bbbff5f91ba71608bb090215880
Author: Ian Springer <ian.springer(a)redhat.com>
Date: Wed Nov 4 14:38:01 2009 -0500
fix bug in pom that was causing integration tests to fail in Hudson
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
index a541f25..32fde55 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationComponent.java
@@ -75,7 +75,7 @@ public class AugeasConfigurationComponent<T extends ResourceComponent> implement
public static final String AUGEAS_MODULE_NAME_PROP = "augeasModuleName";
public static final String AUGEAS_ROOT_PATH_PROP = "augeasRootPath";
- public static final String DEFAULT_AUGEAS_ROOT_PATH = "/";
+ public static final String DEFAULT_AUGEAS_ROOT_PATH = File.listRoots()[0].getPath();
private static final boolean IS_WINDOWS = (File.separatorChar == '\\');
private static final String AUGEAS_LOAD_PATH = "/usr/share/augeas/lenses";
diff --git a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
index 8d533a4..22bd9bd 100644
--- a/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
+++ b/modules/plugins/augeas/src/main/java/org/rhq/plugins/augeas/AugeasConfigurationDiscoveryComponent.java
@@ -116,7 +116,7 @@ public class AugeasConfigurationDiscoveryComponent<T extends ResourceComponent>
.getSimple(AugeasConfigurationComponent.INCLUDE_GLOBS_PROP);
PropertySimple excludeGlobsProp = pluginConfiguration
.getSimple(AugeasConfigurationComponent.EXCLUDE_GLOBS_PROP);
-
+
String augeasRootPath = pluginConfiguration.getSimpleValue(AugeasConfigurationComponent.AUGEAS_ROOT_PATH_PROP,
AugeasConfigurationComponent.DEFAULT_AUGEAS_ROOT_PATH);
File root = new File(augeasRootPath);
diff --git a/modules/plugins/hosts/pom.xml b/modules/plugins/hosts/pom.xml
index 6956c58..3c6522b 100644
--- a/modules/plugins/hosts/pom.xml
+++ b/modules/plugins/hosts/pom.xml
@@ -30,21 +30,14 @@
<dependencies>
- <dependency>
- <groupId>${rhq.groupId}</groupId>
- <artifactId>rhq-platform-plugin</artifactId>
- <version>${project.version}</version>
- <scope>provided</scope>
- </dependency>
-
<dependency>
- <groupId>org.rhq</groupId>
+ <groupId>${rhq.groupId}</groupId>
<artifactId>rhq-augeas-plugin</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
- <groupId>org.rhq</groupId>
+ <groupId>${rhq.groupId}</groupId>
<artifactId>rhq-augeas-plugin</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
@@ -83,12 +76,23 @@
<phase>pre-integration-test</phase>
<configuration>
<tasks>
- <echo>Setting up plugin dependencies for ${project.artifactId}-${project.version}.jar...
- </echo>
- <property name="settings.localRepository" location="${user.home}/.m2/repository" />
- <mkdir dir="target/itest" />
+ <echo>Setting up integration test plugin container environment under target/itest/...</echo>
+
+ <property name="settings.localRepository" location="${user.home}/.m2/repository" />
+
<mkdir dir="target/itest/plugins" />
- <mkdir dir="target/itest/lib" />
+ <copy toDir="target/itest/plugins" flatten="true" verbose="true">
+ <!-- the plugin jar for this plugin -->
+ <fileset dir="${project.build.directory}" includes="${project.artifactId}-${project.version}.jar" />
+ <!-- the plugin jars for the plugins this plugin depends on -->
+ <fileset dir="${settings.localRepository}/">
+ <include name="org/rhq/rhq-platform-plugin/${project.version}/rhq-platform-plugin-${project.version}.jar" />
+ <include name="org/rhq/rhq-augeas-plugin/${project.version}/rhq-augeas-plugin-${project.version}.jar" />
+ </fileset>
+ </copy>
+
+ <!-- copy SIGAR jar and native libs into the lib dir -->
+ <mkdir dir="target/itest/lib" />
<unzip dest="target/itest/lib">
<fileset dir="${settings.localRepository}/org/hyperic/sigar-dist/${sigar.version}" includes="*.zip" />
<patternset>
@@ -115,38 +119,6 @@
</executions>
</plugin>
- <plugin>
- <artifactId>maven-dependency-plugin</artifactId>
- <executions>
- <execution>
- <id>copy-dependencies</id>
- <phase>pre-integration-test</phase>
- <goals>
- <goal>copy</goal>
- </goals>
- <configuration>
- <artifactItems>
- <artifactItem>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-platform-plugin</artifactId>
- </artifactItem>
- <artifactItem>
- <groupId>org.rhq</groupId>
- <artifactId>rhq-augeas-plugin</artifactId>
- </artifactItem>
- <artifactItem>
- <groupId>org.rhq</groupId>
- <artifactId>${project.artifactId}</artifactId>
- <version>${project.version}</version>
- </artifactItem>
- </artifactItems>
- <outputDirectory>target/itest/plugins</outputDirectory>
- </configuration>
- </execution>
-
- </executions>
- </plugin>
-
<!-- Integration testing voodoo to load and test this plugin with its plugin dependencies -->
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
14 years, 5 months
[rhq] Branch 'raw-config' - modules/core
by John Sanda
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java | 26 ++--------
1 file changed, 7 insertions(+), 19 deletions(-)
New commits:
commit a6ef40107c68996f85a6d433c483657d11aed289
Author: John Sanda <john(a)localhost.localdomain>
Date: Fri Nov 27 12:05:11 2009 -0500
Refactoring tests to use common TestUtil class that now contains the serializeAndDeserialize() method that was formerly a private helper method.
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java
index 72da7c0..3da4922 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java
@@ -465,7 +465,7 @@ public class ConfigurationTest {
Configuration config = new Configuration();
config.setId(id);
- Configuration serializedConfig = serializeAndDeserialize(config);
+ Configuration serializedConfig = TestUtil.serializeAndDeserialize(config);
assertEquals(serializedConfig.getId(), id, "Failed to properly serialize the id property");
}
@@ -495,7 +495,7 @@ public class ConfigurationTest {
Configuration config = new Configuration();
config.put(new PropertySimple("x", "1"));
- Configuration serializedConfig = serializeAndDeserialize(config);
+ Configuration serializedConfig = TestUtil.serializeAndDeserialize(config);
assertEquals(serializedConfig.getMap(), config.getMap(), "Failed to property serialize the map property");
}
@@ -526,7 +526,7 @@ public class ConfigurationTest {
Configuration config = new Configuration();
config.setNotes("notes");
- Configuration serializedConfig = serializeAndDeserialize(config);
+ Configuration serializedConfig = TestUtil.serializeAndDeserialize(config);
assertEquals(serializedConfig.getNotes(), config.getNotes(), "Failed to properly serialize the notes property");
}
@@ -556,7 +556,7 @@ public class ConfigurationTest {
Configuration config = new Configuration();
config.setVersion(1L);
- Configuration serializedConfig = serializeAndDeserialize(config);
+ Configuration serializedConfig = TestUtil.serializeAndDeserialize(config);
assertEquals(
serializedConfig.getVersion(),
@@ -590,7 +590,7 @@ public class ConfigurationTest {
Configuration config = new Configuration();
updateModifiedTime(config);
- Configuration serializedConfig = serializeAndDeserialize(config);
+ Configuration serializedConfig = TestUtil.serializeAndDeserialize(config);
assertEquals(
@@ -625,7 +625,7 @@ public class ConfigurationTest {
Configuration config = new Configuration();
updateCreatedTime(config);
- Configuration serializedConfig = serializeAndDeserialize(config);
+ Configuration serializedConfig = TestUtil.serializeAndDeserialize(config);
assertEquals(
serializedConfig.getCreatedTime(),
@@ -660,7 +660,7 @@ public class ConfigurationTest {
config.addRawConfiguration(createRawConfiguration("/tmp/foo.txt"));
config.addRawConfiguration(createRawConfiguration("/tmp/bar.txt"));
- Configuration serializedConfig = serializeAndDeserialize(config);
+ Configuration serializedConfig = TestUtil.serializeAndDeserialize(config);
assertRawConfigurationsEquals(
serializedConfig.getRawConfigurations(),
@@ -677,16 +677,4 @@ public class ConfigurationTest {
config.onPersist();
}
- private Configuration serializeAndDeserialize(Configuration config) throws Exception {
- ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
- ObjectOutputStream ostream = new ObjectOutputStream(byteOutputStream);
-
- ostream.writeObject(config);
-
- ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteOutputStream.toByteArray());
- ObjectInputStream istream = new ObjectInputStream(byteInputStream);
-
- return (Configuration) istream.readObject();
- }
-
}
14 years, 5 months
[rhq] Branch 'ssh-install' - 33 commits - etc/eclipse-tools modules/core modules/enterprise modules/helpers
by mazz
etc/eclipse-tools/templates/schema.xmlcatalog | 8
modules/core/dbutils/pom.xml | 2
modules/core/dbutils/src/main/scripts/dbsetup/amps-schema.xml | 1
modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml | 165 +-
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java | 68
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/DeepCopyable.java | 2
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Property.java | 7
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java | 12
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java | 12
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertySimple.java | 30
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/RawConfiguration.java | 7
modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java | 93 -
modules/core/domain/src/main/java/org/rhq/core/domain/plugin/PluginStatusType.java | 29
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java | 111 +
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyListTest.java | 59
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyMapTest.java | 53
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertySimpleTest.java | 16
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java | 32
modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java | 134 +
modules/core/util/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java | 9
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java | 73
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java | 71
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java | 47
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java | 2
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml | 1
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml | 7
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml | 11
modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp | 775 +++++-----
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml | 24
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml | 27
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml | 15
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml | 8
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java | 23
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java | 315 +++-
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java | 88 -
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java | 16
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java | 79 -
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java | 16
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java | 50
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java | 359 ++++
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java | 16
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java | 9
modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java | 9
modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl | 5
45 files changed, 2091 insertions(+), 807 deletions(-)
New commits:
commit 36af4242ed2ec52213f62b68fb052cebbf138e93
Merge: 8ddbab0... db605e7...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Thu Nov 26 22:51:46 2009 -0500
Merge branch 'master' into ssh-install
commit db605e78ebfb82d01f0ce4130f327c45170540c7
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 17:18:29 2009 -0500
get rid of the update query we don't need anymore
fix tests so they don't rely on that old update query
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index eda26d8..4047d10 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -187,25 +187,6 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " LEFT JOIN p.scheduledJobsConfiguration " //
+ " WHERE p.deployment = 'SERVER' AND p.status = 'INSTALLED' "), //
- // this query does not update the content blob or ctime
- @NamedQuery(name = Plugin.UPDATE_ALL_BUT_CONTENT, query = "" //
- + "UPDATE Plugin p " //
- + " SET p.name = :name, " //
- + " p.displayName = :displayName, " //
- + " p.description = :description, " //
- + " p.enabled = :enabled, " //
- + " p.status = :status, " //
- + " p.help = :help, " //
- + " p.version = :version, " //
- + " p.ampsVersion = :ampsVersion," //
- + " p.deployment = :deployment, " //
- + " p.pluginConfiguration = :pluginConfiguration, " //
- + " p.scheduledJobsConfiguration = :scheduledJobsConfiguration, " //
- + " p.path = :path, " //
- + " p.md5 = :md5, " //
- + " p.mtime = :mtime " //
- + " WHERE p.id = :id"),
-
// this query is how you enable and disable plugins
@NamedQuery(name = Plugin.UPDATE_PLUGINS_ENABLED_BY_IDS, query = "" //
+ "UPDATE Plugin p " //
@@ -256,7 +237,6 @@ public class Plugin implements Serializable {
public static final String QUERY_FIND_BY_IDS_AND_TYPE = "Plugin.findByIdsAndType";
public static final String QUERY_GET_NAMES_BY_ENABLED_AND_TYPE = "Plugin.findByEnabledAndType";
public static final String QUERY_GET_STATUS_BY_NAME_AND_TYPE = "Plugin.getStatusByNameAndType";
- public static final String UPDATE_ALL_BUT_CONTENT = "Plugin.updateAllButContent";
public static final String UPDATE_PLUGINS_ENABLED_BY_IDS = "Plugin.updatePluginsEnabledByIds";
@Column(name = "ID", nullable = false)
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index 07f8f97..729f7c2 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -131,23 +131,39 @@ public class PluginTest extends AbstractEJB3Test {
em.persist(jobsConfig);
em.flush(); // gotta get those two persists to flush to the DB
- q = em.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
- q.setParameter("id", id); // same as the one we just persisted
- q.setParameter("name", name);
- q.setParameter("path", path);
- q.setParameter("displayName", displayName);
- q.setParameter("enabled", enabled);
- q.setParameter("status", status);
- q.setParameter("md5", md5);
- q.setParameter("version", version);
- q.setParameter("ampsVersion", ampsVersion);
- q.setParameter("deployment", deployment);
- q.setParameter("pluginConfiguration", pluginConfig);
- q.setParameter("scheduledJobsConfiguration", jobsConfig);
- q.setParameter("description", description);
- q.setParameter("help", help);
- q.setParameter("mtime", System.currentTimeMillis());
- assert q.executeUpdate() == 1 : "Failed to update the plugin";
+ // do what ServerPluginsBean/ResourceMetadataManagerBean.updateServerPluginExceptContent does
+ Configuration config = plugin.getPluginConfiguration();
+ if (config != null) {
+ config = em.merge(config);
+ plugin.setPluginConfiguration(config);
+ }
+ config = plugin.getScheduledJobsConfiguration();
+ if (config != null) {
+ config = em.merge(config);
+ plugin.setScheduledJobsConfiguration(config);
+ }
+
+ Plugin pluginEntity = em.getReference(Plugin.class, plugin.getId());
+ pluginEntity.setName(name);
+ pluginEntity.setPath(path);
+ pluginEntity.setDisplayName(displayName);
+ pluginEntity.setEnabled(enabled);
+ pluginEntity.setStatus(status);
+ pluginEntity.setMd5(md5);
+ pluginEntity.setVersion(version);
+ pluginEntity.setAmpsVersion(ampsVersion);
+ pluginEntity.setDeployment(deployment);
+ pluginEntity.setPluginConfiguration(pluginConfig);
+ pluginEntity.setScheduledJobsConfiguration(jobsConfig);
+ pluginEntity.setDescription(description);
+ pluginEntity.setHelp(help);
+ pluginEntity.setMtime(System.currentTimeMillis());
+
+ try {
+ em.flush(); // make sure we push this out to the DB now
+ } catch (Exception e) {
+ throw new Exception("Failed to update a plugin that matches [" + plugin + "]", e);
+ }
em.close();
getTransactionManager().commit(); // must commit now
@@ -163,7 +179,7 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.isEnabled() == enabled;
assert plugin.getMD5().equals(md5);
assert plugin.getVersion().equals(version);
- q.setParameter("ampsVersion", ampsVersion);
+ assert plugin.getAmpsVersion().equals(ampsVersion);
assert plugin.getDescription().equals(description);
assert plugin.getDeployment() == PluginDeploymentType.SERVER;
assert plugin.getPluginConfiguration().equals(pluginConfig);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
index 9c971e0..d502f4e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
@@ -198,49 +198,38 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
entityManager.persist(plugin);
} else {
// agent plugins don't support these configs, but if/when they do in the future, this will support it
- boolean needFlush = false;
+ // make sure we create (if necessary) and attach the configs
Configuration config = plugin.getPluginConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setPluginConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
+ config = entityManager.merge(config);
+ plugin.setPluginConfiguration(config);
}
config = plugin.getScheduledJobsConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setScheduledJobsConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
- }
- if (needFlush) {
- entityManager.flush(); // must be flushed to the DB so the JPQL update below works
+ config = entityManager.merge(config);
+ plugin.setScheduledJobsConfiguration(config);
}
// update all the fields except content
- Query q = entityManager.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
- q.setParameter("id", plugin.getId());
- q.setParameter("name", plugin.getName());
- q.setParameter("path", plugin.getPath());
- q.setParameter("displayName", plugin.getDisplayName());
- q.setParameter("enabled", plugin.isEnabled());
- q.setParameter("status", plugin.getStatus());
- q.setParameter("md5", plugin.getMD5());
- q.setParameter("version", plugin.getVersion());
- q.setParameter("ampsVersion", plugin.getAmpsVersion());
- q.setParameter("deployment", plugin.getDeployment());
- q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
- q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
- q.setParameter("description", plugin.getDescription());
- q.setParameter("help", plugin.getHelp());
- q.setParameter("mtime", plugin.getMtime());
- if (q.executeUpdate() != 1) {
+ Plugin pluginEntity = entityManager.getReference(Plugin.class, plugin.getId());
+ pluginEntity.setName(plugin.getName());
+ pluginEntity.setPath(plugin.getPath());
+ pluginEntity.setDisplayName(plugin.getDisplayName());
+ pluginEntity.setEnabled(plugin.isEnabled());
+ pluginEntity.setStatus(plugin.getStatus());
+ pluginEntity.setMd5(plugin.getMD5());
+ pluginEntity.setVersion(plugin.getVersion());
+ pluginEntity.setAmpsVersion(plugin.getAmpsVersion());
+ pluginEntity.setDeployment(plugin.getDeployment());
+ pluginEntity.setPluginConfiguration(plugin.getPluginConfiguration());
+ pluginEntity.setScheduledJobsConfiguration(plugin.getScheduledJobsConfiguration());
+ pluginEntity.setDescription(plugin.getDescription());
+ pluginEntity.setHelp(plugin.getHelp());
+ pluginEntity.setMtime(plugin.getMtime());
+
+ try {
+ entityManager.flush(); // make sure we push this out to the DB now
+ } catch (Exception e) {
throw new Exception("Failed to update a plugin that matches [" + plugin + "]");
}
}
commit dfd17347dd6d8c2707bfab6ced27bd44b66f9120
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 16:42:23 2009 -0500
fix the update method so it can handle the config updates
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index ff7d6ca..49d6e53 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -383,56 +383,39 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (plugin.getId() == 0) {
throw new IllegalArgumentException("Plugin must already exist to update it");
} else {
- // make sure the configs are in the DB properly and we have their refs
- // this is because we are using JPQL update, so we need to do some of this "manually"
- boolean needFlush = false;
+ // make sure we create (if necessary) and attach the configs
Configuration config = plugin.getPluginConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setPluginConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
+ config = entityManager.merge(config);
+ plugin.setPluginConfiguration(config);
}
config = plugin.getScheduledJobsConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setScheduledJobsConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
- }
- if (needFlush) {
- entityManager.flush(); // must be flushed to the DB so the JPQL update below works
+ config = entityManager.merge(config);
+ plugin.setScheduledJobsConfiguration(config);
}
- // now we can JPQL update the row - all but content is updated here.
- // we assured our configs are persisted/attached above
- Query q = entityManager.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
- q.setParameter("id", plugin.getId());
- q.setParameter("name", plugin.getName());
- q.setParameter("path", plugin.getPath());
- q.setParameter("displayName", plugin.getDisplayName());
- q.setParameter("enabled", plugin.isEnabled());
- q.setParameter("status", plugin.getStatus());
- q.setParameter("md5", plugin.getMD5());
- q.setParameter("version", plugin.getVersion());
- q.setParameter("ampsVersion", plugin.getAmpsVersion());
- q.setParameter("deployment", plugin.getDeployment());
- q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
- q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
- q.setParameter("description", plugin.getDescription());
- q.setParameter("help", plugin.getHelp());
- q.setParameter("mtime", plugin.getMtime());
- if (q.executeUpdate() != 1) {
- throw new Exception("Failed to update a plugin that matches [" + plugin + "]");
- }
+ Plugin pluginEntity = entityManager.getReference(Plugin.class, plugin.getId());
+ pluginEntity.setName(plugin.getName());
+ pluginEntity.setPath(plugin.getPath());
+ pluginEntity.setDisplayName(plugin.getDisplayName());
+ pluginEntity.setEnabled(plugin.isEnabled());
+ pluginEntity.setStatus(plugin.getStatus());
+ pluginEntity.setMd5(plugin.getMD5());
+ pluginEntity.setVersion(plugin.getVersion());
+ pluginEntity.setAmpsVersion(plugin.getAmpsVersion());
+ pluginEntity.setDeployment(plugin.getDeployment());
+ pluginEntity.setPluginConfiguration(plugin.getPluginConfiguration());
+ pluginEntity.setScheduledJobsConfiguration(plugin.getScheduledJobsConfiguration());
+ pluginEntity.setDescription(plugin.getDescription());
+ pluginEntity.setHelp(plugin.getHelp());
+ pluginEntity.setMtime(plugin.getMtime());
- entityManager.flush(); // make sure we push this out to the DB now
+ try {
+ entityManager.flush(); // make sure we push this out to the DB now
+ } catch (Exception e) {
+ throw new Exception("Failed to update a plugin that matches [" + plugin + "]", e);
+ }
}
return plugin;
}
commit aadfbe12066b4cab890bc04fbd9a55c76df87fb4
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 13:19:15 2009 -0500
provide an API to get a list of all enabled and disabled plugins grouped by their type
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java
index a79dff5..bbeb84c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java
@@ -42,7 +42,7 @@ public class ContentManagerHelper {
}
MasterServerPluginContainer master = mbean.getMasterPluginContainer();
- pc = master.getPluginContainer(ContentServerPluginContainer.class);
+ pc = master.getPluginContainerByClass(ContentServerPluginContainer.class);
} catch (IllegalStateException ise) {
throw ise;
} catch (Exception e) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 2d67f3f..ff7d6ca 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -26,7 +26,9 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import javax.ejb.EJB;
import javax.ejb.Stateless;
@@ -54,6 +56,7 @@ import org.rhq.enterprise.server.authz.RequiredPermission;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
@@ -173,7 +176,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
String pluginName = doomedPlugin.getName();
doomedPlugins.add(pluginName);
if (master != null) {
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(pluginName);
+ AbstractTypeServerPluginContainer pc = master.getPluginContainerByPlugin(pluginName);
if (pc != null) {
try {
pc.unschedulePluginJobs(pluginName);
@@ -216,7 +219,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
String pluginName = doomedPlugin.getName();
doomedPlugins.add(pluginName);
if (master != null) {
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(pluginName);
+ AbstractTypeServerPluginContainer pc = master.getPluginContainerByPlugin(pluginName);
if (pc != null) {
try {
pc.unschedulePluginJobs(pluginName);
@@ -447,6 +450,27 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return status;
}
+ // we need this method to talk to the master plugin container because the plugin data model
+ // does not contain information as to what type a plugin is. It only has information about
+ // where the plugin is deployed (agent or server) but it doesn't indicate if a plugin
+ // if of type "alert plugin" or "generic plugin". That is only known when the plugin descriptor
+ // is parsed, which happens when the master plugin container is initialized. Therefore, this
+ // needs to get plugin info from the master plugin container while the master is running.
+ public Map<ServerPluginType, List<String>> getAllPluginsGroupedByType() {
+ Map<ServerPluginType, List<String>> allPlugins = new HashMap<ServerPluginType, List<String>>();
+
+ MasterServerPluginContainer master = LookupUtil.getServerPluginService().getMasterPluginContainer();
+ if (master != null) {
+ List<ServerPluginType> types = master.getServerPluginTypes();
+ for (ServerPluginType type : types) {
+ List<String> plugins = master.getAllPluginsByPluginType(type);
+ allPlugins.put(type, plugins);
+ }
+ }
+
+ return allPlugins;
+ }
+
/**
* This will write the contents of the given plugin file to the database.
* This will assume the MD5 in the database is already correct, so this
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index df685d4..a6a09bf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -2,6 +2,7 @@ package org.rhq.enterprise.server.plugin;
import java.io.File;
import java.util.List;
+import java.util.Map;
import javax.ejb.Local;
import javax.persistence.NoResultException;
@@ -9,6 +10,7 @@ import javax.persistence.NoResultException;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginStatusType;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
@@ -173,4 +175,13 @@ public interface ServerPluginsLocal {
* <code>null</code> indicates an unknown plugin.
*/
PluginStatusType getServerPluginStatus(String pluginName);
+
+ /**
+ * This will return a map containing all plugins currently known to the master plugin container.
+ * This will return installed plugins that are both enabled and disabled.
+ * Note that if the master plugin container is not running, an empty map is returned.
+ *
+ * @return names of all enabled and disabled plugins, keyed on their types
+ */
+ Map<ServerPluginType, List<String>> getAllPluginsGroupedByType();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index 8ebabd4..4ab3fb2 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -21,6 +21,7 @@ package org.rhq.enterprise.server.plugin.pc;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -46,11 +47,22 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
public class MasterServerPluginContainer {
private static final Log log = LogFactory.getLog(MasterServerPluginContainer.class);
+ /** The configuration for the master plugin container itself. */
private MasterServerPluginContainerConfiguration configuration;
+
+ /** the plugin containers for all the different types of plugins that are supported */
private Map<ServerPluginType, AbstractTypeServerPluginContainer> pluginContainers = new HashMap<ServerPluginType, AbstractTypeServerPluginContainer>();
+
+ /** the object that provides all the classloaders for all plugins */
private ClassLoaderManager classLoaderManager;
/**
+ * Because the individual plugin containers are only managing enabled plugins (they are never told about plugins that disabled).
+ * this map contains the lists of plugins that are disabled so others can find out what plugins are registered but not running.
+ */
+ private Map<ServerPluginType, List<String>> disabledPlugins = new HashMap<ServerPluginType, List<String>>();
+
+ /**
* Starts the master plugin container, which will load all plugins and begin managing them.
*
* @param config the master configuration
@@ -188,6 +200,7 @@ public class MasterServerPluginContainer {
}
this.pluginContainers.clear();
+ this.disabledPlugins.clear();
this.classLoaderManager = null;
this.configuration = null;
@@ -238,6 +251,55 @@ public class MasterServerPluginContainer {
}
/**
+ * Given a plugin type, this will return the names of all known plugins of that type.
+ * This includes all types that are currently started as well as plugins
+ * that have been disabled.
+ *
+ * If the master plugin container has not been started, this returns an empty list.
+ *
+ * @param pluginType
+ *
+ * @return list of both enabled and disabled plugins of the given type
+ */
+ public List<String> getAllPluginsByPluginType(ServerPluginType pluginType) {
+ List<String> allPlugins = new ArrayList<String>();
+
+ AbstractTypeServerPluginContainer pc = getPluginContainerByPluginType(pluginType);
+ if (pc != null) {
+ // add the enabled plugins
+ ServerPluginManager pluginManager = pc.getPluginManager();
+ if (pluginManager != null) {
+ Collection<ServerPluginEnvironment> envs = pluginManager.getPluginEnvironments();
+ if (envs != null) {
+ for (ServerPluginEnvironment env : envs) {
+ allPlugins.add(env.getPluginName());
+ }
+ }
+ }
+
+ // add the disabled plugins
+ List<String> disabled = this.disabledPlugins.get(pluginType);
+ if (disabled != null) {
+ allPlugins.addAll(disabled);
+ }
+ }
+
+ return allPlugins;
+ }
+
+ /**
+ * This will return all known server plugins types. These are the types of plugins
+ * that are supported by a server plugin container. You can obtain the server
+ * plugin container that manages a particular server plugin type via
+ * {@link #getPluginContainerByPluginType(ServerPluginType)}.
+ *
+ * @return all known server plugin types
+ */
+ public synchronized List<ServerPluginType> getServerPluginTypes() {
+ return new ArrayList<ServerPluginType>(this.pluginContainers.keySet());
+ }
+
+ /**
* Get the plugin container of the given class. This method provides a strongly typed return value,
* based on the type of plugin container the caller wants returned.
*
@@ -245,7 +307,7 @@ public class MasterServerPluginContainer {
* @return the plugin container of the given class (<code>null</code> if none found)
*/
@SuppressWarnings("unchecked")
- public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainer(Class<T> clazz) {
+ public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainerByClass(Class<T> clazz) {
for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
if (clazz.isInstance(pc)) {
return (T) pc;
@@ -262,7 +324,7 @@ public class MasterServerPluginContainer {
* @param pluginName
* @return the plugin container that is managing the named plugin of <code>null</code>
*/
- public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainer(String pluginName) {
+ public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainerByPlugin(String pluginName) {
for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
if (null != pc.getPluginManager().getPluginEnvironment(pluginName)) {
return (T) pc;
@@ -319,7 +381,7 @@ public class MasterServerPluginContainer {
if (pluginFiles != null) {
- List<String> disabledPlugins = getDisabledPluginNames();
+ List<String> allDisabledPlugins = getDisabledPluginNames();
for (File pluginFile : pluginFiles) {
if (pluginFile.getName().endsWith(".jar")) {
@@ -329,12 +391,19 @@ public class MasterServerPluginContainer {
ServerPluginDescriptorType descriptor;
descriptor = ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginUrl);
if (descriptor != null) {
- if (!disabledPlugins.contains(descriptor.getName())) {
+ if (!allDisabledPlugins.contains(descriptor.getName())) {
log.debug("pre-loaded server plugin from URL: " + pluginUrl);
plugins.put(pluginUrl, descriptor);
} else {
log.info("Server plugin [" + descriptor.getName()
+ "] is disabled and will not be initialized");
+ ServerPluginType pluginType = new ServerPluginType(descriptor);
+ List<String> disabledByType = this.disabledPlugins.get(pluginType);
+ if (disabledByType == null) {
+ disabledByType = new ArrayList<String>(1);
+ this.disabledPlugins.put(pluginType, disabledByType);
+ }
+ disabledByType.add(descriptor.getName());
}
}
} catch (Throwable t) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
index feba2fc..3e6bb34 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
@@ -29,6 +29,22 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
public class ServerPluginType {
private final Class<? extends ServerPluginDescriptorType> descriptorType;
+ /**
+ * Given an actual plugin descriptor object, this will create a plugin type
+ * that represents that kind of plugin.
+ *
+ * @param descriptor an actual descriptor parsed from a plugin
+ */
+ public ServerPluginType(ServerPluginDescriptorType descriptor) {
+ this((descriptor != null) ? descriptor.getClass() : null);
+ }
+
+ /**
+ * Given a type of plugin descriptor, this will create a plugin type
+ * that represents that kind of plugin.
+ *
+ * @param descriptorType
+ */
public ServerPluginType(Class<? extends ServerPluginDescriptorType> descriptorType) {
if (descriptorType == null) {
throw new NullPointerException("descriptorType must not be null");
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
index 1dace0b..9f0026b 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
@@ -23,6 +23,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.List;
+import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
@@ -32,12 +33,16 @@ import org.testng.annotations.Test;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.State;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericPluginManager;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener.LifecycleState;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.generic.GenericPluginDescriptorType;
@Test
public class GenericServerPluginTest extends AbstractEJB3Test {
@@ -76,10 +81,21 @@ public class GenericServerPluginTest extends AbstractEJB3Test {
List<ScheduledJobDefinition> schedules = component.context.getSchedules();
assert schedules == null;
+ ServerPluginsLocal serverPluginsLocal = LookupUtil.getServerPlugins();
+ Map<ServerPluginType, List<String>> map = serverPluginsLocal.getAllPluginsGroupedByType();
+ assert map.size() == 1;
+ List<String> pluginNames = map.get(new ServerPluginType(GenericPluginDescriptorType.class));
+ assert pluginNames.size() == 1;
+ assert pluginNames.get(0).equals("TestSimpleGenericPlugin");
+
// make sure everything is shutdown
this.pluginService.stopMasterPluginContainer();
assert pc.state == State.UNINITIALIZED;
assert component.state == LifecycleState.UNINITIALIZED;
+
+ // with the master down, this method should return an empty map
+ map = serverPluginsLocal.getAllPluginsGroupedByType();
+ assert map.size() == 0;
}
private File createPluginJar(String jarName, String descriptorXmlFilename) throws Exception {
commit 07ae93f34338458daa75082ef519b4b1851ddc0c
Merge: 5e17b2f... 2d97557...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 11:08:38 2009 -0500
Merge branch 'master' into pc
commit 2d97557a1e09ab13248f5da0e81a8d530731ed78
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 11:03:16 2009 -0500
Eagerly initializing underlying list and map in PropertyList and PropertyMap to avoid NPEs
This change was already made in the raw-config branch a while back, and needed to be
ported over.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
index 2bc77f9..c3e26a0 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
@@ -68,7 +68,7 @@ public class PropertyList extends Property {
@Cascade( { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.DELETE_ORPHAN })
@OneToMany(mappedBy = "parentList", targetEntity = Property.class, fetch = FetchType.EAGER)
//@IndexColumn(name = "list_index") TODO GH: This seems broken
- private List<Property> list;
+ private List<Property> list = new ArrayList<Property>();
@Transient
String memberPropertyName;
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
index 114720f..e8e15b7 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
@@ -68,7 +68,7 @@ public class PropertyMap extends Property implements AbstractPropertyMap {
@Cascade( { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.DELETE_ORPHAN })
@MapKey(name = "name")
@OneToMany(mappedBy = "parentMap", fetch = FetchType.EAGER)
- private Map<String, Property> map;
+ private Map<String, Property> map = new LinkedHashMap<String, Property>();
/**
* Creates a new unnamed and empty {@link PropertyMap} object.
commit 5e17b2f3837504924ab1ec1b7ba48d017f258ef2
Merge: 45e0f2f... ee2e8e8...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 10:17:56 2009 -0500
Merge branch 'master' into pc
commit 45e0f2f25b7230d65bc561bc63bd1e1cdd7c65f8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 10:15:39 2009 -0500
use the new deepCopy()
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 8cbffc9..2d67f3f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -96,13 +96,13 @@ public class ServerPluginsBean implements ServerPluginsLocal {
Configuration config = plugin.getPluginConfiguration();
if (config != null) {
config = entityManager.find(Configuration.class, config.getId());
- plugin.setPluginConfiguration(config.deepCopyWithoutProxies());
+ plugin.setPluginConfiguration(config.deepCopy());
}
config = plugin.getScheduledJobsConfiguration();
if (config != null) {
config = entityManager.find(Configuration.class, config.getId());
- plugin.setScheduledJobsConfiguration(config.deepCopyWithoutProxies());
+ plugin.setScheduledJobsConfiguration(config.deepCopy());
}
return plugin;
commit b3a962cfa61b2f05b4258b9a25e6e72819473191
Merge: c995032... 37bb080...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 09:57:31 2009 -0500
Merge branch 'master' into pc
commit ee2e8e847b18491a6093135b6ca906d6063679de
Merge: 1bca0f7... 37bb080...
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 09:54:22 2009 -0500
Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq
commit 1bca0f7c0327498c0dcb7ccb5953d3158c83a563
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 09:53:41 2009 -0500
Fixing compilation error that happened as a result of my refactoring RawConfiguration.deepCopy()
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java
index a4ce93b..491612a 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java
@@ -165,7 +165,7 @@ public class RawConfigCollection implements Serializable {
String u2 = updated.substring(2);
String original = new String(getCurrent().getContents());
if (!u2.equals(original)) {
- current = current.deepCopy();
+ current = current.deepCopy(false);
current.setContents(updated.getBytes());
//TODO update other values like MD5
modified.put(current.getPath(), current);
commit c995032cbc61261e353c523259810d076d586519
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 09:51:34 2009 -0500
fix NPE when plugin config or scheduled jobs config is null
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 1415bb5..8cbffc9 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -93,12 +93,17 @@ public class ServerPluginsBean implements ServerPluginsLocal {
public Plugin getServerPluginRelationships(Plugin plugin) {
plugin = getServerPlugin(plugin.getName()); // refresh all but the content field
- int pluginConfigId = plugin.getPluginConfiguration().getId();
- int scheduledJobsId = plugin.getScheduledJobsConfiguration().getId();
- Configuration pluginConfig = entityManager.find(Configuration.class, pluginConfigId);
- Configuration scheduledJobs = entityManager.find(Configuration.class, scheduledJobsId);
- plugin.setPluginConfiguration(pluginConfig.deepCopyWithoutProxies());
- plugin.setScheduledJobsConfiguration(scheduledJobs.deepCopyWithoutProxies());
+ Configuration config = plugin.getPluginConfiguration();
+ if (config != null) {
+ config = entityManager.find(Configuration.class, config.getId());
+ plugin.setPluginConfiguration(config.deepCopyWithoutProxies());
+ }
+
+ config = plugin.getScheduledJobsConfiguration();
+ if (config != null) {
+ config = entityManager.find(Configuration.class, config.getId());
+ plugin.setScheduledJobsConfiguration(config.deepCopyWithoutProxies());
+ }
return plugin;
}
@@ -239,7 +244,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
File currentFile = new File(pluginDir, doomedPlugin.getPath());
currentFile.delete();
} catch (Exception e) {
- log.error("Failed to delete the undeployed plugin [" + doomedPlugin.getPath() + "]. Cause: " + ThrowableUtil.getAllMessages(e));
+ log.error("Failed to delete the undeployed plugin [" + doomedPlugin.getPath() + "]. Cause: "
+ + ThrowableUtil.getAllMessages(e));
}
}
}
@@ -275,7 +281,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
@RequiredPermission(Permission.MANAGE_SETTINGS)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void setServerPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status)
- throws Exception {
+ throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
return; // nothing to do
}
@@ -291,7 +297,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
public Plugin registerServerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception {
if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
- throw new IllegalArgumentException("Plugin [" + plugin.getName() + "] must be a server plugin to be registered");
+ throw new IllegalArgumentException("Plugin [" + plugin.getName()
+ + "] must be a server plugin to be registered");
}
Plugin existingPlugin = null;
@@ -304,7 +311,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (existingPlugin != null) {
if (existingPlugin.getStatus() == PluginStatusType.DELETED) {
- throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName() + "], it has been marked as deleted");
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
+ + "], it has been marked as deleted");
}
Plugin obsolete = ServerPluginDescriptorUtil.determineObsoletePlugin(plugin, existingPlugin);
if (obsolete == existingPlugin) { // yes use == for reference equality
@@ -322,7 +330,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (plugin.getId() == 0) {
PluginStatusType status = getServerPluginStatus(plugin.getName());
if (PluginStatusType.DELETED == status) {
- throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName() + "], it has been previously marked as deleted.");
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
+ + "], it has been previously marked as deleted.");
}
entityManager.persist(plugin);
} else {
@@ -364,7 +373,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
// to entityManager.merge that plugin POJO, it would null out that blob column.
if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
- throw new IllegalArgumentException("Plugin [" + plugin.getName() + "] must be a server plugin to be updated");
+ throw new IllegalArgumentException("Plugin [" + plugin.getName()
+ + "] must be a server plugin to be updated");
}
if (plugin.getId() == 0) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index 803f7cf..df685d4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -42,6 +42,7 @@ public interface ServerPluginsLocal {
*
* @param plugin
* @return the same plugin, with the relationship data loaded
+ * @throws NoResultException when no plugin with that name exists
*/
Plugin getServerPluginRelationships(Plugin plugin);
commit 37bb080675c956c976ffc3110361c11e19ae87a0
Author: Galder Zamarreno <rnd(a)zamarreno.com>
Date: Wed Nov 25 15:20:34 2009 +0100
Operation returns only one result now.
diff --git a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
index 0388d8a..a657f42 100644
--- a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
+++ b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
@@ -527,7 +527,7 @@ public class Props {
private String displayName;
private String description;
private Set<SimpleProperty> params = new LinkedHashSet<SimpleProperty>();
- private Set<SimpleProperty> results = new LinkedHashSet<SimpleProperty>();
+ private SimpleProperty result;
public OperationProps(String name) {
this.name = name;
@@ -557,8 +557,12 @@ public class Props {
return params;
}
- public Set<SimpleProperty> getResults() {
- return results;
+ public SimpleProperty getResult() {
+ return result;
+ }
+
+ public void setResult(SimpleProperty result) {
+ this.result = result;
}
}
}
diff --git a/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl b/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
index ca498b5..0343787 100644
--- a/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
+++ b/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
@@ -60,11 +60,9 @@ name="${props.name}" <#-- TODO separate out plugin name and service name -->
</#list>
</parameters>
</#if>
- <#if operation.results?has_content>
+ <#if operation.result??>
<results>
- <#list operation.results as results>
- <c:simple-property name="${results.name}" />
- </#list>
+ <c:simple-property name="${operation.result.name}" />
</results>
</#if>
</operation>
commit cc1b2af501010b1734b42d4a70e30a43db65d3ee
Author: Galder Zamarreno <rnd(a)zamarreno.com>
Date: Wed Nov 25 14:37:33 2009 +0100
Returns for operations can now be generated.
diff --git a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
index 76b374b..0388d8a 100644
--- a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
+++ b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
@@ -527,6 +527,7 @@ public class Props {
private String displayName;
private String description;
private Set<SimpleProperty> params = new LinkedHashSet<SimpleProperty>();
+ private Set<SimpleProperty> results = new LinkedHashSet<SimpleProperty>();
public OperationProps(String name) {
this.name = name;
@@ -555,5 +556,9 @@ public class Props {
public Set<SimpleProperty> getParams() {
return params;
}
+
+ public Set<SimpleProperty> getResults() {
+ return results;
+ }
}
}
diff --git a/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl b/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
index a148a61..ca498b5 100644
--- a/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
+++ b/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
@@ -60,6 +60,13 @@ name="${props.name}" <#-- TODO separate out plugin name and service name -->
</#list>
</parameters>
</#if>
+ <#if operation.results?has_content>
+ <results>
+ <#list operation.results as results>
+ <c:simple-property name="${results.name}" />
+ </#list>
+ </results>
+ </#if>
</operation>
</#list>
<#else>
commit a0ab1b28c3ef8ab152c4decf9e8dbaebbede80dd
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 00:08:22 2009 -0500
Deleting directory that accidentally included in a previous commit
diff --git a/modules/core/domain/src/main/java/META-INF/MANIFEST.MF b/modules/core/domain/src/main/java/META-INF/MANIFEST.MF
deleted file mode 100644
index 3090f97..0000000
--- a/modules/core/domain/src/main/java/META-INF/MANIFEST.MF
+++ /dev/null
@@ -1,4 +0,0 @@
-Manifest-Version: 1.0
-Class-Path: i18nlog-1.0.9.jar jaxb-api-2.1.jar stax-api-1.0-2.jar acti
- vation-1.1.jar rhq-core-util-1.4.0-SNAPSHOT.jar jdom-1.0.jar
-
commit 1643800fb94b472d11bedc1d5d4d756b4ad54ee0
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 00:07:18 2009 -0500
[US 6] Refactoring Configuration.deepCopy() to properly handle hibernate proxies.
Refactoring implementors of DeepCopyable to take a boolean flag that indicates
whether or not to copy the id field. Unit tests have been updated to reflect the change.
Conflicts:
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java
diff --git a/modules/core/domain/src/main/java/META-INF/MANIFEST.MF b/modules/core/domain/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..3090f97
--- /dev/null
+++ b/modules/core/domain/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,4 @@
+Manifest-Version: 1.0
+Class-Path: i18nlog-1.0.9.jar jaxb-api-2.1.jar stax-api-1.0-2.jar acti
+ vation-1.1.jar rhq-core-util-1.4.0-SNAPSHOT.jar jdom-1.0.jar
+
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
index 3ce2965..62bd8ce 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
@@ -454,55 +454,40 @@ public class Configuration implements Externalizable, Cloneable, AbstractPropert
* @return the new copy
*/
public Configuration deepCopy(boolean keepIds) {
- Configuration copy;
+ Configuration copy = new Configuration();
- try {
- copy = clone();
- } catch (CloneNotSupportedException e) {
- throw new RuntimeException("CloneNotSupported can't happen");
+ if (keepIds) {
+ copy.id = this.id;
}
- if (!keepIds) {
- copy.id = 0;
-
- for (Property property : copy.properties.values()) {
- clearIds(property);
- }
- }
+ copy.notes = this.notes;
+ copy.version = this.version;
+ createDeepCopyOfProperties(copy, keepIds);
+ createDeepCopyOfRawConfigs(copy, keepIds);
return copy;
}
- private void clearIds(Property property) {
- property.setId(0);
-
- if (property instanceof PropertyList) {
- for (Property childProperty : ((PropertyList) property).getList()) {
- clearIds(childProperty);
- }
- } else if (property instanceof PropertyMap) {
- for (Property childProperty : ((PropertyMap) property).getMap().values()) {
- clearIds(childProperty);
- }
- }
-
- return;
- }
-
public Configuration deepCopyWithoutProxies() {
Configuration copy = new Configuration();
copy.notes = this.notes;
copy.version = this.version;
+ createDeepCopyOfProperties(copy, false);
+ createDeepCopyOfRawConfigs(copy, false);
- for (Property property : this.properties.values()) {
- copy.put(property.deepCopy());
- }
+ return copy;
+ }
+ private void createDeepCopyOfRawConfigs(Configuration copy, boolean keepId) {
for (RawConfiguration rawConfig : rawConfigurations) {
- copy.addRawConfiguration(rawConfig.deepCopy());
+ copy.addRawConfiguration(rawConfig.deepCopy(keepId));
}
+ }
- return copy;
+ private void createDeepCopyOfProperties(Configuration copy, boolean keepId) {
+ for (Property property : this.properties.values()) {
+ copy.put(property.deepCopy(keepId));
+ }
}
/**
@@ -664,7 +649,22 @@ public class Configuration implements Externalizable, Cloneable, AbstractPropert
out.writeLong(version);
out.writeLong(ctime);
out.writeLong(mtime);
+ }
// Explicitly do not send the history relationship
+ private Map<String, Property> createDeepCopyOfMap() {
+ Map<String, Property> copy = new HashMap<String, Property>();
+ for (Map.Entry<String, Property> entry : this.properties.entrySet()) {
+ copy.put(entry.getKey(), entry.getValue().deepCopy(true));
+ }
+ return copy;
+ }
+
+ private Set<RawConfiguration> createDeepCopyOfRawConfigs() {
+ Set<RawConfiguration> copy = new HashSet<RawConfiguration>();
+ for (RawConfiguration rawConfig : this.rawConfigurations) {
+ copy.add(rawConfig.deepCopy(true));
+ }
+ return copy;
}
@SuppressWarnings("unchecked")
@@ -694,4 +694,4 @@ public class Configuration implements Externalizable, Cloneable, AbstractPropert
public Map<String, Property> getAllProperties() {
return this.properties;
}
-}
\ No newline at end of file
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/DeepCopyable.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/DeepCopyable.java
index e3e56d5..c680b04 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/DeepCopyable.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/DeepCopyable.java
@@ -25,6 +25,6 @@ package org.rhq.core.domain.configuration;
public interface DeepCopyable<T> {
- T deepCopy();
+ T deepCopy(boolean keepId);
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Property.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Property.java
index f4494c8..5c1ba79 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Property.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Property.java
@@ -127,7 +127,10 @@ public class Property implements Externalizable, DeepCopyable<Property> {
public Property() {
}
- protected Property(Property original) {
+ protected Property(Property original, boolean keepId) {
+ if (keepId) {
+ this.id = original.id;
+ }
this.errorMessage = original.errorMessage;
this.name = original.name;
}
@@ -284,7 +287,7 @@ public class Property implements Externalizable, DeepCopyable<Property> {
return ((this.name != null) ? this.name.hashCode() : 0);
}
- public Property deepCopy() {
+ public Property deepCopy(boolean keepId) {
return null;
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
index a2223d9..2bc77f9 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
@@ -86,8 +86,8 @@ public class PropertyList extends Property {
setName(name);
}
- protected PropertyList(PropertyList original) {
- super(original);
+ protected PropertyList(PropertyList original, boolean keepId) {
+ super(original, keepId);
}
/**
@@ -212,11 +212,11 @@ public class PropertyList extends Property {
return result;
}
- public PropertyList deepCopy() {
- PropertyList copy = new PropertyList(this);
+ public PropertyList deepCopy(boolean keepId) {
+ PropertyList copy = new PropertyList(this, keepId);
for (Property property : list) {
- copy.add(property.deepCopy());
+ copy.add(property.deepCopy(false));
}
return copy;
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
index 137c6fe..114720f 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
@@ -76,8 +76,8 @@ public class PropertyMap extends Property implements AbstractPropertyMap {
public PropertyMap() {
}
- protected PropertyMap(PropertyMap original) {
- super(original);
+ protected PropertyMap(PropertyMap original, boolean keepId) {
+ super(original, keepId);
}
/**
@@ -263,11 +263,11 @@ public class PropertyMap extends Property implements AbstractPropertyMap {
return result;
}
- public PropertyMap deepCopy() {
- PropertyMap copy = new PropertyMap(this);
+ public PropertyMap deepCopy(boolean keepId) {
+ PropertyMap copy = new PropertyMap(this, keepId);
for (Property property : map.values()) {
- copy.put(property.deepCopy());
+ copy.put(property.deepCopy(keepId));
}
return copy;
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 0824553..04aeb7e 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
@@ -70,8 +70,8 @@ public class PropertySimple extends Property implements Externalizable {
override = Boolean.FALSE;
}
- protected PropertySimple(PropertySimple original) {
- super(original);
+ protected PropertySimple(PropertySimple original, boolean keepId) {
+ super(original, keepId);
this.override = original.override;
this.unmaskedStringValue = original.unmaskedStringValue;
this.stringValue = original.stringValue;
@@ -85,9 +85,7 @@ public class PropertySimple extends Property implements Externalizable {
* @param name
* @param value
*/
- public PropertySimple(@NotNull
- String name, @Nullable
- Object value) {
+ public PropertySimple(@NotNull String name, @Nullable Object value) {
setName(name);
setValue(value);
}
@@ -98,8 +96,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setValue(@Nullable
- Object value) {
+ public void setValue(@Nullable Object value) {
if (value == null) {
stringValue = null;
return;
@@ -131,8 +128,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setStringValue(@Nullable
- String value) {
+ public void setStringValue(@Nullable String value) {
this.setValue(value);
}
@@ -157,8 +153,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setBooleanValue(@Nullable
- Boolean value) {
+ public void setBooleanValue(@Nullable Boolean value) {
this.setValue(value);
}
@@ -207,8 +202,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setIntegerValue(@Nullable
- Integer value) {
+ public void setIntegerValue(@Nullable Integer value) {
this.setValue(value);
}
@@ -232,8 +226,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setFloatValue(@Nullable
- Float value) {
+ public void setFloatValue(@Nullable Float value) {
this.setValue(value);
}
@@ -257,8 +250,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setDoubleValue(@Nullable
- Double value) {
+ public void setDoubleValue(@Nullable Double value) {
this.setValue(value);
}
@@ -336,8 +328,8 @@ public class PropertySimple extends Property implements Externalizable {
return result;
}
- public PropertySimple deepCopy() {
- return new PropertySimple(this);
+ public PropertySimple deepCopy(boolean keepId) {
+ return new PropertySimple(this, keepId);
}
@Override
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/RawConfiguration.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/RawConfiguration.java
index ca02070..22a7161 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/RawConfiguration.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/RawConfiguration.java
@@ -243,9 +243,14 @@ public class RawConfiguration implements Serializable, DeepCopyable<RawConfigura
.toString();
}
- public RawConfiguration deepCopy() {
+ public RawConfiguration deepCopy(boolean keepId) {
RawConfiguration copy = new RawConfiguration();
+ if (keepId) {
+ copy.id = this.id;
+ }
+
copy.path = this.path;
+
if (this.contents != null) {
copy.setContents(this.getContents());
}
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java
index 36084ec..85afc00 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java
@@ -38,59 +38,107 @@ import java.util.Set;
public class ConfigurationTest {
@Test
- public void deepCopyWithoutProxiesShouldNotReturnReferenceToOriginalObject() {
+ public void deepCopyShouldNotReturnReferenceToOriginalObjectWhenKeepingIds() {
Configuration original = createConfiguration();
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(true);
assertNotSame(copy, original, "Expected a reference to a new Configuration object, not the original object being copied");
}
@Test
- public void deepCopyWithoutProxiesShouldCopySimpleFields() {
+ public void deepCopyShouldNotReturnReferenceToOriginalObjectWhenNotKeepingIds() {
Configuration original = createConfiguration();
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
+ assertNotSame(copy, original, "Expected a reference to a new Configuration object, not the original object being copied");
+ }
+
+ @Test
+ public void deepCopyShouldCopyAllSimpleFieldsWhenKeepingIds() {
+ Configuration original = createConfiguration();
+ Configuration copy = original.deepCopy(true);
+
+ assertEquals(copy.getId(), original.getId(), "Failed to copy the id property");
assertEquals(copy.getNotes(), original.getNotes(), "Failed to copy the notes property");
assertEquals(copy.getVersion(), original.getVersion(), "Failed to copy version property");
}
@Test
- public void deepCopyWithoutProxiesShouldNotCopyIdProperty() {
+ public void deepCopyShouldNotCopyIdWhenNotKeepingIds() {
Configuration original = createConfiguration();
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
assertFalse(copy.getId() == original.getId(), "The original id property should not be copied");
+ assertEquals(copy.getNotes(), original.getNotes(), "Failed to copy the notes property");
+ assertEquals(copy.getVersion(), original.getVersion(), "Failed to copy version property");
+ }
+
+ @Test
+ public void deepCopyShouldCopyPropertiesWhenKeepingIds() {
+ Configuration original = createConfiguration();
+ original.put(new PropertySimple("simpleProperty", "Simple Property"));
+
+ Configuration copy = original.deepCopy(true);
+
+ assertNotSame(copy.getProperties(), original.getProperties(), "The properties property should not refer to the properties in the original object");
+ assertEquals(copy.getProperties(), original.getProperties(), "Failed to copy the contents of the properties collection");
}
@Test
- public void deepCopyWithoutProxiesShouldCopyProperties() {
+ public void deepCopyShouldCopyPropertiesWhenNotKeepingIds() {
Configuration original = createConfiguration();
original.put(new PropertySimple("simpleProperty", "Simple Property"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
assertNotSame(copy.getProperties(), original.getProperties(), "The properties property should not refer to the properties in the original object");
assertEquals(copy.getProperties(), original.getProperties(), "Failed to copy the contents of the properties collection");
}
@Test
- public void deepCopyWithoutProxiesShouldNotReturnCopyReferenceOfOriginalProperty() {
+ public void deepCopyShouldNotReturnCopyReferenceOfOriginalPropertyWhenKeepingIds() {
Configuration original = createConfiguration();
String propertyName = "simpleProperty";
original.put(new PropertySimple(propertyName, "Simple Property"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(true);
assertNotSame(copy.get(propertyName), original.get(propertyName), "Expected a refernce to a new property, not the original property being copied");
}
@Test
- public void deepCopyWithoutProxiesShouldSetParentReferenceOfCopiedProperties() {
+ public void deepCopyShouldNotReturnCopyReferenceOfOriginalPropertyWhenNotKeepingIds() {
+ Configuration original = createConfiguration();
+ String propertyName = "simpleProperty";
+ original.put(new PropertySimple(propertyName, "Simple Property"));
+
+ Configuration copy = original.deepCopy(false);
+
+ assertNotSame(copy.get(propertyName), original.get(propertyName), "Expected a refernce to a new property, not the original property being copied");
+ }
+
+ @Test
+ public void deepCopyShouldSetParentReferenceOfCopiedPropertiesWhenKeepingIds() {
+ Configuration original = createConfiguration();
+ String propertyName = "simpleProperty";
+ original.put(new PropertySimple(propertyName, "Simple Property"));
+
+ Configuration copy = original.deepCopy(true);
+
+ assertSame(
+ copy.get(propertyName).getConfiguration(),
+ copy,
+ "The reference to the parent configuration should point to the newly copied configuration, not the original configuration"
+ );
+ }
+
+ @Test
+ public void deepCopyShouldSetParentReferenceOfCopiedPropertiesWhenNotKeepingIds() {
Configuration original = createConfiguration();
String propertyName = "simpleProperty";
original.put(new PropertySimple(propertyName, "Simple Property"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
assertSame(
copy.get(propertyName).getConfiguration(),
@@ -100,11 +148,27 @@ public class ConfigurationTest {
}
@Test
- public void deepCopyWithoutProxiesShouldCopyRawConfigurations() {
+ public void deepCopyShouldCopyRawConfigurationsWhenKeepingIds() {
Configuration original = createConfiguration();
original.addRawConfiguration(createRawConfiguration("/tmp/foo"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(true);
+
+ assertNotSame(
+ copy.getRawConfigurations(),
+ original.getRawConfigurations(),
+ "The rawConfigurations property should not refer to the original rawConfigurations of the copied object."
+ );
+
+ assertRawConfigurationsEquals(copy.getRawConfigurations(), original.getRawConfigurations(), "Failed to copy rawConfigurations property.");
+ }
+
+ @Test
+ public void deepCopyShouldCopyRawConfigurationsWhenNotKeepingIds() {
+ Configuration original = createConfiguration();
+ original.addRawConfiguration(createRawConfiguration("/tmp/foo"));
+
+ Configuration copy = original.deepCopy(false);
assertNotSame(
copy.getRawConfigurations(),
@@ -123,11 +187,26 @@ public class ConfigurationTest {
}
@Test
- public void deepCopyWithoutProxiesShouldSetParentReferenceOfCopiedRawConfigurations() {
+ public void deepCopyShouldSetParentReferenceOfCopiedRawConfigurationsWhenKeepingIds() {
+ Configuration original = createConfiguration();
+ original.addRawConfiguration(createRawConfiguration("/tmp/foo"));
+
+ Configuration copy = original.deepCopy(true);
+ RawConfiguration copiedRawConfig = getCopiedRawConfiguration(copy);
+
+ assertSame(
+ copiedRawConfig.getConfiguration(),
+ copy,
+ "The reference to the parent configuration should point to the newly copied configuration, not the original configuration."
+ );
+ }
+
+ @Test
+ public void deepCopyShouldSetParentReferenceOfCopiedRawConfigurationsWhenNotKeepingIds() {
Configuration original = createConfiguration();
original.addRawConfiguration(createRawConfiguration("/tmp/foo"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
RawConfiguration copiedRawConfig = getCopiedRawConfiguration(copy);
assertSame(
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyListTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyListTest.java
index d298001..56d3887 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyListTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyListTest.java
@@ -30,41 +30,52 @@ import org.testng.annotations.Test;
public class PropertyListTest {
@Test
- public void deepCopyShouldCopySimpleFields() {
+ public void deepCopyShouldCopyAllSimpleFields() {
PropertyList original = createPropertyList();
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(true);
assertNotSame(copy, original, "The copy should not reference the original object");
-
+
+ assertEquals(copy.getId(), original.getId(), "Failed to copy the id property");
assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
}
@Test
- public void deepCopyShouldNotCopyIdField() {
+ public void deepCopyShouldNotCopyIdFieldWhenFlagIsFalse() {
PropertyList original = createPropertyList();
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(false);
assertFalse(copy.getId() == original.getId(), "The original id property should not be copied.");
+ assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
+ assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
+ }
+
+ @Test
+ public void deepCopyShouldNotCopyReferenceOfUnderlyingListWhenIdIncluded() {
+ PropertyList original = createPropertyList();
+ PropertyList copy = original.deepCopy(true);
+
+ assertNotSame(original.getList(), copy.getList(), "The values in the underlying list should be copied, not the variable reference to the list.");
}
@Test
- public void deepCopyShouldNotCopyReferenceOfUnderlyingList() {
+ public void deepCopyShouldNotCopyReferenceOfUnderlyingListWhenIdNotIncluded() {
PropertyList original = createPropertyList();
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(false);
assertNotSame(original.getList(), copy.getList(), "The values in the underlying list should be copied, not the variable reference to the list.");
}
@Test
- public void deepCopyShouldCopyProperty() {
+ public void deepCopyShouldCopyPropertyWhenIdIncluded() {
PropertyList original = createPropertyList();
PropertySimple simpleProperty = new PropertySimple("simeplProperty", "Simple Property");
original.add(simpleProperty);
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(true);
assertEquals(copy.getList().size(), original.getList().size(), "Failed to copy simple property contained in original property list");
@@ -72,13 +83,39 @@ public class PropertyListTest {
}
@Test
- public void deepCopyShouldSetParentOfCopiedProperty() {
+ public void deepCopyShouldCopyPropertyWhenIdNotIncluded() {
+ PropertyList original = createPropertyList();
+
+ PropertySimple simpleProperty = new PropertySimple("simeplProperty", "Simple Property");
+ original.add(simpleProperty);
+
+ PropertyList copy = original.deepCopy(false);
+
+ assertEquals(copy.getList().size(), original.getList().size(), "Failed to copy simple property contained in original property list");
+
+ assertNotSame(copy.getList().get(0), original.getList().get(0), "Properties in the list should be copied by value as opposed to just copying the references");
+ }
+
+ @Test
+ public void deepCopyShouldSetParentOfCopiedPropertyWhenIdIncluded() {
+ PropertyList original = createPropertyList();
+
+ PropertySimple simpleProperty = new PropertySimple("simpleProperty", "Simple Property");
+ original.add(simpleProperty);
+
+ PropertyList copy = original.deepCopy(true);
+
+ assertSame(copy.getList().get(0).getParentList(), copy, "The parentList property of copied properties should be set to the new PropertyList");
+ }
+
+ @Test
+ public void deepCopyShouldSetParentOfCopiedPropertyWhenIdNotIncluded() {
PropertyList original = createPropertyList();
PropertySimple simpleProperty = new PropertySimple("simpleProperty", "Simple Property");
original.add(simpleProperty);
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(false);
assertSame(copy.getList().get(0).getParentList(), copy, "The parentList property of copied properties should be set to the new PropertyList");
}
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyMapTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyMapTest.java
index 4a999b6..e73d835 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyMapTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyMapTest.java
@@ -30,40 +30,55 @@ import org.testng.annotations.Test;
public class PropertyMapTest {
@Test
- public void deepCopyShouldCopySimpleFields() {
+ public void deepCopyShouldCopyAllSimpleFields() {
PropertyMap original = createPropertyMap();
- PropertyMap copy = original.deepCopy();
+ PropertyMap copy = original.deepCopy(true);
assertNotSame(copy, original, "The copy should not reference the original object");
+ assertEquals(copy.getId(), original.getId(), "Failed to copy the id property");
assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
}
@Test
- public void deepCopyShouldNotCopyIdField() {
+ public void deepCopyShouldNotCopyIdFieldWhenFlagIsFalse() {
PropertyMap original = createPropertyMap();
- PropertyMap copy = original.deepCopy();
+ PropertyMap copy = original.deepCopy(false);
+
+ assertNotSame(copy, original, "The copy should not reference the original object");
assertFalse(copy.getId() == original.getId(), "The original id property should not be copied.");
+ assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
+ assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
}
@Test
- public void deepCopyShouldNotCopyReferenceOfUnderlyingMap() {
+ public void deepCopyShouldCopyPropertyWhenIdIncluded() {
PropertyMap original = createPropertyMap();
- PropertyMap copy = original.deepCopy();
- assertNotSame(copy.getMap(), original.getMap(), "The values in the underlying map should be copied, not the reference to the map itself");
+ PropertySimple simpleProperty = new PropertySimple("simeplProperty", "Simple Property");
+ original.put(simpleProperty);
+
+ PropertyMap copy = original.deepCopy(true);
+
+ assertEquals(copy.getMap().size(), original.getMap().size(), "Failed to copy simple property contained in original property map");
+
+ assertNotSame(
+ copy.getMap().get(simpleProperty.getName()),
+ original.getMap().get(simpleProperty.getName()),
+ "Properties in the map should be copied by value as opposed to just copying the references"
+ );
}
@Test
- public void deepCopyShouldCopyProperty() {
+ public void deepCopyShouldCopyPropertyWhenIdNotIncluded() {
PropertyMap original = createPropertyMap();
PropertySimple simpleProperty = new PropertySimple("simeplProperty", "Simple Property");
original.put(simpleProperty);
- PropertyMap copy = original.deepCopy();
+ PropertyMap copy = original.deepCopy(false);
assertEquals(copy.getMap().size(), original.getMap().size(), "Failed to copy simple property contained in original property map");
@@ -75,13 +90,29 @@ public class PropertyMapTest {
}
@Test
- public void deepCopyShouldSetParentOfCopiedProperty() {
+ public void deepCopyShouldSetParentOfCopiedPropertyWhenIdIncluded() {
+ PropertyMap original = createPropertyMap();
+
+ PropertySimple simpleProperty = new PropertySimple("simpleProperty", "Simple Property");
+ original.put(simpleProperty);
+
+ PropertyMap copy = original.deepCopy(true);
+
+ assertSame(
+ copy.get(simpleProperty.getName()).getParentMap(),
+ copy,
+ "The parentMap property of copied properties should be set to the new PropertyMap"
+ );
+ }
+
+ @Test
+ public void deepCopyShouldSetParentOfCopiedPropertyWhenIdNotIncluded() {
PropertyMap original = createPropertyMap();
PropertySimple simpleProperty = new PropertySimple("simpleProperty", "Simple Property");
original.put(simpleProperty);
- PropertyMap copy = original.deepCopy();
+ PropertyMap copy = original.deepCopy(false);
assertSame(
copy.get(simpleProperty.getName()).getParentMap(),
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertySimpleTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertySimpleTest.java
index c1b76aa..7b49837 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertySimpleTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertySimpleTest.java
@@ -30,13 +30,14 @@ import org.testng.annotations.Test;
public class PropertySimpleTest {
@Test
- public void deepCopyShouldCopySimpleFields() {
+ public void deepCopyShouldCopyAllSimpleFields() {
PropertySimple original = createProperty();
- PropertySimple copy = original.deepCopy();
+ PropertySimple copy = original.deepCopy(true);
assertNotSame(copy, original, "The copy should not reference the original object");
-
+
+ assertEquals(copy.getId(), original.getId(), "Failed to copy the id property");
assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
assertEquals(copy.getOverride(), original.getOverride(), "Failed to copy the override property");
@@ -45,12 +46,17 @@ public class PropertySimpleTest {
}
@Test
- public void deepCopyShouldNotCopyIdField() {
+ public void deepCopyShouldNotCopyIdFieldWhenFlagIsFalse() {
PropertySimple original = createProperty();
- PropertySimple copy = original.deepCopy();
+ PropertySimple copy = original.deepCopy(false);
assertFalse(copy.getId() == original.getId(), "The original id property should not be copied.");
+ assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
+ assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
+ assertEquals(copy.getOverride(), original.getOverride(), "Failed to copy the override property");
+ assertEquals(copy.getUnmaskedStringValue(), original.getUnmaskedStringValue(), "Failed to copy the unmaskedStringValue property");
+ assertEquals(copy.getStringValue(), original.getStringValue(), "Failed to copy the stringValue property");
}
private PropertySimple createProperty() {
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java
index fb926af..8f0aac8 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java
@@ -212,33 +212,49 @@ public class RawConfigurationTest {
}
@Test
- public void deepCopyShouldCopyPath() {
+ public void deepCopyShouldCopyPathAndIdWhenIdIncluded() {
RawConfiguration original = new RawConfiguration();
original.setPath("/tmp/foo");
+ original.setId(-1);
- RawConfiguration copy = original.deepCopy();
+ RawConfiguration copy = original.deepCopy(true);
+ assertEquals(copy.getId(), copy.getId(), "Failed to copy the id property.");
assertEquals(copy.getPath(), original.getPath(), "Failed to copy the path property.");
}
@Test
- public void deepCopyShouldCopyContents() {
+ public void deepCopyShouldCopyPathAndIdWhenIdNotIncluded() {
+ RawConfiguration original = new RawConfiguration();
+ original.setPath("/tmp/foo");
+ original.setId(-1);
+
+ RawConfiguration copy = original.deepCopy(false);
+
+ assertFalse(copy.getId() == original.getId(), "The original id property should not be copied.");
+ assertEquals(copy.getPath(), original.getPath(), "Failed to copy the path property.");
+ }
+
+ @Test
+ public void deepCopyShouldCopyContentsWhenCopyingId() {
RawConfiguration original = new RawConfiguration();
original.setContents(new byte[] {1, 2, 3, 4, 5});
- RawConfiguration copy = original.deepCopy();
+ RawConfiguration copy = original.deepCopy(true);
assertFalse(original.getContents() == copy.getContents(), "The values in the contents array should be copied, not the reference to the original object.");
assertEquals(copy.getContents(), original.getContents(), "Failed to copy contents property.");
}
@Test
- public void deepCopyShouldNotCopyIdProperty() {
+ public void deepCopyShouldCopyContentsWhenNotCopyingId() {
RawConfiguration original = new RawConfiguration();
- original.setId(1);
+ original.setContents(new byte[] {1, 2, 3, 4, 5});
- RawConfiguration copy = original.deepCopy();
+ RawConfiguration copy = original.deepCopy(false);
- assertFalse(original.getId() == copy.getId(), "The id property should not be copied.");
+ assertFalse(original.getContents() == copy.getContents(), "The values in the contents array should be copied, not the reference to the original object.");
+ assertEquals(copy.getContents(), original.getContents(), "Failed to copy contents property.");
}
+
}
commit 9994ec529ecf93914ab48d25023327ee0eb3f503
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 24 16:41:38 2009 -0500
add a test to confirm that snapshot versions are considered older than candidate releases or releases
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 d9c2a9f..dfee3a5 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
@@ -161,5 +161,14 @@ public class ComparableVersionTest {
assert ver2.compareTo(ver2) == 0;
assert ver1.compareTo(ver2) > 0; // ver1 is after ver2!
assert ver2.compareTo(ver1) < 0; // ver1 is after ver2!
+
+ ver1 = new ComparableVersion("4.0.0-SNAPSHOT");
+ ver2 = new ComparableVersion("4.0.0.CR2"); // CR is an alias for RC
+ assert !ver1.equals(ver2);
+ assert !ver2.equals(ver1);
+ assert ver1.compareTo(ver1) == 0;
+ assert ver2.compareTo(ver2) == 0;
+ assert ver1.compareTo(ver2) < 0;
+ assert ver2.compareTo(ver1) > 0;
}
}
commit 93cd6e74d101d7dc645ac38168b4d0157752bf8d
Author: Justin Harris <jharris(a)redhat.com>
Date: Tue Nov 24 14:57:46 2009 -0500
Moving in some seam functionality to allow for page scoped beans in form submission.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java
new file mode 100644
index 0000000..0bb87bd
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java
@@ -0,0 +1,73 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.admin.plugin;
+
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.AutoCreate;
+import org.jboss.seam.annotations.Factory;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.web.RequestParameter;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Component responsible for looking up a {@link Plugin}, obtaining
+ * the <code>name</code> and <code>type</code> from request parameters.
+ *
+ * @author jharris
+ */
+@Name("installedPlugin")
+public class InstalledPluginComponent {
+
+ @RequestParameter("plugin")
+ private String name;
+ @RequestParameter("pluginType")
+ private PluginDeploymentType type;
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public PluginDeploymentType getType() {
+ return this.type;
+ }
+
+ public void setType(PluginDeploymentType type) {
+ this.type = type;
+ }
+
+ @Factory(value="plugin", autoCreate=true, scope=ScopeType.PAGE)
+ public Plugin lookupPlugin() {
+ if (this.type == PluginDeploymentType.AGENT) {
+ return LookupUtil.getResourceMetadataManager().getPlugin(this.name);
+ } else if (this.type == PluginDeploymentType.SERVER) {
+ ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
+ Plugin plugin = serverPluginsBean.getServerPlugin(this.name);
+ return serverPluginsBean.getServerPluginRelationships(plugin);
+ }
+
+ return null;
+ }
+}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
index b6db223..3fe6988 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
@@ -21,8 +21,13 @@ package org.rhq.enterprise.gui.admin.plugin;
import javax.faces.application.FacesMessage;
import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.Create;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
import org.rhq.core.clientapi.agent.metadata.ConfigurationMetadataParser;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
@@ -40,21 +45,24 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
* @author Greg Hinkle
* @author John Mazzitelli
*/
+(a)Scope(ScopeType.PAGE)
+@Name("InstalledPluginUIBean")
public class InstalledPluginUIBean {
- private final Log log = LogFactory.getLog(InstalledPluginUIBean.class);
+ private static final String OUTCOME_SUCCESS = "success";
public static final String MANAGED_BEAN_NAME = InstalledPluginUIBean.class.getSimpleName();
-
+ private final Log log = LogFactory.getLog(InstalledPluginUIBean.class);
+ @In
private Plugin plugin;
private ConfigurationDefinition pluginConfigurationDefinition;
private ConfigurationDefinition scheduledJobsDefinition;
- public InstalledPluginUIBean() {
- lookupPlugin();
+ public Plugin getPlugin() {
+ return plugin;
}
- public Plugin getPlugin() {
- return this.plugin;
+ public void setPlugin(Plugin plugin) {
+ this.plugin = plugin;
}
public ConfigurationDefinition getPluginConfigurationDefinition() {
@@ -65,40 +73,39 @@ public class InstalledPluginUIBean {
return this.scheduledJobsDefinition;
}
- public void updatePlugin() {
+ public boolean isEditable() {
+ return this.pluginConfigurationDefinition != null || this.scheduledJobsDefinition != null;
+ }
+
+ public String updatePlugin() {
ServerPluginsLocal serverPlugins = LookupUtil.getServerPlugins();
try {
serverPlugins.updateServerPluginExceptContent(EnterpriseFacesContextUtility.getSubject(), plugin);
-
FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO,
- "Configuration settings saved.");
+ "Configuration settings saved.");
+
+ return OUTCOME_SUCCESS;
} catch (Exception e) {
log.error("Error updating the plugin configurations.", e);
FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR,
- "There was an error changing the configuration settings.", e);
- }
+ "There was an error changing the configuration settings.", e);
- lookupPlugin();
+ return null;
+ }
}
- private void lookupPlugin() {
+ @Create
+ public void lookupConfigDefinitions() {
hasPermission();
- String pluginName = FacesContextUtility.getRequiredRequestParameter("plugin", String.class);
- String pluginType = FacesContextUtility.getRequiredRequestParameter("pluginType", String.class);
- PluginDeploymentType deploymentType = PluginDeploymentType.valueOf(pluginType);
- if (deploymentType == PluginDeploymentType.AGENT) {
- this.plugin = LookupUtil.getResourceMetadataManager().getPlugin(pluginName);
- } else {
- ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
- this.plugin = serverPluginsBean.getServerPlugin(pluginName);
- this.plugin = serverPluginsBean.getServerPluginRelationships(this.plugin);
+ String pluginName = this.plugin.getName();
+
+ if (this.plugin.getDeployment() == PluginDeploymentType.SERVER) {
try {
+ ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
ServerPluginDescriptorType descriptor = serverPluginsBean.getServerPluginDescriptor(pluginName);
- this.pluginConfigurationDefinition = ConfigurationMetadataParser.parse("pc:" + pluginName, descriptor
- .getPluginConfiguration());
- this.scheduledJobsDefinition = ConfigurationMetadataParser.parse("jobs:" + pluginName, descriptor
- .getScheduledJobs());
+ this.pluginConfigurationDefinition = ConfigurationMetadataParser.parse("pc:" + pluginName, descriptor.getPluginConfiguration());
+ this.scheduledJobsDefinition = ConfigurationMetadataParser.parse("jobs:" + pluginName, descriptor.getScheduledJobs());
} catch (Exception e) {
String err = "Cannot determine what the plugin configuration or scheduled jobs configuration looks like";
log.error(err + " - Cause: " + e);
@@ -114,8 +121,7 @@ public class InstalledPluginUIBean {
private void hasPermission() {
Subject subject = EnterpriseFacesContextUtility.getSubject();
if (!LookupUtil.getAuthorizationManager().hasGlobalPermission(subject, Permission.MANAGE_SETTINGS)) {
- throw new PermissionException("User [" + subject.getName()
- + "] does not have the proper permissions to view or manage plugins");
+ throw new PermissionException("User [" + subject.getName() + "] does not have the proper permissions to view or manage plugins");
}
}
-}
\ No newline at end of file
+}
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml
index bacb535..64bd31e 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml
@@ -11,6 +11,7 @@
<component name="org.jboss.seam.core.init">
<property name="debug">false</property> <!-- enable only when needed -->
<property name="transactionManagementEnabled">false</property>
+ <property name="jndi-pattern">rhq/#{ejbName}/local</property>
</component>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml
index 11dadd0..a80402b 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml
@@ -20,13 +20,6 @@
<managed-bean-class>org.rhq.enterprise.gui.admin.plugin.InstalledPluginsUIBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
- <managed-bean>
- <description>Visibility for the installed agent and server plugins</description>
- <display-name>Installed Plugin</display-name>
- <managed-bean-name>InstalledPluginUIBean</managed-bean-name>
- <managed-bean-class>org.rhq.enterprise.gui.admin.plugin.InstalledPluginUIBean</managed-bean-class>
- <managed-bean-scope>request</managed-bean-scope>
- </managed-bean>
<managed-bean>
<description>Access to downloads information</description>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml
index 93932df..7f19f4d 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml
@@ -28,6 +28,17 @@
</navigation-case>
</navigation-rule>
+
+ <navigation-rule>
+ <from-view-id>/rhq/admin/plugin/plugin-details-edit.xhtml</from-view-id>
+
+ <navigation-case>
+ <from-outcome>success</from-outcome>
+ <to-view-id>/rhq/admin/plugin/plugin-details-view.xhtml?plugin=#{plugin.name}&pluginType=#{plugin.deployment}</to-view-id>
+ <redirect/>
+ </navigation-case>
+
+ </navigation-rule>
<navigation-rule>
<navigation-case>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml
new file mode 100644
index 0000000..d88afe7
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jstl/core"
+ xmlns:onc="http://jboss.org/on/component"
+ xmlns:rich="http://richfaces.ajax4jsf.org/rich">
+
+<ui:composition template="/rhq/admin/plugin/plugin-details.xhtml">
+ <ui:param name="editMode" value="true"/>
+
+ <ui:define name="post-config">
+ <rich:panel rendered="#{InstalledPluginUIBean.editable}">
+ <h:commandButton value="SAVE" type="submit" action="#{InstalledPluginUIBean.updatePlugin}"
+ alt="Click to Save Changes" styleClass="buttonmed" />
+ <h:commandButton value="RESET" type="reset" immediate="true"
+ title="Click to Reset Fields" styleClass="buttonmed"/>
+ </rich:panel>
+ </ui:define>
+</ui:composition>
+
+</html>
\ No newline at end of file
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml
new file mode 100644
index 0000000..389923a
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jstl/core"
+ xmlns:onc="http://jboss.org/on/component"
+ xmlns:rich="http://richfaces.ajax4jsf.org/rich">
+
+<ui:composition template="/rhq/admin/plugin/plugin-details.xhtml">
+ <ui:param name="editMode" value="false"/>
+
+ <ui:define name="pre-config">
+ <h:panelGrid columns="1" styleClass="buttons-table" columnClasses="button-cell"
+ rendered="#{InstalledPluginUIBean.editable}">
+ <h:outputLink value="/rhq/admin/plugin/plugin-details-edit.xhtml"
+ styleClass="buttonmed">
+ <f:param name="plugin" value="#{installedPlugin.name}"/>
+ <f:param name="pluginType" value="#{installedPlugin.type}"/>
+ <h:outputText value="EDIT"/>
+ </h:outputLink>
+ </h:panelGrid>
+ </ui:define>
+ </ui:composition>
+
+</html>
\ No newline at end of file
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
index fa46dc8..cc11203 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
@@ -35,8 +35,6 @@
layout="table"
width="100%"/>
-
-
<h:form id="pluginsForm">
<rich:panel>
@@ -66,7 +64,6 @@
</h:panelGrid>
-
<rich:panel>
<f:facet name="header">
<h:outputText value="Plugin Help"/>
@@ -76,6 +73,7 @@
</rich:panel>
+ <ui:insert name="pre-config" />
<rich:panel rendered="#{InstalledPluginUIBean.plugin.pluginConfiguration != null}">
<f:facet name="header">
@@ -83,7 +81,8 @@
</f:facet>
<onc:config
configurationDefinition="#{InstalledPluginUIBean.pluginConfigurationDefinition}"
- configuration="#{InstalledPluginUIBean.plugin.pluginConfiguration}" />
+ configuration="#{InstalledPluginUIBean.plugin.pluginConfiguration}"
+ readOnly="#{not editMode}" />
</rich:panel>
<rich:panel rendered="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration != null}">
@@ -92,17 +91,11 @@
</f:facet>
<onc:config
configurationDefinition="#{InstalledPluginUIBean.scheduledJobsDefinition}"
- configuration="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration}" />
+ configuration="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration}"
+ readOnly="#{not editMode}" />
</rich:panel>
- <input type="hidden" name="plugin" value="#{param.plugin}"/>
- <input type="hidden" name="pluginType" value="#{param.pluginType}"/>
-
- <rich:panel rendered="#{InstalledPluginUIBean.plugin.pluginConfiguration != null ||
- InstalledPluginUIBean.plugin.scheduledJobsConfiguration != null}">
- <h:commandButton value="OK" type="submit" action="#{InstalledPluginUIBean.updatePlugin}"
- alt="Click to Save Plugin" styleClass="buttonmed" />
- </rich:panel>
+ <ui:insert name="post-config" />
</rich:panel>
</h:form>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
index 72f941e..5654368 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
@@ -75,7 +75,7 @@
<h:outputText styleClass="headerText" value="Name"/>
</f:facet>
- <h:outputLink value="/rhq/admin/plugin/plugin-details.xhtml">
+ <h:outputLink value="/rhq/admin/plugin/plugin-details-view.xhtml">
<f:param name="plugin" value="#{agentPlugin.name}"/>
<f:param name="pluginType" value="AGENT"/>
<h:outputText value="#{agentPlugin.displayName}"/>
@@ -160,7 +160,7 @@
<h:outputText styleClass="headerText" value="Name"/>
</f:facet>
- <h:outputLink value="/rhq/admin/plugin/plugin-details.xhtml">
+ <h:outputLink value="/rhq/admin/plugin/plugin-details-view.xhtml">
<f:param name="plugin" value="#{serverPlugin.name}"/>
<f:param name="pluginType" value="SERVER"/>
<h:outputText value="#{serverPlugin.displayName}"/>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index ce603da..1415bb5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -16,7 +16,6 @@
* 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.plugin;
import java.io.BufferedInputStream;
@@ -67,14 +66,12 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
@Stateless
@javax.annotation.Resource(name = "RHQ_DS", mappedName = RHQConstants.DATASOURCE_JNDI_NAME)
public class ServerPluginsBean implements ServerPluginsLocal {
- private final Log log = LogFactory.getLog(ServerPluginsBean.class);
+ private final Log log = LogFactory.getLog(ServerPluginsBean.class);
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
private EntityManager entityManager;
-
@javax.annotation.Resource(name = "RHQ_DS")
private DataSource dataSource;
-
@EJB
private ServerPluginsLocal serverPluginsBean; //self
@@ -242,8 +239,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
File currentFile = new File(pluginDir, doomedPlugin.getPath());
currentFile.delete();
} catch (Exception e) {
- log.error("Failed to delete the undeployed plugin [" + doomedPlugin.getPath() + "]. Cause: "
- + ThrowableUtil.getAllMessages(e));
+ log.error("Failed to delete the undeployed plugin [" + doomedPlugin.getPath() + "]. Cause: " + ThrowableUtil.getAllMessages(e));
}
}
}
@@ -279,7 +275,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
@RequiredPermission(Permission.MANAGE_SETTINGS)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void setServerPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status)
- throws Exception {
+ throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
return; // nothing to do
}
@@ -295,8 +291,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
public Plugin registerServerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception {
if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
- throw new IllegalArgumentException("Plugin [" + plugin.getName()
- + "] must be a server plugin to be registered");
+ throw new IllegalArgumentException("Plugin [" + plugin.getName() + "] must be a server plugin to be registered");
}
Plugin existingPlugin = null;
@@ -309,8 +304,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (existingPlugin != null) {
if (existingPlugin.getStatus() == PluginStatusType.DELETED) {
- throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
- + "], it has been marked as deleted");
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName() + "], it has been marked as deleted");
}
Plugin obsolete = ServerPluginDescriptorUtil.determineObsoletePlugin(plugin, existingPlugin);
if (obsolete == existingPlugin) { // yes use == for reference equality
@@ -328,8 +322,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (plugin.getId() == 0) {
PluginStatusType status = getServerPluginStatus(plugin.getName());
if (PluginStatusType.DELETED == status) {
- throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
- + "], it has been previously marked as deleted.");
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName() + "], it has been previously marked as deleted.");
}
entityManager.persist(plugin);
} else {
@@ -371,8 +364,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
// to entityManager.merge that plugin POJO, it would null out that blob column.
if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
- throw new IllegalArgumentException("Plugin [" + plugin.getName()
- + "] must be a server plugin to be updated");
+ throw new IllegalArgumentException("Plugin [" + plugin.getName() + "] must be a server plugin to be updated");
}
if (plugin.getId() == 0) {
commit c8a8622dce3142a91725a0a152bee94be64a9259
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 23 14:05:06 2009 -0500
because we put the byte[] content directly in the plugin entity, we can't entityManager.find() because that would load the full plugin content.
instead, use getReference. when we need to load the relationships, we have to play games by
loading in the configs directly and doing a deep copy (mainly to workaround a hibernate bug)
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 157911d..ce603da 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -94,11 +94,14 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
public Plugin getServerPluginRelationships(Plugin plugin) {
- plugin = entityManager.find(Plugin.class, plugin.getId());
+ plugin = getServerPlugin(plugin.getName()); // refresh all but the content field
- // force eager load
- plugin.getPluginConfiguration().getProperties().size();
- plugin.getScheduledJobsConfiguration().getProperties().size();
+ int pluginConfigId = plugin.getPluginConfiguration().getId();
+ int scheduledJobsId = plugin.getScheduledJobsConfiguration().getId();
+ Configuration pluginConfig = entityManager.find(Configuration.class, pluginConfigId);
+ Configuration scheduledJobs = entityManager.find(Configuration.class, scheduledJobsId);
+ plugin.setPluginConfiguration(pluginConfig.deepCopyWithoutProxies());
+ plugin.setScheduledJobsConfiguration(scheduledJobs.deepCopyWithoutProxies());
return plugin;
}
@@ -146,9 +149,9 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
- public List<Plugin> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
+ public List<String> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
- return new ArrayList<Plugin>(); // nothing to do
+ return new ArrayList<String>(); // nothing to do
}
serverPluginsBean.setServerPluginEnabledFlag(subject, pluginIds, false);
@@ -156,19 +159,24 @@ public class ServerPluginsBean implements ServerPluginsLocal {
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
- List<Plugin> doomedPlugins = new ArrayList<Plugin>();
+ List<String> doomedPlugins = new ArrayList<String>();
for (Integer pluginId : pluginIds) {
- Plugin doomedPlugin = entityManager.find(Plugin.class, pluginId);
+ Plugin doomedPlugin = null;
+ try {
+ doomedPlugin = entityManager.getReference(Plugin.class, pluginId);
+ } catch (Exception ignore) {
+ }
if (doomedPlugin != null) {
- doomedPlugins.add(doomedPlugin);
+ String pluginName = doomedPlugin.getName();
+ doomedPlugins.add(pluginName);
if (master != null) {
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
+ AbstractTypeServerPluginContainer pc = master.getPluginContainer(pluginName);
if (pc != null) {
try {
- pc.unschedulePluginJobs(doomedPlugin.getName());
+ pc.unschedulePluginJobs(pluginName);
} catch (Exception e) {
- log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ log.warn("Failed to unschedule jobs for plugin [" + pluginName + "]", e);
}
}
}
@@ -184,9 +192,9 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
- public List<Plugin> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
+ public List<String> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
- return new ArrayList<Plugin>(); // nothing to do
+ return new ArrayList<String>(); // nothing to do
}
serverPluginsBean.setServerPluginEnabledFlag(subject, pluginIds, false);
@@ -194,19 +202,24 @@ public class ServerPluginsBean implements ServerPluginsLocal {
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
- List<Plugin> doomedPlugins = new ArrayList<Plugin>();
+ List<String> doomedPlugins = new ArrayList<String>();
for (Integer pluginId : pluginIds) {
- Plugin doomedPlugin = entityManager.find(Plugin.class, pluginId);
+ Plugin doomedPlugin = null;
+ try {
+ doomedPlugin = entityManager.getReference(Plugin.class, pluginId);
+ } catch (Exception ignore) {
+ }
if (doomedPlugin != null) {
- doomedPlugins.add(doomedPlugin);
+ String pluginName = doomedPlugin.getName();
+ doomedPlugins.add(pluginName);
if (master != null) {
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
+ AbstractTypeServerPluginContainer pc = master.getPluginContainer(pluginName);
if (pc != null) {
try {
- pc.unschedulePluginJobs(doomedPlugin.getName());
+ pc.unschedulePluginJobs(pluginName);
} catch (Exception e) {
- log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ log.warn("Failed to unschedule jobs for plugin [" + pluginName + "]", e);
}
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index 6f3600e..803f7cf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -86,20 +86,20 @@ public interface ServerPluginsLocal {
*
* @param subject user making the request
* @param pluginIds the plugins to be disabled
- * @return the list of plugins that were disabled
+ * @return the list of names of the plugins that were disabled
* @throws Exception if failed to disable a plugin
*/
- List<Plugin> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
+ List<String> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
/**
* Removes the plugin from the system and restarts the server plugin container.
*
* @param subject user making the request
* @param pluginIds
- * @return the list of plugins that were undeployed
+ * @return the list of names of plugins that were undeployed
* @throws Exception if failed to undeploy a plugin
*/
- List<Plugin> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
+ List<String> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
/**
* Turns on or off the enabled flag in the database but does NOT restart the server plugin container.
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
index e1796bf..d1a6aba 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
@@ -135,6 +135,24 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
assetLazyInitializationException(plugins.get(1));
}
+ public void testUpdatePlugins() throws Exception {
+ Plugin p1 = registerPlugin(1);
+ p1 = this.serverPluginsBean.getServerPlugin(p1.getName());
+ p1 = this.serverPluginsBean.getServerPluginRelationships(p1);
+
+ Plugin p1update = this.serverPluginsBean.updateServerPluginExceptContent(getOverlord(), p1);
+ p1update = this.serverPluginsBean.getServerPluginRelationships(p1update);
+
+ assert p1update.getId() == p1.getId() : p1update;
+ assert p1update.getId() == p1.getId() : p1update;
+ assert p1update.getName().equals(p1.getName()) : p1update;
+ assert p1update.getName().equals(p1.getName()) : p1update;
+ assert p1update.getPluginConfiguration().equals(p1.getPluginConfiguration()) : p1update;
+ assert p1update.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration()) : p1update;
+ p1update.getPluginConfiguration().equals(p1.getPluginConfiguration());
+ p1update.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration());
+ }
+
public void testDisableEnablePlugins() throws Exception {
Plugin p1 = registerPlugin(1);
Plugin p2 = registerPlugin(2);
@@ -142,12 +160,13 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
List<Integer> ids = new ArrayList<Integer>(2);
ids.add(p1.getId());
ids.add(p2.getId());
- List<Plugin> disabled = this.serverPluginsBean.disableServerPlugins(getOverlord(), ids);
+ List<String> disabled = this.serverPluginsBean.disableServerPlugins(getOverlord(), ids);
assert disabled.size() == 2 : disabled;
- assert disabled.contains(p1) : disabled;
- assert disabled.contains(p2) : disabled;
- assert disabled.get(0).getStatus() == PluginStatusType.INSTALLED; // still installed
- assert disabled.get(1).getStatus() == PluginStatusType.INSTALLED; // still installed
+ assert disabled.contains(p1.getName()) : disabled;
+ assert disabled.contains(p2.getName()) : disabled;
+ ;
+ assert this.serverPluginsBean.getServerPlugin(p1.getName()).getStatus() == PluginStatusType.INSTALLED; // still installed
+ assert this.serverPluginsBean.getServerPlugin(p2.getName()).getStatus() == PluginStatusType.INSTALLED; // still installed
List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert pluginNames.contains(p1.getName()) : pluginNames;
assert pluginNames.contains(p2.getName()) : pluginNames;
@@ -195,12 +214,14 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
List<Integer> ids = new ArrayList<Integer>(2);
ids.add(p1.getId());
ids.add(p2.getId());
- List<Plugin> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
+ List<String> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
assert undeployed.size() == 2 : undeployed;
- assert undeployed.contains(p1) : undeployed;
- assert undeployed.contains(p2) : undeployed;
- assert undeployed.get(0).getStatus() == PluginStatusType.DELETED;
- assert undeployed.get(1).getStatus() == PluginStatusType.DELETED;
+ assert undeployed.contains(p1.getName()) : undeployed;
+ assert undeployed.contains(p2.getName()) : undeployed;
+ Plugin p1deleted = getDeletedPluginInTx(p1.getName());
+ Plugin p2deleted = getDeletedPluginInTx(p2.getName());
+ assert p1deleted.getStatus() == PluginStatusType.DELETED;
+ assert p2deleted.getStatus() == PluginStatusType.DELETED;
List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert !pluginNames.contains(p1.getName()) : "deleted plugins should not be returned even here" + pluginNames;
@@ -230,16 +251,18 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
List<Integer> ids = new ArrayList<Integer>(2);
ids.add(p1.getId());
ids.add(p2.getId());
- List<Plugin> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
+ List<String> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
assert undeployed.size() == 2 : undeployed;
- assert undeployed.contains(p1) : undeployed;
- assert undeployed.contains(p2) : undeployed;
- assert undeployed.get(0).getStatus() == PluginStatusType.DELETED;
- assert undeployed.get(0).getPluginConfiguration() == null; // undeploy should have removed this
- assert undeployed.get(0).getScheduledJobsConfiguration() == null; // undeploy should have removed this
- assert undeployed.get(1).getStatus() == PluginStatusType.DELETED;
- assert undeployed.get(1).getPluginConfiguration() == null; // undeploy should have removed this
- assert undeployed.get(1).getScheduledJobsConfiguration() == null; // undeploy should have removed this
+ assert undeployed.contains(p1.getName()) : undeployed;
+ assert undeployed.contains(p2.getName()) : undeployed;
+ Plugin p1deleted = getDeletedPluginInTx(p1.getName());
+ assert p1deleted.getStatus() == PluginStatusType.DELETED;
+ assert p1deleted.getPluginConfiguration() == null; // undeploy should have removed this
+ assert p1deleted.getScheduledJobsConfiguration() == null; // undeploy should have removed this
+ Plugin p2deleted = getDeletedPluginInTx(p1.getName());
+ assert p2deleted.getStatus() == PluginStatusType.DELETED;
+ assert p2deleted.getPluginConfiguration() == null; // undeploy should have removed this
+ assert p2deleted.getScheduledJobsConfiguration() == null; // undeploy should have removed this
List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert !pluginNames.contains(p1.getName()) : "deleted plugins should not be returned even here" + pluginNames;
@@ -320,4 +343,17 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
private Subject getOverlord() {
return LookupUtil.getSubjectManager().getOverlord();
}
+
+ private Plugin getDeletedPluginInTx(String pluginName) throws Exception {
+ EntityManager em = getEntityManager();
+ getTransactionManager().begin();
+ try {
+ Query q = em.createNamedQuery(Plugin.QUERY_FIND_ANY_BY_NAME_AND_TYPE);
+ q.setParameter("name", pluginName);
+ q.setParameter("type", PluginDeploymentType.SERVER);
+ return (Plugin) q.getSingleResult();
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
}
commit 263227e335728de980194c0632ae04938396536e
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 23 11:36:47 2009 -0500
put the proper values in the query params
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 3697caa..157911d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -405,8 +405,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
q.setParameter("version", plugin.getVersion());
q.setParameter("ampsVersion", plugin.getAmpsVersion());
q.setParameter("deployment", plugin.getDeployment());
- q.setParameter("pluginConfiguration", config);
- q.setParameter("scheduledJobsConfiguration", config);
+ q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
+ q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
q.setParameter("description", plugin.getDescription());
q.setParameter("help", plugin.getHelp());
q.setParameter("mtime", plugin.getMtime());
commit e77a657abf17907a25dba4498b6e4993604ed38c
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 23 10:48:13 2009 -0500
the column should be "enabled" since everywhere else we talk about a plugin being enabled or disabled, not active/inactive
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
index 9f7f6b7..72f941e 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
@@ -105,7 +105,7 @@
<rich:column>
<f:facet name="header">
- <h:outputText styleClass="headerText" value="Active"/>
+ <h:outputText styleClass="headerText" value="Enabled"/>
</f:facet>
<h:outputText value="#{agentPlugin.enabled}"/>
@@ -190,7 +190,7 @@
<rich:column>
<f:facet name="header">
- <h:outputText styleClass="headerText" value="Active"/>
+ <h:outputText styleClass="headerText" value="Enabled"/>
</f:facet>
<h:outputText value="#{serverPlugin.enabled}"/>
commit 9af95de196ccc8b854a8f1c952af3a6cfa18e78d
Author: Justin Harris <jharris(a)redhat.com>
Date: Mon Nov 23 10:18:55 2009 -0500
Updating update plugin call to new naming scheme.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
index fac4661..b6db223 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
@@ -69,7 +69,7 @@ public class InstalledPluginUIBean {
ServerPluginsLocal serverPlugins = LookupUtil.getServerPlugins();
try {
- serverPlugins.updatePluginExceptContent(EnterpriseFacesContextUtility.getSubject(), plugin);
+ serverPlugins.updateServerPluginExceptContent(EnterpriseFacesContextUtility.getSubject(), plugin);
FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO,
"Configuration settings saved.");
@@ -78,6 +78,8 @@ public class InstalledPluginUIBean {
FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR,
"There was an error changing the configuration settings.", e);
}
+
+ lookupPlugin();
}
private void lookupPlugin() {
commit 556be90ec7e0285dc9205766805aaa91da2ef258
Author: Justin Harris <jharris(a)redhat.com>
Date: Fri Nov 20 18:34:52 2009 -0500
Adding save button to plugin details page.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
index f6eee0d..fac4661 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
@@ -65,6 +65,21 @@ public class InstalledPluginUIBean {
return this.scheduledJobsDefinition;
}
+ public void updatePlugin() {
+ ServerPluginsLocal serverPlugins = LookupUtil.getServerPlugins();
+
+ try {
+ serverPlugins.updatePluginExceptContent(EnterpriseFacesContextUtility.getSubject(), plugin);
+
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO,
+ "Configuration settings saved.");
+ } catch (Exception e) {
+ log.error("Error updating the plugin configurations.", e);
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR,
+ "There was an error changing the configuration settings.", e);
+ }
+ }
+
private void lookupPlugin() {
hasPermission();
String pluginName = FacesContextUtility.getRequiredRequestParameter("plugin", String.class);
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
index 3921b8e..fa46dc8 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
@@ -76,24 +76,32 @@
</rich:panel>
- <rich:panel>
+
+ <rich:panel rendered="#{InstalledPluginUIBean.plugin.pluginConfiguration != null}">
<f:facet name="header">
<h:outputText value="Plugin Configuration"/>
</f:facet>
<onc:config
configurationDefinition="#{InstalledPluginUIBean.pluginConfigurationDefinition}"
- configuration="#{InstalledPluginUIBean.plugin.pluginConfiguration}"
- readOnly="true" />
+ configuration="#{InstalledPluginUIBean.plugin.pluginConfiguration}" />
</rich:panel>
- <rich:panel>
+ <rich:panel rendered="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration != null}">
<f:facet name="header">
<h:outputText value="Scheduled Jobs"/>
</f:facet>
<onc:config
configurationDefinition="#{InstalledPluginUIBean.scheduledJobsDefinition}"
- configuration="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration}"
- readOnly="true" />
+ configuration="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration}" />
+ </rich:panel>
+
+ <input type="hidden" name="plugin" value="#{param.plugin}"/>
+ <input type="hidden" name="pluginType" value="#{param.pluginType}"/>
+
+ <rich:panel rendered="#{InstalledPluginUIBean.plugin.pluginConfiguration != null ||
+ InstalledPluginUIBean.plugin.scheduledJobsConfiguration != null}">
+ <h:commandButton value="OK" type="submit" action="#{InstalledPluginUIBean.updatePlugin}"
+ alt="Click to Save Plugin" styleClass="buttonmed" />
</rich:panel>
</rich:panel>
commit e144f9a55590182e130ae768b9b494b13f03c2a6
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 22 22:42:30 2009 -0500
convert CRLF to LF
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
index a7c0cbc..2c47b0a 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
@@ -1,397 +1,397 @@
-<%@ page import="java.io.ByteArrayOutputStream" %>
-<%@ page import="java.io.PrintStream" %>
-
-<%@ page import="org.rhq.core.domain.auth.Subject" %>
-<%@ page import="org.rhq.core.domain.util.PersistenceUtility" %>
-
-<%@ page import="org.rhq.enterprise.gui.legacy.util.SessionUtils"%>
-<%@ page import="org.rhq.enterprise.gui.util.WebUtility"%>
-
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences" %>
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences.MetricRangePreferences" %>
-
-<%@ page import="org.rhq.enterprise.server.test.CoreTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.DiscoveryTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.MeasurementTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.SubjectRoleTestBeanLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.AlertTemplateTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.cloud.instance.ServerManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementBaselineManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.core.AgentManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.system.SystemManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.auth.SubjectManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.support.SupportManagerLocal" %>
-<%@page import="org.rhq.enterprise.server.plugin.ServerPluginsLocal"%><html>
-<%@ page import="org.rhq.enterprise.server.util.LookupUtil" %>
-<%@ page import="org.rhq.enterprise.server.scheduler.jobs.DataPurgeJob"%>
-
-<%@ page import="org.rhq.enterprise.server.resource.ResourceTypeManagerRemote"%>
-<%@ page import="org.rhq.core.domain.criteria.ResourceTypeCriteria"%>
-<%@ page import="org.rhq.core.domain.resource.ResourceType"%>
-
-<%@ page import="javax.naming.NamingException" %>
-
-<%@ page contentType="text/html;charset=UTF-8" language="java" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-
-<html>
-<head><title>RHQ Test Control Page</title></head>
-<body>
-
-<jsp:include page="/admin/include/adminTestLinks.html" flush="true" />
-
-<%
- CoreTestLocal coreTestBean;
- DiscoveryTestLocal discoveryTestBean;
- MeasurementTestLocal measurementTestBean;
- ResourceGroupTestBeanLocal resourceGroupTestBean;
- SubjectRoleTestBeanLocal subjectRoleTestBean;
- ServerManagerLocal serverManager;
- AlertTemplateTestLocal alertTemplateTestBean;
- MeasurementBaselineManagerLocal measurementBaselineManager;
- MeasurementScheduleManagerLocal measurementScheduleManager;
- AgentManagerLocal agentManager;
- SystemManagerLocal systemManager;
- SubjectManagerLocal subjectManager;
- SupportManagerLocal supportManager;
- ResourceTypeManagerRemote typeManager;
- ServerPluginsLocal serverPlugins;
-
- coreTestBean = LookupUtil.getCoreTest();
- discoveryTestBean = LookupUtil.getDiscoveryTest();
- measurementTestBean = LookupUtil.getMeasurementTest();
- resourceGroupTestBean = LookupUtil.getResourceGroupTestBean();
- subjectRoleTestBean = LookupUtil.getSubjectRoleTestBean();
- serverManager = LookupUtil.getServerManager();
- alertTemplateTestBean = LookupUtil.getAlertTemplateTestBean();
- measurementBaselineManager = LookupUtil.getMeasurementBaselineManager();
- measurementScheduleManager = LookupUtil.getMeasurementScheduleManager();
- agentManager = LookupUtil.getAgentManager();
- systemManager = LookupUtil.getSystemManager();
- subjectManager = LookupUtil.getSubjectManager();
- supportManager = LookupUtil.getSupportManager();
- typeManager = LookupUtil.getResourceTypeManagerRemote();
- serverPlugins = LookupUtil.getServerPlugins();
-
- String result = null;
- String mode = pageContext.getRequest().getParameter("mode");
- String failure = null;
- try
- {
- if ("registerTestAgent".equals(mode))
- {
- coreTestBean.registerTestAgent();
- }
- else if ("registerTestPluginAndTypeInfo".equals(mode))
- {
- discoveryTestBean.registerTestPluginAndTypeInfo();
- }
- else if ("removeTestPluginAndTypeInfo".equals(mode))
- {
- discoveryTestBean.removeTestPluginAndTypeInfo();
- }
- else if ("sendTestFullInventoryReport".equals(mode))
- {
- discoveryTestBean.sendTestFullInventoryReport();
- }
- else if ("sendTestRuntimeInventoryReport".equals(mode))
- {
- discoveryTestBean.sendTestRuntimeInventoryReport();
- }
- else if ("sendTestMeasurementReport".equals(mode))
- {
- measurementTestBean.sendTestMeasurementReport();
- }
- else if ("sendNewPlatform".equals(mode))
- {
- String address = request.getParameter("address");
- int servers = Integer.parseInt(request.getParameter("servers"));
- int servicesPerServer = Integer.parseInt(request.getParameter("servicesPerServer"));
- discoveryTestBean.sendNewPlatform(address, servers, servicesPerServer);
- }
- else if ("setupCompatibleGroups".equals(mode))
- {
- resourceGroupTestBean.setupCompatibleGroups();
- }
- else if ("setupUberMixedGroup".equals(mode))
- {
- resourceGroupTestBean.setupUberMixedGroup();
- }
- else if ("startStats".equals(mode))
- {
- coreTestBean.enableHibernateStatistics();
- }
- else if ("addProblemResource".equals(mode))
- {
- measurementTestBean.addProblemResource();
- }
- else if ("setAgentCurrentlyScheduledMetrics".equals(mode))
- {
- String value = pageContext.getRequest().getParameter("v");
- measurementTestBean.setAgentCurrentlyScheduledMetrics(Double.valueOf(value));
- }
- else if ("addSubjectsAndRoles".equals(mode))
- {
- String roleCount = pageContext.getRequest().getParameter("roleCount");
- String usersInRoleCount = pageContext.getRequest().getParameter("usersInRoleCount");
- subjectRoleTestBean.createRolesAndUsers(Integer.parseInt(roleCount), Integer.parseInt(usersInRoleCount));
- }
- else if ("clusterGetIdentity".equals(mode))
- {
- String serverName = serverManager.getIdentity();
- pageContext.setAttribute("serverName", "(serverName = " + serverName + ")");
- }
- else if ("cloneAlertTemplate".equals(mode))
- {
- String alertTemplateId = pageContext.getRequest().getParameter("alertTemplateId");
- String numberOfClones = pageContext.getRequest().getParameter("numberOfClones");
- alertTemplateTestBean.cloneAlertTemplate(Integer.parseInt(alertTemplateId), Integer.parseInt(numberOfClones));
- }
- else if ("calculateAutoBaselines".equals(mode))
- {
- // for now, baselines aren't calculated until we hit our day limit, we force it here
- java.util.Properties props = systemManager.getSystemConfiguration();
- props.put("CAM_BASELINE_LASTTIME", "0");
- systemManager.setSystemConfiguration(subjectManager.getOverlord(), props,true);
-
- measurementBaselineManager.calculateAutoBaselines();
- }
- else if ("calculateOOBs".equals(mode))
- {
- DataPurgeJob dpj = new DataPurgeJob();
- dpj.calculateOOBs();
- }
- else if ("checkForSuspectAgents".equals(mode))
- {
- agentManager.checkForSuspectAgents();
- }
- else if ("dataPurgeJob".equals(mode))
- {
- DataPurgeJob.purgeNow();
- }
- else if ("dbMaintenance".equals(mode))
- {
- systemManager.vacuum(subjectManager.getOverlord());
- systemManager.reindex(subjectManager.getOverlord());
- systemManager.analyze(subjectManager.getOverlord());
- }
- else if ("metricDisplayRange".equals(mode))
- {
- int lastHours = Integer.parseInt(pageContext.getRequest().getParameter("lastHours"));
- Subject subject = WebUtility.getSubject(request);
- MeasurementPreferences prefs = new MeasurementPreferences(subject);
- MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
- rangePrefs.lastN = lastHours;
- prefs.setMetricRangePreferences(rangePrefs);
- }
- else if ("errorCorrectSchedules".equals("mode"))
- {
- measurementScheduleManager.errorCorrectSchedules();
- }
- else if ("generateSnapshotReport".equals(mode))
- {
- int resourceId = Integer.parseInt(request.getParameter("resourceId"));
- String name = request.getParameter("name");
- String description = request.getParameter("description");
- java.net.URL url = supportManager.getSnapshotReport(subjectManager.getOverlord(), resourceId, name, description);
- result = "Snapshot Report is located here: " + url.toString();
- }
- else if ("purgeServerPlugin".equals(mode))
- {
- String serverPluginName = request.getParameter("serverPluginName");
- serverPlugins.purgeServerPlugin(subjectManager.getOverlord(), serverPluginName);
- result = "OK - you can now try to re-register a plugin with the name [" + serverPluginName + "]";
- }
- else if ("typeManagerRemote".equals(mode))
- {
- int typeId = Integer.parseInt(request.getParameter("typeId"));
- ResourceTypeCriteria criteria = new ResourceTypeCriteria();
- criteria.addFilterId(typeId);
- criteria.fetchMetricDefinitions(true);
- java.util.List<ResourceType> types = typeManager.findResourceTypesByCriteria(subjectManager.getOverlord(), criteria);
- result = "";
- for (ResourceType type : types) {
- result += type.getName() + " has " + (type.getMetricDefinitions() != null ? type.getMetricDefinitions().size() : "empty") + " metric definitions";
- }
- }
- }
- catch (Exception e)
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- e.printStackTrace(new PrintStream(baos));
- failure = baos.toString();
- }
-
- pageContext.setAttribute("executed", mode);
- pageContext.setAttribute("result", result);
- pageContext.setAttribute("failure", failure);
- pageContext.setAttribute("testAgentReported", Boolean.valueOf(coreTestBean.isTestAgentReported()));
-
-%>
-
-<c:if test="${executed != null}">
- <b>Executed <c:out value="${executed}"/>: </b> <c:out value="${result}"/><br>
- <c:if test="${failure != null}">
- <pre style="background-color: yellow;"><c:out value="${failure}"/></pre>
- </c:if>
-</c:if>
-
-<h2>Administration</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
-Add Lots of Users and Roles
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="addSubjectsAndRoles"/>
- Number of Roles: <input type="text" name="roleCount" size="5"/><br/>
- Number of Users in each Role: <input type="text" name="usersInRoleCount" size="5"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
- <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
-</ul>
-
-<h2>Core</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestAgent"/>
- <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=dbMaintenance"/>
- <a href="<c:out value="${url}"/>">Perform All Database Maintenance Now</a></li>
-</ul>
-
-<h2>Cluster</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=clusterGetIdentity"/>
- <a href="<c:out value="${url}"/>">Get Identity</a> <c:out value="${serverName}"/></li>
-</ul>
-
-<h2>Inventory</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestFullInventoryReport"/>
- <a href="<c:out value="${url}"/>">Send Full Inventory Report</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestRuntimeInventoryReport"/>
- <a href="<c:out value="${url}"/>">Send Runtime Inventory Report</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setupCompatibleGroups"/>
- <a href="<c:out value="${url}"/>">Setup Compatible Groups</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setupUberMixedGroup"/>
- <a href="<c:out value="${url}"/>">Setup Uber Mixed Group</a></li>
-</ul>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=sendNewPlatform"/>
-Send New Platform Inventory Report
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="sendNewPlatform"/>
- Address: <input type="text" name="address" size="30"/><br/>
- Servers: <input type="text" name="servers" size="5"/><br/>
- Services Per Server: <input type="text" name="servicesPerServer" size="5"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-
-<h2>Measurement</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateAutoBaselines"/>
- <a href="<c:out value="${url}"/>">Calculate Auto Baselines</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestMeasurementReport"/>
- <a href="<c:out value="${url}"/>">Send Measurement Report</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=addProblemResource"/>
- <a href="<c:out value="${url}"/>">Add problem Resource</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=100"/>
- <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 100</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=50"/>
- <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 50</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=checkForSuspectAgents"/>
- <a href="<c:out value="${url}"/>">Check For Suspect Agents</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=dataPurgeJob"/>
- <a href="<c:out value="${url}"/>">Force Data Purge Now</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateOOBs"/>
- <a href="<c:out value="${url}"/>">Force calculation of OOBs</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=errorCorrectSchedules"/>
- <a href="<c:out value="${url}"/>">Error-Correct Measurement Schedules</a></li>
-</ul>
-
-<h2>Alerts</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=cloneAlertTemplate"/>
-Template Cloning
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="cloneAlertTemplate"/>
- Alert Template ID: <input type="text" name="alertTemplateId" size="5"/><br/>
- Number of Clones: <input type="text" name="numberOfClones" size="5"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-<h2>Utilities</h2>
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=startStats"/>
- <a href="<c:out value="${url}"/>">Start Hibernate Statistics Collection</a></li>
-</ul>
-
-
-<h2>User Preferences</h2>
-<%
- Subject subject = WebUtility.getSubject(request);
- MeasurementPreferences prefs = new MeasurementPreferences(subject);
- MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
- pageContext.setAttribute("lastHours", String.valueOf(rangePrefs.lastN));
-%>
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="metricDisplayRange"/>
- Last X hours: <input type="text" name="lastHours" size="5" value="<c:out value="${lastHours}"/>"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-<h2>Snapshot Report</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=generateSnapshotReport"/>
-Generate Snapshot Report
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="generateSnapshotReport"/>
- Resource ID: <input type="text" name="resourceId" size="10"/><br/>
- Name: <input type="text" name="name" size="30"/><br/>
- Description: <input type="text" name="description" size="100"/><br/>
- <input type="submit" value="Generate Snapshot" name="Generate Snapshot"/>
-</form>
-
-<h2>Server Plugins</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=purgeServerPlugin"/>
-Purge Server Plugin (allowing you to re-register it again later)
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="purgeServerPlugin"/>
- ServerPluginName: <input type="text" name="serverPluginName" size="30"/><br/>
- <input type="submit" value="Purge Server Plugin" name="Purge Server Plugin"/>
-</form>
-
-<h2>Resource Type Criteria</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=typeManagerRemote"/>
-Query ResourceTypes by Criteria
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="typeManagerRemote"/>
- ResourceType ID: <input type="text" name="typeId" size="10"/><br/>
- <input type="submit" value="Query by Criteria" name="Query by Criteria"/>
-</form>
-
-
-
-</body>
-</html>
+<%@ page import="java.io.ByteArrayOutputStream" %>
+<%@ page import="java.io.PrintStream" %>
+
+<%@ page import="org.rhq.core.domain.auth.Subject" %>
+<%@ page import="org.rhq.core.domain.util.PersistenceUtility" %>
+
+<%@ page import="org.rhq.enterprise.gui.legacy.util.SessionUtils"%>
+<%@ page import="org.rhq.enterprise.gui.util.WebUtility"%>
+
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences" %>
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences.MetricRangePreferences" %>
+
+<%@ page import="org.rhq.enterprise.server.test.CoreTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.DiscoveryTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.MeasurementTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.SubjectRoleTestBeanLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.AlertTemplateTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.cloud.instance.ServerManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementBaselineManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.core.AgentManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.system.SystemManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.auth.SubjectManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.support.SupportManagerLocal" %>
+<%@page import="org.rhq.enterprise.server.plugin.ServerPluginsLocal"%><html>
+<%@ page import="org.rhq.enterprise.server.util.LookupUtil" %>
+<%@ page import="org.rhq.enterprise.server.scheduler.jobs.DataPurgeJob"%>
+
+<%@ page import="org.rhq.enterprise.server.resource.ResourceTypeManagerRemote"%>
+<%@ page import="org.rhq.core.domain.criteria.ResourceTypeCriteria"%>
+<%@ page import="org.rhq.core.domain.resource.ResourceType"%>
+
+<%@ page import="javax.naming.NamingException" %>
+
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
+<html>
+<head><title>RHQ Test Control Page</title></head>
+<body>
+
+<jsp:include page="/admin/include/adminTestLinks.html" flush="true" />
+
+<%
+ CoreTestLocal coreTestBean;
+ DiscoveryTestLocal discoveryTestBean;
+ MeasurementTestLocal measurementTestBean;
+ ResourceGroupTestBeanLocal resourceGroupTestBean;
+ SubjectRoleTestBeanLocal subjectRoleTestBean;
+ ServerManagerLocal serverManager;
+ AlertTemplateTestLocal alertTemplateTestBean;
+ MeasurementBaselineManagerLocal measurementBaselineManager;
+ MeasurementScheduleManagerLocal measurementScheduleManager;
+ AgentManagerLocal agentManager;
+ SystemManagerLocal systemManager;
+ SubjectManagerLocal subjectManager;
+ SupportManagerLocal supportManager;
+ ResourceTypeManagerRemote typeManager;
+ ServerPluginsLocal serverPlugins;
+
+ coreTestBean = LookupUtil.getCoreTest();
+ discoveryTestBean = LookupUtil.getDiscoveryTest();
+ measurementTestBean = LookupUtil.getMeasurementTest();
+ resourceGroupTestBean = LookupUtil.getResourceGroupTestBean();
+ subjectRoleTestBean = LookupUtil.getSubjectRoleTestBean();
+ serverManager = LookupUtil.getServerManager();
+ alertTemplateTestBean = LookupUtil.getAlertTemplateTestBean();
+ measurementBaselineManager = LookupUtil.getMeasurementBaselineManager();
+ measurementScheduleManager = LookupUtil.getMeasurementScheduleManager();
+ agentManager = LookupUtil.getAgentManager();
+ systemManager = LookupUtil.getSystemManager();
+ subjectManager = LookupUtil.getSubjectManager();
+ supportManager = LookupUtil.getSupportManager();
+ typeManager = LookupUtil.getResourceTypeManagerRemote();
+ serverPlugins = LookupUtil.getServerPlugins();
+
+ String result = null;
+ String mode = pageContext.getRequest().getParameter("mode");
+ String failure = null;
+ try
+ {
+ if ("registerTestAgent".equals(mode))
+ {
+ coreTestBean.registerTestAgent();
+ }
+ else if ("registerTestPluginAndTypeInfo".equals(mode))
+ {
+ discoveryTestBean.registerTestPluginAndTypeInfo();
+ }
+ else if ("removeTestPluginAndTypeInfo".equals(mode))
+ {
+ discoveryTestBean.removeTestPluginAndTypeInfo();
+ }
+ else if ("sendTestFullInventoryReport".equals(mode))
+ {
+ discoveryTestBean.sendTestFullInventoryReport();
+ }
+ else if ("sendTestRuntimeInventoryReport".equals(mode))
+ {
+ discoveryTestBean.sendTestRuntimeInventoryReport();
+ }
+ else if ("sendTestMeasurementReport".equals(mode))
+ {
+ measurementTestBean.sendTestMeasurementReport();
+ }
+ else if ("sendNewPlatform".equals(mode))
+ {
+ String address = request.getParameter("address");
+ int servers = Integer.parseInt(request.getParameter("servers"));
+ int servicesPerServer = Integer.parseInt(request.getParameter("servicesPerServer"));
+ discoveryTestBean.sendNewPlatform(address, servers, servicesPerServer);
+ }
+ else if ("setupCompatibleGroups".equals(mode))
+ {
+ resourceGroupTestBean.setupCompatibleGroups();
+ }
+ else if ("setupUberMixedGroup".equals(mode))
+ {
+ resourceGroupTestBean.setupUberMixedGroup();
+ }
+ else if ("startStats".equals(mode))
+ {
+ coreTestBean.enableHibernateStatistics();
+ }
+ else if ("addProblemResource".equals(mode))
+ {
+ measurementTestBean.addProblemResource();
+ }
+ else if ("setAgentCurrentlyScheduledMetrics".equals(mode))
+ {
+ String value = pageContext.getRequest().getParameter("v");
+ measurementTestBean.setAgentCurrentlyScheduledMetrics(Double.valueOf(value));
+ }
+ else if ("addSubjectsAndRoles".equals(mode))
+ {
+ String roleCount = pageContext.getRequest().getParameter("roleCount");
+ String usersInRoleCount = pageContext.getRequest().getParameter("usersInRoleCount");
+ subjectRoleTestBean.createRolesAndUsers(Integer.parseInt(roleCount), Integer.parseInt(usersInRoleCount));
+ }
+ else if ("clusterGetIdentity".equals(mode))
+ {
+ String serverName = serverManager.getIdentity();
+ pageContext.setAttribute("serverName", "(serverName = " + serverName + ")");
+ }
+ else if ("cloneAlertTemplate".equals(mode))
+ {
+ String alertTemplateId = pageContext.getRequest().getParameter("alertTemplateId");
+ String numberOfClones = pageContext.getRequest().getParameter("numberOfClones");
+ alertTemplateTestBean.cloneAlertTemplate(Integer.parseInt(alertTemplateId), Integer.parseInt(numberOfClones));
+ }
+ else if ("calculateAutoBaselines".equals(mode))
+ {
+ // for now, baselines aren't calculated until we hit our day limit, we force it here
+ java.util.Properties props = systemManager.getSystemConfiguration();
+ props.put("CAM_BASELINE_LASTTIME", "0");
+ systemManager.setSystemConfiguration(subjectManager.getOverlord(), props,true);
+
+ measurementBaselineManager.calculateAutoBaselines();
+ }
+ else if ("calculateOOBs".equals(mode))
+ {
+ DataPurgeJob dpj = new DataPurgeJob();
+ dpj.calculateOOBs();
+ }
+ else if ("checkForSuspectAgents".equals(mode))
+ {
+ agentManager.checkForSuspectAgents();
+ }
+ else if ("dataPurgeJob".equals(mode))
+ {
+ DataPurgeJob.purgeNow();
+ }
+ else if ("dbMaintenance".equals(mode))
+ {
+ systemManager.vacuum(subjectManager.getOverlord());
+ systemManager.reindex(subjectManager.getOverlord());
+ systemManager.analyze(subjectManager.getOverlord());
+ }
+ else if ("metricDisplayRange".equals(mode))
+ {
+ int lastHours = Integer.parseInt(pageContext.getRequest().getParameter("lastHours"));
+ Subject subject = WebUtility.getSubject(request);
+ MeasurementPreferences prefs = new MeasurementPreferences(subject);
+ MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
+ rangePrefs.lastN = lastHours;
+ prefs.setMetricRangePreferences(rangePrefs);
+ }
+ else if ("errorCorrectSchedules".equals("mode"))
+ {
+ measurementScheduleManager.errorCorrectSchedules();
+ }
+ else if ("generateSnapshotReport".equals(mode))
+ {
+ int resourceId = Integer.parseInt(request.getParameter("resourceId"));
+ String name = request.getParameter("name");
+ String description = request.getParameter("description");
+ java.net.URL url = supportManager.getSnapshotReport(subjectManager.getOverlord(), resourceId, name, description);
+ result = "Snapshot Report is located here: " + url.toString();
+ }
+ else if ("purgeServerPlugin".equals(mode))
+ {
+ String serverPluginName = request.getParameter("serverPluginName");
+ serverPlugins.purgeServerPlugin(subjectManager.getOverlord(), serverPluginName);
+ result = "OK - you can now try to re-register a plugin with the name [" + serverPluginName + "]";
+ }
+ else if ("typeManagerRemote".equals(mode))
+ {
+ int typeId = Integer.parseInt(request.getParameter("typeId"));
+ ResourceTypeCriteria criteria = new ResourceTypeCriteria();
+ criteria.addFilterId(typeId);
+ criteria.fetchMetricDefinitions(true);
+ java.util.List<ResourceType> types = typeManager.findResourceTypesByCriteria(subjectManager.getOverlord(), criteria);
+ result = "";
+ for (ResourceType type : types) {
+ result += type.getName() + " has " + (type.getMetricDefinitions() != null ? type.getMetricDefinitions().size() : "empty") + " metric definitions";
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ e.printStackTrace(new PrintStream(baos));
+ failure = baos.toString();
+ }
+
+ pageContext.setAttribute("executed", mode);
+ pageContext.setAttribute("result", result);
+ pageContext.setAttribute("failure", failure);
+ pageContext.setAttribute("testAgentReported", Boolean.valueOf(coreTestBean.isTestAgentReported()));
+
+%>
+
+<c:if test="${executed != null}">
+ <b>Executed <c:out value="${executed}"/>: </b> <c:out value="${result}"/><br>
+ <c:if test="${failure != null}">
+ <pre style="background-color: yellow;"><c:out value="${failure}"/></pre>
+ </c:if>
+</c:if>
+
+<h2>Administration</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
+Add Lots of Users and Roles
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="addSubjectsAndRoles"/>
+ Number of Roles: <input type="text" name="roleCount" size="5"/><br/>
+ Number of Users in each Role: <input type="text" name="usersInRoleCount" size="5"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
+ <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
+</ul>
+
+<h2>Core</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestAgent"/>
+ <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=dbMaintenance"/>
+ <a href="<c:out value="${url}"/>">Perform All Database Maintenance Now</a></li>
+</ul>
+
+<h2>Cluster</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=clusterGetIdentity"/>
+ <a href="<c:out value="${url}"/>">Get Identity</a> <c:out value="${serverName}"/></li>
+</ul>
+
+<h2>Inventory</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestFullInventoryReport"/>
+ <a href="<c:out value="${url}"/>">Send Full Inventory Report</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestRuntimeInventoryReport"/>
+ <a href="<c:out value="${url}"/>">Send Runtime Inventory Report</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setupCompatibleGroups"/>
+ <a href="<c:out value="${url}"/>">Setup Compatible Groups</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setupUberMixedGroup"/>
+ <a href="<c:out value="${url}"/>">Setup Uber Mixed Group</a></li>
+</ul>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=sendNewPlatform"/>
+Send New Platform Inventory Report
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="sendNewPlatform"/>
+ Address: <input type="text" name="address" size="30"/><br/>
+ Servers: <input type="text" name="servers" size="5"/><br/>
+ Services Per Server: <input type="text" name="servicesPerServer" size="5"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+
+<h2>Measurement</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateAutoBaselines"/>
+ <a href="<c:out value="${url}"/>">Calculate Auto Baselines</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestMeasurementReport"/>
+ <a href="<c:out value="${url}"/>">Send Measurement Report</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=addProblemResource"/>
+ <a href="<c:out value="${url}"/>">Add problem Resource</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=100"/>
+ <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 100</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=50"/>
+ <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 50</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=checkForSuspectAgents"/>
+ <a href="<c:out value="${url}"/>">Check For Suspect Agents</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=dataPurgeJob"/>
+ <a href="<c:out value="${url}"/>">Force Data Purge Now</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateOOBs"/>
+ <a href="<c:out value="${url}"/>">Force calculation of OOBs</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=errorCorrectSchedules"/>
+ <a href="<c:out value="${url}"/>">Error-Correct Measurement Schedules</a></li>
+</ul>
+
+<h2>Alerts</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=cloneAlertTemplate"/>
+Template Cloning
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="cloneAlertTemplate"/>
+ Alert Template ID: <input type="text" name="alertTemplateId" size="5"/><br/>
+ Number of Clones: <input type="text" name="numberOfClones" size="5"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+<h2>Utilities</h2>
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=startStats"/>
+ <a href="<c:out value="${url}"/>">Start Hibernate Statistics Collection</a></li>
+</ul>
+
+
+<h2>User Preferences</h2>
+<%
+ Subject subject = WebUtility.getSubject(request);
+ MeasurementPreferences prefs = new MeasurementPreferences(subject);
+ MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
+ pageContext.setAttribute("lastHours", String.valueOf(rangePrefs.lastN));
+%>
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="metricDisplayRange"/>
+ Last X hours: <input type="text" name="lastHours" size="5" value="<c:out value="${lastHours}"/>"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+<h2>Snapshot Report</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=generateSnapshotReport"/>
+Generate Snapshot Report
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="generateSnapshotReport"/>
+ Resource ID: <input type="text" name="resourceId" size="10"/><br/>
+ Name: <input type="text" name="name" size="30"/><br/>
+ Description: <input type="text" name="description" size="100"/><br/>
+ <input type="submit" value="Generate Snapshot" name="Generate Snapshot"/>
+</form>
+
+<h2>Server Plugins</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=purgeServerPlugin"/>
+Purge Server Plugin (allowing you to re-register it again later)
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="purgeServerPlugin"/>
+ ServerPluginName: <input type="text" name="serverPluginName" size="30"/><br/>
+ <input type="submit" value="Purge Server Plugin" name="Purge Server Plugin"/>
+</form>
+
+<h2>Resource Type Criteria</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=typeManagerRemote"/>
+Query ResourceTypes by Criteria
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="typeManagerRemote"/>
+ ResourceType ID: <input type="text" name="typeId" size="10"/><br/>
+ <input type="submit" value="Query by Criteria" name="Query by Criteria"/>
+</form>
+
+
+
+</body>
+</html>
commit f04ef82719012571ecfa157eb270c6b0424ad0ac
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 22 22:39:34 2009 -0500
mistakenly deleted the html tag, put it back
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
index 4d5cfd5..a7c0cbc 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
@@ -38,7 +38,7 @@
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-
+<html>
<head><title>RHQ Test Control Page</title></head>
<body>
commit a5fcd064dc1d1eea47c2806754c3244e1c000235
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 22 01:59:12 2009 -0500
since there is no current way to "revive" a undeployed plugin from the real GUI, at least provide _some_ way to get back to a state that will let you re-register a plugin again using the test control.jsp page
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
index f3f0a35..4d5cfd5 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
@@ -24,6 +24,7 @@
<%@ page import="org.rhq.enterprise.server.system.SystemManagerLocal" %>
<%@ page import="org.rhq.enterprise.server.auth.SubjectManagerLocal" %>
<%@ page import="org.rhq.enterprise.server.support.SupportManagerLocal" %>
+<%@page import="org.rhq.enterprise.server.plugin.ServerPluginsLocal"%><html>
<%@ page import="org.rhq.enterprise.server.util.LookupUtil" %>
<%@ page import="org.rhq.enterprise.server.scheduler.jobs.DataPurgeJob"%>
@@ -37,7 +38,7 @@
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-<html>
+
<head><title>RHQ Test Control Page</title></head>
<body>
@@ -58,6 +59,7 @@
SubjectManagerLocal subjectManager;
SupportManagerLocal supportManager;
ResourceTypeManagerRemote typeManager;
+ ServerPluginsLocal serverPlugins;
coreTestBean = LookupUtil.getCoreTest();
discoveryTestBean = LookupUtil.getDiscoveryTest();
@@ -73,6 +75,7 @@
subjectManager = LookupUtil.getSubjectManager();
supportManager = LookupUtil.getSupportManager();
typeManager = LookupUtil.getResourceTypeManagerRemote();
+ serverPlugins = LookupUtil.getServerPlugins();
String result = null;
String mode = pageContext.getRequest().getParameter("mode");
@@ -197,6 +200,12 @@
java.net.URL url = supportManager.getSnapshotReport(subjectManager.getOverlord(), resourceId, name, description);
result = "Snapshot Report is located here: " + url.toString();
}
+ else if ("purgeServerPlugin".equals(mode))
+ {
+ String serverPluginName = request.getParameter("serverPluginName");
+ serverPlugins.purgeServerPlugin(subjectManager.getOverlord(), serverPluginName);
+ result = "OK - you can now try to re-register a plugin with the name [" + serverPluginName + "]";
+ }
else if ("typeManagerRemote".equals(mode))
{
int typeId = Integer.parseInt(request.getParameter("typeId"));
@@ -362,6 +371,16 @@ Generate Snapshot Report
<input type="submit" value="Generate Snapshot" name="Generate Snapshot"/>
</form>
+<h2>Server Plugins</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=purgeServerPlugin"/>
+Purge Server Plugin (allowing you to re-register it again later)
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="purgeServerPlugin"/>
+ ServerPluginName: <input type="text" name="serverPluginName" size="30"/><br/>
+ <input type="submit" value="Purge Server Plugin" name="Purge Server Plugin"/>
+</form>
+
<h2>Resource Type Criteria</h2>
<c:url var="url" value="/admin/test/control.jsp?mode=typeManagerRemote"/>
commit 5413dbb476c615effd97d698ae54b051bcfa02c5
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sat Nov 21 16:17:38 2009 -0500
actually remove all jobs for the undeployed server plugin
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 8a4ab80..3697caa 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -235,6 +235,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
}
+ log.info("Server plugins " + doomedPlugins + " have been undeployed");
+
// only restart if the master was started to begin with; otherwise, leave it down
if (master != null) {
serverPluginService.restartMasterPluginContainer();
@@ -257,6 +259,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
throw new Exception("Failed to update [" + pluginIds.size() + "] plugins. Count was [" + count + "]");
}
+ log.info((enabled ? "Enabling" : "Disabling") + " server plugins with plugin IDs of " + pluginIds);
return;
}
@@ -324,7 +327,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
entityManager.flush();
streamPluginFileContentToDatabase(plugin.getId(), pluginFile);
}
- log.debug("Updated plugin entity [" + plugin + "]");
+ log.info("Server plugin [" + plugin.getName() + "] has been registered in the database");
}
return plugin;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
index 3256bf5..e88e5fd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/AbstractTypeServerPluginContainer.java
@@ -235,7 +235,21 @@ public abstract class AbstractTypeServerPluginContainer {
*/
public void unschedulePluginJobs(String pluginName) throws Exception {
SchedulerLocal scheduler = LookupUtil.getSchedulerBean();
- scheduler.resumeJobGroup(pluginName);
+
+ // note: all jobs for a plugin are placed in the same group, where the group name is the plugin name
+ String groupName = pluginName;
+
+ scheduler.pauseJobGroup(groupName);
+ String[] jobNames = scheduler.getJobNames(groupName);
+ if (jobNames != null) {
+ for (String jobName : jobNames) {
+ boolean deleted = scheduler.deleteJob(jobName, groupName);
+ if (!deleted) {
+ log.warn("Plugin [" + pluginName + "] failed to get its job [" + jobName + "] unscheduled!");
+ }
+ }
+ }
+
return;
}
commit 1093e91f666af1848a7bd5d4fb93ed6cdb9b9c50
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sat Nov 21 13:24:26 2009 -0500
provide API that will allow us to later build a user interface to "resurrect" a deleted plugin - to re-install it if it was undelpoyed before.
this also fixes some tests - server/jar and core/domain plugin tests now all pass properly
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index 67ffc53..eda26d8 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -114,6 +114,31 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " LEFT JOIN p.scheduledJobsConfiguration " //
+ " WHERE p.name=:name AND p.status = 'INSTALLED' "), //
+ // gets the plugin, even if it is deleted
+ // this query does not load the content blob, but loads everything else
+ @NamedQuery(name = Plugin.QUERY_FIND_ANY_BY_NAME_AND_TYPE, query = "" //
+ + " SELECT new org.rhq.core.domain.plugin.Plugin( " //
+ + " p.id, " //
+ + " p.name, " //
+ + " p.path, " //
+ + " p.displayName, " //
+ + " p.enabled, " //
+ + " p.status, " //
+ + " p.description, " //
+ + " p.help, " //
+ + " p.md5, " //
+ + " p.version, " //
+ + " p.ampsVersion, " //
+ + " p.deployment, " //
+ + " p.pluginConfiguration, " //
+ + " p.scheduledJobsConfiguration, " //
+ + " p.ctime, " //
+ + " p.mtime) " //
+ + " FROM Plugin AS p " //
+ + " LEFT JOIN p.pluginConfiguration " //
+ + " LEFT JOIN p.scheduledJobsConfiguration " //
+ + " WHERE p.name=:name AND p.deployment = :type "), //
+
// this query does not load the content blob, but loads everything else
@NamedQuery(name = Plugin.QUERY_FIND_ALL_AGENT, query = "" //
+ " SELECT new org.rhq.core.domain.plugin.Plugin( " //
@@ -227,6 +252,7 @@ public class Plugin implements Serializable {
public static final String QUERY_FIND_ALL_AGENT = "Plugin.findAllAgent";
public static final String QUERY_FIND_ALL_SERVER = "Plugin.findAllServer";
public static final String QUERY_FIND_BY_NAME = "Plugin.findByName";
+ public static final String QUERY_FIND_ANY_BY_NAME_AND_TYPE = "Plugin.findAnyByNameAndType";
public static final String QUERY_FIND_BY_IDS_AND_TYPE = "Plugin.findByIdsAndType";
public static final String QUERY_GET_NAMES_BY_ENABLED_AND_TYPE = "Plugin.findByEnabledAndType";
public static final String QUERY_GET_STATUS_BY_NAME_AND_TYPE = "Plugin.getStatusByNameAndType";
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index 8ab3171..07f8f97 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -48,7 +48,7 @@ import org.rhq.core.util.stream.StreamUtil;
@Test
public class PluginTest extends AbstractEJB3Test {
- public void testUpdate() throws Exception {
+ public void testUpdate() throws Throwable {
boolean done = false;
getTransactionManager().begin();
EntityManager em = getEntityManager();
@@ -81,8 +81,8 @@ public class PluginTest extends AbstractEJB3Test {
em.persist(plugin);
id = plugin.getId();
assert id > 0;
- assert plugin.getPluginConfiguration().getId() > 0 : "did not persist config";
- assert plugin.getScheduledJobsConfiguration().getId() > 0 : "did not persist jobs config";
+ assert plugin.getPluginConfiguration() == null : "there was no config that should have been here";
+ assert plugin.getScheduledJobsConfiguration() == null : "there was no config that should have been here";
q = em.createNamedQuery(Plugin.QUERY_GET_STATUS_BY_NAME_AND_TYPE);
q.setParameter("name", plugin.getName());
@@ -127,6 +127,10 @@ public class PluginTest extends AbstractEJB3Test {
getTransactionManager().begin();
em = getEntityManager();
+ em.persist(pluginConfig);
+ em.persist(jobsConfig);
+ em.flush(); // gotta get those two persists to flush to the DB
+
q = em.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
q.setParameter("id", id); // same as the one we just persisted
q.setParameter("name", name);
@@ -173,12 +177,19 @@ public class PluginTest extends AbstractEJB3Test {
getTransactionManager().commit();
getTransactionManager().begin();
em = getEntityManager();
- em.createNativeQuery("DELETE FROM " + Plugin.TABLE_NAME + " WHERE ID = " + id).executeUpdate();
+ q = em.createNamedQuery(Plugin.QUERY_FIND_ANY_BY_NAME_AND_TYPE);
+ q.setParameter("name", plugin.getName());
+ q.setParameter("type", plugin.getDeployment());
+ Plugin doomed = (Plugin) q.getSingleResult();
+ doomed = em.getReference(Plugin.class, doomed.getId());
+ em.remove(doomed);
+ assert q.getResultList().size() == 0 : "didn't remove the plugin";
em.close();
getTransactionManager().commit();
done = true;
} catch (Throwable t) {
t.printStackTrace();
+ throw t;
} finally {
if (!done) {
getTransactionManager().rollback();
@@ -486,7 +497,13 @@ public class PluginTest extends AbstractEJB3Test {
getTransactionManager().commit();
getTransactionManager().begin();
em = getEntityManager();
- em.createNativeQuery("DELETE FROM " + Plugin.TABLE_NAME + " WHERE ID = " + plugin.getId()).executeUpdate();
+ Query q = em.createNamedQuery(Plugin.QUERY_FIND_ANY_BY_NAME_AND_TYPE);
+ q.setParameter("name", plugin.getName());
+ q.setParameter("type", plugin.getDeployment());
+ Plugin doomed = (Plugin) q.getSingleResult();
+ doomed = em.getReference(Plugin.class, doomed.getId());
+ em.remove(doomed);
+ assert q.getResultList().size() == 0 : "didn't remove the plugin";
em.close();
getTransactionManager().commit();
done = true;
@@ -595,8 +612,13 @@ public class PluginTest extends AbstractEJB3Test {
getTransactionManager().commit();
getTransactionManager().begin();
em = getEntityManager();
- em.createNativeQuery("DELETE FROM " + Plugin.TABLE_NAME + " WHERE ID = " + plugin.getId()).executeUpdate();
- em.close();
+ Query q = em.createNamedQuery(Plugin.QUERY_FIND_ANY_BY_NAME_AND_TYPE);
+ q.setParameter("name", plugin.getName());
+ q.setParameter("type", plugin.getDeployment());
+ Plugin doomed = (Plugin) q.getSingleResult();
+ doomed = em.getReference(Plugin.class, doomed.getId());
+ em.remove(doomed);
+ assert q.getResultList().size() == 0 : "didn't remove the plugin";
getTransactionManager().commit();
done = true;
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 67d5efd..8a4ab80 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -44,6 +44,7 @@ import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
import org.rhq.core.domain.plugin.PluginStatusType;
@@ -213,8 +214,14 @@ public class ServerPluginsBean implements ServerPluginsLocal {
// if this plugin ever gets re-installed, let's support the use-case where the new plugin
// will have different config metadata. Here we null out the old config so the new
// config can be set to the new cofig definition's default values.
- doomedPlugin.setPluginConfiguration(null);
- doomedPlugin.setScheduledJobsConfiguration(null);
+ if (doomedPlugin.getPluginConfiguration() != null) {
+ entityManager.remove(doomedPlugin.getPluginConfiguration());
+ doomedPlugin.setPluginConfiguration(null);
+ }
+ if (doomedPlugin.getScheduledJobsConfiguration() != null) {
+ entityManager.remove(doomedPlugin.getScheduledJobsConfiguration());
+ doomedPlugin.setScheduledJobsConfiguration(null);
+ }
doomedPlugin.setStatus(PluginStatusType.DELETED);
try {
@@ -324,6 +331,22 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public void purgeServerPlugin(Subject subject, String pluginName) {
+ Query q = this.entityManager.createNamedQuery(Plugin.QUERY_FIND_ANY_BY_NAME_AND_TYPE);
+ q.setParameter("name", pluginName);
+ q.setParameter("type", PluginDeploymentType.SERVER);
+ Plugin doomed = (Plugin) q.getSingleResult();
+
+ // get the reference to attach to em and use the em.remove. this cascade deletes too.
+ doomed = this.entityManager.getReference(Plugin.class, doomed.getId());
+ this.entityManager.remove(doomed);
+
+ log.debug("Server plugin [" + pluginName + "] has been purged from the db");
+ return;
+ }
+
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
public Plugin updateServerPluginExceptContent(Subject subject, Plugin plugin) throws Exception {
// this method is here because we need a way to update the plugin's information
@@ -339,6 +362,35 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (plugin.getId() == 0) {
throw new IllegalArgumentException("Plugin must already exist to update it");
} else {
+ // make sure the configs are in the DB properly and we have their refs
+ // this is because we are using JPQL update, so we need to do some of this "manually"
+ boolean needFlush = false;
+ Configuration config = plugin.getPluginConfiguration();
+ if (config != null) {
+ if (config.getId() > 0) {
+ config = entityManager.getReference(Configuration.class, config.getId());
+ plugin.setPluginConfiguration(config);
+ } else {
+ entityManager.persist(config);
+ needFlush = true;
+ }
+ }
+ config = plugin.getScheduledJobsConfiguration();
+ if (config != null) {
+ if (config.getId() > 0) {
+ config = entityManager.getReference(Configuration.class, config.getId());
+ plugin.setScheduledJobsConfiguration(config);
+ } else {
+ entityManager.persist(config);
+ needFlush = true;
+ }
+ }
+ if (needFlush) {
+ entityManager.flush(); // must be flushed to the DB so the JPQL update below works
+ }
+
+ // now we can JPQL update the row - all but content is updated here.
+ // we assured our configs are persisted/attached above
Query q = entityManager.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
q.setParameter("id", plugin.getId());
q.setParameter("name", plugin.getName());
@@ -350,14 +402,16 @@ public class ServerPluginsBean implements ServerPluginsLocal {
q.setParameter("version", plugin.getVersion());
q.setParameter("ampsVersion", plugin.getAmpsVersion());
q.setParameter("deployment", plugin.getDeployment());
- q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
- q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
+ q.setParameter("pluginConfiguration", config);
+ q.setParameter("scheduledJobsConfiguration", config);
q.setParameter("description", plugin.getDescription());
q.setParameter("help", plugin.getHelp());
q.setParameter("mtime", plugin.getMtime());
if (q.executeUpdate() != 1) {
throw new Exception("Failed to update a plugin that matches [" + plugin + "]");
}
+
+ entityManager.flush(); // make sure we push this out to the DB now
}
return plugin;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index 68afc0e..6f3600e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -126,7 +126,8 @@ public interface ServerPluginsLocal {
void setServerPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status) throws Exception;
/**
- * Registers the given plugin to the database.
+ * Registers the given plugin to the database. This does nothing with the master plugin container,
+ * all it does is ensure the database is up-to-date with this new plugin.
*
* @param subject the user that needs to have permissions to add a plugin to the system
* @param plugin the plugin definition
@@ -149,6 +150,20 @@ public interface ServerPluginsLocal {
Plugin updateServerPluginExceptContent(Subject subject, Plugin plugin) throws Exception;
/**
+ * Purges the server plugin from the database. This ensures that, after this method returns,
+ * the given plugin will be unknown. The plugin can be installed again later.
+ *
+ * This has "requires new" semantics, so the results are committed immediately upon return.
+ * This is really a supporting method for {@link #reRegisterServerPlugin(Subject, Plugin, File)} - you'll
+ * probably want to use that instead. Do not blindly purge server plugins using this method unless you
+ * know what you are doing.
+ *
+ * @param subject user making the request
+ * @param pluginName the name of the server plugin to delete
+ */
+ void purgeServerPlugin(Subject subject, String pluginName);
+
+ /**
* Given the name of a server plugin, this will return the status of that plugin.
* Use this to determine if a plugin has been deleted or not.
*
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
index 8250c7d..9c971e0 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
@@ -50,6 +50,7 @@ import org.rhq.core.clientapi.descriptor.AgentPluginDescriptorUtil;
import org.rhq.core.clientapi.descriptor.plugin.PluginDescriptor;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
+import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.content.PackageType;
import org.rhq.core.domain.event.EventDefinition;
@@ -196,6 +197,33 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
if (plugin.getId() == 0) {
entityManager.persist(plugin);
} else {
+ // agent plugins don't support these configs, but if/when they do in the future, this will support it
+ boolean needFlush = false;
+ Configuration config = plugin.getPluginConfiguration();
+ if (config != null) {
+ if (config.getId() > 0) {
+ config = entityManager.getReference(Configuration.class, config.getId());
+ plugin.setPluginConfiguration(config);
+ } else {
+ entityManager.persist(config);
+ needFlush = true;
+ }
+ }
+ config = plugin.getScheduledJobsConfiguration();
+ if (config != null) {
+ if (config.getId() > 0) {
+ config = entityManager.getReference(Configuration.class, config.getId());
+ plugin.setScheduledJobsConfiguration(config);
+ } else {
+ entityManager.persist(config);
+ needFlush = true;
+ }
+ }
+ if (needFlush) {
+ entityManager.flush(); // must be flushed to the DB so the JPQL update below works
+ }
+
+ // update all the fields except content
Query q = entityManager.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
q.setParameter("id", plugin.getId());
q.setParameter("name", plugin.getName());
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
index d5817a2..e1796bf 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
@@ -74,10 +74,11 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
getTransactionManager().begin();
em = getEntityManager();
- Query q = em.createQuery("SELECT p FROM Plugin p WHERE p.name LIKE 'serverplugintest%'");
+ Query q = em
+ .createQuery("SELECT p FROM Plugin p LEFT JOIN FETCH p.pluginConfiguration LEFT JOIN FETCH p.scheduledJobsConfiguration WHERE p.name LIKE 'serverplugintest%'");
List<Plugin> doomed = q.getResultList();
for (Plugin plugin : doomed) {
- em.remove(plugin);
+ em.remove(em.getReference(Plugin.class, plugin.getId()));
}
getTransactionManager().commit();
@@ -207,17 +208,70 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(true);
assert !pluginNames.contains(p1.getName()) : pluginNames;
assert !pluginNames.contains(p2.getName()) : pluginNames;
+ }
+
+ public void testReRegisterPlugins() throws Exception {
+
+ PluginStatusType status;
+
+ status = this.serverPluginsBean.getServerPluginStatus(TEST_PLUGIN_NAME_PREFIX + "1");
+ assert status == null;
+ status = this.serverPluginsBean.getServerPluginStatus(TEST_PLUGIN_NAME_PREFIX + "2");
+ assert status == null;
+
+ Plugin p1 = registerPlugin(1);
+ Plugin p2 = registerPlugin(2);
+
+ status = this.serverPluginsBean.getServerPluginStatus(p1.getName());
+ assert status == PluginStatusType.INSTALLED;
+ status = this.serverPluginsBean.getServerPluginStatus(p2.getName());
+ assert status == PluginStatusType.INSTALLED;
- // re-install them - need to implement this feature
- // this.serverPluginsBean.enableServerPlugins(getOverlord(), ids);
- // pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
- // assert pluginNames.contains(p1.getName()) : pluginNames;
- // assert pluginNames.contains(p2.getName()) : pluginNames;
- // assert undeployed.get(0).getStatus() == PluginStatusType.INSTALLED;
- // assert undeployed.get(1).getStatus() == PluginStatusType.INSTALLED;
- // pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
- // assert !pluginNames.contains(p1.getName()) : pluginNames;
- // assert !pluginNames.contains(p2.getName()) : pluginNames;
+ List<Integer> ids = new ArrayList<Integer>(2);
+ ids.add(p1.getId());
+ ids.add(p2.getId());
+ List<Plugin> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
+ assert undeployed.size() == 2 : undeployed;
+ assert undeployed.contains(p1) : undeployed;
+ assert undeployed.contains(p2) : undeployed;
+ assert undeployed.get(0).getStatus() == PluginStatusType.DELETED;
+ assert undeployed.get(0).getPluginConfiguration() == null; // undeploy should have removed this
+ assert undeployed.get(0).getScheduledJobsConfiguration() == null; // undeploy should have removed this
+ assert undeployed.get(1).getStatus() == PluginStatusType.DELETED;
+ assert undeployed.get(1).getPluginConfiguration() == null; // undeploy should have removed this
+ assert undeployed.get(1).getScheduledJobsConfiguration() == null; // undeploy should have removed this
+
+ List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
+ assert !pluginNames.contains(p1.getName()) : "deleted plugins should not be returned even here" + pluginNames;
+ assert !pluginNames.contains(p2.getName()) : "deleted plugins should not be returned even here" + pluginNames;
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(true);
+ assert !pluginNames.contains(p1.getName()) : pluginNames;
+ assert !pluginNames.contains(p2.getName()) : pluginNames;
+
+ // purge them completely from the DB to prepare to re-register them
+ this.serverPluginsBean.purgeServerPlugin(getOverlord(), p1.getName());
+ this.serverPluginsBean.purgeServerPlugin(getOverlord(), p2.getName());
+
+ // we just purged the database, make sure our entity ID's are all zero, since the original IDs are gone
+ p1.setId(0);
+ p2.setId(0);
+ p1.setPluginConfiguration(p1.getPluginConfiguration().deepCopy(false));
+ p2.setPluginConfiguration(p2.getPluginConfiguration().deepCopy(false));
+ p1.setScheduledJobsConfiguration(p1.getScheduledJobsConfiguration().deepCopy(false));
+ p2.setScheduledJobsConfiguration(p2.getScheduledJobsConfiguration().deepCopy(false));
+
+ // re-register them now
+ Plugin p1again = this.serverPluginsBean.registerServerPlugin(getOverlord(), p1, null);
+ Plugin p2again = this.serverPluginsBean.registerServerPlugin(getOverlord(), p2, null);
+
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(true);
+ assert pluginNames.contains(p1.getName()) : pluginNames;
+ assert pluginNames.contains(p2.getName()) : pluginNames;
+ assert p1again.getStatus() == PluginStatusType.INSTALLED;
+ assert p2again.getStatus() == PluginStatusType.INSTALLED;
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
+ assert !pluginNames.contains(p1.getName()) : pluginNames;
+ assert !pluginNames.contains(p2.getName()) : pluginNames;
}
private Plugin registerPlugin(int index) throws Exception {
commit 45180dcd79713f2f29e7051b2f1bed396dce9d2b
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sat Nov 21 10:42:18 2009 -0500
do not attempt to register plugins that were previously undeployed.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index 552179f..67ffc53 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -56,6 +56,11 @@ import org.rhq.core.util.MessageDigestGenerator;
@Entity
@NamedQueries( {
//
+ @NamedQuery(name = Plugin.QUERY_GET_STATUS_BY_NAME_AND_TYPE, query = "" //
+ + " SELECT p.status " //
+ + " FROM Plugin AS p " //
+ + " WHERE p.name = :name AND p.deployment = :type "), //
+
@NamedQuery(name = Plugin.QUERY_GET_NAMES_BY_ENABLED_AND_TYPE, query = "" //
+ " SELECT p.name " //
+ " FROM Plugin AS p " //
@@ -224,6 +229,7 @@ public class Plugin implements Serializable {
public static final String QUERY_FIND_BY_NAME = "Plugin.findByName";
public static final String QUERY_FIND_BY_IDS_AND_TYPE = "Plugin.findByIdsAndType";
public static final String QUERY_GET_NAMES_BY_ENABLED_AND_TYPE = "Plugin.findByEnabledAndType";
+ public static final String QUERY_GET_STATUS_BY_NAME_AND_TYPE = "Plugin.getStatusByNameAndType";
public static final String UPDATE_ALL_BUT_CONTENT = "Plugin.updateAllButContent";
public static final String UPDATE_PLUGINS_ENABLED_BY_IDS = "Plugin.updatePluginsEnabledByIds";
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index 7e3ad25..8ab3171 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -73,12 +73,22 @@ public class PluginTest extends AbstractEJB3Test {
plugin.setHelp(null);
plugin.setContent(content);
+ Query q = em.createNamedQuery(Plugin.QUERY_GET_STATUS_BY_NAME_AND_TYPE);
+ q.setParameter("name", plugin.getName());
+ q.setParameter("type", plugin.getDeployment());
+ assert q.getResultList().size() == 0; // not in the db yet
+
em.persist(plugin);
id = plugin.getId();
assert id > 0;
assert plugin.getPluginConfiguration().getId() > 0 : "did not persist config";
assert plugin.getScheduledJobsConfiguration().getId() > 0 : "did not persist jobs config";
+ q = em.createNamedQuery(Plugin.QUERY_GET_STATUS_BY_NAME_AND_TYPE);
+ q.setParameter("name", plugin.getName());
+ q.setParameter("type", plugin.getDeployment());
+ assert ((PluginStatusType) q.getSingleResult()) == PluginStatusType.INSTALLED;
+
plugin = em.find(Plugin.class, id);
assert plugin != null;
assert plugin.getId() == id;
@@ -117,7 +127,7 @@ public class PluginTest extends AbstractEJB3Test {
getTransactionManager().begin();
em = getEntityManager();
- Query q = em.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
+ q = em.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
q.setParameter("id", id); // same as the one we just persisted
q.setParameter("name", name);
q.setParameter("path", path);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
index a172719..6bd8c0f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
@@ -53,6 +53,7 @@ import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.core.domain.plugin.PluginStatusType;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.jdbc.JDBCUtil;
import org.rhq.core.util.stream.StreamUtil;
@@ -175,8 +176,17 @@ public class ServerPluginScanner {
}
ServerPluginsLocal serverPluginsManager = LookupUtil.getServerPlugins();
- SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
- serverPluginsManager.registerPlugin(subjectManager.getOverlord(), plugin, pluginFile);
+
+ // see if this plugin has been deleted previously; if so, don't register and delete the file
+ PluginStatusType status = serverPluginsManager.getServerPluginStatus(pluginName);
+ if (PluginStatusType.DELETED == status) {
+ log.warn("Plugin file [" + pluginFile + "] has been detected but that plugin with name [" + pluginName
+ + "] was previously undeployed. Will not re-register that plugin and the file will be deleted.");
+ pluginFile.delete();
+ } else {
+ SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
+ serverPluginsManager.registerServerPlugin(subjectManager.getOverlord(), plugin, pluginFile);
+ }
} catch (Exception e) {
log.error("Failed to register RHQ plugin file [" + pluginFile + "]", e);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 577ea92..67d5efd 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -121,7 +121,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return descriptor;
}
- public List<String> getPluginNamesByEnabled(boolean enabled) {
+ public List<String> getServerPluginNamesByEnabled(boolean enabled) {
Query query = entityManager.createNamedQuery(Plugin.QUERY_GET_NAMES_BY_ENABLED_AND_TYPE);
query.setParameter("enabled", Boolean.valueOf(enabled));
query.setParameter("type", PluginDeploymentType.SERVER);
@@ -134,7 +134,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return; // nothing to do
}
- serverPluginsBean.setPluginEnabledFlag(subject, pluginIds, true);
+ serverPluginsBean.setServerPluginEnabledFlag(subject, pluginIds, true);
// only restart the master if it was started to begin with
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
@@ -150,7 +150,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return new ArrayList<Plugin>(); // nothing to do
}
- serverPluginsBean.setPluginEnabledFlag(subject, pluginIds, false);
+ serverPluginsBean.setServerPluginEnabledFlag(subject, pluginIds, false);
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
@@ -188,7 +188,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return new ArrayList<Plugin>(); // nothing to do
}
- serverPluginsBean.setPluginEnabledFlag(subject, pluginIds, false);
+ serverPluginsBean.setServerPluginEnabledFlag(subject, pluginIds, false);
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
@@ -238,7 +238,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
@RequiredPermission(Permission.MANAGE_SETTINGS)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
- public void setPluginEnabledFlag(Subject subject, List<Integer> pluginIds, boolean enabled) throws Exception {
+ public void setServerPluginEnabledFlag(Subject subject, List<Integer> pluginIds, boolean enabled) throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
return; // nothing to do
}
@@ -255,20 +255,21 @@ public class ServerPluginsBean implements ServerPluginsLocal {
@RequiredPermission(Permission.MANAGE_SETTINGS)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
- public void setPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status) throws Exception {
+ public void setServerPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status)
+ throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
return; // nothing to do
}
List<Plugin> plugins = getServerPluginsById(pluginIds);
for (Plugin plugin : plugins) {
plugin.setStatus(status);
- updatePluginExceptContent(subject, plugin);
+ updateServerPluginExceptContent(subject, plugin);
}
return;
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
- public Plugin registerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception {
+ public Plugin registerServerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception {
if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
throw new IllegalArgumentException("Plugin [" + plugin.getName()
@@ -302,9 +303,14 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
if (plugin.getId() == 0) {
+ PluginStatusType status = getServerPluginStatus(plugin.getName());
+ if (PluginStatusType.DELETED == status) {
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
+ + "], it has been previously marked as deleted.");
+ }
entityManager.persist(plugin);
} else {
- plugin = updatePluginExceptContent(subject, plugin);
+ plugin = updateServerPluginExceptContent(subject, plugin);
}
if (pluginFile != null) {
@@ -318,11 +324,18 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
- public Plugin updatePluginExceptContent(Subject subject, Plugin plugin) throws Exception {
+ public Plugin updateServerPluginExceptContent(Subject subject, Plugin plugin) throws Exception {
+
// this method is here because we need a way to update the plugin's information
// without blowing away the content data. Because we do not want to load the
// content blob in memory, the plugin's content field will be null - if we were
// to entityManager.merge that plugin POJO, it would null out that blob column.
+
+ if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
+ throw new IllegalArgumentException("Plugin [" + plugin.getName()
+ + "] must be a server plugin to be updated");
+ }
+
if (plugin.getId() == 0) {
throw new IllegalArgumentException("Plugin must already exist to update it");
} else {
@@ -349,6 +362,19 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return plugin;
}
+ public PluginStatusType getServerPluginStatus(String pluginName) {
+ Query q = entityManager.createNamedQuery(Plugin.QUERY_GET_STATUS_BY_NAME_AND_TYPE);
+ q.setParameter("name", pluginName);
+ q.setParameter("type", PluginDeploymentType.SERVER);
+ PluginStatusType status;
+ try {
+ status = (PluginStatusType) q.getSingleResult();
+ } catch (NoResultException nre) {
+ status = null; // doesn't exist in the DB, tell the caller this by returning null
+ }
+ return status;
+ }
+
/**
* This will write the contents of the given plugin file to the database.
* This will assume the MD5 in the database is already correct, so this
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index 528d87c..68afc0e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -70,7 +70,7 @@ public interface ServerPluginsLocal {
* if <code>false</code>, return only the names of plugins that are disabled.
* @return list of plugin names that match the enabled criteria
*/
- List<String> getPluginNamesByEnabled(boolean enabled);
+ List<String> getServerPluginNamesByEnabled(boolean enabled);
/**
* Enables the plugins and restarts the server plugin container.
@@ -110,7 +110,7 @@ public interface ServerPluginsLocal {
* @param enabled the value of the enabled flag for the plugins
* @throws if failed to update a plugin
*/
- void setPluginEnabledFlag(Subject subject, List<Integer> pluginIds, boolean enabled) throws Exception;
+ void setServerPluginEnabledFlag(Subject subject, List<Integer> pluginIds, boolean enabled) throws Exception;
/**
* Sets the status flag in the database but does NOT restart the server plugin container.
@@ -123,7 +123,7 @@ public interface ServerPluginsLocal {
* @param enabled the value of the enabled flag for the plugins
* @throws if failed to update one of the plugins
*/
- void setPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status) throws Exception;
+ void setServerPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status) throws Exception;
/**
* Registers the given plugin to the database.
@@ -134,7 +134,7 @@ public interface ServerPluginsLocal {
* @return the plugin after being persisted
* @throws Exception if failed to fully register the plugin
*/
- Plugin registerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception;
+ Plugin registerServerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception;
/**
* Given a plugin that already exists, this will update that plugin's data in the database,
@@ -146,5 +146,15 @@ public interface ServerPluginsLocal {
* @return the updated plugin
* @throws Exception if the plugin did not already exist or an error occurred that caused the update to fail
*/
- public Plugin updatePluginExceptContent(Subject subject, Plugin plugin) throws Exception;
+ Plugin updateServerPluginExceptContent(Subject subject, Plugin plugin) throws Exception;
+
+ /**
+ * Given the name of a server plugin, this will return the status of that plugin.
+ * Use this to determine if a plugin has been deleted or not.
+ *
+ * @param pluginName the name of the plugin whose status is to be returned.
+ * @return the status of the plugin, to indicate if the plugin has been deleted or is installed.
+ * <code>null</code> indicates an unknown plugin.
+ */
+ PluginStatusType getServerPluginStatus(String pluginName);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index 40bb776..8ebabd4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -357,7 +357,7 @@ public class MasterServerPluginContainer {
* @return names of "blacklisted" plugins that should not be loaded
*/
protected List<String> getDisabledPluginNames() {
- List<String> disabledPlugins = LookupUtil.getServerPlugins().getPluginNamesByEnabled(false);
+ List<String> disabledPlugins = LookupUtil.getServerPlugins().getServerPluginNamesByEnabled(false);
return disabledPlugins;
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
index 3301ba0..d5817a2 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
@@ -46,6 +46,9 @@ import org.rhq.enterprise.server.util.LookupUtil;
*/
@Test
public class ServerPluginsBeanTest extends AbstractEJB3Test {
+
+ private static final String TEST_PLUGIN_NAME_PREFIX = "serverplugintest";
+
private ServerPluginsLocal serverPluginsBean;
@BeforeMethod
@@ -96,10 +99,10 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
public void testGetPlugins() throws Exception {
Plugin p1 = registerPlugin(1);
Plugin p2 = registerPlugin(2);
- List<String> pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(true);
assert pluginNames.contains(p1.getName()) : pluginNames;
assert pluginNames.contains(p2.getName()) : pluginNames;
- pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert !pluginNames.contains(p1.getName()) : pluginNames;
assert !pluginNames.contains(p2.getName()) : pluginNames;
@@ -144,19 +147,19 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
assert disabled.contains(p2) : disabled;
assert disabled.get(0).getStatus() == PluginStatusType.INSTALLED; // still installed
assert disabled.get(1).getStatus() == PluginStatusType.INSTALLED; // still installed
- List<String> pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert pluginNames.contains(p1.getName()) : pluginNames;
assert pluginNames.contains(p2.getName()) : pluginNames;
- pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(true);
assert !pluginNames.contains(p1.getName()) : pluginNames;
assert !pluginNames.contains(p2.getName()) : pluginNames;
// re-enable them
this.serverPluginsBean.enableServerPlugins(getOverlord(), ids);
- pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(true);
assert pluginNames.contains(p1.getName()) : pluginNames;
assert pluginNames.contains(p2.getName()) : pluginNames;
- pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert !pluginNames.contains(p1.getName()) : pluginNames;
assert !pluginNames.contains(p2.getName()) : pluginNames;
@@ -173,9 +176,21 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
public void testUndeployPlugins() throws Exception {
+ PluginStatusType status;
+
+ status = this.serverPluginsBean.getServerPluginStatus(TEST_PLUGIN_NAME_PREFIX + "1");
+ assert status == null;
+ status = this.serverPluginsBean.getServerPluginStatus(TEST_PLUGIN_NAME_PREFIX + "2");
+ assert status == null;
+
Plugin p1 = registerPlugin(1);
Plugin p2 = registerPlugin(2);
+ status = this.serverPluginsBean.getServerPluginStatus(p1.getName());
+ assert status == PluginStatusType.INSTALLED;
+ status = this.serverPluginsBean.getServerPluginStatus(p2.getName());
+ assert status == PluginStatusType.INSTALLED;
+
List<Integer> ids = new ArrayList<Integer>(2);
ids.add(p1.getId());
ids.add(p2.getId());
@@ -186,10 +201,10 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
assert undeployed.get(0).getStatus() == PluginStatusType.DELETED;
assert undeployed.get(1).getStatus() == PluginStatusType.DELETED;
- List<String> pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert !pluginNames.contains(p1.getName()) : "deleted plugins should not be returned even here" + pluginNames;
assert !pluginNames.contains(p2.getName()) : "deleted plugins should not be returned even here" + pluginNames;
- pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(true);
assert !pluginNames.contains(p1.getName()) : pluginNames;
assert !pluginNames.contains(p2.getName()) : pluginNames;
@@ -206,12 +221,12 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
}
private Plugin registerPlugin(int index) throws Exception {
- Plugin plugin = new Plugin(0, "serverplugintest" + index, "path", "displayName", true,
+ Plugin plugin = new Plugin(0, TEST_PLUGIN_NAME_PREFIX + index, "path", "displayName", true,
PluginStatusType.INSTALLED, "description", "help", "md5", "version", "ampsVersion",
PluginDeploymentType.SERVER, createPluginConfiguration(), createScheduledJobsConfiguration(), System
.currentTimeMillis(), System.currentTimeMillis());
- plugin = this.serverPluginsBean.registerPlugin(getOverlord(), plugin, null);
+ plugin = this.serverPluginsBean.registerServerPlugin(getOverlord(), plugin, null);
assert plugin.getId() > 0;
assert plugin.isEnabled() == true;
assert plugin.getDeployment() == PluginDeploymentType.SERVER;
commit 26c981d4720dbb65e02ea9ae5994d0888e8275c5
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 20 18:20:27 2009 -0500
do not stream plugins to filesystem if the database flagged it as deleted
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
index d6cf6fe..a172719 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
@@ -353,7 +353,7 @@ public class ServerPluginScanner {
// get all the plugins
ps = conn.prepareStatement("SELECT NAME, PATH, MD5, MTIME, VERSION FROM " + Plugin.TABLE_NAME
- + " WHERE DEPLOYMENT = 'SERVER'");
+ + " WHERE DEPLOYMENT = 'SERVER' AND STATUS = 'INSTALLED' ");
rs = ps.executeQuery();
while (rs.next()) {
String name = rs.getString(1);
@@ -451,7 +451,7 @@ public class ServerPluginScanner {
// write all our updated plugins to the file system
ps = conn.prepareStatement("SELECT CONTENT FROM " + Plugin.TABLE_NAME
- + " WHERE DEPLOYMENT = 'SERVER' AND NAME = ?");
+ + " WHERE DEPLOYMENT = 'SERVER' AND STATUS = 'INSTALLED' AND NAME = ?");
for (Plugin plugin : updatedPlugins) {
File file = new File(this.getServerPluginDir(), plugin.getPath());
@@ -516,8 +516,9 @@ public class ServerPluginScanner {
ResultSet rs = null;
TransactionManager tm = null;
- String sql = "UPDATE " + Plugin.TABLE_NAME
- + " SET CONTENT = ?, MD5 = ?, MTIME = ?, PATH = ? WHERE DEPLOYMENT = 'SERVER' AND NAME = ?";
+ String sql = "UPDATE "
+ + Plugin.TABLE_NAME
+ + " SET CONTENT = ?, MD5 = ?, MTIME = ?, PATH = ? WHERE DEPLOYMENT = 'SERVER' AND STATUS = 'INSTALLED' AND NAME = ?";
// if 'different' is true, give bogus data so the plugin deployer will think the plugin on the file system is new
String md5 = (!different) ? MessageDigestGenerator.getDigestString(file) : "TO BE UPDATED";
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index bfd828d..577ea92 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -284,6 +284,10 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
if (existingPlugin != null) {
+ if (existingPlugin.getStatus() == PluginStatusType.DELETED) {
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
+ + "], it has been marked as deleted");
+ }
Plugin obsolete = ServerPluginDescriptorUtil.determineObsoletePlugin(plugin, existingPlugin);
if (obsolete == existingPlugin) { // yes use == for reference equality
newOrUpdated = true;
commit 487407253bff60da59588b7bc814e6d14b0fb04c
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 20 17:47:29 2009 -0500
add the ability to mark a plugin DELETED. add authz to server plugin SLSB calls. add tests
diff --git a/modules/core/dbutils/pom.xml b/modules/core/dbutils/pom.xml
index 6f6f12b..8f466be 100644
--- a/modules/core/dbutils/pom.xml
+++ b/modules/core/dbutils/pom.xml
@@ -22,7 +22,7 @@
<properties>
<scm.module.path>modules/core/dbutils/</scm.module.path>
- <db.schema.version>2.69</db.schema.version>
+ <db.schema.version>2.69.1</db.schema.version>
</properties>
<dependencies>
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/amps-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/amps-schema.xml
index 5120803..dbc4a19 100644
--- a/modules/core/dbutils/src/main/scripts/dbsetup/amps-schema.xml
+++ b/modules/core/dbutils/src/main/scripts/dbsetup/amps-schema.xml
@@ -12,6 +12,7 @@
<column name="VERSION" size="200" type="VARCHAR2" required="false"/>
<column name="AMPS_VERSION" size="16" type="VARCHAR2" required="false"/>
<column name="ENABLED" type="BOOLEAN" required="true"/>
+ <column name="STATUS" size="16" type="VARCHAR2" required="true"/>
<column name="HELP" type="CLOB" required="false"/>
<column name="PATH" size="500" type="VARCHAR2" required="true"/>
<column name="MD5" size="100" type="VARCHAR2" required="true"/>
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 4cc035a..07831eb 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -2172,6 +2172,17 @@
</schema-directSQL>
</schemaSpec>
+ <schemaSpec version="2.69.1">
+ <!-- add the new column that indicates if this is plugin has been deleted -->
+ <schema-addColumn table="RHQ_PLUGIN" column="STATUS" columnType="VARCHAR2" precision="16"/>
+ <schema-directSQL>
+ <statement desc="Updating existing plugins with status of INSTALLED">
+ UPDATE RHQ_PLUGIN SET STATUS = 'INSTALLED'
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_PLUGIN" column="STATUS" nullable="FALSE"/>
+ </schemaSpec>
+
</dbupgrade>
</target>
</project>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index 2b3913d..552179f 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -59,7 +59,7 @@ import org.rhq.core.util.MessageDigestGenerator;
@NamedQuery(name = Plugin.QUERY_GET_NAMES_BY_ENABLED_AND_TYPE, query = "" //
+ " SELECT p.name " //
+ " FROM Plugin AS p " //
- + " WHERE p.enabled = :enabled AND p.deployment = :type"), //
+ + " WHERE p.enabled = :enabled AND p.deployment = :type AND p.status = 'INSTALLED' "), //
// this query does not load the content blob, but loads everything else
@NamedQuery(name = Plugin.QUERY_FIND_BY_IDS_AND_TYPE, query = "" //
@@ -69,6 +69,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.path, " //
+ " p.displayName, " //
+ " p.enabled, " //
+ + " p.status, " //
+ " p.description, " //
+ " p.help, " //
+ " p.md5, " //
@@ -82,7 +83,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " FROM Plugin AS p " //
+ " LEFT JOIN p.pluginConfiguration " //
+ " LEFT JOIN p.scheduledJobsConfiguration " //
- + " WHERE p.id IN (:ids) AND p.deployment = :type"), //
+ + " WHERE p.id IN (:ids) AND p.deployment = :type AND p.status = 'INSTALLED' "), //
// this query does not load the content blob, but loads everything else
@NamedQuery(name = Plugin.QUERY_FIND_BY_NAME, query = "" //
@@ -92,6 +93,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.path, " //
+ " p.displayName, " //
+ " p.enabled, " //
+ + " p.status, " //
+ " p.description, " //
+ " p.help, " //
+ " p.md5, " //
@@ -105,7 +107,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " FROM Plugin AS p " //
+ " LEFT JOIN p.pluginConfiguration " //
+ " LEFT JOIN p.scheduledJobsConfiguration " //
- + " WHERE p.name=:name"), //
+ + " WHERE p.name=:name AND p.status = 'INSTALLED' "), //
// this query does not load the content blob, but loads everything else
@NamedQuery(name = Plugin.QUERY_FIND_ALL_AGENT, query = "" //
@@ -115,6 +117,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.path, " //
+ " p.displayName, " //
+ " p.enabled, " //
+ + " p.status, " //
+ " p.description, " //
+ " p.help, " //
+ " p.md5, " //
@@ -128,7 +131,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " FROM Plugin AS p " //
+ " LEFT JOIN p.pluginConfiguration " //
+ " LEFT JOIN p.scheduledJobsConfiguration " //
- + " WHERE p.deployment = 'AGENT'"), //
+ + " WHERE p.deployment = 'AGENT' AND p.status = 'INSTALLED' "), //
// this query does not load the content blob, but loads everything else
@NamedQuery(name = Plugin.QUERY_FIND_ALL_SERVER, query = "" //
@@ -138,6 +141,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.path, " //
+ " p.displayName, " //
+ " p.enabled, " //
+ + " p.status, " //
+ " p.description, " //
+ " p.help, " //
+ " p.md5, " //
@@ -151,7 +155,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " FROM Plugin AS p " //
+ " LEFT JOIN p.pluginConfiguration " //
+ " LEFT JOIN p.scheduledJobsConfiguration " //
- + " WHERE p.deployment = 'SERVER'"), //
+ + " WHERE p.deployment = 'SERVER' AND p.status = 'INSTALLED' "), //
// this query does not update the content blob or ctime
@NamedQuery(name = Plugin.UPDATE_ALL_BUT_CONTENT, query = "" //
@@ -160,6 +164,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.displayName = :displayName, " //
+ " p.description = :description, " //
+ " p.enabled = :enabled, " //
+ + " p.status = :status, " //
+ " p.help = :help, " //
+ " p.version = :version, " //
+ " p.ampsVersion = :ampsVersion," //
@@ -185,6 +190,7 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " p.path, " //
+ " p.displayName, " //
+ " p.enabled, " //
+ + " p.status, " //
+ " p.description, " //
+ " p.help, " //
+ " p.md5, " //
@@ -198,7 +204,8 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " FROM Plugin p " //
+ " LEFT JOIN p.pluginConfiguration " //
+ " LEFT JOIN p.scheduledJobsConfiguration " //
- + " WHERE p.name IN ( SELECT rt.plugin " //
+ + " WHERE p.status = 'INSTALLED' AND " //
+ + " p.name IN ( SELECT rt.plugin " //
+ " FROM Resource res " //
+ " JOIN res.resourceType rt " //
+ " WHERE ( rt.category = :resourceCategory OR :resourceCategory IS NULL ) " //
@@ -249,6 +256,10 @@ public class Plugin implements Serializable {
@Column(name = "ENABLED", nullable = false)
private boolean enabled = true;
+ @Column(name = "STATUS", nullable = false)
+ @Enumerated(EnumType.STRING)
+ private PluginStatusType status = PluginStatusType.INSTALLED;
+
@Column(name = "HELP", nullable = true)
private String help;
@@ -334,6 +345,7 @@ public class Plugin implements Serializable {
* @param path
* @param displayName
* @param enabled
+ * @param status
* @param description
* @param help
* @param md5
@@ -345,14 +357,16 @@ public class Plugin implements Serializable {
* @param ctime
* @param mtime
*/
- public Plugin(int id, String name, String path, String displayName, boolean enabled, String description,
- String help, String md5, String version, String ampsVersion, PluginDeploymentType deployment,
- Configuration pluginConfig, Configuration scheduledJobsConfig, long ctime, long mtime) {
+ public Plugin(int id, String name, String path, String displayName, boolean enabled, PluginStatusType status,
+ String description, String help, String md5, String version, String ampsVersion,
+ PluginDeploymentType deployment, Configuration pluginConfig, Configuration scheduledJobsConfig, long ctime,
+ long mtime) {
this.id = id;
this.name = name;
this.path = path;
this.displayName = displayName;
this.enabled = enabled;
+ this.status = status;
this.description = description;
this.help = help;
this.md5 = md5;
@@ -455,6 +469,17 @@ public class Plugin implements Serializable {
this.enabled = enabled;
}
+ public PluginStatusType getStatus() {
+ return status;
+ }
+
+ public void setStatus(PluginStatusType status) {
+ this.status = status;
+ if (this.status == PluginStatusType.DELETED) {
+ this.enabled = false;
+ }
+ }
+
public String getHelp() {
return help;
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/PluginStatusType.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/PluginStatusType.java
new file mode 100644
index 0000000..40fd9ab
--- /dev/null
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/PluginStatusType.java
@@ -0,0 +1,29 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin;
+
+/**
+ * Indicates if a plugin is installed or has been deleted.
+ *
+ * @author John Mazzitelli
+ */
+public enum PluginStatusType {
+ INSTALLED, DELETED
+}
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index 77d9312..7e3ad25 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -41,6 +41,7 @@ import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.core.domain.plugin.PluginStatusType;
import org.rhq.core.domain.test.AbstractEJB3Test;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.core.util.stream.StreamUtil;
@@ -58,12 +59,14 @@ public class PluginTest extends AbstractEJB3Test {
String path = "/test/Update";
String displayName = "Plugin Test - testUpdate";
boolean enabled = true;
+ PluginStatusType status = PluginStatusType.INSTALLED;
String md5 = "abcdef";
byte[] content = "the content is here".getBytes();
Plugin plugin = new Plugin(name, path);
plugin.setDisplayName(displayName);
plugin.setEnabled(enabled);
+ plugin.setStatus(status);
plugin.setMD5(md5);
plugin.setVersion(null);
plugin.setDescription(null);
@@ -83,6 +86,7 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.getPath().equals(path);
assert plugin.getDisplayName().equals(displayName);
assert plugin.isEnabled() == enabled;
+ assert plugin.getStatus() == PluginStatusType.INSTALLED;
assert plugin.getMD5().equals(md5);
assert plugin.getVersion() == null;
assert plugin.getDescription() == null;
@@ -119,6 +123,7 @@ public class PluginTest extends AbstractEJB3Test {
q.setParameter("path", path);
q.setParameter("displayName", displayName);
q.setParameter("enabled", enabled);
+ q.setParameter("status", status);
q.setParameter("md5", md5);
q.setParameter("version", version);
q.setParameter("ampsVersion", ampsVersion);
@@ -179,11 +184,13 @@ public class PluginTest extends AbstractEJB3Test {
String path = "/test/Persist";
String displayName = "Plugin Test - testPersist";
boolean enabled = true;
+ PluginStatusType status = PluginStatusType.INSTALLED;
String md5 = "abcdef";
Plugin plugin = new Plugin(name, path);
plugin.setDisplayName(displayName);
plugin.setEnabled(enabled);
+ plugin.setStatus(status);
plugin.setMD5(md5);
// the following are the only nullable fields
@@ -202,6 +209,7 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.getPath().equals(path);
assert plugin.getDisplayName().equals(displayName);
assert plugin.isEnabled() == enabled;
+ assert plugin.getStatus() == PluginStatusType.INSTALLED;
assert plugin.getMD5().equals(md5);
assert plugin.getVersion() == null;
assert plugin.getDescription() == null;
@@ -210,6 +218,17 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.getScheduledJobsConfiguration() == null;
assert plugin.getHelp() == null;
assert plugin.getContent() == null;
+
+ // side check - see that "deleting" a plugin also sets enabled to false
+ assert plugin.isEnabled() == true;
+ assert plugin.getStatus() == PluginStatusType.INSTALLED;
+ plugin.setStatus(PluginStatusType.DELETED);
+ assert plugin.getStatus() == PluginStatusType.DELETED;
+ assert plugin.isEnabled() == false;
+ plugin = em.merge(plugin);
+ assert plugin.getStatus() == PluginStatusType.DELETED;
+ assert plugin.isEnabled() == false;
+
} finally {
getTransactionManager().rollback();
}
@@ -334,6 +353,25 @@ public class PluginTest extends AbstractEJB3Test {
}
assert got_it : "findAll query failed to get our plugin";
+ // mark a plugin deleted - all of our queries should then never see it
+ plugin.setStatus(PluginStatusType.DELETED);
+ em.merge(plugin);
+
+ query = em.createNamedQuery(Plugin.QUERY_FIND_BY_NAME);
+ query.setParameter("name", name);
+ List<?> results = query.getResultList();
+ assert results.size() == 0;
+
+ query = em.createNamedQuery(Plugin.QUERY_FIND_BY_IDS_AND_TYPE);
+ query.setParameter("ids", Arrays.asList(Integer.valueOf(plugin.getId())));
+ query.setParameter("type", plugin.getDeployment());
+ results = query.getResultList();
+ assert results.size() == 0;
+
+ query = em.createNamedQuery(Plugin.QUERY_FIND_ALL_SERVER);
+ results = query.getResultList();
+ assert results.size() == 0;
+
} finally {
getTransactionManager().rollback();
}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
index 9fd46f2..cfc99cf 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginsUIBean.java
@@ -38,6 +38,7 @@ import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.gui.util.FacesContextUtility;
import org.rhq.core.gui.util.StringUtility;
+import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.core.util.stream.StreamUtil;
import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility;
import org.rhq.enterprise.server.authz.PermissionException;
@@ -79,9 +80,7 @@ public class InstalledPluginsUIBean {
scanner.scanAndRegister();
FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Done scanning for updated plugins.");
} catch (Exception e) {
- String err = "Failed to scan for updated plugins";
- log.error(err + " - Cause: " + e);
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, err, e);
+ processException("Failed to scan for updated plugins", e);
}
}
@@ -118,9 +117,7 @@ public class InstalledPluginsUIBean {
+ "]. A scan is required now in order to register it.");
FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "New plugin uploaded: " + newPluginFilename);
} catch (Exception e) {
- String err = "Failed to process uploaded plugin";
- log.error(err + " - Cause: " + e);
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, err, e);
+ processException("Failed to process uploaded plugin", e);
}
return;
@@ -132,8 +129,15 @@ public class InstalledPluginsUIBean {
for (Plugin selectedPlugin : selectedPlugins) {
selectedPluginNames.add(selectedPlugin.getName());
}
- serverPluginsBean.enableServerPlugins(getIds(selectedPlugins));
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Enabled server plugins: " + selectedPluginNames);
+
+ try {
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
+ serverPluginsBean.enableServerPlugins(subject, getIds(selectedPlugins));
+ FacesContextUtility
+ .addMessage(FacesMessage.SEVERITY_INFO, "Enabled server plugins: " + selectedPluginNames);
+ } catch (Exception e) {
+ processException("Failed to enable server plugins", e);
+ }
return;
}
@@ -143,8 +147,15 @@ public class InstalledPluginsUIBean {
for (Plugin selectedPlugin : selectedPlugins) {
selectedPluginNames.add(selectedPlugin.getName());
}
- serverPluginsBean.disableServerPlugins(getIds(selectedPlugins));
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Disabled server plugins: " + selectedPluginNames);
+
+ try {
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
+ serverPluginsBean.disableServerPlugins(subject, getIds(selectedPlugins));
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Disabled server plugins: "
+ + selectedPluginNames);
+ } catch (Exception e) {
+ processException("Failed to disable server plugins", e);
+ }
return;
}
@@ -154,8 +165,15 @@ public class InstalledPluginsUIBean {
for (Plugin selectedPlugin : selectedPlugins) {
selectedPluginNames.add(selectedPlugin.getName());
}
- serverPluginsBean.undeployServerPlugins(getIds(selectedPlugins));
- FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Undeployed server plugins: " + selectedPluginNames);
+
+ try {
+ Subject subject = EnterpriseFacesContextUtility.getSubject();
+ serverPluginsBean.undeployServerPlugins(subject, getIds(selectedPlugins));
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Undeployed server plugins: "
+ + selectedPluginNames);
+ } catch (Exception e) {
+ processException("Failed to undeploy server plugins", e);
+ }
return;
}
@@ -193,4 +211,9 @@ public class InstalledPluginsUIBean {
+ "] does not have the proper permissions to view or manage plugins");
}
}
+
+ private void processException(String errMsg, Exception e) {
+ log.error(errMsg + ". Cause: " + ThrowableUtil.getAllMessages(e));
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, errMsg, e);
+ }
}
\ No newline at end of file
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
index fc4b6eb..d6cf6fe 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/plugin/ServerPluginScanner.java
@@ -176,7 +176,7 @@ public class ServerPluginScanner {
ServerPluginsLocal serverPluginsManager = LookupUtil.getServerPlugins();
SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager();
- serverPluginsManager.registerPlugin(subjectManager.getOverlord(), plugin, descriptor, pluginFile);
+ serverPluginsManager.registerPlugin(subjectManager.getOverlord(), plugin, pluginFile);
} catch (Exception e) {
log.error("Failed to register RHQ plugin file [" + pluginFile + "]", e);
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 27234f8..bfd828d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -46,6 +46,8 @@ import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.core.domain.plugin.PluginStatusType;
+import org.rhq.core.util.exception.ThrowableUtil;
import org.rhq.core.util.jdbc.JDBCUtil;
import org.rhq.enterprise.server.RHQConstants;
import org.rhq.enterprise.server.authz.RequiredPermission;
@@ -102,7 +104,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
public List<Plugin> getServerPluginsById(List<Integer> pluginIds) {
if (pluginIds == null || pluginIds.size() == 0) {
- return new ArrayList<Plugin>();
+ return new ArrayList<Plugin>(); // nothing to do
}
Query query = entityManager.createNamedQuery(Plugin.QUERY_FIND_BY_IDS_AND_TYPE);
query.setParameter("ids", pluginIds);
@@ -126,14 +128,29 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return query.getResultList();
}
- public void enableServerPlugins(List<Integer> pluginIds) {
- serverPluginsBean.setPluginEnabledFlag(pluginIds, true);
- LookupUtil.getServerPluginService().restartMasterPluginContainer();
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
+ public void enableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
+ if (pluginIds == null || pluginIds.size() == 0) {
+ return; // nothing to do
+ }
+
+ serverPluginsBean.setPluginEnabledFlag(subject, pluginIds, true);
+
+ // only restart the master if it was started to begin with
+ ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
+ if (serverPluginService.isMasterPluginContainerStarted()) {
+ serverPluginService.restartMasterPluginContainer();
+ }
return;
}
- public List<Plugin> disableServerPlugins(List<Integer> pluginIds) {
- serverPluginsBean.setPluginEnabledFlag(pluginIds, false);
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
+ public List<Plugin> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
+ if (pluginIds == null || pluginIds.size() == 0) {
+ return new ArrayList<Plugin>(); // nothing to do
+ }
+
+ serverPluginsBean.setPluginEnabledFlag(subject, pluginIds, false);
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
@@ -144,23 +161,34 @@ public class ServerPluginsBean implements ServerPluginsLocal {
Plugin doomedPlugin = entityManager.find(Plugin.class, pluginId);
if (doomedPlugin != null) {
doomedPlugins.add(doomedPlugin);
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
- if (pc != null) {
- try {
- pc.unschedulePluginJobs(doomedPlugin.getName());
- } catch (Exception e) {
- log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ if (master != null) {
+ AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
+ if (pc != null) {
+ try {
+ pc.unschedulePluginJobs(doomedPlugin.getName());
+ } catch (Exception e) {
+ log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ }
}
}
}
}
- serverPluginService.restartMasterPluginContainer();
+ // only restart if the master was started to begin with; otherwise, leave it down
+ if (master != null) {
+ serverPluginService.restartMasterPluginContainer();
+ }
+
return doomedPlugins;
}
- public List<Plugin> undeployServerPlugins(List<Integer> pluginIds) {
- serverPluginsBean.setPluginEnabledFlag(pluginIds, false);
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
+ public List<Plugin> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
+ if (pluginIds == null || pluginIds.size() == 0) {
+ return new ArrayList<Plugin>(); // nothing to do
+ }
+
+ serverPluginsBean.setPluginEnabledFlag(subject, pluginIds, false);
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
@@ -171,12 +199,14 @@ public class ServerPluginsBean implements ServerPluginsLocal {
Plugin doomedPlugin = entityManager.find(Plugin.class, pluginId);
if (doomedPlugin != null) {
doomedPlugins.add(doomedPlugin);
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
- if (pc != null) {
- try {
- pc.unschedulePluginJobs(doomedPlugin.getName());
- } catch (Exception e) {
- log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ if (master != null) {
+ AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
+ if (pc != null) {
+ try {
+ pc.unschedulePluginJobs(doomedPlugin.getName());
+ } catch (Exception e) {
+ log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ }
}
}
@@ -185,35 +215,65 @@ public class ServerPluginsBean implements ServerPluginsLocal {
// config can be set to the new cofig definition's default values.
doomedPlugin.setPluginConfiguration(null);
doomedPlugin.setScheduledJobsConfiguration(null);
-
- // TODO: this really won't do anything, our server plugin scanner will see it missing
- // and stream it back on the file system. Need to add a DELETED column to RHQ_PLUGIN
- // and call doomedPlugin.setDeleted(true). When deleted is true, our scanner can
- // skip writing the file to disk. All plugin queries should avoid returning
- // plugin rows that have deleted=true. Only then will removing it from the
- // file system as we do below actually help.
- File pluginDir = serverPluginService.getServerPluginsDirectory();
- File currentFile = new File(pluginDir, doomedPlugin.getPath());
- currentFile.delete();
+ doomedPlugin.setStatus(PluginStatusType.DELETED);
+
+ try {
+ File pluginDir = serverPluginService.getServerPluginsDirectory();
+ File currentFile = new File(pluginDir, doomedPlugin.getPath());
+ currentFile.delete();
+ } catch (Exception e) {
+ log.error("Failed to delete the undeployed plugin [" + doomedPlugin.getPath() + "]. Cause: "
+ + ThrowableUtil.getAllMessages(e));
+ }
}
}
- serverPluginService.restartMasterPluginContainer();
+ // only restart if the master was started to begin with; otherwise, leave it down
+ if (master != null) {
+ serverPluginService.restartMasterPluginContainer();
+ }
+
return doomedPlugins;
}
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
- public void setPluginEnabledFlag(List<Integer> pluginIds, boolean enabled) {
+ public void setPluginEnabledFlag(Subject subject, List<Integer> pluginIds, boolean enabled) throws Exception {
+ if (pluginIds == null || pluginIds.size() == 0) {
+ return; // nothing to do
+ }
Query q = entityManager.createNamedQuery(Plugin.UPDATE_PLUGINS_ENABLED_BY_IDS);
q.setParameter("ids", pluginIds);
q.setParameter("enabled", Boolean.valueOf(enabled));
- q.executeUpdate();
+ int count = q.executeUpdate();
+ if (count != pluginIds.size()) {
+ throw new Exception("Failed to update [" + pluginIds.size() + "] plugins. Count was [" + count + "]");
+ }
+
+ return;
+ }
+
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
+ @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
+ public void setPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status) throws Exception {
+ if (pluginIds == null || pluginIds.size() == 0) {
+ return; // nothing to do
+ }
+ List<Plugin> plugins = getServerPluginsById(pluginIds);
+ for (Plugin plugin : plugins) {
+ plugin.setStatus(status);
+ updatePluginExceptContent(subject, plugin);
+ }
return;
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
- public void registerPlugin(Subject subject, Plugin plugin, ServerPluginDescriptorType descriptor, File pluginFile)
- throws Exception {
+ public Plugin registerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception {
+
+ if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
+ throw new IllegalArgumentException("Plugin [" + plugin.getName()
+ + "] must be a server plugin to be registered");
+ }
Plugin existingPlugin = null;
boolean newOrUpdated = false;
@@ -240,7 +300,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (plugin.getId() == 0) {
entityManager.persist(plugin);
} else {
- plugin = updatePluginExceptContent(plugin);
+ plugin = updatePluginExceptContent(subject, plugin);
}
if (pluginFile != null) {
@@ -250,10 +310,11 @@ public class ServerPluginsBean implements ServerPluginsLocal {
log.debug("Updated plugin entity [" + plugin + "]");
}
- return;
+ return plugin;
}
- public Plugin updatePluginExceptContent(Plugin plugin) throws Exception {
+ @RequiredPermission(Permission.MANAGE_SETTINGS)
+ public Plugin updatePluginExceptContent(Subject subject, Plugin plugin) throws Exception {
// this method is here because we need a way to update the plugin's information
// without blowing away the content data. Because we do not want to load the
// content blob in memory, the plugin's content field will be null - if we were
@@ -267,6 +328,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
q.setParameter("path", plugin.getPath());
q.setParameter("displayName", plugin.getDisplayName());
q.setParameter("enabled", plugin.isEnabled());
+ q.setParameter("status", plugin.getStatus());
q.setParameter("md5", plugin.getMD5());
q.setParameter("version", plugin.getVersion());
q.setParameter("ampsVersion", plugin.getAmpsVersion());
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index 64efe4d..528d87c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -8,6 +8,7 @@ import javax.persistence.NoResultException;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginStatusType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
@@ -40,7 +41,6 @@ public interface ServerPluginsLocal {
* Call this method to fill in that data that wasn't originally loaded.
*
* @param plugin
- *
* @return the same plugin, with the relationship data loaded
*/
Plugin getServerPluginRelationships(Plugin plugin);
@@ -49,7 +49,6 @@ public interface ServerPluginsLocal {
* Get a list of plugins from their IDs.
*
* @param pluginIds the IDs of the plugins to load.
- *
* @return plugins matching the given IDs
*/
List<Plugin> getServerPluginsById(List<Integer> pluginIds);
@@ -76,56 +75,76 @@ public interface ServerPluginsLocal {
/**
* Enables the plugins and restarts the server plugin container.
*
+ * @param subject user making the request
* @param pluginIds the plugins to be enabled
+ * @throws Exception if failed to disable a plugin
*/
- void enableServerPlugins(List<Integer> pluginIds);
+ void enableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
/**
* Disables the plugins and restarts the server plugin container.
*
+ * @param subject user making the request
* @param pluginIds the plugins to be disabled
- *
* @return the list of plugins that were disabled
+ * @throws Exception if failed to disable a plugin
*/
- List<Plugin> disableServerPlugins(List<Integer> pluginIds);
+ List<Plugin> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
/**
* Removes the plugin from the system and restarts the server plugin container.
*
+ * @param subject user making the request
* @param pluginIds
- *
* @return the list of plugins that were undeployed
+ * @throws Exception if failed to undeploy a plugin
*/
- List<Plugin> undeployServerPlugins(List<Integer> pluginIds);
+ List<Plugin> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
/**
* Turns on or off the enabled flag in the database but does NOT restart the server plugin container.
+ * This has "requires new" semantics, so the results are committed immediately upon return.
+ *
+ * @param subject user making the request
+ * @param pluginIds the plugins to be enabled
+ * @param enabled the value of the enabled flag for the plugins
+ * @throws if failed to update a plugin
+ */
+ void setPluginEnabledFlag(Subject subject, List<Integer> pluginIds, boolean enabled) throws Exception;
+
+ /**
+ * Sets the status flag in the database but does NOT restart the server plugin container.
+ * If the status is {@link PluginStatusType#DELETED}, the enabled flag is also flipped to <code>false</code>.
*
+ * This has "requires new" semantics, so the results are committed immediately upon return.
+ *
+ * @param subject user making the request
* @param pluginIds the plugins to be enabled
* @param enabled the value of the enabled flag for the plugins
+ * @throws if failed to update one of the plugins
*/
- void setPluginEnabledFlag(List<Integer> pluginIds, boolean enabled);
+ void setPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status) throws Exception;
/**
* Registers the given plugin to the database.
*
* @param subject the user that needs to have permissions to add a plugin to the system
* @param plugin the plugin definition
- * @param descriptor the plugin descriptor that was found in the plugin file
* @param pluginFile the actual plugin file itself
+ * @return the plugin after being persisted
* @throws Exception if failed to fully register the plugin
*/
- void registerPlugin(Subject subject, Plugin plugin, ServerPluginDescriptorType descriptor, File pluginFile)
- throws Exception;
+ Plugin registerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception;
/**
* Given a plugin that already exists, this will update that plugin's data in the database,
* except for the content, which is left as-is. If the plugin did not yet exist, an exception is thrown.
* You can use this to update the plugin's scheduled jobs configuration and plugin configuration.
*
+ * @param subject user making the request
* @param plugin existing plugin with updated data
* @return the updated plugin
* @throws Exception if the plugin did not already exist or an error occurred that caused the update to fail
*/
- public Plugin updatePluginExceptContent(Plugin plugin) throws Exception;
+ public Plugin updatePluginExceptContent(Subject subject, Plugin plugin) throws Exception;
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
index 90639d2..8250c7d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
@@ -202,6 +202,7 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
q.setParameter("path", plugin.getPath());
q.setParameter("displayName", plugin.getDisplayName());
q.setParameter("enabled", plugin.isEnabled());
+ q.setParameter("status", plugin.getStatus());
q.setParameter("md5", plugin.getMD5());
q.setParameter("version", plugin.getVersion());
q.setParameter("ampsVersion", plugin.getAmpsVersion());
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
new file mode 100644
index 0000000..3301ba0
--- /dev/null
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
@@ -0,0 +1,254 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import org.hibernate.LazyInitializationException;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import org.rhq.core.domain.auth.Subject;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.PropertyMap;
+import org.rhq.core.domain.configuration.PropertySimple;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.core.domain.plugin.PluginStatusType;
+import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService;
+import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * @author John Mazzitelli
+ */
+@Test
+public class ServerPluginsBeanTest extends AbstractEJB3Test {
+ private ServerPluginsLocal serverPluginsBean;
+
+ @BeforeMethod
+ public void beforeMethod() {
+ TestGenericServerPluginService pluginService;
+ pluginService = new TestGenericServerPluginService();
+ prepareCustomServerPluginService(pluginService);
+
+ serverPluginsBean = LookupUtil.getServerPlugins();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void afterMethod() {
+
+ EntityManager em = null;
+
+ try {
+ unprepareServerPluginService();
+ } catch (Exception e) {
+ }
+
+ try {
+ getTransactionManager().begin();
+ em = getEntityManager();
+
+ Query q = em.createQuery("SELECT p FROM Plugin p WHERE p.name LIKE 'serverplugintest%'");
+ List<Plugin> doomed = q.getResultList();
+ for (Plugin plugin : doomed) {
+ em.remove(plugin);
+ }
+
+ getTransactionManager().commit();
+ em.close();
+ em = null;
+ } catch (Exception e) {
+ try {
+ System.out.println("CANNOT CLEAN UP TEST: Cause: " + e);
+ getTransactionManager().rollback();
+ } catch (Exception ignore) {
+ }
+ } finally {
+ if (null != em) {
+ em.close();
+ }
+ }
+ }
+
+ public void testGetPlugins() throws Exception {
+ Plugin p1 = registerPlugin(1);
+ Plugin p2 = registerPlugin(2);
+ List<String> pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ assert pluginNames.contains(p1.getName()) : pluginNames;
+ assert pluginNames.contains(p2.getName()) : pluginNames;
+ pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ assert !pluginNames.contains(p1.getName()) : pluginNames;
+ assert !pluginNames.contains(p2.getName()) : pluginNames;
+
+ Plugin plugin = this.serverPluginsBean.getServerPlugin(p1.getName());
+ assert plugin.getId() == p1.getId() : plugin;
+ assert plugin.getName().equals(p1.getName()) : plugin;
+ assetLazyInitializationException(plugin);
+
+ plugin = this.serverPluginsBean.getServerPluginRelationships(plugin);
+ assert plugin.getPluginConfiguration() != null;
+ assert plugin.getScheduledJobsConfiguration() != null;
+ assert plugin.getPluginConfiguration().equals(p1.getPluginConfiguration());
+ assert plugin.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration());
+
+ List<Plugin> plugins = this.serverPluginsBean.getServerPlugins();
+ assert plugins.contains(p1) : plugins;
+ assert plugins.contains(p2) : plugins;
+ assetLazyInitializationException(plugins.get(0));
+ assetLazyInitializationException(plugins.get(1));
+
+ List<Integer> ids = new ArrayList<Integer>(2);
+ ids.add(p1.getId());
+ ids.add(p2.getId());
+ plugins = this.serverPluginsBean.getServerPluginsById(ids);
+ assert plugins.size() == 2 : plugins;
+ assert plugins.contains(p1) : plugins;
+ assert plugins.contains(p2) : plugins;
+ assetLazyInitializationException(plugins.get(0));
+ assetLazyInitializationException(plugins.get(1));
+ }
+
+ public void testDisableEnablePlugins() throws Exception {
+ Plugin p1 = registerPlugin(1);
+ Plugin p2 = registerPlugin(2);
+
+ List<Integer> ids = new ArrayList<Integer>(2);
+ ids.add(p1.getId());
+ ids.add(p2.getId());
+ List<Plugin> disabled = this.serverPluginsBean.disableServerPlugins(getOverlord(), ids);
+ assert disabled.size() == 2 : disabled;
+ assert disabled.contains(p1) : disabled;
+ assert disabled.contains(p2) : disabled;
+ assert disabled.get(0).getStatus() == PluginStatusType.INSTALLED; // still installed
+ assert disabled.get(1).getStatus() == PluginStatusType.INSTALLED; // still installed
+ List<String> pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ assert pluginNames.contains(p1.getName()) : pluginNames;
+ assert pluginNames.contains(p2.getName()) : pluginNames;
+ pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ assert !pluginNames.contains(p1.getName()) : pluginNames;
+ assert !pluginNames.contains(p2.getName()) : pluginNames;
+
+ // re-enable them
+ this.serverPluginsBean.enableServerPlugins(getOverlord(), ids);
+ pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ assert pluginNames.contains(p1.getName()) : pluginNames;
+ assert pluginNames.contains(p2.getName()) : pluginNames;
+ pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ assert !pluginNames.contains(p1.getName()) : pluginNames;
+ assert !pluginNames.contains(p2.getName()) : pluginNames;
+
+ // make sure none of these enable/disable settings lost our config
+ Plugin plugin = this.serverPluginsBean.getServerPlugin(p1.getName());
+ plugin = this.serverPluginsBean.getServerPluginRelationships(plugin);
+ assert plugin.getPluginConfiguration() != null; // no LazyInitException should be thrown!
+ assert plugin.getPluginConfiguration().equals(p1.getPluginConfiguration());
+ plugin = this.serverPluginsBean.getServerPlugin(p2.getName());
+ plugin = this.serverPluginsBean.getServerPluginRelationships(plugin);
+ assert plugin.getPluginConfiguration() != null; // no LazyInitException should be thrown!
+ assert plugin.getPluginConfiguration().equals(p1.getPluginConfiguration());
+ }
+
+ public void testUndeployPlugins() throws Exception {
+
+ Plugin p1 = registerPlugin(1);
+ Plugin p2 = registerPlugin(2);
+
+ List<Integer> ids = new ArrayList<Integer>(2);
+ ids.add(p1.getId());
+ ids.add(p2.getId());
+ List<Plugin> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
+ assert undeployed.size() == 2 : undeployed;
+ assert undeployed.contains(p1) : undeployed;
+ assert undeployed.contains(p2) : undeployed;
+ assert undeployed.get(0).getStatus() == PluginStatusType.DELETED;
+ assert undeployed.get(1).getStatus() == PluginStatusType.DELETED;
+
+ List<String> pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ assert !pluginNames.contains(p1.getName()) : "deleted plugins should not be returned even here" + pluginNames;
+ assert !pluginNames.contains(p2.getName()) : "deleted plugins should not be returned even here" + pluginNames;
+ pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ assert !pluginNames.contains(p1.getName()) : pluginNames;
+ assert !pluginNames.contains(p2.getName()) : pluginNames;
+
+ // re-install them - need to implement this feature
+ // this.serverPluginsBean.enableServerPlugins(getOverlord(), ids);
+ // pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(true);
+ // assert pluginNames.contains(p1.getName()) : pluginNames;
+ // assert pluginNames.contains(p2.getName()) : pluginNames;
+ // assert undeployed.get(0).getStatus() == PluginStatusType.INSTALLED;
+ // assert undeployed.get(1).getStatus() == PluginStatusType.INSTALLED;
+ // pluginNames = this.serverPluginsBean.getPluginNamesByEnabled(false);
+ // assert !pluginNames.contains(p1.getName()) : pluginNames;
+ // assert !pluginNames.contains(p2.getName()) : pluginNames;
+ }
+
+ private Plugin registerPlugin(int index) throws Exception {
+ Plugin plugin = new Plugin(0, "serverplugintest" + index, "path", "displayName", true,
+ PluginStatusType.INSTALLED, "description", "help", "md5", "version", "ampsVersion",
+ PluginDeploymentType.SERVER, createPluginConfiguration(), createScheduledJobsConfiguration(), System
+ .currentTimeMillis(), System.currentTimeMillis());
+
+ plugin = this.serverPluginsBean.registerPlugin(getOverlord(), plugin, null);
+ assert plugin.getId() > 0;
+ assert plugin.isEnabled() == true;
+ assert plugin.getDeployment() == PluginDeploymentType.SERVER;
+ assert plugin.getStatus() == PluginStatusType.INSTALLED;
+ assert plugin.getPluginConfiguration() != null;
+ assert plugin.getScheduledJobsConfiguration() != null;
+ return plugin;
+ }
+
+ private void assetLazyInitializationException(Plugin plugin) {
+ try {
+ plugin.getPluginConfiguration().toString();
+ assert false : "Should have thrown a lazy-initialization exception - we didn't load config";
+ } catch (LazyInitializationException ok) {
+ }
+ try {
+ plugin.getScheduledJobsConfiguration().toString();
+ assert false : "Should have thrown a lazy-initialization exception - we didn't load config";
+ } catch (LazyInitializationException ok) {
+ }
+ }
+
+ private Configuration createPluginConfiguration() {
+ Configuration config = new Configuration();
+ config.put(new PropertySimple("simpleprop1", "simpleprop1value"));
+ return config;
+ }
+
+ private Configuration createScheduledJobsConfiguration() {
+ Configuration config = new Configuration();
+ PropertyMap map = new PropertyMap("jobname");
+ config.put(map);
+ map.put(new PropertySimple("methodName", "methodNameValue"));
+ return config;
+ }
+
+ private Subject getOverlord() {
+ return LookupUtil.getSubjectManager().getOverlord();
+ }
+}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
index 2d30403..592a3d9 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/TestGenericServerPluginService.java
@@ -29,6 +29,7 @@ import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.definition.ConfigurationDefinition;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.core.domain.plugin.PluginStatusType;
import org.rhq.core.util.MessageDigestGenerator;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
@@ -195,10 +196,10 @@ public class TestGenericServerPluginService extends ServerPluginService implemen
File pluginFile = new File(env.getPluginUrl().toURI());
Plugin plugin = new Plugin(0, env.getPluginName(), pluginFile.getName(), pluginDescriptor
- .getDisplayName(), true, pluginDescriptor.getDescription(), "", MessageDigestGenerator
- .getDigestString(pluginFile), pluginDescriptor.getVersion(), pluginDescriptor.getVersion(),
- PluginDeploymentType.SERVER, pluginConfig, scheduledJobsConfig, System.currentTimeMillis(), System
- .currentTimeMillis());
+ .getDisplayName(), true, PluginStatusType.INSTALLED, pluginDescriptor.getDescription(), "",
+ MessageDigestGenerator.getDigestString(pluginFile), pluginDescriptor.getVersion(), pluginDescriptor
+ .getVersion(), PluginDeploymentType.SERVER, pluginConfig, scheduledJobsConfig, System
+ .currentTimeMillis(), System.currentTimeMillis());
return plugin;
} catch (Exception e) {
throw new RuntimeException(e);
commit d191decc1328210999f7ace3be051dde164b29f9
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 20 14:52:19 2009 -0500
out out tabs! fix formatting
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 3e12bad..4cc035a 100644
--- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
+++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml
@@ -1484,39 +1484,39 @@
</schema-directSQL>
<schema-addColumn table="RHQ_RAW_CONFIG" column="CONFIG_ID" columnType="INTEGER"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="CONFIG_ID"
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="CONFIG_ID"
columnType="INTEGER"
nullable="false"/>
<schema-addColumn table="RHQ_RAW_CONFIG" column="PATH" columnType="VARCHAR2"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="PATH"
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="PATH"
columnType="VARCHAR2"
precision="512"/>
<schema-addColumn table="RHQ_RAW_CONFIG" column="CONTENTS" columnType="BLOB"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="CONTENTS"
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="CONTENTS"
columnType="BLOB"
nullable="false"/>
<schema-addColumn table="RHQ_RAW_CONFIG" column="SHA256" columnType="VARCHAR2"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="SHA256"
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="SHA256"
columnType="VARCHAR2"
- precision="64"
+ precision="64"
nullable="false"/>
<schema-addColumn table="RHQ_RAW_CONFIG" column="CTIME" columnType="LONG"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="CTIME"
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="CTIME"
columnType="LONG"
nullable="false"/>
<schema-addColumn table="RHQ_RAW_CONFIG" column="MTIME" columnType="LONG"/>
- <schema-alterColumn table="RHQ_RAW_CONFIG"
- column="MTIME"
+ <schema-alterColumn table="RHQ_RAW_CONFIG"
+ column="MTIME"
columnType="LONG"
nullable="false"/>
@@ -2024,62 +2024,60 @@
<schema-addColumn table="RHQ_REPO" column="IS_CANDIDATE" columnType="BOOLEAN"/>
<schema-alterColumn table="RHQ_REPO" column="IS_CANDIDATE" nullable="false" />
</schemaSpec>
-
- <!-- Generic tagging support -->
+
+ <!-- Generic tagging support -->
<schemaSpec version="2.64">
- <schema-createSequence name="RHQ_TAG_ID_SEQ" initial="10001" />
- <schema-directSQL>
- <statement>
- CREATE TABLE RHQ_TAG ( ID INTEGER PRIMARY KEY )
- </statement>
- </schema-directSQL>
- <schema-alterColumn table="RHQ_TAG" column="ID" nullable="false" />
- <schema-addColumn table="RHQ_TAG" column="NAME" precision="200" columnType="VARCHAR2" />
- <schema-alterColumn table="RHQ_TAG" column="NAME" nullable="false" />
- <schema-addColumn table="RHQ_TAG" column="DESCRIPTION" precision="500" columnType="VARCHAR2" />
- </schemaSpec>
-
- <!-- Distribution Files -->
- <schemaSpec version="2.65">
- <schema-directSQL>
- <statement>
- CREATE TABLE RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID INTEGER )
- </statement>
- </schema-directSQL>
- <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="DISTRIBUTION_ID" nullable="false" />
- <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" precision="256" columnType="VARCHAR2" />
- <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" nullable="false" />
- <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" precision="64" columnType="VARCHAR2" />
- <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" nullable="false" />
- <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" columnType="LONG" />
- <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" nullable="false" />
- <schema-directSQL>
- <statement targetDBVendor="postgresql">
- CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
- ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
- </statement>
- <statement targetDBVendor="oracle">
- CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
- ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
- </statement>
- </schema-directSQL>
- <schema-directSQL>
- <statement targetDBVendor="oracle">
- ALTER TABLE RHQ_DISTRIBUTION_FILE
- ADD CONSTRAINT RHQ_DIST_FILE_FKEY
- FOREIGN KEY ( DISTRIBUTION_ID)
- REFERENCES RHQ_DISTRIBUTION ( ID )
- </statement>
- <statement targetDBVendor="postgresql">
- ALTER TABLE RHQ_DISTRIBUTION_FILE
- ADD CONSTRAINT RHQ_DIST_FILE_FKEY
- FOREIGN KEY ( DISTRIBUTION_ID)
- REFERENCES RHQ_DISTRIBUTION ( ID )
- </statement>
- </schema-directSQL>
-
+ <schema-createSequence name="RHQ_TAG_ID_SEQ" initial="10001" />
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_TAG ( ID INTEGER PRIMARY KEY )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_TAG" column="ID" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="NAME" precision="200" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_TAG" column="NAME" nullable="false" />
+ <schema-addColumn table="RHQ_TAG" column="DESCRIPTION" precision="500" columnType="VARCHAR2" />
</schemaSpec>
+ <!-- Distribution Files -->
+ <schemaSpec version="2.65">
+ <schema-directSQL>
+ <statement>
+ CREATE TABLE RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID INTEGER )
+ </statement>
+ </schema-directSQL>
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="DISTRIBUTION_ID" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" precision="256" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="RELATIVE_FILENAME" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" precision="64" columnType="VARCHAR2" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="MD5SUM" nullable="false" />
+ <schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" columnType="LONG" />
+ <schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="LAST_MODIFIED" nullable="false" />
+ <schema-directSQL>
+ <statement targetDBVendor="postgresql">
+ CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
+ ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
+ </statement>
+ <statement targetDBVendor="oracle">
+ CREATE UNIQUE INDEX RHQ_DISTRIBUTION_FILE_IDX
+ ON RHQ_DISTRIBUTION_FILE ( DISTRIBUTION_ID, RELATIVE_FILENAME )
+ </statement>
+ </schema-directSQL>
+ <schema-directSQL>
+ <statement targetDBVendor="oracle">
+ ALTER TABLE RHQ_DISTRIBUTION_FILE
+ ADD CONSTRAINT RHQ_DIST_FILE_FKEY
+ FOREIGN KEY ( DISTRIBUTION_ID)
+ REFERENCES RHQ_DISTRIBUTION ( ID )
+ </statement>
+ <statement targetDBVendor="postgresql">
+ ALTER TABLE RHQ_DISTRIBUTION_FILE
+ ADD CONSTRAINT RHQ_DIST_FILE_FKEY
+ FOREIGN KEY ( DISTRIBUTION_ID)
+ REFERENCES RHQ_DISTRIBUTION ( ID )
+ </statement>
+ </schema-directSQL>
+ </schemaSpec>
<!-- RHQ_REPO_TAG_MAP -->
<schemaSpec version="2.66">
@@ -2123,23 +2121,23 @@
</schemaSpec>
<schemaSpec version="2.68">
- <schema-createSequence name="RHQ_DISTRIBUTION_FILE_SEQ" initial="10001" />
+ <schema-createSequence name="RHQ_DISTRIBUTION_FILE_SEQ" initial="10001" />
<schema-directSQL>
- <statement>
- ALTER TABLE RHQ_DISTRIBUTION_FILE DROP CONSTRAINT RHQ_DISTRIBUTION_FILE_PKEY
- </statement>
+ <statement>
+ ALTER TABLE RHQ_DISTRIBUTION_FILE DROP CONSTRAINT RHQ_DISTRIBUTION_FILE_PKEY
+ </statement>
</schema-directSQL>
-
+
<schema-addColumn table="RHQ_DISTRIBUTION_FILE" column="ID" columnType="INTEGER" />
<schema-alterColumn table="RHQ_DISTRIBUTION_FILE" column="ID" nullable="false" />
-
- <schema-directSQL>
- <statement>
- ALTER TABLE RHQ_DISTRIBUTION_FILE ALTER COLUMN ID SET DEFAULT NEXTVAL('RHQ_DISTRIBUTION_FILE_ID_SEQ')
- </statement>
+
+ <schema-directSQL>
+ <statement>
+ ALTER TABLE RHQ_DISTRIBUTION_FILE ALTER COLUMN ID SET DEFAULT NEXTVAL('RHQ_DISTRIBUTION_FILE_ID_SEQ')
+ </statement>
</schema-directSQL>
- </schemaSpec>
-
+ </schemaSpec>
+
<!-- Add support for server-side plugins -->
<schemaSpec version="2.69">
<!-- add the new column that indicates if this is deployed on the SERVER or AGENT -->
commit ccefb1d4df35a99cc4b241781668662380f65625
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Fri Nov 20 13:58:48 2009 -0500
update schema catalog for eclipse usrs
diff --git a/etc/eclipse-tools/templates/schema.xmlcatalog b/etc/eclipse-tools/templates/schema.xmlcatalog
index 3107878..d4054bb 100644
--- a/etc/eclipse-tools/templates/schema.xmlcatalog
+++ b/etc/eclipse-tools/templates/schema.xmlcatalog
@@ -2,6 +2,10 @@
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<uri name="urn:xmlns:rhq-configuration" uri="platform:/resource/rhq/modules/core/client-api/src/main/resources/rhq-configuration.xsd"/>
<uri name="urn:xmlns:rhq-plugin" uri="platform:/resource/rhq/modules/core/client-api/src/main/resources/rhq-plugin.xsd"/>
-<uri name="urn:xmlns:rhq-serverplugin.content" uri="platform:/resource/rhq/modules/core/client-api/src/main/resources/rhq-serverplugin-content.xsd"/>
-<uri name="urn:xmlns:rhq-perspective" uri="platform:/resource/rhq/modules/core/client-api/src/main/resources/rhq-perspective.xsd"/>
+<uri name="urn:xmlns:rhq-contentsource-packagedetails" uri="platform:/resource/rhq/modules/enterprise/server/xml-schemas/src/main/resources/rhq-contentsource-packagedetails.xsd"/>
+<uri name="urn:xmlns:rhq-serverplugin" uri="platform:/resource/rhq/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin.xsd"/>
+<uri name="urn:xmlns:rhq-serverplugin.generic" uri="platform:/resource/rhq/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-generic.xsd"/>
+<uri name="urn:xmlns:rhq-serverplugin.alert" uri="platform:/resource/rhq/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-alert.xsd"/>
+<uri name="urn:xmlns:rhq-serverplugin.content" uri="platform:/resource/rhq/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-content.xsd"/>
+<uri name="urn:xmlns:rhq-serverplugin.perspective" uri="platform:/resource/rhq/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-perspective.xsd"/>
</catalog>
14 years, 5 months
[rhq] Branch 'alertPlugin' - modules/core modules/enterprise modules/helpers
by Heiko W. Rupp
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java | 68
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/DeepCopyable.java | 2
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Property.java | 7
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java | 12
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java | 12
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertySimple.java | 30
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/RawConfiguration.java | 7
modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java | 20
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java | 111 +
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyListTest.java | 59
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyMapTest.java | 53
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertySimpleTest.java | 16
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java | 32
modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java | 52
modules/core/util/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java | 9
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java | 73
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java | 71
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java | 2
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml | 1
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml | 7
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml | 11
modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp | 775 +++++-----
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml | 24
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml | 27
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml | 15
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml | 8
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java | 154 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java | 20
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java | 77
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java | 16
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java | 59
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java | 74
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java | 16
modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java | 9
modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl | 5
36 files changed, 1228 insertions(+), 708 deletions(-)
New commits:
commit 1bc8c0ef34db2b4584914fea447befe023a62efb
Author: Heiko W. Rupp <pilhuhn(a)fedorapeople.org>
Date: Thu Nov 26 20:19:20 2009 +0100
Squashed commit of the following:
commit db605e78ebfb82d01f0ce4130f327c45170540c7
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 17:18:29 2009 -0500
get rid of the update query we don't need anymore
fix tests so they don't rely on that old update query
commit dfd17347dd6d8c2707bfab6ced27bd44b66f9120
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 16:42:23 2009 -0500
fix the update method so it can handle the config updates
commit aadfbe12066b4cab890bc04fbd9a55c76df87fb4
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 13:19:15 2009 -0500
provide an API to get a list of all enabled and disabled plugins grouped by their type
commit 07ae93f34338458daa75082ef519b4b1851ddc0c
Merge: 5e17b2f 2d97557
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 11:08:38 2009 -0500
Merge branch 'master' into pc
commit 2d97557a1e09ab13248f5da0e81a8d530731ed78
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 11:03:16 2009 -0500
Eagerly initializing underlying list and map in PropertyList and PropertyMap to avoid NPEs
This change was already made in the raw-config branch a while back, and needed to be
ported over.
commit 5e17b2f3837504924ab1ec1b7ba48d017f258ef2
Merge: 45e0f2f ee2e8e8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 10:17:56 2009 -0500
Merge branch 'master' into pc
commit 45e0f2f25b7230d65bc561bc63bd1e1cdd7c65f8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 10:15:39 2009 -0500
use the new deepCopy()
commit b3a962cfa61b2f05b4258b9a25e6e72819473191
Merge: c995032 37bb080
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 09:57:31 2009 -0500
Merge branch 'master' into pc
commit ee2e8e847b18491a6093135b6ca906d6063679de
Merge: 1bca0f7 37bb080
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 09:54:22 2009 -0500
Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq
commit 1bca0f7c0327498c0dcb7ccb5953d3158c83a563
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 09:53:41 2009 -0500
Fixing compilation error that happened as a result of my refactoring RawConfiguration.deepCopy()
commit c995032cbc61261e353c523259810d076d586519
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 09:51:34 2009 -0500
fix NPE when plugin config or scheduled jobs config is null
commit 37bb080675c956c976ffc3110361c11e19ae87a0
Author: Galder Zamarreno <rnd(a)zamarreno.com>
Date: Wed Nov 25 15:20:34 2009 +0100
Operation returns only one result now.
commit cc1b2af501010b1734b42d4a70e30a43db65d3ee
Author: Galder Zamarreno <rnd(a)zamarreno.com>
Date: Wed Nov 25 14:37:33 2009 +0100
Returns for operations can now be generated.
commit a0ab1b28c3ef8ab152c4decf9e8dbaebbede80dd
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 00:08:22 2009 -0500
Deleting directory that accidentally included in a previous commit
commit 1643800fb94b472d11bedc1d5d4d756b4ad54ee0
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 00:07:18 2009 -0500
[US 6] Refactoring Configuration.deepCopy() to properly handle hibernate proxies.
Refactoring implementors of DeepCopyable to take a boolean flag that indicates
whether or not to copy the id field. Unit tests have been updated to reflect the change.
Conflicts:
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java
commit 9994ec529ecf93914ab48d25023327ee0eb3f503
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 24 16:41:38 2009 -0500
add a test to confirm that snapshot versions are considered older than candidate releases or releases
commit 93cd6e74d101d7dc645ac38168b4d0157752bf8d
Author: Justin Harris <jharris(a)redhat.com>
Date: Tue Nov 24 14:57:46 2009 -0500
Moving in some seam functionality to allow for page scoped beans in form submission.
commit c8a8622dce3142a91725a0a152bee94be64a9259
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 23 14:05:06 2009 -0500
because we put the byte[] content directly in the plugin entity, we can't entityManager.find() because that would load the full plugin content.
instead, use getReference. when we need to load the relationships, we have to play games by
loading in the configs directly and doing a deep copy (mainly to workaround a hibernate bug)
commit 263227e335728de980194c0632ae04938396536e
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 23 11:36:47 2009 -0500
put the proper values in the query params
commit e77a657abf17907a25dba4498b6e4993604ed38c
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 23 10:48:13 2009 -0500
the column should be "enabled" since everywhere else we talk about a plugin being enabled or disabled, not active/inactive
commit 9af95de196ccc8b854a8f1c952af3a6cfa18e78d
Author: Justin Harris <jharris(a)redhat.com>
Date: Mon Nov 23 10:18:55 2009 -0500
Updating update plugin call to new naming scheme.
commit 556be90ec7e0285dc9205766805aaa91da2ef258
Author: Justin Harris <jharris(a)redhat.com>
Date: Fri Nov 20 18:34:52 2009 -0500
Adding save button to plugin details page.
commit e144f9a55590182e130ae768b9b494b13f03c2a6
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 22 22:42:30 2009 -0500
convert CRLF to LF
commit f04ef82719012571ecfa157eb270c6b0424ad0ac
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 22 22:39:34 2009 -0500
mistakenly deleted the html tag, put it back
commit a5fcd064dc1d1eea47c2806754c3244e1c000235
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 22 01:59:12 2009 -0500
since there is no current way to "revive" a undeployed plugin from the real GUI, at least provide _some_ way to get back to a state that will let you re-register a plugin again using the test control.jsp page
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
index 3ce2965..62bd8ce 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Configuration.java
@@ -454,55 +454,40 @@ public class Configuration implements Externalizable, Cloneable, AbstractPropert
* @return the new copy
*/
public Configuration deepCopy(boolean keepIds) {
- Configuration copy;
+ Configuration copy = new Configuration();
- try {
- copy = clone();
- } catch (CloneNotSupportedException e) {
- throw new RuntimeException("CloneNotSupported can't happen");
+ if (keepIds) {
+ copy.id = this.id;
}
- if (!keepIds) {
- copy.id = 0;
-
- for (Property property : copy.properties.values()) {
- clearIds(property);
- }
- }
+ copy.notes = this.notes;
+ copy.version = this.version;
+ createDeepCopyOfProperties(copy, keepIds);
+ createDeepCopyOfRawConfigs(copy, keepIds);
return copy;
}
- private void clearIds(Property property) {
- property.setId(0);
-
- if (property instanceof PropertyList) {
- for (Property childProperty : ((PropertyList) property).getList()) {
- clearIds(childProperty);
- }
- } else if (property instanceof PropertyMap) {
- for (Property childProperty : ((PropertyMap) property).getMap().values()) {
- clearIds(childProperty);
- }
- }
-
- return;
- }
-
public Configuration deepCopyWithoutProxies() {
Configuration copy = new Configuration();
copy.notes = this.notes;
copy.version = this.version;
+ createDeepCopyOfProperties(copy, false);
+ createDeepCopyOfRawConfigs(copy, false);
- for (Property property : this.properties.values()) {
- copy.put(property.deepCopy());
- }
+ return copy;
+ }
+ private void createDeepCopyOfRawConfigs(Configuration copy, boolean keepId) {
for (RawConfiguration rawConfig : rawConfigurations) {
- copy.addRawConfiguration(rawConfig.deepCopy());
+ copy.addRawConfiguration(rawConfig.deepCopy(keepId));
}
+ }
- return copy;
+ private void createDeepCopyOfProperties(Configuration copy, boolean keepId) {
+ for (Property property : this.properties.values()) {
+ copy.put(property.deepCopy(keepId));
+ }
}
/**
@@ -664,7 +649,22 @@ public class Configuration implements Externalizable, Cloneable, AbstractPropert
out.writeLong(version);
out.writeLong(ctime);
out.writeLong(mtime);
+ }
// Explicitly do not send the history relationship
+ private Map<String, Property> createDeepCopyOfMap() {
+ Map<String, Property> copy = new HashMap<String, Property>();
+ for (Map.Entry<String, Property> entry : this.properties.entrySet()) {
+ copy.put(entry.getKey(), entry.getValue().deepCopy(true));
+ }
+ return copy;
+ }
+
+ private Set<RawConfiguration> createDeepCopyOfRawConfigs() {
+ Set<RawConfiguration> copy = new HashSet<RawConfiguration>();
+ for (RawConfiguration rawConfig : this.rawConfigurations) {
+ copy.add(rawConfig.deepCopy(true));
+ }
+ return copy;
}
@SuppressWarnings("unchecked")
@@ -694,4 +694,4 @@ public class Configuration implements Externalizable, Cloneable, AbstractPropert
public Map<String, Property> getAllProperties() {
return this.properties;
}
-}
\ No newline at end of file
+}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/DeepCopyable.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/DeepCopyable.java
index e3e56d5..c680b04 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/DeepCopyable.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/DeepCopyable.java
@@ -25,6 +25,6 @@ package org.rhq.core.domain.configuration;
public interface DeepCopyable<T> {
- T deepCopy();
+ T deepCopy(boolean keepId);
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Property.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Property.java
index f4494c8..5c1ba79 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Property.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/Property.java
@@ -127,7 +127,10 @@ public class Property implements Externalizable, DeepCopyable<Property> {
public Property() {
}
- protected Property(Property original) {
+ protected Property(Property original, boolean keepId) {
+ if (keepId) {
+ this.id = original.id;
+ }
this.errorMessage = original.errorMessage;
this.name = original.name;
}
@@ -284,7 +287,7 @@ public class Property implements Externalizable, DeepCopyable<Property> {
return ((this.name != null) ? this.name.hashCode() : 0);
}
- public Property deepCopy() {
+ public Property deepCopy(boolean keepId) {
return null;
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
index a2223d9..c3e26a0 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyList.java
@@ -68,7 +68,7 @@ public class PropertyList extends Property {
@Cascade( { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.DELETE_ORPHAN })
@OneToMany(mappedBy = "parentList", targetEntity = Property.class, fetch = FetchType.EAGER)
//@IndexColumn(name = "list_index") TODO GH: This seems broken
- private List<Property> list;
+ private List<Property> list = new ArrayList<Property>();
@Transient
String memberPropertyName;
@@ -86,8 +86,8 @@ public class PropertyList extends Property {
setName(name);
}
- protected PropertyList(PropertyList original) {
- super(original);
+ protected PropertyList(PropertyList original, boolean keepId) {
+ super(original, keepId);
}
/**
@@ -212,11 +212,11 @@ public class PropertyList extends Property {
return result;
}
- public PropertyList deepCopy() {
- PropertyList copy = new PropertyList(this);
+ public PropertyList deepCopy(boolean keepId) {
+ PropertyList copy = new PropertyList(this, keepId);
for (Property property : list) {
- copy.add(property.deepCopy());
+ copy.add(property.deepCopy(false));
}
return copy;
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
index 137c6fe..e8e15b7 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/PropertyMap.java
@@ -68,7 +68,7 @@ public class PropertyMap extends Property implements AbstractPropertyMap {
@Cascade( { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH, CascadeType.DELETE_ORPHAN })
@MapKey(name = "name")
@OneToMany(mappedBy = "parentMap", fetch = FetchType.EAGER)
- private Map<String, Property> map;
+ private Map<String, Property> map = new LinkedHashMap<String, Property>();
/**
* Creates a new unnamed and empty {@link PropertyMap} object.
@@ -76,8 +76,8 @@ public class PropertyMap extends Property implements AbstractPropertyMap {
public PropertyMap() {
}
- protected PropertyMap(PropertyMap original) {
- super(original);
+ protected PropertyMap(PropertyMap original, boolean keepId) {
+ super(original, keepId);
}
/**
@@ -263,11 +263,11 @@ public class PropertyMap extends Property implements AbstractPropertyMap {
return result;
}
- public PropertyMap deepCopy() {
- PropertyMap copy = new PropertyMap(this);
+ public PropertyMap deepCopy(boolean keepId) {
+ PropertyMap copy = new PropertyMap(this, keepId);
for (Property property : map.values()) {
- copy.put(property.deepCopy());
+ copy.put(property.deepCopy(keepId));
}
return copy;
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 0824553..04aeb7e 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
@@ -70,8 +70,8 @@ public class PropertySimple extends Property implements Externalizable {
override = Boolean.FALSE;
}
- protected PropertySimple(PropertySimple original) {
- super(original);
+ protected PropertySimple(PropertySimple original, boolean keepId) {
+ super(original, keepId);
this.override = original.override;
this.unmaskedStringValue = original.unmaskedStringValue;
this.stringValue = original.stringValue;
@@ -85,9 +85,7 @@ public class PropertySimple extends Property implements Externalizable {
* @param name
* @param value
*/
- public PropertySimple(@NotNull
- String name, @Nullable
- Object value) {
+ public PropertySimple(@NotNull String name, @Nullable Object value) {
setName(name);
setValue(value);
}
@@ -98,8 +96,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setValue(@Nullable
- Object value) {
+ public void setValue(@Nullable Object value) {
if (value == null) {
stringValue = null;
return;
@@ -131,8 +128,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setStringValue(@Nullable
- String value) {
+ public void setStringValue(@Nullable String value) {
this.setValue(value);
}
@@ -157,8 +153,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setBooleanValue(@Nullable
- Boolean value) {
+ public void setBooleanValue(@Nullable Boolean value) {
this.setValue(value);
}
@@ -207,8 +202,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setIntegerValue(@Nullable
- Integer value) {
+ public void setIntegerValue(@Nullable Integer value) {
this.setValue(value);
}
@@ -232,8 +226,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setFloatValue(@Nullable
- Float value) {
+ public void setFloatValue(@Nullable Float value) {
this.setValue(value);
}
@@ -257,8 +250,7 @@ public class PropertySimple extends Property implements Externalizable {
*
* @param value
*/
- public void setDoubleValue(@Nullable
- Double value) {
+ public void setDoubleValue(@Nullable Double value) {
this.setValue(value);
}
@@ -336,8 +328,8 @@ public class PropertySimple extends Property implements Externalizable {
return result;
}
- public PropertySimple deepCopy() {
- return new PropertySimple(this);
+ public PropertySimple deepCopy(boolean keepId) {
+ return new PropertySimple(this, keepId);
}
@Override
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/RawConfiguration.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/RawConfiguration.java
index ca02070..22a7161 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/RawConfiguration.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/RawConfiguration.java
@@ -243,9 +243,14 @@ public class RawConfiguration implements Serializable, DeepCopyable<RawConfigura
.toString();
}
- public RawConfiguration deepCopy() {
+ public RawConfiguration deepCopy(boolean keepId) {
RawConfiguration copy = new RawConfiguration();
+ if (keepId) {
+ copy.id = this.id;
+ }
+
copy.path = this.path;
+
if (this.contents != null) {
copy.setContents(this.getContents());
}
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index eda26d8..4047d10 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -187,25 +187,6 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " LEFT JOIN p.scheduledJobsConfiguration " //
+ " WHERE p.deployment = 'SERVER' AND p.status = 'INSTALLED' "), //
- // this query does not update the content blob or ctime
- @NamedQuery(name = Plugin.UPDATE_ALL_BUT_CONTENT, query = "" //
- + "UPDATE Plugin p " //
- + " SET p.name = :name, " //
- + " p.displayName = :displayName, " //
- + " p.description = :description, " //
- + " p.enabled = :enabled, " //
- + " p.status = :status, " //
- + " p.help = :help, " //
- + " p.version = :version, " //
- + " p.ampsVersion = :ampsVersion," //
- + " p.deployment = :deployment, " //
- + " p.pluginConfiguration = :pluginConfiguration, " //
- + " p.scheduledJobsConfiguration = :scheduledJobsConfiguration, " //
- + " p.path = :path, " //
- + " p.md5 = :md5, " //
- + " p.mtime = :mtime " //
- + " WHERE p.id = :id"),
-
// this query is how you enable and disable plugins
@NamedQuery(name = Plugin.UPDATE_PLUGINS_ENABLED_BY_IDS, query = "" //
+ "UPDATE Plugin p " //
@@ -256,7 +237,6 @@ public class Plugin implements Serializable {
public static final String QUERY_FIND_BY_IDS_AND_TYPE = "Plugin.findByIdsAndType";
public static final String QUERY_GET_NAMES_BY_ENABLED_AND_TYPE = "Plugin.findByEnabledAndType";
public static final String QUERY_GET_STATUS_BY_NAME_AND_TYPE = "Plugin.getStatusByNameAndType";
- public static final String UPDATE_ALL_BUT_CONTENT = "Plugin.updateAllButContent";
public static final String UPDATE_PLUGINS_ENABLED_BY_IDS = "Plugin.updatePluginsEnabledByIds";
@Column(name = "ID", nullable = false)
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java
index 36084ec..85afc00 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ConfigurationTest.java
@@ -38,59 +38,107 @@ import java.util.Set;
public class ConfigurationTest {
@Test
- public void deepCopyWithoutProxiesShouldNotReturnReferenceToOriginalObject() {
+ public void deepCopyShouldNotReturnReferenceToOriginalObjectWhenKeepingIds() {
Configuration original = createConfiguration();
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(true);
assertNotSame(copy, original, "Expected a reference to a new Configuration object, not the original object being copied");
}
@Test
- public void deepCopyWithoutProxiesShouldCopySimpleFields() {
+ public void deepCopyShouldNotReturnReferenceToOriginalObjectWhenNotKeepingIds() {
Configuration original = createConfiguration();
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
+ assertNotSame(copy, original, "Expected a reference to a new Configuration object, not the original object being copied");
+ }
+
+ @Test
+ public void deepCopyShouldCopyAllSimpleFieldsWhenKeepingIds() {
+ Configuration original = createConfiguration();
+ Configuration copy = original.deepCopy(true);
+
+ assertEquals(copy.getId(), original.getId(), "Failed to copy the id property");
assertEquals(copy.getNotes(), original.getNotes(), "Failed to copy the notes property");
assertEquals(copy.getVersion(), original.getVersion(), "Failed to copy version property");
}
@Test
- public void deepCopyWithoutProxiesShouldNotCopyIdProperty() {
+ public void deepCopyShouldNotCopyIdWhenNotKeepingIds() {
Configuration original = createConfiguration();
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
assertFalse(copy.getId() == original.getId(), "The original id property should not be copied");
+ assertEquals(copy.getNotes(), original.getNotes(), "Failed to copy the notes property");
+ assertEquals(copy.getVersion(), original.getVersion(), "Failed to copy version property");
+ }
+
+ @Test
+ public void deepCopyShouldCopyPropertiesWhenKeepingIds() {
+ Configuration original = createConfiguration();
+ original.put(new PropertySimple("simpleProperty", "Simple Property"));
+
+ Configuration copy = original.deepCopy(true);
+
+ assertNotSame(copy.getProperties(), original.getProperties(), "The properties property should not refer to the properties in the original object");
+ assertEquals(copy.getProperties(), original.getProperties(), "Failed to copy the contents of the properties collection");
}
@Test
- public void deepCopyWithoutProxiesShouldCopyProperties() {
+ public void deepCopyShouldCopyPropertiesWhenNotKeepingIds() {
Configuration original = createConfiguration();
original.put(new PropertySimple("simpleProperty", "Simple Property"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
assertNotSame(copy.getProperties(), original.getProperties(), "The properties property should not refer to the properties in the original object");
assertEquals(copy.getProperties(), original.getProperties(), "Failed to copy the contents of the properties collection");
}
@Test
- public void deepCopyWithoutProxiesShouldNotReturnCopyReferenceOfOriginalProperty() {
+ public void deepCopyShouldNotReturnCopyReferenceOfOriginalPropertyWhenKeepingIds() {
Configuration original = createConfiguration();
String propertyName = "simpleProperty";
original.put(new PropertySimple(propertyName, "Simple Property"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(true);
assertNotSame(copy.get(propertyName), original.get(propertyName), "Expected a refernce to a new property, not the original property being copied");
}
@Test
- public void deepCopyWithoutProxiesShouldSetParentReferenceOfCopiedProperties() {
+ public void deepCopyShouldNotReturnCopyReferenceOfOriginalPropertyWhenNotKeepingIds() {
+ Configuration original = createConfiguration();
+ String propertyName = "simpleProperty";
+ original.put(new PropertySimple(propertyName, "Simple Property"));
+
+ Configuration copy = original.deepCopy(false);
+
+ assertNotSame(copy.get(propertyName), original.get(propertyName), "Expected a refernce to a new property, not the original property being copied");
+ }
+
+ @Test
+ public void deepCopyShouldSetParentReferenceOfCopiedPropertiesWhenKeepingIds() {
+ Configuration original = createConfiguration();
+ String propertyName = "simpleProperty";
+ original.put(new PropertySimple(propertyName, "Simple Property"));
+
+ Configuration copy = original.deepCopy(true);
+
+ assertSame(
+ copy.get(propertyName).getConfiguration(),
+ copy,
+ "The reference to the parent configuration should point to the newly copied configuration, not the original configuration"
+ );
+ }
+
+ @Test
+ public void deepCopyShouldSetParentReferenceOfCopiedPropertiesWhenNotKeepingIds() {
Configuration original = createConfiguration();
String propertyName = "simpleProperty";
original.put(new PropertySimple(propertyName, "Simple Property"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
assertSame(
copy.get(propertyName).getConfiguration(),
@@ -100,11 +148,27 @@ public class ConfigurationTest {
}
@Test
- public void deepCopyWithoutProxiesShouldCopyRawConfigurations() {
+ public void deepCopyShouldCopyRawConfigurationsWhenKeepingIds() {
Configuration original = createConfiguration();
original.addRawConfiguration(createRawConfiguration("/tmp/foo"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(true);
+
+ assertNotSame(
+ copy.getRawConfigurations(),
+ original.getRawConfigurations(),
+ "The rawConfigurations property should not refer to the original rawConfigurations of the copied object."
+ );
+
+ assertRawConfigurationsEquals(copy.getRawConfigurations(), original.getRawConfigurations(), "Failed to copy rawConfigurations property.");
+ }
+
+ @Test
+ public void deepCopyShouldCopyRawConfigurationsWhenNotKeepingIds() {
+ Configuration original = createConfiguration();
+ original.addRawConfiguration(createRawConfiguration("/tmp/foo"));
+
+ Configuration copy = original.deepCopy(false);
assertNotSame(
copy.getRawConfigurations(),
@@ -123,11 +187,26 @@ public class ConfigurationTest {
}
@Test
- public void deepCopyWithoutProxiesShouldSetParentReferenceOfCopiedRawConfigurations() {
+ public void deepCopyShouldSetParentReferenceOfCopiedRawConfigurationsWhenKeepingIds() {
+ Configuration original = createConfiguration();
+ original.addRawConfiguration(createRawConfiguration("/tmp/foo"));
+
+ Configuration copy = original.deepCopy(true);
+ RawConfiguration copiedRawConfig = getCopiedRawConfiguration(copy);
+
+ assertSame(
+ copiedRawConfig.getConfiguration(),
+ copy,
+ "The reference to the parent configuration should point to the newly copied configuration, not the original configuration."
+ );
+ }
+
+ @Test
+ public void deepCopyShouldSetParentReferenceOfCopiedRawConfigurationsWhenNotKeepingIds() {
Configuration original = createConfiguration();
original.addRawConfiguration(createRawConfiguration("/tmp/foo"));
- Configuration copy = original.deepCopyWithoutProxies();
+ Configuration copy = original.deepCopy(false);
RawConfiguration copiedRawConfig = getCopiedRawConfiguration(copy);
assertSame(
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyListTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyListTest.java
index d298001..56d3887 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyListTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyListTest.java
@@ -30,41 +30,52 @@ import org.testng.annotations.Test;
public class PropertyListTest {
@Test
- public void deepCopyShouldCopySimpleFields() {
+ public void deepCopyShouldCopyAllSimpleFields() {
PropertyList original = createPropertyList();
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(true);
assertNotSame(copy, original, "The copy should not reference the original object");
-
+
+ assertEquals(copy.getId(), original.getId(), "Failed to copy the id property");
assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
}
@Test
- public void deepCopyShouldNotCopyIdField() {
+ public void deepCopyShouldNotCopyIdFieldWhenFlagIsFalse() {
PropertyList original = createPropertyList();
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(false);
assertFalse(copy.getId() == original.getId(), "The original id property should not be copied.");
+ assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
+ assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
+ }
+
+ @Test
+ public void deepCopyShouldNotCopyReferenceOfUnderlyingListWhenIdIncluded() {
+ PropertyList original = createPropertyList();
+ PropertyList copy = original.deepCopy(true);
+
+ assertNotSame(original.getList(), copy.getList(), "The values in the underlying list should be copied, not the variable reference to the list.");
}
@Test
- public void deepCopyShouldNotCopyReferenceOfUnderlyingList() {
+ public void deepCopyShouldNotCopyReferenceOfUnderlyingListWhenIdNotIncluded() {
PropertyList original = createPropertyList();
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(false);
assertNotSame(original.getList(), copy.getList(), "The values in the underlying list should be copied, not the variable reference to the list.");
}
@Test
- public void deepCopyShouldCopyProperty() {
+ public void deepCopyShouldCopyPropertyWhenIdIncluded() {
PropertyList original = createPropertyList();
PropertySimple simpleProperty = new PropertySimple("simeplProperty", "Simple Property");
original.add(simpleProperty);
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(true);
assertEquals(copy.getList().size(), original.getList().size(), "Failed to copy simple property contained in original property list");
@@ -72,13 +83,39 @@ public class PropertyListTest {
}
@Test
- public void deepCopyShouldSetParentOfCopiedProperty() {
+ public void deepCopyShouldCopyPropertyWhenIdNotIncluded() {
+ PropertyList original = createPropertyList();
+
+ PropertySimple simpleProperty = new PropertySimple("simeplProperty", "Simple Property");
+ original.add(simpleProperty);
+
+ PropertyList copy = original.deepCopy(false);
+
+ assertEquals(copy.getList().size(), original.getList().size(), "Failed to copy simple property contained in original property list");
+
+ assertNotSame(copy.getList().get(0), original.getList().get(0), "Properties in the list should be copied by value as opposed to just copying the references");
+ }
+
+ @Test
+ public void deepCopyShouldSetParentOfCopiedPropertyWhenIdIncluded() {
+ PropertyList original = createPropertyList();
+
+ PropertySimple simpleProperty = new PropertySimple("simpleProperty", "Simple Property");
+ original.add(simpleProperty);
+
+ PropertyList copy = original.deepCopy(true);
+
+ assertSame(copy.getList().get(0).getParentList(), copy, "The parentList property of copied properties should be set to the new PropertyList");
+ }
+
+ @Test
+ public void deepCopyShouldSetParentOfCopiedPropertyWhenIdNotIncluded() {
PropertyList original = createPropertyList();
PropertySimple simpleProperty = new PropertySimple("simpleProperty", "Simple Property");
original.add(simpleProperty);
- PropertyList copy = original.deepCopy();
+ PropertyList copy = original.deepCopy(false);
assertSame(copy.getList().get(0).getParentList(), copy, "The parentList property of copied properties should be set to the new PropertyList");
}
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyMapTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyMapTest.java
index 4a999b6..e73d835 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyMapTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertyMapTest.java
@@ -30,40 +30,55 @@ import org.testng.annotations.Test;
public class PropertyMapTest {
@Test
- public void deepCopyShouldCopySimpleFields() {
+ public void deepCopyShouldCopyAllSimpleFields() {
PropertyMap original = createPropertyMap();
- PropertyMap copy = original.deepCopy();
+ PropertyMap copy = original.deepCopy(true);
assertNotSame(copy, original, "The copy should not reference the original object");
+ assertEquals(copy.getId(), original.getId(), "Failed to copy the id property");
assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
}
@Test
- public void deepCopyShouldNotCopyIdField() {
+ public void deepCopyShouldNotCopyIdFieldWhenFlagIsFalse() {
PropertyMap original = createPropertyMap();
- PropertyMap copy = original.deepCopy();
+ PropertyMap copy = original.deepCopy(false);
+
+ assertNotSame(copy, original, "The copy should not reference the original object");
assertFalse(copy.getId() == original.getId(), "The original id property should not be copied.");
+ assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
+ assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
}
@Test
- public void deepCopyShouldNotCopyReferenceOfUnderlyingMap() {
+ public void deepCopyShouldCopyPropertyWhenIdIncluded() {
PropertyMap original = createPropertyMap();
- PropertyMap copy = original.deepCopy();
- assertNotSame(copy.getMap(), original.getMap(), "The values in the underlying map should be copied, not the reference to the map itself");
+ PropertySimple simpleProperty = new PropertySimple("simeplProperty", "Simple Property");
+ original.put(simpleProperty);
+
+ PropertyMap copy = original.deepCopy(true);
+
+ assertEquals(copy.getMap().size(), original.getMap().size(), "Failed to copy simple property contained in original property map");
+
+ assertNotSame(
+ copy.getMap().get(simpleProperty.getName()),
+ original.getMap().get(simpleProperty.getName()),
+ "Properties in the map should be copied by value as opposed to just copying the references"
+ );
}
@Test
- public void deepCopyShouldCopyProperty() {
+ public void deepCopyShouldCopyPropertyWhenIdNotIncluded() {
PropertyMap original = createPropertyMap();
PropertySimple simpleProperty = new PropertySimple("simeplProperty", "Simple Property");
original.put(simpleProperty);
- PropertyMap copy = original.deepCopy();
+ PropertyMap copy = original.deepCopy(false);
assertEquals(copy.getMap().size(), original.getMap().size(), "Failed to copy simple property contained in original property map");
@@ -75,13 +90,29 @@ public class PropertyMapTest {
}
@Test
- public void deepCopyShouldSetParentOfCopiedProperty() {
+ public void deepCopyShouldSetParentOfCopiedPropertyWhenIdIncluded() {
+ PropertyMap original = createPropertyMap();
+
+ PropertySimple simpleProperty = new PropertySimple("simpleProperty", "Simple Property");
+ original.put(simpleProperty);
+
+ PropertyMap copy = original.deepCopy(true);
+
+ assertSame(
+ copy.get(simpleProperty.getName()).getParentMap(),
+ copy,
+ "The parentMap property of copied properties should be set to the new PropertyMap"
+ );
+ }
+
+ @Test
+ public void deepCopyShouldSetParentOfCopiedPropertyWhenIdNotIncluded() {
PropertyMap original = createPropertyMap();
PropertySimple simpleProperty = new PropertySimple("simpleProperty", "Simple Property");
original.put(simpleProperty);
- PropertyMap copy = original.deepCopy();
+ PropertyMap copy = original.deepCopy(false);
assertSame(
copy.get(simpleProperty.getName()).getParentMap(),
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertySimpleTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertySimpleTest.java
index c1b76aa..7b49837 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertySimpleTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PropertySimpleTest.java
@@ -30,13 +30,14 @@ import org.testng.annotations.Test;
public class PropertySimpleTest {
@Test
- public void deepCopyShouldCopySimpleFields() {
+ public void deepCopyShouldCopyAllSimpleFields() {
PropertySimple original = createProperty();
- PropertySimple copy = original.deepCopy();
+ PropertySimple copy = original.deepCopy(true);
assertNotSame(copy, original, "The copy should not reference the original object");
-
+
+ assertEquals(copy.getId(), original.getId(), "Failed to copy the id property");
assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
assertEquals(copy.getOverride(), original.getOverride(), "Failed to copy the override property");
@@ -45,12 +46,17 @@ public class PropertySimpleTest {
}
@Test
- public void deepCopyShouldNotCopyIdField() {
+ public void deepCopyShouldNotCopyIdFieldWhenFlagIsFalse() {
PropertySimple original = createProperty();
- PropertySimple copy = original.deepCopy();
+ PropertySimple copy = original.deepCopy(false);
assertFalse(copy.getId() == original.getId(), "The original id property should not be copied.");
+ assertEquals(copy.getName(), original.getName(), "Failed to copy the name property");
+ assertEquals(copy.getErrorMessage(), original.getErrorMessage(), "Failed to copy the errorMessage property");
+ assertEquals(copy.getOverride(), original.getOverride(), "Failed to copy the override property");
+ assertEquals(copy.getUnmaskedStringValue(), original.getUnmaskedStringValue(), "Failed to copy the unmaskedStringValue property");
+ assertEquals(copy.getStringValue(), original.getStringValue(), "Failed to copy the stringValue property");
}
private PropertySimple createProperty() {
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java
index fb926af..8f0aac8 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/RawConfigurationTest.java
@@ -212,33 +212,49 @@ public class RawConfigurationTest {
}
@Test
- public void deepCopyShouldCopyPath() {
+ public void deepCopyShouldCopyPathAndIdWhenIdIncluded() {
RawConfiguration original = new RawConfiguration();
original.setPath("/tmp/foo");
+ original.setId(-1);
- RawConfiguration copy = original.deepCopy();
+ RawConfiguration copy = original.deepCopy(true);
+ assertEquals(copy.getId(), copy.getId(), "Failed to copy the id property.");
assertEquals(copy.getPath(), original.getPath(), "Failed to copy the path property.");
}
@Test
- public void deepCopyShouldCopyContents() {
+ public void deepCopyShouldCopyPathAndIdWhenIdNotIncluded() {
+ RawConfiguration original = new RawConfiguration();
+ original.setPath("/tmp/foo");
+ original.setId(-1);
+
+ RawConfiguration copy = original.deepCopy(false);
+
+ assertFalse(copy.getId() == original.getId(), "The original id property should not be copied.");
+ assertEquals(copy.getPath(), original.getPath(), "Failed to copy the path property.");
+ }
+
+ @Test
+ public void deepCopyShouldCopyContentsWhenCopyingId() {
RawConfiguration original = new RawConfiguration();
original.setContents(new byte[] {1, 2, 3, 4, 5});
- RawConfiguration copy = original.deepCopy();
+ RawConfiguration copy = original.deepCopy(true);
assertFalse(original.getContents() == copy.getContents(), "The values in the contents array should be copied, not the reference to the original object.");
assertEquals(copy.getContents(), original.getContents(), "Failed to copy contents property.");
}
@Test
- public void deepCopyShouldNotCopyIdProperty() {
+ public void deepCopyShouldCopyContentsWhenNotCopyingId() {
RawConfiguration original = new RawConfiguration();
- original.setId(1);
+ original.setContents(new byte[] {1, 2, 3, 4, 5});
- RawConfiguration copy = original.deepCopy();
+ RawConfiguration copy = original.deepCopy(false);
- assertFalse(original.getId() == copy.getId(), "The id property should not be copied.");
+ assertFalse(original.getContents() == copy.getContents(), "The values in the contents array should be copied, not the reference to the original object.");
+ assertEquals(copy.getContents(), original.getContents(), "Failed to copy contents property.");
}
+
}
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index 07f8f97..729f7c2 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -131,23 +131,39 @@ public class PluginTest extends AbstractEJB3Test {
em.persist(jobsConfig);
em.flush(); // gotta get those two persists to flush to the DB
- q = em.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
- q.setParameter("id", id); // same as the one we just persisted
- q.setParameter("name", name);
- q.setParameter("path", path);
- q.setParameter("displayName", displayName);
- q.setParameter("enabled", enabled);
- q.setParameter("status", status);
- q.setParameter("md5", md5);
- q.setParameter("version", version);
- q.setParameter("ampsVersion", ampsVersion);
- q.setParameter("deployment", deployment);
- q.setParameter("pluginConfiguration", pluginConfig);
- q.setParameter("scheduledJobsConfiguration", jobsConfig);
- q.setParameter("description", description);
- q.setParameter("help", help);
- q.setParameter("mtime", System.currentTimeMillis());
- assert q.executeUpdate() == 1 : "Failed to update the plugin";
+ // do what ServerPluginsBean/ResourceMetadataManagerBean.updateServerPluginExceptContent does
+ Configuration config = plugin.getPluginConfiguration();
+ if (config != null) {
+ config = em.merge(config);
+ plugin.setPluginConfiguration(config);
+ }
+ config = plugin.getScheduledJobsConfiguration();
+ if (config != null) {
+ config = em.merge(config);
+ plugin.setScheduledJobsConfiguration(config);
+ }
+
+ Plugin pluginEntity = em.getReference(Plugin.class, plugin.getId());
+ pluginEntity.setName(name);
+ pluginEntity.setPath(path);
+ pluginEntity.setDisplayName(displayName);
+ pluginEntity.setEnabled(enabled);
+ pluginEntity.setStatus(status);
+ pluginEntity.setMd5(md5);
+ pluginEntity.setVersion(version);
+ pluginEntity.setAmpsVersion(ampsVersion);
+ pluginEntity.setDeployment(deployment);
+ pluginEntity.setPluginConfiguration(pluginConfig);
+ pluginEntity.setScheduledJobsConfiguration(jobsConfig);
+ pluginEntity.setDescription(description);
+ pluginEntity.setHelp(help);
+ pluginEntity.setMtime(System.currentTimeMillis());
+
+ try {
+ em.flush(); // make sure we push this out to the DB now
+ } catch (Exception e) {
+ throw new Exception("Failed to update a plugin that matches [" + plugin + "]", e);
+ }
em.close();
getTransactionManager().commit(); // must commit now
@@ -163,7 +179,7 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.isEnabled() == enabled;
assert plugin.getMD5().equals(md5);
assert plugin.getVersion().equals(version);
- q.setParameter("ampsVersion", ampsVersion);
+ assert plugin.getAmpsVersion().equals(ampsVersion);
assert plugin.getDescription().equals(description);
assert plugin.getDeployment() == PluginDeploymentType.SERVER;
assert plugin.getPluginConfiguration().equals(pluginConfig);
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 d9c2a9f..dfee3a5 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
@@ -161,5 +161,14 @@ public class ComparableVersionTest {
assert ver2.compareTo(ver2) == 0;
assert ver1.compareTo(ver2) > 0; // ver1 is after ver2!
assert ver2.compareTo(ver1) < 0; // ver1 is after ver2!
+
+ ver1 = new ComparableVersion("4.0.0-SNAPSHOT");
+ ver2 = new ComparableVersion("4.0.0.CR2"); // CR is an alias for RC
+ assert !ver1.equals(ver2);
+ assert !ver2.equals(ver1);
+ assert ver1.compareTo(ver1) == 0;
+ assert ver2.compareTo(ver2) == 0;
+ assert ver1.compareTo(ver2) < 0;
+ assert ver2.compareTo(ver1) > 0;
}
}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java
new file mode 100644
index 0000000..0bb87bd
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java
@@ -0,0 +1,73 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.admin.plugin;
+
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.AutoCreate;
+import org.jboss.seam.annotations.Factory;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.web.RequestParameter;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Component responsible for looking up a {@link Plugin}, obtaining
+ * the <code>name</code> and <code>type</code> from request parameters.
+ *
+ * @author jharris
+ */
+@Name("installedPlugin")
+public class InstalledPluginComponent {
+
+ @RequestParameter("plugin")
+ private String name;
+ @RequestParameter("pluginType")
+ private PluginDeploymentType type;
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public PluginDeploymentType getType() {
+ return this.type;
+ }
+
+ public void setType(PluginDeploymentType type) {
+ this.type = type;
+ }
+
+ @Factory(value="plugin", autoCreate=true, scope=ScopeType.PAGE)
+ public Plugin lookupPlugin() {
+ if (this.type == PluginDeploymentType.AGENT) {
+ return LookupUtil.getResourceMetadataManager().getPlugin(this.name);
+ } else if (this.type == PluginDeploymentType.SERVER) {
+ ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
+ Plugin plugin = serverPluginsBean.getServerPlugin(this.name);
+ return serverPluginsBean.getServerPluginRelationships(plugin);
+ }
+
+ return null;
+ }
+}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
index f6eee0d..3fe6988 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
@@ -21,8 +21,13 @@ package org.rhq.enterprise.gui.admin.plugin;
import javax.faces.application.FacesMessage;
import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.Create;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
import org.rhq.core.clientapi.agent.metadata.ConfigurationMetadataParser;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
@@ -40,21 +45,24 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
* @author Greg Hinkle
* @author John Mazzitelli
*/
+(a)Scope(ScopeType.PAGE)
+@Name("InstalledPluginUIBean")
public class InstalledPluginUIBean {
- private final Log log = LogFactory.getLog(InstalledPluginUIBean.class);
+ private static final String OUTCOME_SUCCESS = "success";
public static final String MANAGED_BEAN_NAME = InstalledPluginUIBean.class.getSimpleName();
-
+ private final Log log = LogFactory.getLog(InstalledPluginUIBean.class);
+ @In
private Plugin plugin;
private ConfigurationDefinition pluginConfigurationDefinition;
private ConfigurationDefinition scheduledJobsDefinition;
- public InstalledPluginUIBean() {
- lookupPlugin();
+ public Plugin getPlugin() {
+ return plugin;
}
- public Plugin getPlugin() {
- return this.plugin;
+ public void setPlugin(Plugin plugin) {
+ this.plugin = plugin;
}
public ConfigurationDefinition getPluginConfigurationDefinition() {
@@ -65,23 +73,39 @@ public class InstalledPluginUIBean {
return this.scheduledJobsDefinition;
}
- private void lookupPlugin() {
+ public boolean isEditable() {
+ return this.pluginConfigurationDefinition != null || this.scheduledJobsDefinition != null;
+ }
+
+ public String updatePlugin() {
+ ServerPluginsLocal serverPlugins = LookupUtil.getServerPlugins();
+
+ try {
+ serverPlugins.updateServerPluginExceptContent(EnterpriseFacesContextUtility.getSubject(), plugin);
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO,
+ "Configuration settings saved.");
+
+ return OUTCOME_SUCCESS;
+ } catch (Exception e) {
+ log.error("Error updating the plugin configurations.", e);
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR,
+ "There was an error changing the configuration settings.", e);
+
+ return null;
+ }
+ }
+
+ @Create
+ public void lookupConfigDefinitions() {
hasPermission();
- String pluginName = FacesContextUtility.getRequiredRequestParameter("plugin", String.class);
- String pluginType = FacesContextUtility.getRequiredRequestParameter("pluginType", String.class);
- PluginDeploymentType deploymentType = PluginDeploymentType.valueOf(pluginType);
- if (deploymentType == PluginDeploymentType.AGENT) {
- this.plugin = LookupUtil.getResourceMetadataManager().getPlugin(pluginName);
- } else {
- ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
- this.plugin = serverPluginsBean.getServerPlugin(pluginName);
- this.plugin = serverPluginsBean.getServerPluginRelationships(this.plugin);
+ String pluginName = this.plugin.getName();
+
+ if (this.plugin.getDeployment() == PluginDeploymentType.SERVER) {
try {
+ ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
ServerPluginDescriptorType descriptor = serverPluginsBean.getServerPluginDescriptor(pluginName);
- this.pluginConfigurationDefinition = ConfigurationMetadataParser.parse("pc:" + pluginName, descriptor
- .getPluginConfiguration());
- this.scheduledJobsDefinition = ConfigurationMetadataParser.parse("jobs:" + pluginName, descriptor
- .getScheduledJobs());
+ this.pluginConfigurationDefinition = ConfigurationMetadataParser.parse("pc:" + pluginName, descriptor.getPluginConfiguration());
+ this.scheduledJobsDefinition = ConfigurationMetadataParser.parse("jobs:" + pluginName, descriptor.getScheduledJobs());
} catch (Exception e) {
String err = "Cannot determine what the plugin configuration or scheduled jobs configuration looks like";
log.error(err + " - Cause: " + e);
@@ -97,8 +121,7 @@ public class InstalledPluginUIBean {
private void hasPermission() {
Subject subject = EnterpriseFacesContextUtility.getSubject();
if (!LookupUtil.getAuthorizationManager().hasGlobalPermission(subject, Permission.MANAGE_SETTINGS)) {
- throw new PermissionException("User [" + subject.getName()
- + "] does not have the proper permissions to view or manage plugins");
+ throw new PermissionException("User [" + subject.getName() + "] does not have the proper permissions to view or manage plugins");
}
}
-}
\ No newline at end of file
+}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java
index a4ce93b..491612a 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/configuration/resource/RawConfigCollection.java
@@ -165,7 +165,7 @@ public class RawConfigCollection implements Serializable {
String u2 = updated.substring(2);
String original = new String(getCurrent().getContents());
if (!u2.equals(original)) {
- current = current.deepCopy();
+ current = current.deepCopy(false);
current.setContents(updated.getBytes());
//TODO update other values like MD5
modified.put(current.getPath(), current);
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml
index bacb535..64bd31e 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml
@@ -11,6 +11,7 @@
<component name="org.jboss.seam.core.init">
<property name="debug">false</property> <!-- enable only when needed -->
<property name="transactionManagementEnabled">false</property>
+ <property name="jndi-pattern">rhq/#{ejbName}/local</property>
</component>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml
index 11dadd0..a80402b 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml
@@ -20,13 +20,6 @@
<managed-bean-class>org.rhq.enterprise.gui.admin.plugin.InstalledPluginsUIBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
- <managed-bean>
- <description>Visibility for the installed agent and server plugins</description>
- <display-name>Installed Plugin</display-name>
- <managed-bean-name>InstalledPluginUIBean</managed-bean-name>
- <managed-bean-class>org.rhq.enterprise.gui.admin.plugin.InstalledPluginUIBean</managed-bean-class>
- <managed-bean-scope>request</managed-bean-scope>
- </managed-bean>
<managed-bean>
<description>Access to downloads information</description>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml
index 93932df..7f19f4d 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml
@@ -28,6 +28,17 @@
</navigation-case>
</navigation-rule>
+
+ <navigation-rule>
+ <from-view-id>/rhq/admin/plugin/plugin-details-edit.xhtml</from-view-id>
+
+ <navigation-case>
+ <from-outcome>success</from-outcome>
+ <to-view-id>/rhq/admin/plugin/plugin-details-view.xhtml?plugin=#{plugin.name}&pluginType=#{plugin.deployment}</to-view-id>
+ <redirect/>
+ </navigation-case>
+
+ </navigation-rule>
<navigation-rule>
<navigation-case>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
index f3f0a35..2c47b0a 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
@@ -1,378 +1,397 @@
-<%@ page import="java.io.ByteArrayOutputStream" %>
-<%@ page import="java.io.PrintStream" %>
-
-<%@ page import="org.rhq.core.domain.auth.Subject" %>
-<%@ page import="org.rhq.core.domain.util.PersistenceUtility" %>
-
-<%@ page import="org.rhq.enterprise.gui.legacy.util.SessionUtils"%>
-<%@ page import="org.rhq.enterprise.gui.util.WebUtility"%>
-
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences" %>
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences.MetricRangePreferences" %>
-
-<%@ page import="org.rhq.enterprise.server.test.CoreTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.DiscoveryTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.MeasurementTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.SubjectRoleTestBeanLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.AlertTemplateTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.cloud.instance.ServerManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementBaselineManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.core.AgentManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.system.SystemManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.auth.SubjectManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.support.SupportManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.util.LookupUtil" %>
-<%@ page import="org.rhq.enterprise.server.scheduler.jobs.DataPurgeJob"%>
-
-<%@ page import="org.rhq.enterprise.server.resource.ResourceTypeManagerRemote"%>
-<%@ page import="org.rhq.core.domain.criteria.ResourceTypeCriteria"%>
-<%@ page import="org.rhq.core.domain.resource.ResourceType"%>
-
-<%@ page import="javax.naming.NamingException" %>
-
-<%@ page contentType="text/html;charset=UTF-8" language="java" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-
-<html>
-<head><title>RHQ Test Control Page</title></head>
-<body>
-
-<jsp:include page="/admin/include/adminTestLinks.html" flush="true" />
-
-<%
- CoreTestLocal coreTestBean;
- DiscoveryTestLocal discoveryTestBean;
- MeasurementTestLocal measurementTestBean;
- ResourceGroupTestBeanLocal resourceGroupTestBean;
- SubjectRoleTestBeanLocal subjectRoleTestBean;
- ServerManagerLocal serverManager;
- AlertTemplateTestLocal alertTemplateTestBean;
- MeasurementBaselineManagerLocal measurementBaselineManager;
- MeasurementScheduleManagerLocal measurementScheduleManager;
- AgentManagerLocal agentManager;
- SystemManagerLocal systemManager;
- SubjectManagerLocal subjectManager;
- SupportManagerLocal supportManager;
- ResourceTypeManagerRemote typeManager;
-
- coreTestBean = LookupUtil.getCoreTest();
- discoveryTestBean = LookupUtil.getDiscoveryTest();
- measurementTestBean = LookupUtil.getMeasurementTest();
- resourceGroupTestBean = LookupUtil.getResourceGroupTestBean();
- subjectRoleTestBean = LookupUtil.getSubjectRoleTestBean();
- serverManager = LookupUtil.getServerManager();
- alertTemplateTestBean = LookupUtil.getAlertTemplateTestBean();
- measurementBaselineManager = LookupUtil.getMeasurementBaselineManager();
- measurementScheduleManager = LookupUtil.getMeasurementScheduleManager();
- agentManager = LookupUtil.getAgentManager();
- systemManager = LookupUtil.getSystemManager();
- subjectManager = LookupUtil.getSubjectManager();
- supportManager = LookupUtil.getSupportManager();
- typeManager = LookupUtil.getResourceTypeManagerRemote();
-
- String result = null;
- String mode = pageContext.getRequest().getParameter("mode");
- String failure = null;
- try
- {
- if ("registerTestAgent".equals(mode))
- {
- coreTestBean.registerTestAgent();
- }
- else if ("registerTestPluginAndTypeInfo".equals(mode))
- {
- discoveryTestBean.registerTestPluginAndTypeInfo();
- }
- else if ("removeTestPluginAndTypeInfo".equals(mode))
- {
- discoveryTestBean.removeTestPluginAndTypeInfo();
- }
- else if ("sendTestFullInventoryReport".equals(mode))
- {
- discoveryTestBean.sendTestFullInventoryReport();
- }
- else if ("sendTestRuntimeInventoryReport".equals(mode))
- {
- discoveryTestBean.sendTestRuntimeInventoryReport();
- }
- else if ("sendTestMeasurementReport".equals(mode))
- {
- measurementTestBean.sendTestMeasurementReport();
- }
- else if ("sendNewPlatform".equals(mode))
- {
- String address = request.getParameter("address");
- int servers = Integer.parseInt(request.getParameter("servers"));
- int servicesPerServer = Integer.parseInt(request.getParameter("servicesPerServer"));
- discoveryTestBean.sendNewPlatform(address, servers, servicesPerServer);
- }
- else if ("setupCompatibleGroups".equals(mode))
- {
- resourceGroupTestBean.setupCompatibleGroups();
- }
- else if ("setupUberMixedGroup".equals(mode))
- {
- resourceGroupTestBean.setupUberMixedGroup();
- }
- else if ("startStats".equals(mode))
- {
- coreTestBean.enableHibernateStatistics();
- }
- else if ("addProblemResource".equals(mode))
- {
- measurementTestBean.addProblemResource();
- }
- else if ("setAgentCurrentlyScheduledMetrics".equals(mode))
- {
- String value = pageContext.getRequest().getParameter("v");
- measurementTestBean.setAgentCurrentlyScheduledMetrics(Double.valueOf(value));
- }
- else if ("addSubjectsAndRoles".equals(mode))
- {
- String roleCount = pageContext.getRequest().getParameter("roleCount");
- String usersInRoleCount = pageContext.getRequest().getParameter("usersInRoleCount");
- subjectRoleTestBean.createRolesAndUsers(Integer.parseInt(roleCount), Integer.parseInt(usersInRoleCount));
- }
- else if ("clusterGetIdentity".equals(mode))
- {
- String serverName = serverManager.getIdentity();
- pageContext.setAttribute("serverName", "(serverName = " + serverName + ")");
- }
- else if ("cloneAlertTemplate".equals(mode))
- {
- String alertTemplateId = pageContext.getRequest().getParameter("alertTemplateId");
- String numberOfClones = pageContext.getRequest().getParameter("numberOfClones");
- alertTemplateTestBean.cloneAlertTemplate(Integer.parseInt(alertTemplateId), Integer.parseInt(numberOfClones));
- }
- else if ("calculateAutoBaselines".equals(mode))
- {
- // for now, baselines aren't calculated until we hit our day limit, we force it here
- java.util.Properties props = systemManager.getSystemConfiguration();
- props.put("CAM_BASELINE_LASTTIME", "0");
- systemManager.setSystemConfiguration(subjectManager.getOverlord(), props,true);
-
- measurementBaselineManager.calculateAutoBaselines();
- }
- else if ("calculateOOBs".equals(mode))
- {
- DataPurgeJob dpj = new DataPurgeJob();
- dpj.calculateOOBs();
- }
- else if ("checkForSuspectAgents".equals(mode))
- {
- agentManager.checkForSuspectAgents();
- }
- else if ("dataPurgeJob".equals(mode))
- {
- DataPurgeJob.purgeNow();
- }
- else if ("dbMaintenance".equals(mode))
- {
- systemManager.vacuum(subjectManager.getOverlord());
- systemManager.reindex(subjectManager.getOverlord());
- systemManager.analyze(subjectManager.getOverlord());
- }
- else if ("metricDisplayRange".equals(mode))
- {
- int lastHours = Integer.parseInt(pageContext.getRequest().getParameter("lastHours"));
- Subject subject = WebUtility.getSubject(request);
- MeasurementPreferences prefs = new MeasurementPreferences(subject);
- MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
- rangePrefs.lastN = lastHours;
- prefs.setMetricRangePreferences(rangePrefs);
- }
- else if ("errorCorrectSchedules".equals("mode"))
- {
- measurementScheduleManager.errorCorrectSchedules();
- }
- else if ("generateSnapshotReport".equals(mode))
- {
- int resourceId = Integer.parseInt(request.getParameter("resourceId"));
- String name = request.getParameter("name");
- String description = request.getParameter("description");
- java.net.URL url = supportManager.getSnapshotReport(subjectManager.getOverlord(), resourceId, name, description);
- result = "Snapshot Report is located here: " + url.toString();
- }
- else if ("typeManagerRemote".equals(mode))
- {
- int typeId = Integer.parseInt(request.getParameter("typeId"));
- ResourceTypeCriteria criteria = new ResourceTypeCriteria();
- criteria.addFilterId(typeId);
- criteria.fetchMetricDefinitions(true);
- java.util.List<ResourceType> types = typeManager.findResourceTypesByCriteria(subjectManager.getOverlord(), criteria);
- result = "";
- for (ResourceType type : types) {
- result += type.getName() + " has " + (type.getMetricDefinitions() != null ? type.getMetricDefinitions().size() : "empty") + " metric definitions";
- }
- }
- }
- catch (Exception e)
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- e.printStackTrace(new PrintStream(baos));
- failure = baos.toString();
- }
-
- pageContext.setAttribute("executed", mode);
- pageContext.setAttribute("result", result);
- pageContext.setAttribute("failure", failure);
- pageContext.setAttribute("testAgentReported", Boolean.valueOf(coreTestBean.isTestAgentReported()));
-
-%>
-
-<c:if test="${executed != null}">
- <b>Executed <c:out value="${executed}"/>: </b> <c:out value="${result}"/><br>
- <c:if test="${failure != null}">
- <pre style="background-color: yellow;"><c:out value="${failure}"/></pre>
- </c:if>
-</c:if>
-
-<h2>Administration</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
-Add Lots of Users and Roles
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="addSubjectsAndRoles"/>
- Number of Roles: <input type="text" name="roleCount" size="5"/><br/>
- Number of Users in each Role: <input type="text" name="usersInRoleCount" size="5"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
- <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
-</ul>
-
-<h2>Core</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestAgent"/>
- <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=dbMaintenance"/>
- <a href="<c:out value="${url}"/>">Perform All Database Maintenance Now</a></li>
-</ul>
-
-<h2>Cluster</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=clusterGetIdentity"/>
- <a href="<c:out value="${url}"/>">Get Identity</a> <c:out value="${serverName}"/></li>
-</ul>
-
-<h2>Inventory</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestFullInventoryReport"/>
- <a href="<c:out value="${url}"/>">Send Full Inventory Report</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestRuntimeInventoryReport"/>
- <a href="<c:out value="${url}"/>">Send Runtime Inventory Report</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setupCompatibleGroups"/>
- <a href="<c:out value="${url}"/>">Setup Compatible Groups</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setupUberMixedGroup"/>
- <a href="<c:out value="${url}"/>">Setup Uber Mixed Group</a></li>
-</ul>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=sendNewPlatform"/>
-Send New Platform Inventory Report
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="sendNewPlatform"/>
- Address: <input type="text" name="address" size="30"/><br/>
- Servers: <input type="text" name="servers" size="5"/><br/>
- Services Per Server: <input type="text" name="servicesPerServer" size="5"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-
-<h2>Measurement</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateAutoBaselines"/>
- <a href="<c:out value="${url}"/>">Calculate Auto Baselines</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestMeasurementReport"/>
- <a href="<c:out value="${url}"/>">Send Measurement Report</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=addProblemResource"/>
- <a href="<c:out value="${url}"/>">Add problem Resource</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=100"/>
- <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 100</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=50"/>
- <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 50</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=checkForSuspectAgents"/>
- <a href="<c:out value="${url}"/>">Check For Suspect Agents</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=dataPurgeJob"/>
- <a href="<c:out value="${url}"/>">Force Data Purge Now</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateOOBs"/>
- <a href="<c:out value="${url}"/>">Force calculation of OOBs</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=errorCorrectSchedules"/>
- <a href="<c:out value="${url}"/>">Error-Correct Measurement Schedules</a></li>
-</ul>
-
-<h2>Alerts</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=cloneAlertTemplate"/>
-Template Cloning
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="cloneAlertTemplate"/>
- Alert Template ID: <input type="text" name="alertTemplateId" size="5"/><br/>
- Number of Clones: <input type="text" name="numberOfClones" size="5"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-<h2>Utilities</h2>
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=startStats"/>
- <a href="<c:out value="${url}"/>">Start Hibernate Statistics Collection</a></li>
-</ul>
-
-
-<h2>User Preferences</h2>
-<%
- Subject subject = WebUtility.getSubject(request);
- MeasurementPreferences prefs = new MeasurementPreferences(subject);
- MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
- pageContext.setAttribute("lastHours", String.valueOf(rangePrefs.lastN));
-%>
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="metricDisplayRange"/>
- Last X hours: <input type="text" name="lastHours" size="5" value="<c:out value="${lastHours}"/>"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-<h2>Snapshot Report</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=generateSnapshotReport"/>
-Generate Snapshot Report
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="generateSnapshotReport"/>
- Resource ID: <input type="text" name="resourceId" size="10"/><br/>
- Name: <input type="text" name="name" size="30"/><br/>
- Description: <input type="text" name="description" size="100"/><br/>
- <input type="submit" value="Generate Snapshot" name="Generate Snapshot"/>
-</form>
-
-<h2>Resource Type Criteria</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=typeManagerRemote"/>
-Query ResourceTypes by Criteria
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="typeManagerRemote"/>
- ResourceType ID: <input type="text" name="typeId" size="10"/><br/>
- <input type="submit" value="Query by Criteria" name="Query by Criteria"/>
-</form>
-
-
-
-</body>
-</html>
+<%@ page import="java.io.ByteArrayOutputStream" %>
+<%@ page import="java.io.PrintStream" %>
+
+<%@ page import="org.rhq.core.domain.auth.Subject" %>
+<%@ page import="org.rhq.core.domain.util.PersistenceUtility" %>
+
+<%@ page import="org.rhq.enterprise.gui.legacy.util.SessionUtils"%>
+<%@ page import="org.rhq.enterprise.gui.util.WebUtility"%>
+
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences" %>
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences.MetricRangePreferences" %>
+
+<%@ page import="org.rhq.enterprise.server.test.CoreTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.DiscoveryTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.MeasurementTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.SubjectRoleTestBeanLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.AlertTemplateTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.cloud.instance.ServerManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementBaselineManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.core.AgentManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.system.SystemManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.auth.SubjectManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.support.SupportManagerLocal" %>
+<%@page import="org.rhq.enterprise.server.plugin.ServerPluginsLocal"%><html>
+<%@ page import="org.rhq.enterprise.server.util.LookupUtil" %>
+<%@ page import="org.rhq.enterprise.server.scheduler.jobs.DataPurgeJob"%>
+
+<%@ page import="org.rhq.enterprise.server.resource.ResourceTypeManagerRemote"%>
+<%@ page import="org.rhq.core.domain.criteria.ResourceTypeCriteria"%>
+<%@ page import="org.rhq.core.domain.resource.ResourceType"%>
+
+<%@ page import="javax.naming.NamingException" %>
+
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
+<html>
+<head><title>RHQ Test Control Page</title></head>
+<body>
+
+<jsp:include page="/admin/include/adminTestLinks.html" flush="true" />
+
+<%
+ CoreTestLocal coreTestBean;
+ DiscoveryTestLocal discoveryTestBean;
+ MeasurementTestLocal measurementTestBean;
+ ResourceGroupTestBeanLocal resourceGroupTestBean;
+ SubjectRoleTestBeanLocal subjectRoleTestBean;
+ ServerManagerLocal serverManager;
+ AlertTemplateTestLocal alertTemplateTestBean;
+ MeasurementBaselineManagerLocal measurementBaselineManager;
+ MeasurementScheduleManagerLocal measurementScheduleManager;
+ AgentManagerLocal agentManager;
+ SystemManagerLocal systemManager;
+ SubjectManagerLocal subjectManager;
+ SupportManagerLocal supportManager;
+ ResourceTypeManagerRemote typeManager;
+ ServerPluginsLocal serverPlugins;
+
+ coreTestBean = LookupUtil.getCoreTest();
+ discoveryTestBean = LookupUtil.getDiscoveryTest();
+ measurementTestBean = LookupUtil.getMeasurementTest();
+ resourceGroupTestBean = LookupUtil.getResourceGroupTestBean();
+ subjectRoleTestBean = LookupUtil.getSubjectRoleTestBean();
+ serverManager = LookupUtil.getServerManager();
+ alertTemplateTestBean = LookupUtil.getAlertTemplateTestBean();
+ measurementBaselineManager = LookupUtil.getMeasurementBaselineManager();
+ measurementScheduleManager = LookupUtil.getMeasurementScheduleManager();
+ agentManager = LookupUtil.getAgentManager();
+ systemManager = LookupUtil.getSystemManager();
+ subjectManager = LookupUtil.getSubjectManager();
+ supportManager = LookupUtil.getSupportManager();
+ typeManager = LookupUtil.getResourceTypeManagerRemote();
+ serverPlugins = LookupUtil.getServerPlugins();
+
+ String result = null;
+ String mode = pageContext.getRequest().getParameter("mode");
+ String failure = null;
+ try
+ {
+ if ("registerTestAgent".equals(mode))
+ {
+ coreTestBean.registerTestAgent();
+ }
+ else if ("registerTestPluginAndTypeInfo".equals(mode))
+ {
+ discoveryTestBean.registerTestPluginAndTypeInfo();
+ }
+ else if ("removeTestPluginAndTypeInfo".equals(mode))
+ {
+ discoveryTestBean.removeTestPluginAndTypeInfo();
+ }
+ else if ("sendTestFullInventoryReport".equals(mode))
+ {
+ discoveryTestBean.sendTestFullInventoryReport();
+ }
+ else if ("sendTestRuntimeInventoryReport".equals(mode))
+ {
+ discoveryTestBean.sendTestRuntimeInventoryReport();
+ }
+ else if ("sendTestMeasurementReport".equals(mode))
+ {
+ measurementTestBean.sendTestMeasurementReport();
+ }
+ else if ("sendNewPlatform".equals(mode))
+ {
+ String address = request.getParameter("address");
+ int servers = Integer.parseInt(request.getParameter("servers"));
+ int servicesPerServer = Integer.parseInt(request.getParameter("servicesPerServer"));
+ discoveryTestBean.sendNewPlatform(address, servers, servicesPerServer);
+ }
+ else if ("setupCompatibleGroups".equals(mode))
+ {
+ resourceGroupTestBean.setupCompatibleGroups();
+ }
+ else if ("setupUberMixedGroup".equals(mode))
+ {
+ resourceGroupTestBean.setupUberMixedGroup();
+ }
+ else if ("startStats".equals(mode))
+ {
+ coreTestBean.enableHibernateStatistics();
+ }
+ else if ("addProblemResource".equals(mode))
+ {
+ measurementTestBean.addProblemResource();
+ }
+ else if ("setAgentCurrentlyScheduledMetrics".equals(mode))
+ {
+ String value = pageContext.getRequest().getParameter("v");
+ measurementTestBean.setAgentCurrentlyScheduledMetrics(Double.valueOf(value));
+ }
+ else if ("addSubjectsAndRoles".equals(mode))
+ {
+ String roleCount = pageContext.getRequest().getParameter("roleCount");
+ String usersInRoleCount = pageContext.getRequest().getParameter("usersInRoleCount");
+ subjectRoleTestBean.createRolesAndUsers(Integer.parseInt(roleCount), Integer.parseInt(usersInRoleCount));
+ }
+ else if ("clusterGetIdentity".equals(mode))
+ {
+ String serverName = serverManager.getIdentity();
+ pageContext.setAttribute("serverName", "(serverName = " + serverName + ")");
+ }
+ else if ("cloneAlertTemplate".equals(mode))
+ {
+ String alertTemplateId = pageContext.getRequest().getParameter("alertTemplateId");
+ String numberOfClones = pageContext.getRequest().getParameter("numberOfClones");
+ alertTemplateTestBean.cloneAlertTemplate(Integer.parseInt(alertTemplateId), Integer.parseInt(numberOfClones));
+ }
+ else if ("calculateAutoBaselines".equals(mode))
+ {
+ // for now, baselines aren't calculated until we hit our day limit, we force it here
+ java.util.Properties props = systemManager.getSystemConfiguration();
+ props.put("CAM_BASELINE_LASTTIME", "0");
+ systemManager.setSystemConfiguration(subjectManager.getOverlord(), props,true);
+
+ measurementBaselineManager.calculateAutoBaselines();
+ }
+ else if ("calculateOOBs".equals(mode))
+ {
+ DataPurgeJob dpj = new DataPurgeJob();
+ dpj.calculateOOBs();
+ }
+ else if ("checkForSuspectAgents".equals(mode))
+ {
+ agentManager.checkForSuspectAgents();
+ }
+ else if ("dataPurgeJob".equals(mode))
+ {
+ DataPurgeJob.purgeNow();
+ }
+ else if ("dbMaintenance".equals(mode))
+ {
+ systemManager.vacuum(subjectManager.getOverlord());
+ systemManager.reindex(subjectManager.getOverlord());
+ systemManager.analyze(subjectManager.getOverlord());
+ }
+ else if ("metricDisplayRange".equals(mode))
+ {
+ int lastHours = Integer.parseInt(pageContext.getRequest().getParameter("lastHours"));
+ Subject subject = WebUtility.getSubject(request);
+ MeasurementPreferences prefs = new MeasurementPreferences(subject);
+ MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
+ rangePrefs.lastN = lastHours;
+ prefs.setMetricRangePreferences(rangePrefs);
+ }
+ else if ("errorCorrectSchedules".equals("mode"))
+ {
+ measurementScheduleManager.errorCorrectSchedules();
+ }
+ else if ("generateSnapshotReport".equals(mode))
+ {
+ int resourceId = Integer.parseInt(request.getParameter("resourceId"));
+ String name = request.getParameter("name");
+ String description = request.getParameter("description");
+ java.net.URL url = supportManager.getSnapshotReport(subjectManager.getOverlord(), resourceId, name, description);
+ result = "Snapshot Report is located here: " + url.toString();
+ }
+ else if ("purgeServerPlugin".equals(mode))
+ {
+ String serverPluginName = request.getParameter("serverPluginName");
+ serverPlugins.purgeServerPlugin(subjectManager.getOverlord(), serverPluginName);
+ result = "OK - you can now try to re-register a plugin with the name [" + serverPluginName + "]";
+ }
+ else if ("typeManagerRemote".equals(mode))
+ {
+ int typeId = Integer.parseInt(request.getParameter("typeId"));
+ ResourceTypeCriteria criteria = new ResourceTypeCriteria();
+ criteria.addFilterId(typeId);
+ criteria.fetchMetricDefinitions(true);
+ java.util.List<ResourceType> types = typeManager.findResourceTypesByCriteria(subjectManager.getOverlord(), criteria);
+ result = "";
+ for (ResourceType type : types) {
+ result += type.getName() + " has " + (type.getMetricDefinitions() != null ? type.getMetricDefinitions().size() : "empty") + " metric definitions";
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ e.printStackTrace(new PrintStream(baos));
+ failure = baos.toString();
+ }
+
+ pageContext.setAttribute("executed", mode);
+ pageContext.setAttribute("result", result);
+ pageContext.setAttribute("failure", failure);
+ pageContext.setAttribute("testAgentReported", Boolean.valueOf(coreTestBean.isTestAgentReported()));
+
+%>
+
+<c:if test="${executed != null}">
+ <b>Executed <c:out value="${executed}"/>: </b> <c:out value="${result}"/><br>
+ <c:if test="${failure != null}">
+ <pre style="background-color: yellow;"><c:out value="${failure}"/></pre>
+ </c:if>
+</c:if>
+
+<h2>Administration</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
+Add Lots of Users and Roles
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="addSubjectsAndRoles"/>
+ Number of Roles: <input type="text" name="roleCount" size="5"/><br/>
+ Number of Users in each Role: <input type="text" name="usersInRoleCount" size="5"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
+ <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
+</ul>
+
+<h2>Core</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestAgent"/>
+ <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=dbMaintenance"/>
+ <a href="<c:out value="${url}"/>">Perform All Database Maintenance Now</a></li>
+</ul>
+
+<h2>Cluster</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=clusterGetIdentity"/>
+ <a href="<c:out value="${url}"/>">Get Identity</a> <c:out value="${serverName}"/></li>
+</ul>
+
+<h2>Inventory</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestFullInventoryReport"/>
+ <a href="<c:out value="${url}"/>">Send Full Inventory Report</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestRuntimeInventoryReport"/>
+ <a href="<c:out value="${url}"/>">Send Runtime Inventory Report</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setupCompatibleGroups"/>
+ <a href="<c:out value="${url}"/>">Setup Compatible Groups</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setupUberMixedGroup"/>
+ <a href="<c:out value="${url}"/>">Setup Uber Mixed Group</a></li>
+</ul>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=sendNewPlatform"/>
+Send New Platform Inventory Report
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="sendNewPlatform"/>
+ Address: <input type="text" name="address" size="30"/><br/>
+ Servers: <input type="text" name="servers" size="5"/><br/>
+ Services Per Server: <input type="text" name="servicesPerServer" size="5"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+
+<h2>Measurement</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateAutoBaselines"/>
+ <a href="<c:out value="${url}"/>">Calculate Auto Baselines</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestMeasurementReport"/>
+ <a href="<c:out value="${url}"/>">Send Measurement Report</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=addProblemResource"/>
+ <a href="<c:out value="${url}"/>">Add problem Resource</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=100"/>
+ <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 100</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=50"/>
+ <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 50</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=checkForSuspectAgents"/>
+ <a href="<c:out value="${url}"/>">Check For Suspect Agents</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=dataPurgeJob"/>
+ <a href="<c:out value="${url}"/>">Force Data Purge Now</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateOOBs"/>
+ <a href="<c:out value="${url}"/>">Force calculation of OOBs</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=errorCorrectSchedules"/>
+ <a href="<c:out value="${url}"/>">Error-Correct Measurement Schedules</a></li>
+</ul>
+
+<h2>Alerts</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=cloneAlertTemplate"/>
+Template Cloning
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="cloneAlertTemplate"/>
+ Alert Template ID: <input type="text" name="alertTemplateId" size="5"/><br/>
+ Number of Clones: <input type="text" name="numberOfClones" size="5"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+<h2>Utilities</h2>
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=startStats"/>
+ <a href="<c:out value="${url}"/>">Start Hibernate Statistics Collection</a></li>
+</ul>
+
+
+<h2>User Preferences</h2>
+<%
+ Subject subject = WebUtility.getSubject(request);
+ MeasurementPreferences prefs = new MeasurementPreferences(subject);
+ MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
+ pageContext.setAttribute("lastHours", String.valueOf(rangePrefs.lastN));
+%>
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="metricDisplayRange"/>
+ Last X hours: <input type="text" name="lastHours" size="5" value="<c:out value="${lastHours}"/>"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+<h2>Snapshot Report</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=generateSnapshotReport"/>
+Generate Snapshot Report
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="generateSnapshotReport"/>
+ Resource ID: <input type="text" name="resourceId" size="10"/><br/>
+ Name: <input type="text" name="name" size="30"/><br/>
+ Description: <input type="text" name="description" size="100"/><br/>
+ <input type="submit" value="Generate Snapshot" name="Generate Snapshot"/>
+</form>
+
+<h2>Server Plugins</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=purgeServerPlugin"/>
+Purge Server Plugin (allowing you to re-register it again later)
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="purgeServerPlugin"/>
+ ServerPluginName: <input type="text" name="serverPluginName" size="30"/><br/>
+ <input type="submit" value="Purge Server Plugin" name="Purge Server Plugin"/>
+</form>
+
+<h2>Resource Type Criteria</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=typeManagerRemote"/>
+Query ResourceTypes by Criteria
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="typeManagerRemote"/>
+ ResourceType ID: <input type="text" name="typeId" size="10"/><br/>
+ <input type="submit" value="Query by Criteria" name="Query by Criteria"/>
+</form>
+
+
+
+</body>
+</html>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml
new file mode 100644
index 0000000..d88afe7
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jstl/core"
+ xmlns:onc="http://jboss.org/on/component"
+ xmlns:rich="http://richfaces.ajax4jsf.org/rich">
+
+<ui:composition template="/rhq/admin/plugin/plugin-details.xhtml">
+ <ui:param name="editMode" value="true"/>
+
+ <ui:define name="post-config">
+ <rich:panel rendered="#{InstalledPluginUIBean.editable}">
+ <h:commandButton value="SAVE" type="submit" action="#{InstalledPluginUIBean.updatePlugin}"
+ alt="Click to Save Changes" styleClass="buttonmed" />
+ <h:commandButton value="RESET" type="reset" immediate="true"
+ title="Click to Reset Fields" styleClass="buttonmed"/>
+ </rich:panel>
+ </ui:define>
+</ui:composition>
+
+</html>
\ No newline at end of file
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml
new file mode 100644
index 0000000..389923a
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jstl/core"
+ xmlns:onc="http://jboss.org/on/component"
+ xmlns:rich="http://richfaces.ajax4jsf.org/rich">
+
+<ui:composition template="/rhq/admin/plugin/plugin-details.xhtml">
+ <ui:param name="editMode" value="false"/>
+
+ <ui:define name="pre-config">
+ <h:panelGrid columns="1" styleClass="buttons-table" columnClasses="button-cell"
+ rendered="#{InstalledPluginUIBean.editable}">
+ <h:outputLink value="/rhq/admin/plugin/plugin-details-edit.xhtml"
+ styleClass="buttonmed">
+ <f:param name="plugin" value="#{installedPlugin.name}"/>
+ <f:param name="pluginType" value="#{installedPlugin.type}"/>
+ <h:outputText value="EDIT"/>
+ </h:outputLink>
+ </h:panelGrid>
+ </ui:define>
+ </ui:composition>
+
+</html>
\ No newline at end of file
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
index 3921b8e..cc11203 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
@@ -35,8 +35,6 @@
layout="table"
width="100%"/>
-
-
<h:form id="pluginsForm">
<rich:panel>
@@ -66,7 +64,6 @@
</h:panelGrid>
-
<rich:panel>
<f:facet name="header">
<h:outputText value="Plugin Help"/>
@@ -76,25 +73,29 @@
</rich:panel>
- <rich:panel>
+ <ui:insert name="pre-config" />
+
+ <rich:panel rendered="#{InstalledPluginUIBean.plugin.pluginConfiguration != null}">
<f:facet name="header">
<h:outputText value="Plugin Configuration"/>
</f:facet>
<onc:config
configurationDefinition="#{InstalledPluginUIBean.pluginConfigurationDefinition}"
configuration="#{InstalledPluginUIBean.plugin.pluginConfiguration}"
- readOnly="true" />
+ readOnly="#{not editMode}" />
</rich:panel>
- <rich:panel>
+ <rich:panel rendered="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration != null}">
<f:facet name="header">
<h:outputText value="Scheduled Jobs"/>
</f:facet>
<onc:config
configurationDefinition="#{InstalledPluginUIBean.scheduledJobsDefinition}"
configuration="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration}"
- readOnly="true" />
+ readOnly="#{not editMode}" />
</rich:panel>
+
+ <ui:insert name="post-config" />
</rich:panel>
</h:form>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
index 9f7f6b7..5654368 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
@@ -75,7 +75,7 @@
<h:outputText styleClass="headerText" value="Name"/>
</f:facet>
- <h:outputLink value="/rhq/admin/plugin/plugin-details.xhtml">
+ <h:outputLink value="/rhq/admin/plugin/plugin-details-view.xhtml">
<f:param name="plugin" value="#{agentPlugin.name}"/>
<f:param name="pluginType" value="AGENT"/>
<h:outputText value="#{agentPlugin.displayName}"/>
@@ -105,7 +105,7 @@
<rich:column>
<f:facet name="header">
- <h:outputText styleClass="headerText" value="Active"/>
+ <h:outputText styleClass="headerText" value="Enabled"/>
</f:facet>
<h:outputText value="#{agentPlugin.enabled}"/>
@@ -160,7 +160,7 @@
<h:outputText styleClass="headerText" value="Name"/>
</f:facet>
- <h:outputLink value="/rhq/admin/plugin/plugin-details.xhtml">
+ <h:outputLink value="/rhq/admin/plugin/plugin-details-view.xhtml">
<f:param name="plugin" value="#{serverPlugin.name}"/>
<f:param name="pluginType" value="SERVER"/>
<h:outputText value="#{serverPlugin.displayName}"/>
@@ -190,7 +190,7 @@
<rich:column>
<f:facet name="header">
- <h:outputText styleClass="headerText" value="Active"/>
+ <h:outputText styleClass="headerText" value="Enabled"/>
</f:facet>
<h:outputText value="#{serverPlugin.enabled}"/>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java
index a79dff5..bbeb84c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java
@@ -42,7 +42,7 @@ public class ContentManagerHelper {
}
MasterServerPluginContainer master = mbean.getMasterPluginContainer();
- pc = master.getPluginContainer(ContentServerPluginContainer.class);
+ pc = master.getPluginContainerByClass(ContentServerPluginContainer.class);
} catch (IllegalStateException ise) {
throw ise;
} catch (Exception e) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 3697caa..49d6e53 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -16,7 +16,6 @@
* 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.plugin;
import java.io.BufferedInputStream;
@@ -27,7 +26,9 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import javax.ejb.EJB;
import javax.ejb.Stateless;
@@ -55,6 +56,7 @@ import org.rhq.enterprise.server.authz.RequiredPermission;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
@@ -67,14 +69,12 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
@Stateless
@javax.annotation.Resource(name = "RHQ_DS", mappedName = RHQConstants.DATASOURCE_JNDI_NAME)
public class ServerPluginsBean implements ServerPluginsLocal {
- private final Log log = LogFactory.getLog(ServerPluginsBean.class);
+ private final Log log = LogFactory.getLog(ServerPluginsBean.class);
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
private EntityManager entityManager;
-
@javax.annotation.Resource(name = "RHQ_DS")
private DataSource dataSource;
-
@EJB
private ServerPluginsLocal serverPluginsBean; //self
@@ -94,11 +94,19 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
public Plugin getServerPluginRelationships(Plugin plugin) {
- plugin = entityManager.find(Plugin.class, plugin.getId());
+ plugin = getServerPlugin(plugin.getName()); // refresh all but the content field
+
+ Configuration config = plugin.getPluginConfiguration();
+ if (config != null) {
+ config = entityManager.find(Configuration.class, config.getId());
+ plugin.setPluginConfiguration(config.deepCopy());
+ }
- // force eager load
- plugin.getPluginConfiguration().getProperties().size();
- plugin.getScheduledJobsConfiguration().getProperties().size();
+ config = plugin.getScheduledJobsConfiguration();
+ if (config != null) {
+ config = entityManager.find(Configuration.class, config.getId());
+ plugin.setScheduledJobsConfiguration(config.deepCopy());
+ }
return plugin;
}
@@ -146,9 +154,9 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
- public List<Plugin> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
+ public List<String> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
- return new ArrayList<Plugin>(); // nothing to do
+ return new ArrayList<String>(); // nothing to do
}
serverPluginsBean.setServerPluginEnabledFlag(subject, pluginIds, false);
@@ -156,19 +164,24 @@ public class ServerPluginsBean implements ServerPluginsLocal {
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
- List<Plugin> doomedPlugins = new ArrayList<Plugin>();
+ List<String> doomedPlugins = new ArrayList<String>();
for (Integer pluginId : pluginIds) {
- Plugin doomedPlugin = entityManager.find(Plugin.class, pluginId);
+ Plugin doomedPlugin = null;
+ try {
+ doomedPlugin = entityManager.getReference(Plugin.class, pluginId);
+ } catch (Exception ignore) {
+ }
if (doomedPlugin != null) {
- doomedPlugins.add(doomedPlugin);
+ String pluginName = doomedPlugin.getName();
+ doomedPlugins.add(pluginName);
if (master != null) {
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
+ AbstractTypeServerPluginContainer pc = master.getPluginContainerByPlugin(pluginName);
if (pc != null) {
try {
- pc.unschedulePluginJobs(doomedPlugin.getName());
+ pc.unschedulePluginJobs(pluginName);
} catch (Exception e) {
- log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ log.warn("Failed to unschedule jobs for plugin [" + pluginName + "]", e);
}
}
}
@@ -184,9 +197,9 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
- public List<Plugin> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
+ public List<String> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
- return new ArrayList<Plugin>(); // nothing to do
+ return new ArrayList<String>(); // nothing to do
}
serverPluginsBean.setServerPluginEnabledFlag(subject, pluginIds, false);
@@ -194,19 +207,24 @@ public class ServerPluginsBean implements ServerPluginsLocal {
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
- List<Plugin> doomedPlugins = new ArrayList<Plugin>();
+ List<String> doomedPlugins = new ArrayList<String>();
for (Integer pluginId : pluginIds) {
- Plugin doomedPlugin = entityManager.find(Plugin.class, pluginId);
+ Plugin doomedPlugin = null;
+ try {
+ doomedPlugin = entityManager.getReference(Plugin.class, pluginId);
+ } catch (Exception ignore) {
+ }
if (doomedPlugin != null) {
- doomedPlugins.add(doomedPlugin);
+ String pluginName = doomedPlugin.getName();
+ doomedPlugins.add(pluginName);
if (master != null) {
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
+ AbstractTypeServerPluginContainer pc = master.getPluginContainerByPlugin(pluginName);
if (pc != null) {
try {
- pc.unschedulePluginJobs(doomedPlugin.getName());
+ pc.unschedulePluginJobs(pluginName);
} catch (Exception e) {
- log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ log.warn("Failed to unschedule jobs for plugin [" + pluginName + "]", e);
}
}
}
@@ -365,56 +383,39 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (plugin.getId() == 0) {
throw new IllegalArgumentException("Plugin must already exist to update it");
} else {
- // make sure the configs are in the DB properly and we have their refs
- // this is because we are using JPQL update, so we need to do some of this "manually"
- boolean needFlush = false;
+ // make sure we create (if necessary) and attach the configs
Configuration config = plugin.getPluginConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setPluginConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
+ config = entityManager.merge(config);
+ plugin.setPluginConfiguration(config);
}
config = plugin.getScheduledJobsConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setScheduledJobsConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
- }
- if (needFlush) {
- entityManager.flush(); // must be flushed to the DB so the JPQL update below works
+ config = entityManager.merge(config);
+ plugin.setScheduledJobsConfiguration(config);
}
- // now we can JPQL update the row - all but content is updated here.
- // we assured our configs are persisted/attached above
- Query q = entityManager.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
- q.setParameter("id", plugin.getId());
- q.setParameter("name", plugin.getName());
- q.setParameter("path", plugin.getPath());
- q.setParameter("displayName", plugin.getDisplayName());
- q.setParameter("enabled", plugin.isEnabled());
- q.setParameter("status", plugin.getStatus());
- q.setParameter("md5", plugin.getMD5());
- q.setParameter("version", plugin.getVersion());
- q.setParameter("ampsVersion", plugin.getAmpsVersion());
- q.setParameter("deployment", plugin.getDeployment());
- q.setParameter("pluginConfiguration", config);
- q.setParameter("scheduledJobsConfiguration", config);
- q.setParameter("description", plugin.getDescription());
- q.setParameter("help", plugin.getHelp());
- q.setParameter("mtime", plugin.getMtime());
- if (q.executeUpdate() != 1) {
- throw new Exception("Failed to update a plugin that matches [" + plugin + "]");
- }
+ Plugin pluginEntity = entityManager.getReference(Plugin.class, plugin.getId());
+ pluginEntity.setName(plugin.getName());
+ pluginEntity.setPath(plugin.getPath());
+ pluginEntity.setDisplayName(plugin.getDisplayName());
+ pluginEntity.setEnabled(plugin.isEnabled());
+ pluginEntity.setStatus(plugin.getStatus());
+ pluginEntity.setMd5(plugin.getMD5());
+ pluginEntity.setVersion(plugin.getVersion());
+ pluginEntity.setAmpsVersion(plugin.getAmpsVersion());
+ pluginEntity.setDeployment(plugin.getDeployment());
+ pluginEntity.setPluginConfiguration(plugin.getPluginConfiguration());
+ pluginEntity.setScheduledJobsConfiguration(plugin.getScheduledJobsConfiguration());
+ pluginEntity.setDescription(plugin.getDescription());
+ pluginEntity.setHelp(plugin.getHelp());
+ pluginEntity.setMtime(plugin.getMtime());
- entityManager.flush(); // make sure we push this out to the DB now
+ try {
+ entityManager.flush(); // make sure we push this out to the DB now
+ } catch (Exception e) {
+ throw new Exception("Failed to update a plugin that matches [" + plugin + "]", e);
+ }
}
return plugin;
}
@@ -432,6 +433,27 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return status;
}
+ // we need this method to talk to the master plugin container because the plugin data model
+ // does not contain information as to what type a plugin is. It only has information about
+ // where the plugin is deployed (agent or server) but it doesn't indicate if a plugin
+ // if of type "alert plugin" or "generic plugin". That is only known when the plugin descriptor
+ // is parsed, which happens when the master plugin container is initialized. Therefore, this
+ // needs to get plugin info from the master plugin container while the master is running.
+ public Map<ServerPluginType, List<String>> getAllPluginsGroupedByType() {
+ Map<ServerPluginType, List<String>> allPlugins = new HashMap<ServerPluginType, List<String>>();
+
+ MasterServerPluginContainer master = LookupUtil.getServerPluginService().getMasterPluginContainer();
+ if (master != null) {
+ List<ServerPluginType> types = master.getServerPluginTypes();
+ for (ServerPluginType type : types) {
+ List<String> plugins = master.getAllPluginsByPluginType(type);
+ allPlugins.put(type, plugins);
+ }
+ }
+
+ return allPlugins;
+ }
+
/**
* This will write the contents of the given plugin file to the database.
* This will assume the MD5 in the database is already correct, so this
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index 6f3600e..a6a09bf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -2,6 +2,7 @@ package org.rhq.enterprise.server.plugin;
import java.io.File;
import java.util.List;
+import java.util.Map;
import javax.ejb.Local;
import javax.persistence.NoResultException;
@@ -9,6 +10,7 @@ import javax.persistence.NoResultException;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginStatusType;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
@@ -42,6 +44,7 @@ public interface ServerPluginsLocal {
*
* @param plugin
* @return the same plugin, with the relationship data loaded
+ * @throws NoResultException when no plugin with that name exists
*/
Plugin getServerPluginRelationships(Plugin plugin);
@@ -86,20 +89,20 @@ public interface ServerPluginsLocal {
*
* @param subject user making the request
* @param pluginIds the plugins to be disabled
- * @return the list of plugins that were disabled
+ * @return the list of names of the plugins that were disabled
* @throws Exception if failed to disable a plugin
*/
- List<Plugin> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
+ List<String> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
/**
* Removes the plugin from the system and restarts the server plugin container.
*
* @param subject user making the request
* @param pluginIds
- * @return the list of plugins that were undeployed
+ * @return the list of names of plugins that were undeployed
* @throws Exception if failed to undeploy a plugin
*/
- List<Plugin> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
+ List<String> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
/**
* Turns on or off the enabled flag in the database but does NOT restart the server plugin container.
@@ -172,4 +175,13 @@ public interface ServerPluginsLocal {
* <code>null</code> indicates an unknown plugin.
*/
PluginStatusType getServerPluginStatus(String pluginName);
+
+ /**
+ * This will return a map containing all plugins currently known to the master plugin container.
+ * This will return installed plugins that are both enabled and disabled.
+ * Note that if the master plugin container is not running, an empty map is returned.
+ *
+ * @return names of all enabled and disabled plugins, keyed on their types
+ */
+ Map<ServerPluginType, List<String>> getAllPluginsGroupedByType();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index 8ebabd4..4ab3fb2 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -21,6 +21,7 @@ package org.rhq.enterprise.server.plugin.pc;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -46,11 +47,22 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
public class MasterServerPluginContainer {
private static final Log log = LogFactory.getLog(MasterServerPluginContainer.class);
+ /** The configuration for the master plugin container itself. */
private MasterServerPluginContainerConfiguration configuration;
+
+ /** the plugin containers for all the different types of plugins that are supported */
private Map<ServerPluginType, AbstractTypeServerPluginContainer> pluginContainers = new HashMap<ServerPluginType, AbstractTypeServerPluginContainer>();
+
+ /** the object that provides all the classloaders for all plugins */
private ClassLoaderManager classLoaderManager;
/**
+ * Because the individual plugin containers are only managing enabled plugins (they are never told about plugins that disabled).
+ * this map contains the lists of plugins that are disabled so others can find out what plugins are registered but not running.
+ */
+ private Map<ServerPluginType, List<String>> disabledPlugins = new HashMap<ServerPluginType, List<String>>();
+
+ /**
* Starts the master plugin container, which will load all plugins and begin managing them.
*
* @param config the master configuration
@@ -188,6 +200,7 @@ public class MasterServerPluginContainer {
}
this.pluginContainers.clear();
+ this.disabledPlugins.clear();
this.classLoaderManager = null;
this.configuration = null;
@@ -238,6 +251,55 @@ public class MasterServerPluginContainer {
}
/**
+ * Given a plugin type, this will return the names of all known plugins of that type.
+ * This includes all types that are currently started as well as plugins
+ * that have been disabled.
+ *
+ * If the master plugin container has not been started, this returns an empty list.
+ *
+ * @param pluginType
+ *
+ * @return list of both enabled and disabled plugins of the given type
+ */
+ public List<String> getAllPluginsByPluginType(ServerPluginType pluginType) {
+ List<String> allPlugins = new ArrayList<String>();
+
+ AbstractTypeServerPluginContainer pc = getPluginContainerByPluginType(pluginType);
+ if (pc != null) {
+ // add the enabled plugins
+ ServerPluginManager pluginManager = pc.getPluginManager();
+ if (pluginManager != null) {
+ Collection<ServerPluginEnvironment> envs = pluginManager.getPluginEnvironments();
+ if (envs != null) {
+ for (ServerPluginEnvironment env : envs) {
+ allPlugins.add(env.getPluginName());
+ }
+ }
+ }
+
+ // add the disabled plugins
+ List<String> disabled = this.disabledPlugins.get(pluginType);
+ if (disabled != null) {
+ allPlugins.addAll(disabled);
+ }
+ }
+
+ return allPlugins;
+ }
+
+ /**
+ * This will return all known server plugins types. These are the types of plugins
+ * that are supported by a server plugin container. You can obtain the server
+ * plugin container that manages a particular server plugin type via
+ * {@link #getPluginContainerByPluginType(ServerPluginType)}.
+ *
+ * @return all known server plugin types
+ */
+ public synchronized List<ServerPluginType> getServerPluginTypes() {
+ return new ArrayList<ServerPluginType>(this.pluginContainers.keySet());
+ }
+
+ /**
* Get the plugin container of the given class. This method provides a strongly typed return value,
* based on the type of plugin container the caller wants returned.
*
@@ -245,7 +307,7 @@ public class MasterServerPluginContainer {
* @return the plugin container of the given class (<code>null</code> if none found)
*/
@SuppressWarnings("unchecked")
- public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainer(Class<T> clazz) {
+ public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainerByClass(Class<T> clazz) {
for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
if (clazz.isInstance(pc)) {
return (T) pc;
@@ -262,7 +324,7 @@ public class MasterServerPluginContainer {
* @param pluginName
* @return the plugin container that is managing the named plugin of <code>null</code>
*/
- public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainer(String pluginName) {
+ public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainerByPlugin(String pluginName) {
for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
if (null != pc.getPluginManager().getPluginEnvironment(pluginName)) {
return (T) pc;
@@ -319,7 +381,7 @@ public class MasterServerPluginContainer {
if (pluginFiles != null) {
- List<String> disabledPlugins = getDisabledPluginNames();
+ List<String> allDisabledPlugins = getDisabledPluginNames();
for (File pluginFile : pluginFiles) {
if (pluginFile.getName().endsWith(".jar")) {
@@ -329,12 +391,19 @@ public class MasterServerPluginContainer {
ServerPluginDescriptorType descriptor;
descriptor = ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginUrl);
if (descriptor != null) {
- if (!disabledPlugins.contains(descriptor.getName())) {
+ if (!allDisabledPlugins.contains(descriptor.getName())) {
log.debug("pre-loaded server plugin from URL: " + pluginUrl);
plugins.put(pluginUrl, descriptor);
} else {
log.info("Server plugin [" + descriptor.getName()
+ "] is disabled and will not be initialized");
+ ServerPluginType pluginType = new ServerPluginType(descriptor);
+ List<String> disabledByType = this.disabledPlugins.get(pluginType);
+ if (disabledByType == null) {
+ disabledByType = new ArrayList<String>(1);
+ this.disabledPlugins.put(pluginType, disabledByType);
+ }
+ disabledByType.add(descriptor.getName());
}
}
} catch (Throwable t) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
index feba2fc..3e6bb34 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
@@ -29,6 +29,22 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
public class ServerPluginType {
private final Class<? extends ServerPluginDescriptorType> descriptorType;
+ /**
+ * Given an actual plugin descriptor object, this will create a plugin type
+ * that represents that kind of plugin.
+ *
+ * @param descriptor an actual descriptor parsed from a plugin
+ */
+ public ServerPluginType(ServerPluginDescriptorType descriptor) {
+ this((descriptor != null) ? descriptor.getClass() : null);
+ }
+
+ /**
+ * Given a type of plugin descriptor, this will create a plugin type
+ * that represents that kind of plugin.
+ *
+ * @param descriptorType
+ */
public ServerPluginType(Class<? extends ServerPluginDescriptorType> descriptorType) {
if (descriptorType == null) {
throw new NullPointerException("descriptorType must not be null");
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
index 9c971e0..d502f4e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
@@ -198,49 +198,38 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
entityManager.persist(plugin);
} else {
// agent plugins don't support these configs, but if/when they do in the future, this will support it
- boolean needFlush = false;
+ // make sure we create (if necessary) and attach the configs
Configuration config = plugin.getPluginConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setPluginConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
+ config = entityManager.merge(config);
+ plugin.setPluginConfiguration(config);
}
config = plugin.getScheduledJobsConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setScheduledJobsConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
- }
- if (needFlush) {
- entityManager.flush(); // must be flushed to the DB so the JPQL update below works
+ config = entityManager.merge(config);
+ plugin.setScheduledJobsConfiguration(config);
}
// update all the fields except content
- Query q = entityManager.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
- q.setParameter("id", plugin.getId());
- q.setParameter("name", plugin.getName());
- q.setParameter("path", plugin.getPath());
- q.setParameter("displayName", plugin.getDisplayName());
- q.setParameter("enabled", plugin.isEnabled());
- q.setParameter("status", plugin.getStatus());
- q.setParameter("md5", plugin.getMD5());
- q.setParameter("version", plugin.getVersion());
- q.setParameter("ampsVersion", plugin.getAmpsVersion());
- q.setParameter("deployment", plugin.getDeployment());
- q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
- q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
- q.setParameter("description", plugin.getDescription());
- q.setParameter("help", plugin.getHelp());
- q.setParameter("mtime", plugin.getMtime());
- if (q.executeUpdate() != 1) {
+ Plugin pluginEntity = entityManager.getReference(Plugin.class, plugin.getId());
+ pluginEntity.setName(plugin.getName());
+ pluginEntity.setPath(plugin.getPath());
+ pluginEntity.setDisplayName(plugin.getDisplayName());
+ pluginEntity.setEnabled(plugin.isEnabled());
+ pluginEntity.setStatus(plugin.getStatus());
+ pluginEntity.setMd5(plugin.getMD5());
+ pluginEntity.setVersion(plugin.getVersion());
+ pluginEntity.setAmpsVersion(plugin.getAmpsVersion());
+ pluginEntity.setDeployment(plugin.getDeployment());
+ pluginEntity.setPluginConfiguration(plugin.getPluginConfiguration());
+ pluginEntity.setScheduledJobsConfiguration(plugin.getScheduledJobsConfiguration());
+ pluginEntity.setDescription(plugin.getDescription());
+ pluginEntity.setHelp(plugin.getHelp());
+ pluginEntity.setMtime(plugin.getMtime());
+
+ try {
+ entityManager.flush(); // make sure we push this out to the DB now
+ } catch (Exception e) {
throw new Exception("Failed to update a plugin that matches [" + plugin + "]");
}
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
index e1796bf..d1a6aba 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
@@ -135,6 +135,24 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
assetLazyInitializationException(plugins.get(1));
}
+ public void testUpdatePlugins() throws Exception {
+ Plugin p1 = registerPlugin(1);
+ p1 = this.serverPluginsBean.getServerPlugin(p1.getName());
+ p1 = this.serverPluginsBean.getServerPluginRelationships(p1);
+
+ Plugin p1update = this.serverPluginsBean.updateServerPluginExceptContent(getOverlord(), p1);
+ p1update = this.serverPluginsBean.getServerPluginRelationships(p1update);
+
+ assert p1update.getId() == p1.getId() : p1update;
+ assert p1update.getId() == p1.getId() : p1update;
+ assert p1update.getName().equals(p1.getName()) : p1update;
+ assert p1update.getName().equals(p1.getName()) : p1update;
+ assert p1update.getPluginConfiguration().equals(p1.getPluginConfiguration()) : p1update;
+ assert p1update.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration()) : p1update;
+ p1update.getPluginConfiguration().equals(p1.getPluginConfiguration());
+ p1update.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration());
+ }
+
public void testDisableEnablePlugins() throws Exception {
Plugin p1 = registerPlugin(1);
Plugin p2 = registerPlugin(2);
@@ -142,12 +160,13 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
List<Integer> ids = new ArrayList<Integer>(2);
ids.add(p1.getId());
ids.add(p2.getId());
- List<Plugin> disabled = this.serverPluginsBean.disableServerPlugins(getOverlord(), ids);
+ List<String> disabled = this.serverPluginsBean.disableServerPlugins(getOverlord(), ids);
assert disabled.size() == 2 : disabled;
- assert disabled.contains(p1) : disabled;
- assert disabled.contains(p2) : disabled;
- assert disabled.get(0).getStatus() == PluginStatusType.INSTALLED; // still installed
- assert disabled.get(1).getStatus() == PluginStatusType.INSTALLED; // still installed
+ assert disabled.contains(p1.getName()) : disabled;
+ assert disabled.contains(p2.getName()) : disabled;
+ ;
+ assert this.serverPluginsBean.getServerPlugin(p1.getName()).getStatus() == PluginStatusType.INSTALLED; // still installed
+ assert this.serverPluginsBean.getServerPlugin(p2.getName()).getStatus() == PluginStatusType.INSTALLED; // still installed
List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert pluginNames.contains(p1.getName()) : pluginNames;
assert pluginNames.contains(p2.getName()) : pluginNames;
@@ -195,12 +214,14 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
List<Integer> ids = new ArrayList<Integer>(2);
ids.add(p1.getId());
ids.add(p2.getId());
- List<Plugin> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
+ List<String> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
assert undeployed.size() == 2 : undeployed;
- assert undeployed.contains(p1) : undeployed;
- assert undeployed.contains(p2) : undeployed;
- assert undeployed.get(0).getStatus() == PluginStatusType.DELETED;
- assert undeployed.get(1).getStatus() == PluginStatusType.DELETED;
+ assert undeployed.contains(p1.getName()) : undeployed;
+ assert undeployed.contains(p2.getName()) : undeployed;
+ Plugin p1deleted = getDeletedPluginInTx(p1.getName());
+ Plugin p2deleted = getDeletedPluginInTx(p2.getName());
+ assert p1deleted.getStatus() == PluginStatusType.DELETED;
+ assert p2deleted.getStatus() == PluginStatusType.DELETED;
List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert !pluginNames.contains(p1.getName()) : "deleted plugins should not be returned even here" + pluginNames;
@@ -230,16 +251,18 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
List<Integer> ids = new ArrayList<Integer>(2);
ids.add(p1.getId());
ids.add(p2.getId());
- List<Plugin> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
+ List<String> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
assert undeployed.size() == 2 : undeployed;
- assert undeployed.contains(p1) : undeployed;
- assert undeployed.contains(p2) : undeployed;
- assert undeployed.get(0).getStatus() == PluginStatusType.DELETED;
- assert undeployed.get(0).getPluginConfiguration() == null; // undeploy should have removed this
- assert undeployed.get(0).getScheduledJobsConfiguration() == null; // undeploy should have removed this
- assert undeployed.get(1).getStatus() == PluginStatusType.DELETED;
- assert undeployed.get(1).getPluginConfiguration() == null; // undeploy should have removed this
- assert undeployed.get(1).getScheduledJobsConfiguration() == null; // undeploy should have removed this
+ assert undeployed.contains(p1.getName()) : undeployed;
+ assert undeployed.contains(p2.getName()) : undeployed;
+ Plugin p1deleted = getDeletedPluginInTx(p1.getName());
+ assert p1deleted.getStatus() == PluginStatusType.DELETED;
+ assert p1deleted.getPluginConfiguration() == null; // undeploy should have removed this
+ assert p1deleted.getScheduledJobsConfiguration() == null; // undeploy should have removed this
+ Plugin p2deleted = getDeletedPluginInTx(p1.getName());
+ assert p2deleted.getStatus() == PluginStatusType.DELETED;
+ assert p2deleted.getPluginConfiguration() == null; // undeploy should have removed this
+ assert p2deleted.getScheduledJobsConfiguration() == null; // undeploy should have removed this
List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert !pluginNames.contains(p1.getName()) : "deleted plugins should not be returned even here" + pluginNames;
@@ -320,4 +343,17 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
private Subject getOverlord() {
return LookupUtil.getSubjectManager().getOverlord();
}
+
+ private Plugin getDeletedPluginInTx(String pluginName) throws Exception {
+ EntityManager em = getEntityManager();
+ getTransactionManager().begin();
+ try {
+ Query q = em.createNamedQuery(Plugin.QUERY_FIND_ANY_BY_NAME_AND_TYPE);
+ q.setParameter("name", pluginName);
+ q.setParameter("type", PluginDeploymentType.SERVER);
+ return (Plugin) q.getSingleResult();
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
}
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
index 1dace0b..9f0026b 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
@@ -23,6 +23,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.List;
+import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
@@ -32,12 +33,16 @@ import org.testng.annotations.Test;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.State;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericPluginManager;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener.LifecycleState;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.generic.GenericPluginDescriptorType;
@Test
public class GenericServerPluginTest extends AbstractEJB3Test {
@@ -76,10 +81,21 @@ public class GenericServerPluginTest extends AbstractEJB3Test {
List<ScheduledJobDefinition> schedules = component.context.getSchedules();
assert schedules == null;
+ ServerPluginsLocal serverPluginsLocal = LookupUtil.getServerPlugins();
+ Map<ServerPluginType, List<String>> map = serverPluginsLocal.getAllPluginsGroupedByType();
+ assert map.size() == 1;
+ List<String> pluginNames = map.get(new ServerPluginType(GenericPluginDescriptorType.class));
+ assert pluginNames.size() == 1;
+ assert pluginNames.get(0).equals("TestSimpleGenericPlugin");
+
// make sure everything is shutdown
this.pluginService.stopMasterPluginContainer();
assert pc.state == State.UNINITIALIZED;
assert component.state == LifecycleState.UNINITIALIZED;
+
+ // with the master down, this method should return an empty map
+ map = serverPluginsLocal.getAllPluginsGroupedByType();
+ assert map.size() == 0;
}
private File createPluginJar(String jarName, String descriptorXmlFilename) throws Exception {
diff --git a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
index 76b374b..a657f42 100644
--- a/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
+++ b/modules/helpers/pluginGen/src/main/java/org/rhq/helpers/pluginGen/Props.java
@@ -527,6 +527,7 @@ public class Props {
private String displayName;
private String description;
private Set<SimpleProperty> params = new LinkedHashSet<SimpleProperty>();
+ private SimpleProperty result;
public OperationProps(String name) {
this.name = name;
@@ -555,5 +556,13 @@ public class Props {
public Set<SimpleProperty> getParams() {
return params;
}
+
+ public SimpleProperty getResult() {
+ return result;
+ }
+
+ public void setResult(SimpleProperty result) {
+ this.result = result;
+ }
}
}
diff --git a/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl b/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
index a148a61..0343787 100644
--- a/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
+++ b/modules/helpers/pluginGen/src/main/resources/descriptorMain.ftl
@@ -60,6 +60,11 @@ name="${props.name}" <#-- TODO separate out plugin name and service name -->
</#list>
</parameters>
</#if>
+ <#if operation.result??>
+ <results>
+ <c:simple-property name="${operation.result.name}" />
+ </results>
+ </#if>
</operation>
</#list>
<#else>
14 years, 5 months
[rhq] Branch 'alertPlugin' - modules/enterprise
by Heiko W. Rupp
modules/enterprise/server/plugins/alert-email/src/main/resources/META-INF/rhq-serverplugin.xml | 4 ++--
modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-alert.xsd | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
New commits:
commit a3290f235cb329a4bdda1d05574190ddee327c26
Author: Heiko W. Rupp <pilhuhn(a)fedorapeople.org>
Date: Thu Nov 26 17:58:07 2009 +0100
Follow schema conventions to separate words by dash and don't do camelCase
diff --git a/modules/enterprise/server/plugins/alert-email/src/main/resources/META-INF/rhq-serverplugin.xml b/modules/enterprise/server/plugins/alert-email/src/main/resources/META-INF/rhq-serverplugin.xml
index 7f97f64..2590490 100644
--- a/modules/enterprise/server/plugins/alert-email/src/main/resources/META-INF/rhq-serverplugin.xml
+++ b/modules/enterprise/server/plugins/alert-email/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -34,10 +34,10 @@
</serverplugin:plugin-configuration>
<!-- How does this sender show up in drop downs etc -->
- <shortName>Email</shortName>
+ <short-name>Email</short-name>
<!-- Class that does the actual sending -->
- <pluginClass>EmailSender</pluginClass>
+ <plugin-class>EmailSender</plugin-class>
<!-- What can a user configure when defining an alert -->
<alert-configuration>
diff --git a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-alert.xsd b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-alert.xsd
index dc4d925..404887f 100644
--- a/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-alert.xsd
+++ b/modules/enterprise/server/xml-schemas/src/main/resources/rhq-serverplugin-alert.xsd
@@ -40,14 +40,14 @@
<xs:complexContent>
<xs:extension base="serverplugin:ServerPluginDescriptorType">
<xs:sequence>
- <xs:element name="shortName" minOccurs="1" maxOccurs="1">
+ <xs:element name="short-name" minOccurs="1" maxOccurs="1">
<xs:annotation>
<xs:documentation>
The short name of this plugin as it will be shown in Headers and drop down boxes
</xs:documentation>
</xs:annotation>
</xs:element>
- <xs:element name="pluginClass" minOccurs="1" maxOccurs="1">
+ <xs:element name="plugin-class" minOccurs="1" maxOccurs="1">
<xs:annotation>
<xs:documentation>
The name of the class implementing the plugin functionality. This class needs to
14 years, 5 months
[rhq] Branch 'alertPlugin' - modules/enterprise
by Heiko W. Rupp
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertSender.java | 2 --
1 file changed, 2 deletions(-)
New commits:
commit 2f9837111d710e0365e8969f64019c8809c396c3
Author: Heiko W. Rupp <pilhuhn(a)fedorapeople.org>
Date: Thu Nov 26 13:46:28 2009 +0100
This logger is not needed.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertSender.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertSender.java
index 6adc6f6..4acf335 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertSender.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertSender.java
@@ -37,8 +37,6 @@ import org.rhq.core.domain.configuration.Configuration;
*/
public abstract class AlertSender {
- private final Log log = LogFactory.getLog(AlertSender.class);
-
/** Configuration from the global per plugin type preferences */
protected Configuration preferences;
14 years, 5 months
[rhq] Branch 'alertPlugin' - 2 commits - modules/enterprise
by Heiko W. Rupp
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertSenderPluginManager.java | 114 ++++++++
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertServerPluginContainer.java | 23 +
modules/enterprise/server/plugins/alert-email/pom.xml | 137 ++++++++++
modules/enterprise/server/plugins/alert-email/src/main/java/org/rhq/enterprise/server/plugins/alertEmail/EmailAlertComponent.java | 50 +++
modules/enterprise/server/plugins/alert-email/src/main/java/org/rhq/enterprise/server/plugins/alertEmail/EmailSender.java | 75 +++++
modules/enterprise/server/plugins/alert-email/src/main/resources/META-INF/rhq-serverplugin.xml | 48 +++
6 files changed, 446 insertions(+), 1 deletion(-)
New commits:
commit f6cf4f19e4fe10bbb853c138a67b5653ca16c5ed
Author: Heiko W. Rupp <pilhuhn(a)fedorapeople.org>
Date: Thu Nov 26 11:47:07 2009 +0100
A first implementation of an AlertSender that sends via email
diff --git a/modules/enterprise/server/plugins/alert-email/pom.xml b/modules/enterprise/server/plugins/alert-email/pom.xml
new file mode 100644
index 0000000..d76bdbb
--- /dev/null
+++ b/modules/enterprise/server/plugins/alert-email/pom.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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">
+ <parent>
+ <artifactId>rhq-enterprise-server-plugins-parent</artifactId>
+ <groupId>org.rhq</groupId>
+ <version>1.4.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.rhq</groupId>
+ <artifactId>alert-email</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+
+ <name>RHQ Enterprise Server Email Alert Plugin</name>
+
+ <scm>
+ <connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/enterprise/server/...</connection>
+ <developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/enterprise/server/...</developerConnection>
+ </scm>
+
+ <properties>
+ <scm.module.path>modules/enterprise/server/plugins/disk/</scm.module.path>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.mail</groupId>
+ <artifactId>mail</artifactId>
+ <version>1.3.1</version>
+ <scope>provided</scope> <!-- by JBossAS -->
+ </dependency>
+
+ <dependency>
+ <groupId>org.rhq</groupId>
+ <artifactId>rhq-enterprise-server</artifactId>
+ <version>1.4.0-SNAPSHOT</version>
+ <scope>provided</scope> <!-- by JBossAS -->
+ </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>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ <version>1.0</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>
+ <!-- needed for referenced domain entities that use Hibernate annotations -->
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludedGroups>${rhq.testng.excludedGroups}</excludedGroups>
+ <!--
+ <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y</argLine>
+ -->
+ </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}/rhq-serverplugins</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>
+
+ </profiles>
+
+
+</project>
\ No newline at end of file
diff --git a/modules/enterprise/server/plugins/alert-email/src/main/java/org/rhq/enterprise/server/plugins/alertEmail/EmailAlertComponent.java b/modules/enterprise/server/plugins/alert-email/src/main/java/org/rhq/enterprise/server/plugins/alertEmail/EmailAlertComponent.java
new file mode 100644
index 0000000..8d858af
--- /dev/null
+++ b/modules/enterprise/server/plugins/alert-email/src/main/java/org/rhq/enterprise/server/plugins/alertEmail/EmailAlertComponent.java
@@ -0,0 +1,50 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugins.alertEmail;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.enterprise.server.plugin.pc.ServerPluginComponent;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginContext;
+
+/**
+ * Stateful component class of this plugin
+ * @author Heiko W. Rupp
+ */
+public class EmailAlertComponent implements ServerPluginComponent {
+
+ private final Log log = LogFactory.getLog(EmailAlertComponent.class);
+
+ public void start() {
+ log.info("Alert:Email - start()");
+ }
+
+ public void initialize(ServerPluginContext context) throws Exception {
+ log.info("Alert:Email - initialize()");
+ }
+
+ public void shutdown() {
+ log.info("Alert:Email - shutdown");
+ }
+
+ public void stop() {
+ log.info("Alert:Email - stop");
+ }
+}
diff --git a/modules/enterprise/server/plugins/alert-email/src/main/java/org/rhq/enterprise/server/plugins/alertEmail/EmailSender.java b/modules/enterprise/server/plugins/alert-email/src/main/java/org/rhq/enterprise/server/plugins/alertEmail/EmailSender.java
new file mode 100644
index 0000000..581eb94
--- /dev/null
+++ b/modules/enterprise/server/plugins/alert-email/src/main/java/org/rhq/enterprise/server/plugins/alertEmail/EmailSender.java
@@ -0,0 +1,75 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugins.alertEmail;
+
+import java.util.Properties;
+
+import javax.mail.Message;
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.InternetAddress;
+
+import com.sun.mail.smtp.SMTPMessage;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.rhq.core.domain.alert.Alert;
+import org.rhq.enterprise.server.plugin.pc.alert.AlertSender;
+import org.rhq.enterprise.server.plugin.pc.alert.ResultState;
+import org.rhq.enterprise.server.plugin.pc.alert.SenderResult;
+
+/**
+ * Class to send emails.
+ * @author Heiko W. Rupp
+ */
+public class EmailSender extends AlertSender {
+
+ private final Log log = LogFactory.getLog(EmailSender.class);
+
+ @Override
+ public SenderResult send(Alert alert) {
+
+ String emailAddress = alertParameters.getSimpleValue("emailAddress",null);
+ if (emailAddress==null) {
+ log.warn("Email address was null, should not happen");
+ return new SenderResult(ResultState.FAILURE,"No email address given");
+ }
+
+ String mailserver = preferences.getSimpleValue("mailserver","localhost"); // TODO get RHQ default one
+ String senderAddress = preferences.getSimpleValue("senderEmail","rhqadmin@localhost"); // TODO get RHQ default one
+
+ Properties props = new Properties();
+ props.put("mail.smtp.host",mailserver);
+ Session session = Session.getDefaultInstance(props); // TODO pass authenticator
+ Message message = new SMTPMessage(session);
+ try {
+ message.setFrom(new InternetAddress(senderAddress));
+ message.setRecipient(Message.RecipientType.TO,new InternetAddress("hwr(a)redhat.com"));
+ message.setSubject("Alert on " + "Dummy - TODO");
+ message.setText("Li la lu, nur der Mann im Mond schaut zu");
+ Transport.send(message);
+ }
+ catch (Exception e) {
+ log.warn("Sending of email failed: " + e);
+ return new SenderResult(ResultState.FAILURE,"Send failed: " + e.getMessage());
+ }
+ return new SenderResult(ResultState.SUCCESS, "Emails sent to XXXX");
+ }
+}
diff --git a/modules/enterprise/server/plugins/alert-email/src/main/resources/META-INF/rhq-serverplugin.xml b/modules/enterprise/server/plugins/alert-email/src/main/resources/META-INF/rhq-serverplugin.xml
new file mode 100644
index 0000000..7f97f64
--- /dev/null
+++ b/modules/enterprise/server/plugins/alert-email/src/main/resources/META-INF/rhq-serverplugin.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<alert-plugin
+ name="alert-email"
+ displayName="Alert:Email"
+ xmlns="urn:xmlns:rhq-serverplugin.alert"
+ xmlns:c="urn:xmlns:rhq-configuration"
+ xmlns:serverplugin="urn:xmlns:rhq-serverplugin"
+ package="org.rhq.enterprise.server.plugins.alertEmail"
+ description="Alert sender plugin that sends alert notifications via email"
+ version="1.0"
+ >
+
+ <serverplugin:help>
+ This alert sender plugin is used to send emails when alerts were triggered.
+ </serverplugin:help>
+
+ <!-- startup & tear down listener, + scheduled jobs
+ <serverplugin:plugin-component class="Foo" />
+ -->
+
+
+ <!-- Global preferences for all email alerts -->
+ <serverplugin:plugin-configuration>
+ <c:simple-property name="mailserver" displayName="Mail server address" type="longString"
+ description="Address of the mail server to use (if not the default RHQ one )"/>
+ <c:simple-property name="senderEmail" displayName="Email of sender" type="string"
+ description="Email of the account from which alert emails should come from"/>
+ <c:simple-property name="needsLogin" displayName="Needs credentials?"
+ description="Mark this field if the server needs credentials to send email and give them below" type="boolean"/>
+ <c:simple-property name="user" type="string"/>
+ <c:simple-property name="password" type="password" />
+
+ </serverplugin:plugin-configuration>
+
+ <!-- How does this sender show up in drop downs etc -->
+ <shortName>Email</shortName>
+
+ <!-- Class that does the actual sending -->
+ <pluginClass>EmailSender</pluginClass>
+
+ <!-- What can a user configure when defining an alert -->
+ <alert-configuration>
+ <c:simple-property name="emailAddress" displayName="Receiver Email Address(es)" type="longString"
+ description="Email addresses (separated by comma) used for notifications."/>
+ </alert-configuration>
+
+</alert-plugin>
\ No newline at end of file
commit 8536432a274b918a2e78bfa2d9e1ceaf253937b3
Author: Heiko W. Rupp <pilhuhn(a)fedorapeople.org>
Date: Thu Nov 26 11:45:03 2009 +0100
Start of PluginManager implementation for alerts.
This provides listing of plugins and instantiation of senders.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertSenderPluginManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertSenderPluginManager.java
new file mode 100644
index 0000000..bc939bf
--- /dev/null
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertSenderPluginManager.java
@@ -0,0 +1,114 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.plugin.pc.alert;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.w3c.dom.Element;
+
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginEnvironment;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginManager;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.alert.AlertPluginDescriptorType;
+
+/**
+ * TODO
+ * @author Heiko W. Rupp
+ */
+public class AlertSenderPluginManager extends ServerPluginManager {
+
+ private final Log log = getLog();
+ private Map<String,String> pluginNameToType = new HashMap<String, String>();
+ private Map<String,String> pluginClassByName = new HashMap<String, String>();
+ private Map<String,ServerPluginEnvironment> pluginEnvByName = new HashMap<String, ServerPluginEnvironment>();
+
+ public AlertSenderPluginManager(AbstractTypeServerPluginContainer pc) {
+ super(pc);
+ }
+
+ @Override
+ public void loadPlugin(ServerPluginEnvironment env) throws Exception {
+ super.loadPlugin(env); // TODO: Customise this generated block
+
+ AlertPluginDescriptorType type = (AlertPluginDescriptorType) env.getPluginDescriptor();
+
+ String className = ((Element)type.getPluginClass()).getTextContent();
+ if (!className.contains(".")) {
+ className = type.getPackage() + "." + className;
+ }
+ try {
+ Class.forName(className,false,env.getPluginClassLoader());
+ }
+ catch (Exception e) {
+ log.warn("Can't find pluginClass " + className + ". Plugin will be ignored");
+ return;
+ }
+ String shortName = ((Element) type.getShortName()).getTextContent();
+ pluginClassByName.put(shortName,className);
+ pluginNameToType.put(shortName,env.getPluginName());
+ pluginEnvByName.put(shortName,env);
+
+ }
+
+
+ public AlertSender getAlertSenderForType(String shortName) {
+
+ String className = pluginClassByName.get(shortName);
+ ServerPluginEnvironment env = pluginEnvByName.get(shortName);
+ Class clazz;
+ try {
+ clazz = Class.forName(className,true,env.getPluginClassLoader());
+ }
+ catch (Exception e) {
+ log.error(e); // TODO
+ return null;
+ }
+
+ AlertSender sender;
+ try {
+ sender = (AlertSender) clazz.newInstance();
+ } catch (InstantiationException e) {
+ e.printStackTrace(); // TODO: Customise this generated block
+ return null;
+ } catch (IllegalAccessException e) {
+ e.printStackTrace(); // TODO: Customise this generated block
+ return null;
+ }
+
+ sender.alertParameters = new Configuration(); // TODO
+ sender.preferences = new Configuration(); // TODO
+
+ return sender;
+ }
+
+ /**
+ * Return the list of deployed alert sender plug-ins by their <shortName>
+ * @return List of plugin names
+ */
+ public List<String> getPluginList() {
+ return new ArrayList<String>(pluginClassByName.keySet());
+ }
+}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertServerPluginContainer.java
index 2c3068f..d9025a9 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/AlertServerPluginContainer.java
@@ -21,12 +21,13 @@ package org.rhq.enterprise.server.plugin.pc.alert;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginManager;
import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.alert.AlertPluginDescriptorType;
/**
* Manages alert plugins.
- *
+ *
* @author John Mazzitelli
*/
public class AlertServerPluginContainer extends AbstractTypeServerPluginContainer {
@@ -39,4 +40,24 @@ public class AlertServerPluginContainer extends AbstractTypeServerPluginContaine
public ServerPluginType getSupportedServerPluginType() {
return new ServerPluginType(AlertPluginDescriptorType.class);
}
+
+ @Override
+ public ServerPluginManager getPluginManager() {
+ return super.getPluginManager(); // TODO: Customise this generated block
+ }
+
+ @Override
+ public void initialize() throws Exception {
+ super.initialize(); // TODO: Customise this generated block
+ }
+
+ @Override
+ public void start() {
+ super.start(); // TODO: Customise this generated block
+ }
+
+ @Override
+ protected ServerPluginManager createPluginManager() {
+ return new AlertSenderPluginManager(this);
+ }
}
14 years, 5 months
[rhq] Branch 'raw-config' - 2 commits - modules/core
by John Sanda
modules/core/domain/src/main/java/org/rhq/core/domain/configuration/AbstractConfigurationUpdate.java | 6
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/AbstractConfigurationUpdateTest.java | 114 ++++++++++
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PluginConfigurationUpdateTest.java | 67 +++++
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ResourceConfigurationUpdateTest.java | 67 +++++
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/TestUtil.java | 45 +++
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/group/GroupPluginConfigurationUpdateTest.java | 51 ++++
modules/core/domain/src/test/java/org/rhq/core/domain/configuration/group/GroupResourceConfigurationUpdateTest.java | 51 ++++
7 files changed, 400 insertions(+), 1 deletion(-)
New commits:
commit c2f668eb47020a14173e897e02ef84b0e29fc6a4
Merge: 4743488... 6a2d6ad...
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 22:31:11 2009 -0500
Merge branch 'raw-config' of ssh://git.fedorahosted.org/git/rhq/rhq into raw-config
commit 4743488a8b743afb2965cb9a242b5dc8c7fb37cd
Author: John Sanda <john(a)localhost.localdomain>
Date: Wed Nov 25 22:24:44 2009 -0500
[BZ 541486] Fixing serialization bug for configuration update objects
The fix involved nothing more than making AbstractConfigurationUpdate implement Serializable. I have also
added unit tests for all implementing classes to verify correct serialization behavior.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/AbstractConfigurationUpdate.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/AbstractConfigurationUpdate.java
index 8fd3150..0231f78 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/AbstractConfigurationUpdate.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/AbstractConfigurationUpdate.java
@@ -24,6 +24,7 @@ package org.rhq.core.domain.configuration;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
+import java.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
@@ -44,7 +45,10 @@ import javax.xml.bind.annotation.XmlTransient;
* Base class for resource configuration and plugin configuration updates (i.e. history items).
*/
@XmlAccessorType(XmlAccessType.FIELD)
-public abstract class AbstractConfigurationUpdate {
+public abstract class AbstractConfigurationUpdate implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
@JoinColumn(name = "CONFIGURATION_ID", referencedColumnName = "ID", nullable = false)
@OneToOne(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER)
@XmlTransient
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/AbstractConfigurationUpdateTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/AbstractConfigurationUpdateTest.java
new file mode 100644
index 0000000..7195cde
--- /dev/null
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/AbstractConfigurationUpdateTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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 org.testng.annotations.Test;
+
+public abstract class AbstractConfigurationUpdateTest {
+
+
+ @Test
+ public void serializationShouldCopyConfiguration() throws Exception {
+ Configuration config = new Configuration();
+ config.put(new PropertySimple("x", "1"));
+
+ ResourceConfigurationUpdate update = new ResourceConfigurationUpdate();
+ update.setConfiguration(config);
+
+ ResourceConfigurationUpdate serializedUpdate = TestUtil.serializeAndDeserialize(update);
+
+ org.testng.Assert.assertEquals(
+ serializedUpdate.getConfiguration(),
+ update.getConfiguration(),
+ "Failed to properly serialize the 'configuration' property"
+ );
+ }
+
+ @Test
+ public void serializationShouldCopyErrorMessage() throws Exception {
+ ResourceConfigurationUpdate update = new ResourceConfigurationUpdate();
+ update.setErrorMessage("update error");
+
+ ResourceConfigurationUpdate serializedUpdate = TestUtil.serializeAndDeserialize(update);
+
+ org.testng.Assert.assertEquals(
+ serializedUpdate.getErrorMessage(),
+ update.getErrorMessage(),
+ "Failed to properly serialize the 'errorMessage' property"
+ );
+ }
+
+ @Test
+ public void serializationShouldCopyStatus() throws Exception {
+ ResourceConfigurationUpdate update = new ResourceConfigurationUpdate();
+ update.setStatus(ConfigurationUpdateStatus.SUCCESS);
+
+ ResourceConfigurationUpdate serializedUpdate = TestUtil.serializeAndDeserialize(update);
+
+ org.testng.Assert.assertEquals(
+ serializedUpdate.getStatus(),
+ update.getStatus(),
+ "Failed to properly serialize the 'status' property"
+ );
+ }
+
+ @Test
+ public void serializationShouldCopySubjectName() throws Exception {
+ ResourceConfigurationUpdate update = new ResourceConfigurationUpdate(null, new Configuration(), "rhqadmin");
+
+ ResourceConfigurationUpdate serializedUpdate = TestUtil.serializeAndDeserialize(update);
+
+ org.testng.Assert.assertEquals(
+ serializedUpdate.getSubjectName(),
+ update.getSubjectName(),
+ "Failed to properly serialize the 'subjectName' property"
+ );
+ }
+
+ @Test
+ public void serializationShouldCopyCreatedTime() throws Exception {
+ ResourceConfigurationUpdate update = new ResourceConfigurationUpdate();
+
+ ResourceConfigurationUpdate serializedUpdate = TestUtil.serializeAndDeserialize(update);
+
+ org.testng.Assert.assertEquals(
+ serializedUpdate.getCreatedTime(),
+ update.getCreatedTime(),
+ "Failed to properly serialize the 'createdTime' property"
+ );
+ }
+
+ @Test
+ public void serializationShouldCopyModifiedTime() throws Exception {
+ ResourceConfigurationUpdate update = new ResourceConfigurationUpdate();
+
+ ResourceConfigurationUpdate serializedUpdate = TestUtil.serializeAndDeserialize(update);
+
+ org.testng.Assert.assertEquals(
+ serializedUpdate.getModifiedTime(),
+ update.getModifiedTime(),
+ "Failed to properly serialize the 'modifiedTime' property"
+ );
+ }
+}
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PluginConfigurationUpdateTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PluginConfigurationUpdateTest.java
new file mode 100644
index 0000000..ee63afd
--- /dev/null
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/PluginConfigurationUpdateTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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 org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.configuration.group.GroupResourceConfigurationUpdate;
+import org.rhq.core.domain.configuration.group.GroupPluginConfigurationUpdate;
+
+public class PluginConfigurationUpdateTest extends AbstractConfigurationUpdateTest {
+
+ @Test
+ public void serializationShouldCopyResource() throws Exception {
+ Resource resource = new Resource();
+ resource.setUuid("1234");
+
+ PluginConfigurationUpdate update = new PluginConfigurationUpdate();
+ update.setResource(resource);
+
+ PluginConfigurationUpdate serializedUpdate = TestUtil.serializeAndDeserialize(update);
+
+ assertEquals(
+ serializedUpdate.getResource(),
+ update.getResource(),
+ "Failed to properly serialize the 'resource' property"
+ );
+ }
+
+ @Test
+ public void serializationShouldCopyGroupConfigurationUpdate() throws Exception {
+ PluginConfigurationUpdate update = new PluginConfigurationUpdate();
+ update.setGroupConfigurationUpdate(new GroupPluginConfigurationUpdate(new ResourceGroup("resourceGroup"),
+ "rhqadmin"));
+
+ PluginConfigurationUpdate serializedUpdate = TestUtil.serializeAndDeserialize(update);
+
+ assertEquals(
+ serializedUpdate.getGroupConfigurationUpdate(),
+ update.getGroupConfigurationUpdate(),
+ "Failed to properly serialize the 'groupConfigurationUpdate' property"
+ );
+ }
+
+}
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ResourceConfigurationUpdateTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ResourceConfigurationUpdateTest.java
new file mode 100644
index 0000000..8a967a6
--- /dev/null
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/ResourceConfigurationUpdateTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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 static org.testng.Assert.*;
+
+import org.testng.annotations.Test;
+import org.rhq.core.domain.resource.Resource;
+import org.rhq.core.domain.resource.group.ResourceGroup;
+import org.rhq.core.domain.configuration.group.GroupResourceConfigurationUpdate;
+
+public class ResourceConfigurationUpdateTest extends AbstractConfigurationUpdateTest {
+
+ @Test
+ public void serializationShouldCopyResource() throws Exception {
+ Resource resource = new Resource();
+ resource.setUuid("1234");
+
+ ResourceConfigurationUpdate update = new ResourceConfigurationUpdate();
+ update.setResource(resource);
+
+ ResourceConfigurationUpdate serializedUpdate = TestUtil.serializeAndDeserialize(update);
+
+ assertEquals(
+ serializedUpdate.getResource(),
+ update.getResource(),
+ "Failed to properly serialize the 'resource' property"
+ );
+ }
+
+ @Test
+ public void serializationShouldCopyGroupConfigurationUpdate() throws Exception {
+ ResourceConfigurationUpdate update = new ResourceConfigurationUpdate();
+ update.setGroupConfigurationUpdate(new GroupResourceConfigurationUpdate(new ResourceGroup("resourceGroup"),
+ "rhqadmin"));
+
+ ResourceConfigurationUpdate serializedUpdate = TestUtil.serializeAndDeserialize(update);
+
+ assertEquals(
+ serializedUpdate.getGroupConfigurationUpdate(),
+ update.getGroupConfigurationUpdate(),
+ "Failed to properly serialize the 'groupConfigurationUpdate' property"
+ );
+ }
+
+}
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/TestUtil.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/TestUtil.java
new file mode 100644
index 0000000..c1fac86
--- /dev/null
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/TestUtil.java
@@ -0,0 +1,45 @@
+/*
+ * 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.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ObjectInputStream;
+
+public class TestUtil {
+
+ public static <T> T serializeAndDeserialize(T object) throws Exception {
+ ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
+ ObjectOutputStream ostream = new ObjectOutputStream(byteOutputStream);
+
+ ostream.writeObject(object);
+
+ ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteOutputStream.toByteArray());
+ ObjectInputStream istream = new ObjectInputStream(byteInputStream);
+
+ return (T) istream.readObject();
+ }
+
+}
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/group/GroupPluginConfigurationUpdateTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/group/GroupPluginConfigurationUpdateTest.java
new file mode 100644
index 0000000..0be4172
--- /dev/null
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/group/GroupPluginConfigurationUpdateTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.group;
+
+import org.rhq.core.domain.configuration.AbstractConfigurationUpdateTest;
+import org.rhq.core.domain.configuration.ResourceConfigurationUpdate;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.TestUtil;
+import org.rhq.core.domain.configuration.PluginConfigurationUpdate;
+import org.rhq.core.domain.resource.Resource;
+import org.testng.annotations.Test;
+import static org.testng.Assert.assertEquals;
+
+public class GroupPluginConfigurationUpdateTest extends AbstractConfigurationUpdateTest {
+
+ @Test
+ public void serializationShouldCopyConfigurationUpdates() throws Exception {
+ GroupPluginConfigurationUpdate update = new GroupPluginConfigurationUpdate();
+ update.getConfigurationUpdates().add(new PluginConfigurationUpdate(new Resource(), new Configuration(),
+ "rhqadmin"));
+
+ GroupPluginConfigurationUpdate serializedUpdate = TestUtil.serializeAndDeserialize(update);
+
+ assertEquals(
+ serializedUpdate.getConfigurationUpdates(),
+ update.getConfigurationUpdates(),
+ "Failed to properly serialize the 'configurationUpdate' property"
+ );
+ }
+}
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/group/GroupResourceConfigurationUpdateTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/group/GroupResourceConfigurationUpdateTest.java
new file mode 100644
index 0000000..ebb9008
--- /dev/null
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/configuration/group/GroupResourceConfigurationUpdateTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.group;
+
+import static org.testng.Assert.*;
+
+import org.rhq.core.domain.configuration.AbstractConfigurationUpdateTest;
+import org.rhq.core.domain.configuration.ResourceConfigurationUpdate;
+import org.rhq.core.domain.configuration.Configuration;
+import org.rhq.core.domain.configuration.TestUtil;
+import org.rhq.core.domain.resource.Resource;
+import org.testng.annotations.Test;
+
+public class GroupResourceConfigurationUpdateTest extends AbstractConfigurationUpdateTest {
+
+ @Test
+ public void serializationShouldCopyConfigurationUpdates() throws Exception {
+ GroupResourceConfigurationUpdate update = new GroupResourceConfigurationUpdate();
+ update.addConfigurationUpdate(new ResourceConfigurationUpdate(new Resource(), new Configuration(), "rhqadmin"));
+
+ GroupResourceConfigurationUpdate serializedUpdate = TestUtil.serializeAndDeserialize(update);
+
+ assertEquals(
+ serializedUpdate.getConfigurationUpdates(),
+ update.getConfigurationUpdates(),
+ "Failed to properly serialize the 'configurationUpdate' property"
+ );
+ }
+
+}
14 years, 5 months
[rhq] 18 commits - modules/core modules/enterprise
by mazz
modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java | 20
modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java | 52
modules/core/util/src/test/java/org/apache/maven/artifact/versioning/ComparableVersionTest.java | 9
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java | 73
modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java | 71
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml | 1
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml | 7
modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml | 11
modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp | 775 +++++-----
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml | 24
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml | 27
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml | 15
modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml | 8
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java | 2
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java | 154 +
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java | 20
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java | 77
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java | 16
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java | 59
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java | 74
modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java | 16
21 files changed, 924 insertions(+), 587 deletions(-)
New commits:
commit db605e78ebfb82d01f0ce4130f327c45170540c7
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 17:18:29 2009 -0500
get rid of the update query we don't need anymore
fix tests so they don't rely on that old update query
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index eda26d8..4047d10 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -187,25 +187,6 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " LEFT JOIN p.scheduledJobsConfiguration " //
+ " WHERE p.deployment = 'SERVER' AND p.status = 'INSTALLED' "), //
- // this query does not update the content blob or ctime
- @NamedQuery(name = Plugin.UPDATE_ALL_BUT_CONTENT, query = "" //
- + "UPDATE Plugin p " //
- + " SET p.name = :name, " //
- + " p.displayName = :displayName, " //
- + " p.description = :description, " //
- + " p.enabled = :enabled, " //
- + " p.status = :status, " //
- + " p.help = :help, " //
- + " p.version = :version, " //
- + " p.ampsVersion = :ampsVersion," //
- + " p.deployment = :deployment, " //
- + " p.pluginConfiguration = :pluginConfiguration, " //
- + " p.scheduledJobsConfiguration = :scheduledJobsConfiguration, " //
- + " p.path = :path, " //
- + " p.md5 = :md5, " //
- + " p.mtime = :mtime " //
- + " WHERE p.id = :id"),
-
// this query is how you enable and disable plugins
@NamedQuery(name = Plugin.UPDATE_PLUGINS_ENABLED_BY_IDS, query = "" //
+ "UPDATE Plugin p " //
@@ -256,7 +237,6 @@ public class Plugin implements Serializable {
public static final String QUERY_FIND_BY_IDS_AND_TYPE = "Plugin.findByIdsAndType";
public static final String QUERY_GET_NAMES_BY_ENABLED_AND_TYPE = "Plugin.findByEnabledAndType";
public static final String QUERY_GET_STATUS_BY_NAME_AND_TYPE = "Plugin.getStatusByNameAndType";
- public static final String UPDATE_ALL_BUT_CONTENT = "Plugin.updateAllButContent";
public static final String UPDATE_PLUGINS_ENABLED_BY_IDS = "Plugin.updatePluginsEnabledByIds";
@Column(name = "ID", nullable = false)
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index 07f8f97..729f7c2 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -131,23 +131,39 @@ public class PluginTest extends AbstractEJB3Test {
em.persist(jobsConfig);
em.flush(); // gotta get those two persists to flush to the DB
- q = em.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
- q.setParameter("id", id); // same as the one we just persisted
- q.setParameter("name", name);
- q.setParameter("path", path);
- q.setParameter("displayName", displayName);
- q.setParameter("enabled", enabled);
- q.setParameter("status", status);
- q.setParameter("md5", md5);
- q.setParameter("version", version);
- q.setParameter("ampsVersion", ampsVersion);
- q.setParameter("deployment", deployment);
- q.setParameter("pluginConfiguration", pluginConfig);
- q.setParameter("scheduledJobsConfiguration", jobsConfig);
- q.setParameter("description", description);
- q.setParameter("help", help);
- q.setParameter("mtime", System.currentTimeMillis());
- assert q.executeUpdate() == 1 : "Failed to update the plugin";
+ // do what ServerPluginsBean/ResourceMetadataManagerBean.updateServerPluginExceptContent does
+ Configuration config = plugin.getPluginConfiguration();
+ if (config != null) {
+ config = em.merge(config);
+ plugin.setPluginConfiguration(config);
+ }
+ config = plugin.getScheduledJobsConfiguration();
+ if (config != null) {
+ config = em.merge(config);
+ plugin.setScheduledJobsConfiguration(config);
+ }
+
+ Plugin pluginEntity = em.getReference(Plugin.class, plugin.getId());
+ pluginEntity.setName(name);
+ pluginEntity.setPath(path);
+ pluginEntity.setDisplayName(displayName);
+ pluginEntity.setEnabled(enabled);
+ pluginEntity.setStatus(status);
+ pluginEntity.setMd5(md5);
+ pluginEntity.setVersion(version);
+ pluginEntity.setAmpsVersion(ampsVersion);
+ pluginEntity.setDeployment(deployment);
+ pluginEntity.setPluginConfiguration(pluginConfig);
+ pluginEntity.setScheduledJobsConfiguration(jobsConfig);
+ pluginEntity.setDescription(description);
+ pluginEntity.setHelp(help);
+ pluginEntity.setMtime(System.currentTimeMillis());
+
+ try {
+ em.flush(); // make sure we push this out to the DB now
+ } catch (Exception e) {
+ throw new Exception("Failed to update a plugin that matches [" + plugin + "]", e);
+ }
em.close();
getTransactionManager().commit(); // must commit now
@@ -163,7 +179,7 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.isEnabled() == enabled;
assert plugin.getMD5().equals(md5);
assert plugin.getVersion().equals(version);
- q.setParameter("ampsVersion", ampsVersion);
+ assert plugin.getAmpsVersion().equals(ampsVersion);
assert plugin.getDescription().equals(description);
assert plugin.getDeployment() == PluginDeploymentType.SERVER;
assert plugin.getPluginConfiguration().equals(pluginConfig);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
index 9c971e0..d502f4e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
@@ -198,49 +198,38 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
entityManager.persist(plugin);
} else {
// agent plugins don't support these configs, but if/when they do in the future, this will support it
- boolean needFlush = false;
+ // make sure we create (if necessary) and attach the configs
Configuration config = plugin.getPluginConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setPluginConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
+ config = entityManager.merge(config);
+ plugin.setPluginConfiguration(config);
}
config = plugin.getScheduledJobsConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setScheduledJobsConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
- }
- if (needFlush) {
- entityManager.flush(); // must be flushed to the DB so the JPQL update below works
+ config = entityManager.merge(config);
+ plugin.setScheduledJobsConfiguration(config);
}
// update all the fields except content
- Query q = entityManager.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
- q.setParameter("id", plugin.getId());
- q.setParameter("name", plugin.getName());
- q.setParameter("path", plugin.getPath());
- q.setParameter("displayName", plugin.getDisplayName());
- q.setParameter("enabled", plugin.isEnabled());
- q.setParameter("status", plugin.getStatus());
- q.setParameter("md5", plugin.getMD5());
- q.setParameter("version", plugin.getVersion());
- q.setParameter("ampsVersion", plugin.getAmpsVersion());
- q.setParameter("deployment", plugin.getDeployment());
- q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
- q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
- q.setParameter("description", plugin.getDescription());
- q.setParameter("help", plugin.getHelp());
- q.setParameter("mtime", plugin.getMtime());
- if (q.executeUpdate() != 1) {
+ Plugin pluginEntity = entityManager.getReference(Plugin.class, plugin.getId());
+ pluginEntity.setName(plugin.getName());
+ pluginEntity.setPath(plugin.getPath());
+ pluginEntity.setDisplayName(plugin.getDisplayName());
+ pluginEntity.setEnabled(plugin.isEnabled());
+ pluginEntity.setStatus(plugin.getStatus());
+ pluginEntity.setMd5(plugin.getMD5());
+ pluginEntity.setVersion(plugin.getVersion());
+ pluginEntity.setAmpsVersion(plugin.getAmpsVersion());
+ pluginEntity.setDeployment(plugin.getDeployment());
+ pluginEntity.setPluginConfiguration(plugin.getPluginConfiguration());
+ pluginEntity.setScheduledJobsConfiguration(plugin.getScheduledJobsConfiguration());
+ pluginEntity.setDescription(plugin.getDescription());
+ pluginEntity.setHelp(plugin.getHelp());
+ pluginEntity.setMtime(plugin.getMtime());
+
+ try {
+ entityManager.flush(); // make sure we push this out to the DB now
+ } catch (Exception e) {
throw new Exception("Failed to update a plugin that matches [" + plugin + "]");
}
}
commit dfd17347dd6d8c2707bfab6ced27bd44b66f9120
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 16:42:23 2009 -0500
fix the update method so it can handle the config updates
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index ff7d6ca..49d6e53 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -383,56 +383,39 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (plugin.getId() == 0) {
throw new IllegalArgumentException("Plugin must already exist to update it");
} else {
- // make sure the configs are in the DB properly and we have their refs
- // this is because we are using JPQL update, so we need to do some of this "manually"
- boolean needFlush = false;
+ // make sure we create (if necessary) and attach the configs
Configuration config = plugin.getPluginConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setPluginConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
+ config = entityManager.merge(config);
+ plugin.setPluginConfiguration(config);
}
config = plugin.getScheduledJobsConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setScheduledJobsConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
- }
- if (needFlush) {
- entityManager.flush(); // must be flushed to the DB so the JPQL update below works
+ config = entityManager.merge(config);
+ plugin.setScheduledJobsConfiguration(config);
}
- // now we can JPQL update the row - all but content is updated here.
- // we assured our configs are persisted/attached above
- Query q = entityManager.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
- q.setParameter("id", plugin.getId());
- q.setParameter("name", plugin.getName());
- q.setParameter("path", plugin.getPath());
- q.setParameter("displayName", plugin.getDisplayName());
- q.setParameter("enabled", plugin.isEnabled());
- q.setParameter("status", plugin.getStatus());
- q.setParameter("md5", plugin.getMD5());
- q.setParameter("version", plugin.getVersion());
- q.setParameter("ampsVersion", plugin.getAmpsVersion());
- q.setParameter("deployment", plugin.getDeployment());
- q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
- q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
- q.setParameter("description", plugin.getDescription());
- q.setParameter("help", plugin.getHelp());
- q.setParameter("mtime", plugin.getMtime());
- if (q.executeUpdate() != 1) {
- throw new Exception("Failed to update a plugin that matches [" + plugin + "]");
- }
+ Plugin pluginEntity = entityManager.getReference(Plugin.class, plugin.getId());
+ pluginEntity.setName(plugin.getName());
+ pluginEntity.setPath(plugin.getPath());
+ pluginEntity.setDisplayName(plugin.getDisplayName());
+ pluginEntity.setEnabled(plugin.isEnabled());
+ pluginEntity.setStatus(plugin.getStatus());
+ pluginEntity.setMd5(plugin.getMD5());
+ pluginEntity.setVersion(plugin.getVersion());
+ pluginEntity.setAmpsVersion(plugin.getAmpsVersion());
+ pluginEntity.setDeployment(plugin.getDeployment());
+ pluginEntity.setPluginConfiguration(plugin.getPluginConfiguration());
+ pluginEntity.setScheduledJobsConfiguration(plugin.getScheduledJobsConfiguration());
+ pluginEntity.setDescription(plugin.getDescription());
+ pluginEntity.setHelp(plugin.getHelp());
+ pluginEntity.setMtime(plugin.getMtime());
- entityManager.flush(); // make sure we push this out to the DB now
+ try {
+ entityManager.flush(); // make sure we push this out to the DB now
+ } catch (Exception e) {
+ throw new Exception("Failed to update a plugin that matches [" + plugin + "]", e);
+ }
}
return plugin;
}
commit aadfbe12066b4cab890bc04fbd9a55c76df87fb4
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 13:19:15 2009 -0500
provide an API to get a list of all enabled and disabled plugins grouped by their type
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java
index a79dff5..bbeb84c 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/content/ContentManagerHelper.java
@@ -42,7 +42,7 @@ public class ContentManagerHelper {
}
MasterServerPluginContainer master = mbean.getMasterPluginContainer();
- pc = master.getPluginContainer(ContentServerPluginContainer.class);
+ pc = master.getPluginContainerByClass(ContentServerPluginContainer.class);
} catch (IllegalStateException ise) {
throw ise;
} catch (Exception e) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 2d67f3f..ff7d6ca 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -26,7 +26,9 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import javax.ejb.EJB;
import javax.ejb.Stateless;
@@ -54,6 +56,7 @@ import org.rhq.enterprise.server.authz.RequiredPermission;
import org.rhq.enterprise.server.plugin.pc.AbstractTypeServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.ServerPluginDescriptorUtil;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
@@ -173,7 +176,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
String pluginName = doomedPlugin.getName();
doomedPlugins.add(pluginName);
if (master != null) {
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(pluginName);
+ AbstractTypeServerPluginContainer pc = master.getPluginContainerByPlugin(pluginName);
if (pc != null) {
try {
pc.unschedulePluginJobs(pluginName);
@@ -216,7 +219,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
String pluginName = doomedPlugin.getName();
doomedPlugins.add(pluginName);
if (master != null) {
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(pluginName);
+ AbstractTypeServerPluginContainer pc = master.getPluginContainerByPlugin(pluginName);
if (pc != null) {
try {
pc.unschedulePluginJobs(pluginName);
@@ -447,6 +450,27 @@ public class ServerPluginsBean implements ServerPluginsLocal {
return status;
}
+ // we need this method to talk to the master plugin container because the plugin data model
+ // does not contain information as to what type a plugin is. It only has information about
+ // where the plugin is deployed (agent or server) but it doesn't indicate if a plugin
+ // if of type "alert plugin" or "generic plugin". That is only known when the plugin descriptor
+ // is parsed, which happens when the master plugin container is initialized. Therefore, this
+ // needs to get plugin info from the master plugin container while the master is running.
+ public Map<ServerPluginType, List<String>> getAllPluginsGroupedByType() {
+ Map<ServerPluginType, List<String>> allPlugins = new HashMap<ServerPluginType, List<String>>();
+
+ MasterServerPluginContainer master = LookupUtil.getServerPluginService().getMasterPluginContainer();
+ if (master != null) {
+ List<ServerPluginType> types = master.getServerPluginTypes();
+ for (ServerPluginType type : types) {
+ List<String> plugins = master.getAllPluginsByPluginType(type);
+ allPlugins.put(type, plugins);
+ }
+ }
+
+ return allPlugins;
+ }
+
/**
* This will write the contents of the given plugin file to the database.
* This will assume the MD5 in the database is already correct, so this
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index df685d4..a6a09bf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -2,6 +2,7 @@ package org.rhq.enterprise.server.plugin;
import java.io.File;
import java.util.List;
+import java.util.Map;
import javax.ejb.Local;
import javax.persistence.NoResultException;
@@ -9,6 +10,7 @@ import javax.persistence.NoResultException;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.plugin.Plugin;
import org.rhq.core.domain.plugin.PluginStatusType;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDescriptorType;
/**
@@ -173,4 +175,13 @@ public interface ServerPluginsLocal {
* <code>null</code> indicates an unknown plugin.
*/
PluginStatusType getServerPluginStatus(String pluginName);
+
+ /**
+ * This will return a map containing all plugins currently known to the master plugin container.
+ * This will return installed plugins that are both enabled and disabled.
+ * Note that if the master plugin container is not running, an empty map is returned.
+ *
+ * @return names of all enabled and disabled plugins, keyed on their types
+ */
+ Map<ServerPluginType, List<String>> getAllPluginsGroupedByType();
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
index 8ebabd4..4ab3fb2 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java
@@ -21,6 +21,7 @@ package org.rhq.enterprise.server.plugin.pc;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -46,11 +47,22 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
public class MasterServerPluginContainer {
private static final Log log = LogFactory.getLog(MasterServerPluginContainer.class);
+ /** The configuration for the master plugin container itself. */
private MasterServerPluginContainerConfiguration configuration;
+
+ /** the plugin containers for all the different types of plugins that are supported */
private Map<ServerPluginType, AbstractTypeServerPluginContainer> pluginContainers = new HashMap<ServerPluginType, AbstractTypeServerPluginContainer>();
+
+ /** the object that provides all the classloaders for all plugins */
private ClassLoaderManager classLoaderManager;
/**
+ * Because the individual plugin containers are only managing enabled plugins (they are never told about plugins that disabled).
+ * this map contains the lists of plugins that are disabled so others can find out what plugins are registered but not running.
+ */
+ private Map<ServerPluginType, List<String>> disabledPlugins = new HashMap<ServerPluginType, List<String>>();
+
+ /**
* Starts the master plugin container, which will load all plugins and begin managing them.
*
* @param config the master configuration
@@ -188,6 +200,7 @@ public class MasterServerPluginContainer {
}
this.pluginContainers.clear();
+ this.disabledPlugins.clear();
this.classLoaderManager = null;
this.configuration = null;
@@ -238,6 +251,55 @@ public class MasterServerPluginContainer {
}
/**
+ * Given a plugin type, this will return the names of all known plugins of that type.
+ * This includes all types that are currently started as well as plugins
+ * that have been disabled.
+ *
+ * If the master plugin container has not been started, this returns an empty list.
+ *
+ * @param pluginType
+ *
+ * @return list of both enabled and disabled plugins of the given type
+ */
+ public List<String> getAllPluginsByPluginType(ServerPluginType pluginType) {
+ List<String> allPlugins = new ArrayList<String>();
+
+ AbstractTypeServerPluginContainer pc = getPluginContainerByPluginType(pluginType);
+ if (pc != null) {
+ // add the enabled plugins
+ ServerPluginManager pluginManager = pc.getPluginManager();
+ if (pluginManager != null) {
+ Collection<ServerPluginEnvironment> envs = pluginManager.getPluginEnvironments();
+ if (envs != null) {
+ for (ServerPluginEnvironment env : envs) {
+ allPlugins.add(env.getPluginName());
+ }
+ }
+ }
+
+ // add the disabled plugins
+ List<String> disabled = this.disabledPlugins.get(pluginType);
+ if (disabled != null) {
+ allPlugins.addAll(disabled);
+ }
+ }
+
+ return allPlugins;
+ }
+
+ /**
+ * This will return all known server plugins types. These are the types of plugins
+ * that are supported by a server plugin container. You can obtain the server
+ * plugin container that manages a particular server plugin type via
+ * {@link #getPluginContainerByPluginType(ServerPluginType)}.
+ *
+ * @return all known server plugin types
+ */
+ public synchronized List<ServerPluginType> getServerPluginTypes() {
+ return new ArrayList<ServerPluginType>(this.pluginContainers.keySet());
+ }
+
+ /**
* Get the plugin container of the given class. This method provides a strongly typed return value,
* based on the type of plugin container the caller wants returned.
*
@@ -245,7 +307,7 @@ public class MasterServerPluginContainer {
* @return the plugin container of the given class (<code>null</code> if none found)
*/
@SuppressWarnings("unchecked")
- public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainer(Class<T> clazz) {
+ public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainerByClass(Class<T> clazz) {
for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
if (clazz.isInstance(pc)) {
return (T) pc;
@@ -262,7 +324,7 @@ public class MasterServerPluginContainer {
* @param pluginName
* @return the plugin container that is managing the named plugin of <code>null</code>
*/
- public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainer(String pluginName) {
+ public synchronized <T extends AbstractTypeServerPluginContainer> T getPluginContainerByPlugin(String pluginName) {
for (AbstractTypeServerPluginContainer pc : this.pluginContainers.values()) {
if (null != pc.getPluginManager().getPluginEnvironment(pluginName)) {
return (T) pc;
@@ -319,7 +381,7 @@ public class MasterServerPluginContainer {
if (pluginFiles != null) {
- List<String> disabledPlugins = getDisabledPluginNames();
+ List<String> allDisabledPlugins = getDisabledPluginNames();
for (File pluginFile : pluginFiles) {
if (pluginFile.getName().endsWith(".jar")) {
@@ -329,12 +391,19 @@ public class MasterServerPluginContainer {
ServerPluginDescriptorType descriptor;
descriptor = ServerPluginDescriptorUtil.loadPluginDescriptorFromUrl(pluginUrl);
if (descriptor != null) {
- if (!disabledPlugins.contains(descriptor.getName())) {
+ if (!allDisabledPlugins.contains(descriptor.getName())) {
log.debug("pre-loaded server plugin from URL: " + pluginUrl);
plugins.put(pluginUrl, descriptor);
} else {
log.info("Server plugin [" + descriptor.getName()
+ "] is disabled and will not be initialized");
+ ServerPluginType pluginType = new ServerPluginType(descriptor);
+ List<String> disabledByType = this.disabledPlugins.get(pluginType);
+ if (disabledByType == null) {
+ disabledByType = new ArrayList<String>(1);
+ this.disabledPlugins.put(pluginType, disabledByType);
+ }
+ disabledByType.add(descriptor.getName());
}
}
} catch (Throwable t) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
index feba2fc..3e6bb34 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginType.java
@@ -29,6 +29,22 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
public class ServerPluginType {
private final Class<? extends ServerPluginDescriptorType> descriptorType;
+ /**
+ * Given an actual plugin descriptor object, this will create a plugin type
+ * that represents that kind of plugin.
+ *
+ * @param descriptor an actual descriptor parsed from a plugin
+ */
+ public ServerPluginType(ServerPluginDescriptorType descriptor) {
+ this((descriptor != null) ? descriptor.getClass() : null);
+ }
+
+ /**
+ * Given a type of plugin descriptor, this will create a plugin type
+ * that represents that kind of plugin.
+ *
+ * @param descriptorType
+ */
public ServerPluginType(Class<? extends ServerPluginDescriptorType> descriptorType) {
if (descriptorType == null) {
throw new NullPointerException("descriptorType must not be null");
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
index 1dace0b..9f0026b 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/pc/generic/GenericServerPluginTest.java
@@ -23,6 +23,7 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.List;
+import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
@@ -32,12 +33,16 @@ import org.testng.annotations.Test;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.util.stream.StreamUtil;
+import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
+import org.rhq.enterprise.server.plugin.pc.ServerPluginType;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.State;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericPluginManager;
import org.rhq.enterprise.server.plugin.pc.generic.TestGenericServerPluginService.TestGenericServerPluginContainer;
import org.rhq.enterprise.server.plugin.pc.generic.TestLifecycleListener.LifecycleState;
import org.rhq.enterprise.server.test.AbstractEJB3Test;
+import org.rhq.enterprise.server.util.LookupUtil;
import org.rhq.enterprise.server.xmlschema.ScheduledJobDefinition;
+import org.rhq.enterprise.server.xmlschema.generated.serverplugin.generic.GenericPluginDescriptorType;
@Test
public class GenericServerPluginTest extends AbstractEJB3Test {
@@ -76,10 +81,21 @@ public class GenericServerPluginTest extends AbstractEJB3Test {
List<ScheduledJobDefinition> schedules = component.context.getSchedules();
assert schedules == null;
+ ServerPluginsLocal serverPluginsLocal = LookupUtil.getServerPlugins();
+ Map<ServerPluginType, List<String>> map = serverPluginsLocal.getAllPluginsGroupedByType();
+ assert map.size() == 1;
+ List<String> pluginNames = map.get(new ServerPluginType(GenericPluginDescriptorType.class));
+ assert pluginNames.size() == 1;
+ assert pluginNames.get(0).equals("TestSimpleGenericPlugin");
+
// make sure everything is shutdown
this.pluginService.stopMasterPluginContainer();
assert pc.state == State.UNINITIALIZED;
assert component.state == LifecycleState.UNINITIALIZED;
+
+ // with the master down, this method should return an empty map
+ map = serverPluginsLocal.getAllPluginsGroupedByType();
+ assert map.size() == 0;
}
private File createPluginJar(String jarName, String descriptorXmlFilename) throws Exception {
commit 07ae93f34338458daa75082ef519b4b1851ddc0c
Merge: 5e17b2f... 2d97557...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 11:08:38 2009 -0500
Merge branch 'master' into pc
commit 5e17b2f3837504924ab1ec1b7ba48d017f258ef2
Merge: 45e0f2f... ee2e8e8...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 10:17:56 2009 -0500
Merge branch 'master' into pc
commit 45e0f2f25b7230d65bc561bc63bd1e1cdd7c65f8
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 10:15:39 2009 -0500
use the new deepCopy()
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 8cbffc9..2d67f3f 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -96,13 +96,13 @@ public class ServerPluginsBean implements ServerPluginsLocal {
Configuration config = plugin.getPluginConfiguration();
if (config != null) {
config = entityManager.find(Configuration.class, config.getId());
- plugin.setPluginConfiguration(config.deepCopyWithoutProxies());
+ plugin.setPluginConfiguration(config.deepCopy());
}
config = plugin.getScheduledJobsConfiguration();
if (config != null) {
config = entityManager.find(Configuration.class, config.getId());
- plugin.setScheduledJobsConfiguration(config.deepCopyWithoutProxies());
+ plugin.setScheduledJobsConfiguration(config.deepCopy());
}
return plugin;
commit b3a962cfa61b2f05b4258b9a25e6e72819473191
Merge: c995032... 37bb080...
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 09:57:31 2009 -0500
Merge branch 'master' into pc
commit c995032cbc61261e353c523259810d076d586519
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 09:51:34 2009 -0500
fix NPE when plugin config or scheduled jobs config is null
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 1415bb5..8cbffc9 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -93,12 +93,17 @@ public class ServerPluginsBean implements ServerPluginsLocal {
public Plugin getServerPluginRelationships(Plugin plugin) {
plugin = getServerPlugin(plugin.getName()); // refresh all but the content field
- int pluginConfigId = plugin.getPluginConfiguration().getId();
- int scheduledJobsId = plugin.getScheduledJobsConfiguration().getId();
- Configuration pluginConfig = entityManager.find(Configuration.class, pluginConfigId);
- Configuration scheduledJobs = entityManager.find(Configuration.class, scheduledJobsId);
- plugin.setPluginConfiguration(pluginConfig.deepCopyWithoutProxies());
- plugin.setScheduledJobsConfiguration(scheduledJobs.deepCopyWithoutProxies());
+ Configuration config = plugin.getPluginConfiguration();
+ if (config != null) {
+ config = entityManager.find(Configuration.class, config.getId());
+ plugin.setPluginConfiguration(config.deepCopyWithoutProxies());
+ }
+
+ config = plugin.getScheduledJobsConfiguration();
+ if (config != null) {
+ config = entityManager.find(Configuration.class, config.getId());
+ plugin.setScheduledJobsConfiguration(config.deepCopyWithoutProxies());
+ }
return plugin;
}
@@ -239,7 +244,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
File currentFile = new File(pluginDir, doomedPlugin.getPath());
currentFile.delete();
} catch (Exception e) {
- log.error("Failed to delete the undeployed plugin [" + doomedPlugin.getPath() + "]. Cause: " + ThrowableUtil.getAllMessages(e));
+ log.error("Failed to delete the undeployed plugin [" + doomedPlugin.getPath() + "]. Cause: "
+ + ThrowableUtil.getAllMessages(e));
}
}
}
@@ -275,7 +281,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
@RequiredPermission(Permission.MANAGE_SETTINGS)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void setServerPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status)
- throws Exception {
+ throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
return; // nothing to do
}
@@ -291,7 +297,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
public Plugin registerServerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception {
if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
- throw new IllegalArgumentException("Plugin [" + plugin.getName() + "] must be a server plugin to be registered");
+ throw new IllegalArgumentException("Plugin [" + plugin.getName()
+ + "] must be a server plugin to be registered");
}
Plugin existingPlugin = null;
@@ -304,7 +311,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (existingPlugin != null) {
if (existingPlugin.getStatus() == PluginStatusType.DELETED) {
- throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName() + "], it has been marked as deleted");
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
+ + "], it has been marked as deleted");
}
Plugin obsolete = ServerPluginDescriptorUtil.determineObsoletePlugin(plugin, existingPlugin);
if (obsolete == existingPlugin) { // yes use == for reference equality
@@ -322,7 +330,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (plugin.getId() == 0) {
PluginStatusType status = getServerPluginStatus(plugin.getName());
if (PluginStatusType.DELETED == status) {
- throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName() + "], it has been previously marked as deleted.");
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
+ + "], it has been previously marked as deleted.");
}
entityManager.persist(plugin);
} else {
@@ -364,7 +373,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
// to entityManager.merge that plugin POJO, it would null out that blob column.
if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
- throw new IllegalArgumentException("Plugin [" + plugin.getName() + "] must be a server plugin to be updated");
+ throw new IllegalArgumentException("Plugin [" + plugin.getName()
+ + "] must be a server plugin to be updated");
}
if (plugin.getId() == 0) {
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index 803f7cf..df685d4 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -42,6 +42,7 @@ public interface ServerPluginsLocal {
*
* @param plugin
* @return the same plugin, with the relationship data loaded
+ * @throws NoResultException when no plugin with that name exists
*/
Plugin getServerPluginRelationships(Plugin plugin);
commit 9994ec529ecf93914ab48d25023327ee0eb3f503
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Tue Nov 24 16:41:38 2009 -0500
add a test to confirm that snapshot versions are considered older than candidate releases or releases
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 d9c2a9f..dfee3a5 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
@@ -161,5 +161,14 @@ public class ComparableVersionTest {
assert ver2.compareTo(ver2) == 0;
assert ver1.compareTo(ver2) > 0; // ver1 is after ver2!
assert ver2.compareTo(ver1) < 0; // ver1 is after ver2!
+
+ ver1 = new ComparableVersion("4.0.0-SNAPSHOT");
+ ver2 = new ComparableVersion("4.0.0.CR2"); // CR is an alias for RC
+ assert !ver1.equals(ver2);
+ assert !ver2.equals(ver1);
+ assert ver1.compareTo(ver1) == 0;
+ assert ver2.compareTo(ver2) == 0;
+ assert ver1.compareTo(ver2) < 0;
+ assert ver2.compareTo(ver1) > 0;
}
}
commit 93cd6e74d101d7dc645ac38168b4d0157752bf8d
Author: Justin Harris <jharris(a)redhat.com>
Date: Tue Nov 24 14:57:46 2009 -0500
Moving in some seam functionality to allow for page scoped beans in form submission.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java
new file mode 100644
index 0000000..0bb87bd
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginComponent.java
@@ -0,0 +1,73 @@
+/*
+ * RHQ Management Platform
+ * Copyright (C) 2005-2009 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.admin.plugin;
+
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.AutoCreate;
+import org.jboss.seam.annotations.Factory;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.web.RequestParameter;
+import org.rhq.core.domain.plugin.Plugin;
+import org.rhq.core.domain.plugin.PluginDeploymentType;
+import org.rhq.enterprise.server.plugin.ServerPluginsLocal;
+import org.rhq.enterprise.server.util.LookupUtil;
+
+/**
+ * Component responsible for looking up a {@link Plugin}, obtaining
+ * the <code>name</code> and <code>type</code> from request parameters.
+ *
+ * @author jharris
+ */
+@Name("installedPlugin")
+public class InstalledPluginComponent {
+
+ @RequestParameter("plugin")
+ private String name;
+ @RequestParameter("pluginType")
+ private PluginDeploymentType type;
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public PluginDeploymentType getType() {
+ return this.type;
+ }
+
+ public void setType(PluginDeploymentType type) {
+ this.type = type;
+ }
+
+ @Factory(value="plugin", autoCreate=true, scope=ScopeType.PAGE)
+ public Plugin lookupPlugin() {
+ if (this.type == PluginDeploymentType.AGENT) {
+ return LookupUtil.getResourceMetadataManager().getPlugin(this.name);
+ } else if (this.type == PluginDeploymentType.SERVER) {
+ ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
+ Plugin plugin = serverPluginsBean.getServerPlugin(this.name);
+ return serverPluginsBean.getServerPluginRelationships(plugin);
+ }
+
+ return null;
+ }
+}
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
index b6db223..3fe6988 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
@@ -21,8 +21,13 @@ package org.rhq.enterprise.gui.admin.plugin;
import javax.faces.application.FacesMessage;
import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.Create;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
import org.rhq.core.clientapi.agent.metadata.ConfigurationMetadataParser;
import org.rhq.core.domain.auth.Subject;
import org.rhq.core.domain.authz.Permission;
@@ -40,21 +45,24 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
* @author Greg Hinkle
* @author John Mazzitelli
*/
+(a)Scope(ScopeType.PAGE)
+@Name("InstalledPluginUIBean")
public class InstalledPluginUIBean {
- private final Log log = LogFactory.getLog(InstalledPluginUIBean.class);
+ private static final String OUTCOME_SUCCESS = "success";
public static final String MANAGED_BEAN_NAME = InstalledPluginUIBean.class.getSimpleName();
-
+ private final Log log = LogFactory.getLog(InstalledPluginUIBean.class);
+ @In
private Plugin plugin;
private ConfigurationDefinition pluginConfigurationDefinition;
private ConfigurationDefinition scheduledJobsDefinition;
- public InstalledPluginUIBean() {
- lookupPlugin();
+ public Plugin getPlugin() {
+ return plugin;
}
- public Plugin getPlugin() {
- return this.plugin;
+ public void setPlugin(Plugin plugin) {
+ this.plugin = plugin;
}
public ConfigurationDefinition getPluginConfigurationDefinition() {
@@ -65,40 +73,39 @@ public class InstalledPluginUIBean {
return this.scheduledJobsDefinition;
}
- public void updatePlugin() {
+ public boolean isEditable() {
+ return this.pluginConfigurationDefinition != null || this.scheduledJobsDefinition != null;
+ }
+
+ public String updatePlugin() {
ServerPluginsLocal serverPlugins = LookupUtil.getServerPlugins();
try {
serverPlugins.updateServerPluginExceptContent(EnterpriseFacesContextUtility.getSubject(), plugin);
-
FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO,
- "Configuration settings saved.");
+ "Configuration settings saved.");
+
+ return OUTCOME_SUCCESS;
} catch (Exception e) {
log.error("Error updating the plugin configurations.", e);
FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR,
- "There was an error changing the configuration settings.", e);
- }
+ "There was an error changing the configuration settings.", e);
- lookupPlugin();
+ return null;
+ }
}
- private void lookupPlugin() {
+ @Create
+ public void lookupConfigDefinitions() {
hasPermission();
- String pluginName = FacesContextUtility.getRequiredRequestParameter("plugin", String.class);
- String pluginType = FacesContextUtility.getRequiredRequestParameter("pluginType", String.class);
- PluginDeploymentType deploymentType = PluginDeploymentType.valueOf(pluginType);
- if (deploymentType == PluginDeploymentType.AGENT) {
- this.plugin = LookupUtil.getResourceMetadataManager().getPlugin(pluginName);
- } else {
- ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
- this.plugin = serverPluginsBean.getServerPlugin(pluginName);
- this.plugin = serverPluginsBean.getServerPluginRelationships(this.plugin);
+ String pluginName = this.plugin.getName();
+
+ if (this.plugin.getDeployment() == PluginDeploymentType.SERVER) {
try {
+ ServerPluginsLocal serverPluginsBean = LookupUtil.getServerPlugins();
ServerPluginDescriptorType descriptor = serverPluginsBean.getServerPluginDescriptor(pluginName);
- this.pluginConfigurationDefinition = ConfigurationMetadataParser.parse("pc:" + pluginName, descriptor
- .getPluginConfiguration());
- this.scheduledJobsDefinition = ConfigurationMetadataParser.parse("jobs:" + pluginName, descriptor
- .getScheduledJobs());
+ this.pluginConfigurationDefinition = ConfigurationMetadataParser.parse("pc:" + pluginName, descriptor.getPluginConfiguration());
+ this.scheduledJobsDefinition = ConfigurationMetadataParser.parse("jobs:" + pluginName, descriptor.getScheduledJobs());
} catch (Exception e) {
String err = "Cannot determine what the plugin configuration or scheduled jobs configuration looks like";
log.error(err + " - Cause: " + e);
@@ -114,8 +121,7 @@ public class InstalledPluginUIBean {
private void hasPermission() {
Subject subject = EnterpriseFacesContextUtility.getSubject();
if (!LookupUtil.getAuthorizationManager().hasGlobalPermission(subject, Permission.MANAGE_SETTINGS)) {
- throw new PermissionException("User [" + subject.getName()
- + "] does not have the proper permissions to view or manage plugins");
+ throw new PermissionException("User [" + subject.getName() + "] does not have the proper permissions to view or manage plugins");
}
}
-}
\ No newline at end of file
+}
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml
index bacb535..64bd31e 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/components.xml
@@ -11,6 +11,7 @@
<component name="org.jboss.seam.core.init">
<property name="debug">false</property> <!-- enable only when needed -->
<property name="transactionManagementEnabled">false</property>
+ <property name="jndi-pattern">rhq/#{ejbName}/local</property>
</component>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml
index 11dadd0..a80402b 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-managed-beans/admin-beans.xml
@@ -20,13 +20,6 @@
<managed-bean-class>org.rhq.enterprise.gui.admin.plugin.InstalledPluginsUIBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
- <managed-bean>
- <description>Visibility for the installed agent and server plugins</description>
- <display-name>Installed Plugin</display-name>
- <managed-bean-name>InstalledPluginUIBean</managed-bean-name>
- <managed-bean-class>org.rhq.enterprise.gui.admin.plugin.InstalledPluginUIBean</managed-bean-class>
- <managed-bean-scope>request</managed-bean-scope>
- </managed-bean>
<managed-bean>
<description>Access to downloads information</description>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml
index 93932df..7f19f4d 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/jsf-navigation/admin-navigation.xml
@@ -28,6 +28,17 @@
</navigation-case>
</navigation-rule>
+
+ <navigation-rule>
+ <from-view-id>/rhq/admin/plugin/plugin-details-edit.xhtml</from-view-id>
+
+ <navigation-case>
+ <from-outcome>success</from-outcome>
+ <to-view-id>/rhq/admin/plugin/plugin-details-view.xhtml?plugin=#{plugin.name}&pluginType=#{plugin.deployment}</to-view-id>
+ <redirect/>
+ </navigation-case>
+
+ </navigation-rule>
<navigation-rule>
<navigation-case>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml
new file mode 100644
index 0000000..d88afe7
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-edit.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jstl/core"
+ xmlns:onc="http://jboss.org/on/component"
+ xmlns:rich="http://richfaces.ajax4jsf.org/rich">
+
+<ui:composition template="/rhq/admin/plugin/plugin-details.xhtml">
+ <ui:param name="editMode" value="true"/>
+
+ <ui:define name="post-config">
+ <rich:panel rendered="#{InstalledPluginUIBean.editable}">
+ <h:commandButton value="SAVE" type="submit" action="#{InstalledPluginUIBean.updatePlugin}"
+ alt="Click to Save Changes" styleClass="buttonmed" />
+ <h:commandButton value="RESET" type="reset" immediate="true"
+ title="Click to Reset Fields" styleClass="buttonmed"/>
+ </rich:panel>
+ </ui:define>
+</ui:composition>
+
+</html>
\ No newline at end of file
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml
new file mode 100644
index 0000000..389923a
--- /dev/null
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details-view.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:h="http://java.sun.com/jsf/html"
+ xmlns:f="http://java.sun.com/jsf/core"
+ xmlns:ui="http://java.sun.com/jsf/facelets"
+ xmlns:c="http://java.sun.com/jstl/core"
+ xmlns:onc="http://jboss.org/on/component"
+ xmlns:rich="http://richfaces.ajax4jsf.org/rich">
+
+<ui:composition template="/rhq/admin/plugin/plugin-details.xhtml">
+ <ui:param name="editMode" value="false"/>
+
+ <ui:define name="pre-config">
+ <h:panelGrid columns="1" styleClass="buttons-table" columnClasses="button-cell"
+ rendered="#{InstalledPluginUIBean.editable}">
+ <h:outputLink value="/rhq/admin/plugin/plugin-details-edit.xhtml"
+ styleClass="buttonmed">
+ <f:param name="plugin" value="#{installedPlugin.name}"/>
+ <f:param name="pluginType" value="#{installedPlugin.type}"/>
+ <h:outputText value="EDIT"/>
+ </h:outputLink>
+ </h:panelGrid>
+ </ui:define>
+ </ui:composition>
+
+</html>
\ No newline at end of file
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
index fa46dc8..cc11203 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
@@ -35,8 +35,6 @@
layout="table"
width="100%"/>
-
-
<h:form id="pluginsForm">
<rich:panel>
@@ -66,7 +64,6 @@
</h:panelGrid>
-
<rich:panel>
<f:facet name="header">
<h:outputText value="Plugin Help"/>
@@ -76,6 +73,7 @@
</rich:panel>
+ <ui:insert name="pre-config" />
<rich:panel rendered="#{InstalledPluginUIBean.plugin.pluginConfiguration != null}">
<f:facet name="header">
@@ -83,7 +81,8 @@
</f:facet>
<onc:config
configurationDefinition="#{InstalledPluginUIBean.pluginConfigurationDefinition}"
- configuration="#{InstalledPluginUIBean.plugin.pluginConfiguration}" />
+ configuration="#{InstalledPluginUIBean.plugin.pluginConfiguration}"
+ readOnly="#{not editMode}" />
</rich:panel>
<rich:panel rendered="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration != null}">
@@ -92,17 +91,11 @@
</f:facet>
<onc:config
configurationDefinition="#{InstalledPluginUIBean.scheduledJobsDefinition}"
- configuration="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration}" />
+ configuration="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration}"
+ readOnly="#{not editMode}" />
</rich:panel>
- <input type="hidden" name="plugin" value="#{param.plugin}"/>
- <input type="hidden" name="pluginType" value="#{param.pluginType}"/>
-
- <rich:panel rendered="#{InstalledPluginUIBean.plugin.pluginConfiguration != null ||
- InstalledPluginUIBean.plugin.scheduledJobsConfiguration != null}">
- <h:commandButton value="OK" type="submit" action="#{InstalledPluginUIBean.updatePlugin}"
- alt="Click to Save Plugin" styleClass="buttonmed" />
- </rich:panel>
+ <ui:insert name="post-config" />
</rich:panel>
</h:form>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
index 72f941e..5654368 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
@@ -75,7 +75,7 @@
<h:outputText styleClass="headerText" value="Name"/>
</f:facet>
- <h:outputLink value="/rhq/admin/plugin/plugin-details.xhtml">
+ <h:outputLink value="/rhq/admin/plugin/plugin-details-view.xhtml">
<f:param name="plugin" value="#{agentPlugin.name}"/>
<f:param name="pluginType" value="AGENT"/>
<h:outputText value="#{agentPlugin.displayName}"/>
@@ -160,7 +160,7 @@
<h:outputText styleClass="headerText" value="Name"/>
</f:facet>
- <h:outputLink value="/rhq/admin/plugin/plugin-details.xhtml">
+ <h:outputLink value="/rhq/admin/plugin/plugin-details-view.xhtml">
<f:param name="plugin" value="#{serverPlugin.name}"/>
<f:param name="pluginType" value="SERVER"/>
<h:outputText value="#{serverPlugin.displayName}"/>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index ce603da..1415bb5 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -16,7 +16,6 @@
* 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.plugin;
import java.io.BufferedInputStream;
@@ -67,14 +66,12 @@ import org.rhq.enterprise.server.xmlschema.generated.serverplugin.ServerPluginDe
@Stateless
@javax.annotation.Resource(name = "RHQ_DS", mappedName = RHQConstants.DATASOURCE_JNDI_NAME)
public class ServerPluginsBean implements ServerPluginsLocal {
- private final Log log = LogFactory.getLog(ServerPluginsBean.class);
+ private final Log log = LogFactory.getLog(ServerPluginsBean.class);
@PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME)
private EntityManager entityManager;
-
@javax.annotation.Resource(name = "RHQ_DS")
private DataSource dataSource;
-
@EJB
private ServerPluginsLocal serverPluginsBean; //self
@@ -242,8 +239,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
File currentFile = new File(pluginDir, doomedPlugin.getPath());
currentFile.delete();
} catch (Exception e) {
- log.error("Failed to delete the undeployed plugin [" + doomedPlugin.getPath() + "]. Cause: "
- + ThrowableUtil.getAllMessages(e));
+ log.error("Failed to delete the undeployed plugin [" + doomedPlugin.getPath() + "]. Cause: " + ThrowableUtil.getAllMessages(e));
}
}
}
@@ -279,7 +275,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
@RequiredPermission(Permission.MANAGE_SETTINGS)
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void setServerPluginStatus(Subject subject, List<Integer> pluginIds, PluginStatusType status)
- throws Exception {
+ throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
return; // nothing to do
}
@@ -295,8 +291,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
public Plugin registerServerPlugin(Subject subject, Plugin plugin, File pluginFile) throws Exception {
if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
- throw new IllegalArgumentException("Plugin [" + plugin.getName()
- + "] must be a server plugin to be registered");
+ throw new IllegalArgumentException("Plugin [" + plugin.getName() + "] must be a server plugin to be registered");
}
Plugin existingPlugin = null;
@@ -309,8 +304,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (existingPlugin != null) {
if (existingPlugin.getStatus() == PluginStatusType.DELETED) {
- throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
- + "], it has been marked as deleted");
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName() + "], it has been marked as deleted");
}
Plugin obsolete = ServerPluginDescriptorUtil.determineObsoletePlugin(plugin, existingPlugin);
if (obsolete == existingPlugin) { // yes use == for reference equality
@@ -328,8 +322,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
if (plugin.getId() == 0) {
PluginStatusType status = getServerPluginStatus(plugin.getName());
if (PluginStatusType.DELETED == status) {
- throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName()
- + "], it has been previously marked as deleted.");
+ throw new IllegalArgumentException("Cannot register plugin [" + plugin.getName() + "], it has been previously marked as deleted.");
}
entityManager.persist(plugin);
} else {
@@ -371,8 +364,7 @@ public class ServerPluginsBean implements ServerPluginsLocal {
// to entityManager.merge that plugin POJO, it would null out that blob column.
if (plugin.getDeployment() != PluginDeploymentType.SERVER) {
- throw new IllegalArgumentException("Plugin [" + plugin.getName()
- + "] must be a server plugin to be updated");
+ throw new IllegalArgumentException("Plugin [" + plugin.getName() + "] must be a server plugin to be updated");
}
if (plugin.getId() == 0) {
commit c8a8622dce3142a91725a0a152bee94be64a9259
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 23 14:05:06 2009 -0500
because we put the byte[] content directly in the plugin entity, we can't entityManager.find() because that would load the full plugin content.
instead, use getReference. when we need to load the relationships, we have to play games by
loading in the configs directly and doing a deep copy (mainly to workaround a hibernate bug)
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 157911d..ce603da 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -94,11 +94,14 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
public Plugin getServerPluginRelationships(Plugin plugin) {
- plugin = entityManager.find(Plugin.class, plugin.getId());
+ plugin = getServerPlugin(plugin.getName()); // refresh all but the content field
- // force eager load
- plugin.getPluginConfiguration().getProperties().size();
- plugin.getScheduledJobsConfiguration().getProperties().size();
+ int pluginConfigId = plugin.getPluginConfiguration().getId();
+ int scheduledJobsId = plugin.getScheduledJobsConfiguration().getId();
+ Configuration pluginConfig = entityManager.find(Configuration.class, pluginConfigId);
+ Configuration scheduledJobs = entityManager.find(Configuration.class, scheduledJobsId);
+ plugin.setPluginConfiguration(pluginConfig.deepCopyWithoutProxies());
+ plugin.setScheduledJobsConfiguration(scheduledJobs.deepCopyWithoutProxies());
return plugin;
}
@@ -146,9 +149,9 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
- public List<Plugin> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
+ public List<String> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
- return new ArrayList<Plugin>(); // nothing to do
+ return new ArrayList<String>(); // nothing to do
}
serverPluginsBean.setServerPluginEnabledFlag(subject, pluginIds, false);
@@ -156,19 +159,24 @@ public class ServerPluginsBean implements ServerPluginsLocal {
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
- List<Plugin> doomedPlugins = new ArrayList<Plugin>();
+ List<String> doomedPlugins = new ArrayList<String>();
for (Integer pluginId : pluginIds) {
- Plugin doomedPlugin = entityManager.find(Plugin.class, pluginId);
+ Plugin doomedPlugin = null;
+ try {
+ doomedPlugin = entityManager.getReference(Plugin.class, pluginId);
+ } catch (Exception ignore) {
+ }
if (doomedPlugin != null) {
- doomedPlugins.add(doomedPlugin);
+ String pluginName = doomedPlugin.getName();
+ doomedPlugins.add(pluginName);
if (master != null) {
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
+ AbstractTypeServerPluginContainer pc = master.getPluginContainer(pluginName);
if (pc != null) {
try {
- pc.unschedulePluginJobs(doomedPlugin.getName());
+ pc.unschedulePluginJobs(pluginName);
} catch (Exception e) {
- log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ log.warn("Failed to unschedule jobs for plugin [" + pluginName + "]", e);
}
}
}
@@ -184,9 +192,9 @@ public class ServerPluginsBean implements ServerPluginsLocal {
}
@RequiredPermission(Permission.MANAGE_SETTINGS)
- public List<Plugin> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
+ public List<String> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception {
if (pluginIds == null || pluginIds.size() == 0) {
- return new ArrayList<Plugin>(); // nothing to do
+ return new ArrayList<String>(); // nothing to do
}
serverPluginsBean.setServerPluginEnabledFlag(subject, pluginIds, false);
@@ -194,19 +202,24 @@ public class ServerPluginsBean implements ServerPluginsLocal {
ServerPluginServiceManagement serverPluginService = LookupUtil.getServerPluginService();
MasterServerPluginContainer master = serverPluginService.getMasterPluginContainer();
- List<Plugin> doomedPlugins = new ArrayList<Plugin>();
+ List<String> doomedPlugins = new ArrayList<String>();
for (Integer pluginId : pluginIds) {
- Plugin doomedPlugin = entityManager.find(Plugin.class, pluginId);
+ Plugin doomedPlugin = null;
+ try {
+ doomedPlugin = entityManager.getReference(Plugin.class, pluginId);
+ } catch (Exception ignore) {
+ }
if (doomedPlugin != null) {
- doomedPlugins.add(doomedPlugin);
+ String pluginName = doomedPlugin.getName();
+ doomedPlugins.add(pluginName);
if (master != null) {
- AbstractTypeServerPluginContainer pc = master.getPluginContainer(doomedPlugin.getName());
+ AbstractTypeServerPluginContainer pc = master.getPluginContainer(pluginName);
if (pc != null) {
try {
- pc.unschedulePluginJobs(doomedPlugin.getName());
+ pc.unschedulePluginJobs(pluginName);
} catch (Exception e) {
- log.warn("Failed to unschedule jobs for plugin [" + doomedPlugin.getName() + "]", e);
+ log.warn("Failed to unschedule jobs for plugin [" + pluginName + "]", e);
}
}
}
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
index 6f3600e..803f7cf 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsLocal.java
@@ -86,20 +86,20 @@ public interface ServerPluginsLocal {
*
* @param subject user making the request
* @param pluginIds the plugins to be disabled
- * @return the list of plugins that were disabled
+ * @return the list of names of the plugins that were disabled
* @throws Exception if failed to disable a plugin
*/
- List<Plugin> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
+ List<String> disableServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
/**
* Removes the plugin from the system and restarts the server plugin container.
*
* @param subject user making the request
* @param pluginIds
- * @return the list of plugins that were undeployed
+ * @return the list of names of plugins that were undeployed
* @throws Exception if failed to undeploy a plugin
*/
- List<Plugin> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
+ List<String> undeployServerPlugins(Subject subject, List<Integer> pluginIds) throws Exception;
/**
* Turns on or off the enabled flag in the database but does NOT restart the server plugin container.
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
index e1796bf..d1a6aba 100644
--- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
+++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/plugin/ServerPluginsBeanTest.java
@@ -135,6 +135,24 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
assetLazyInitializationException(plugins.get(1));
}
+ public void testUpdatePlugins() throws Exception {
+ Plugin p1 = registerPlugin(1);
+ p1 = this.serverPluginsBean.getServerPlugin(p1.getName());
+ p1 = this.serverPluginsBean.getServerPluginRelationships(p1);
+
+ Plugin p1update = this.serverPluginsBean.updateServerPluginExceptContent(getOverlord(), p1);
+ p1update = this.serverPluginsBean.getServerPluginRelationships(p1update);
+
+ assert p1update.getId() == p1.getId() : p1update;
+ assert p1update.getId() == p1.getId() : p1update;
+ assert p1update.getName().equals(p1.getName()) : p1update;
+ assert p1update.getName().equals(p1.getName()) : p1update;
+ assert p1update.getPluginConfiguration().equals(p1.getPluginConfiguration()) : p1update;
+ assert p1update.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration()) : p1update;
+ p1update.getPluginConfiguration().equals(p1.getPluginConfiguration());
+ p1update.getScheduledJobsConfiguration().equals(p1.getScheduledJobsConfiguration());
+ }
+
public void testDisableEnablePlugins() throws Exception {
Plugin p1 = registerPlugin(1);
Plugin p2 = registerPlugin(2);
@@ -142,12 +160,13 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
List<Integer> ids = new ArrayList<Integer>(2);
ids.add(p1.getId());
ids.add(p2.getId());
- List<Plugin> disabled = this.serverPluginsBean.disableServerPlugins(getOverlord(), ids);
+ List<String> disabled = this.serverPluginsBean.disableServerPlugins(getOverlord(), ids);
assert disabled.size() == 2 : disabled;
- assert disabled.contains(p1) : disabled;
- assert disabled.contains(p2) : disabled;
- assert disabled.get(0).getStatus() == PluginStatusType.INSTALLED; // still installed
- assert disabled.get(1).getStatus() == PluginStatusType.INSTALLED; // still installed
+ assert disabled.contains(p1.getName()) : disabled;
+ assert disabled.contains(p2.getName()) : disabled;
+ ;
+ assert this.serverPluginsBean.getServerPlugin(p1.getName()).getStatus() == PluginStatusType.INSTALLED; // still installed
+ assert this.serverPluginsBean.getServerPlugin(p2.getName()).getStatus() == PluginStatusType.INSTALLED; // still installed
List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert pluginNames.contains(p1.getName()) : pluginNames;
assert pluginNames.contains(p2.getName()) : pluginNames;
@@ -195,12 +214,14 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
List<Integer> ids = new ArrayList<Integer>(2);
ids.add(p1.getId());
ids.add(p2.getId());
- List<Plugin> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
+ List<String> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
assert undeployed.size() == 2 : undeployed;
- assert undeployed.contains(p1) : undeployed;
- assert undeployed.contains(p2) : undeployed;
- assert undeployed.get(0).getStatus() == PluginStatusType.DELETED;
- assert undeployed.get(1).getStatus() == PluginStatusType.DELETED;
+ assert undeployed.contains(p1.getName()) : undeployed;
+ assert undeployed.contains(p2.getName()) : undeployed;
+ Plugin p1deleted = getDeletedPluginInTx(p1.getName());
+ Plugin p2deleted = getDeletedPluginInTx(p2.getName());
+ assert p1deleted.getStatus() == PluginStatusType.DELETED;
+ assert p2deleted.getStatus() == PluginStatusType.DELETED;
List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert !pluginNames.contains(p1.getName()) : "deleted plugins should not be returned even here" + pluginNames;
@@ -230,16 +251,18 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
List<Integer> ids = new ArrayList<Integer>(2);
ids.add(p1.getId());
ids.add(p2.getId());
- List<Plugin> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
+ List<String> undeployed = this.serverPluginsBean.undeployServerPlugins(getOverlord(), ids);
assert undeployed.size() == 2 : undeployed;
- assert undeployed.contains(p1) : undeployed;
- assert undeployed.contains(p2) : undeployed;
- assert undeployed.get(0).getStatus() == PluginStatusType.DELETED;
- assert undeployed.get(0).getPluginConfiguration() == null; // undeploy should have removed this
- assert undeployed.get(0).getScheduledJobsConfiguration() == null; // undeploy should have removed this
- assert undeployed.get(1).getStatus() == PluginStatusType.DELETED;
- assert undeployed.get(1).getPluginConfiguration() == null; // undeploy should have removed this
- assert undeployed.get(1).getScheduledJobsConfiguration() == null; // undeploy should have removed this
+ assert undeployed.contains(p1.getName()) : undeployed;
+ assert undeployed.contains(p2.getName()) : undeployed;
+ Plugin p1deleted = getDeletedPluginInTx(p1.getName());
+ assert p1deleted.getStatus() == PluginStatusType.DELETED;
+ assert p1deleted.getPluginConfiguration() == null; // undeploy should have removed this
+ assert p1deleted.getScheduledJobsConfiguration() == null; // undeploy should have removed this
+ Plugin p2deleted = getDeletedPluginInTx(p1.getName());
+ assert p2deleted.getStatus() == PluginStatusType.DELETED;
+ assert p2deleted.getPluginConfiguration() == null; // undeploy should have removed this
+ assert p2deleted.getScheduledJobsConfiguration() == null; // undeploy should have removed this
List<String> pluginNames = this.serverPluginsBean.getServerPluginNamesByEnabled(false);
assert !pluginNames.contains(p1.getName()) : "deleted plugins should not be returned even here" + pluginNames;
@@ -320,4 +343,17 @@ public class ServerPluginsBeanTest extends AbstractEJB3Test {
private Subject getOverlord() {
return LookupUtil.getSubjectManager().getOverlord();
}
+
+ private Plugin getDeletedPluginInTx(String pluginName) throws Exception {
+ EntityManager em = getEntityManager();
+ getTransactionManager().begin();
+ try {
+ Query q = em.createNamedQuery(Plugin.QUERY_FIND_ANY_BY_NAME_AND_TYPE);
+ q.setParameter("name", pluginName);
+ q.setParameter("type", PluginDeploymentType.SERVER);
+ return (Plugin) q.getSingleResult();
+ } finally {
+ getTransactionManager().rollback();
+ }
+ }
}
commit 263227e335728de980194c0632ae04938396536e
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 23 11:36:47 2009 -0500
put the proper values in the query params
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
index 3697caa..157911d 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/ServerPluginsBean.java
@@ -405,8 +405,8 @@ public class ServerPluginsBean implements ServerPluginsLocal {
q.setParameter("version", plugin.getVersion());
q.setParameter("ampsVersion", plugin.getAmpsVersion());
q.setParameter("deployment", plugin.getDeployment());
- q.setParameter("pluginConfiguration", config);
- q.setParameter("scheduledJobsConfiguration", config);
+ q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
+ q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
q.setParameter("description", plugin.getDescription());
q.setParameter("help", plugin.getHelp());
q.setParameter("mtime", plugin.getMtime());
commit e77a657abf17907a25dba4498b6e4993604ed38c
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Mon Nov 23 10:48:13 2009 -0500
the column should be "enabled" since everywhere else we talk about a plugin being enabled or disabled, not active/inactive
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
index 9f7f6b7..72f941e 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-list.xhtml
@@ -105,7 +105,7 @@
<rich:column>
<f:facet name="header">
- <h:outputText styleClass="headerText" value="Active"/>
+ <h:outputText styleClass="headerText" value="Enabled"/>
</f:facet>
<h:outputText value="#{agentPlugin.enabled}"/>
@@ -190,7 +190,7 @@
<rich:column>
<f:facet name="header">
- <h:outputText styleClass="headerText" value="Active"/>
+ <h:outputText styleClass="headerText" value="Enabled"/>
</f:facet>
<h:outputText value="#{serverPlugin.enabled}"/>
commit 9af95de196ccc8b854a8f1c952af3a6cfa18e78d
Author: Justin Harris <jharris(a)redhat.com>
Date: Mon Nov 23 10:18:55 2009 -0500
Updating update plugin call to new naming scheme.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
index fac4661..b6db223 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
@@ -69,7 +69,7 @@ public class InstalledPluginUIBean {
ServerPluginsLocal serverPlugins = LookupUtil.getServerPlugins();
try {
- serverPlugins.updatePluginExceptContent(EnterpriseFacesContextUtility.getSubject(), plugin);
+ serverPlugins.updateServerPluginExceptContent(EnterpriseFacesContextUtility.getSubject(), plugin);
FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO,
"Configuration settings saved.");
@@ -78,6 +78,8 @@ public class InstalledPluginUIBean {
FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR,
"There was an error changing the configuration settings.", e);
}
+
+ lookupPlugin();
}
private void lookupPlugin() {
commit 556be90ec7e0285dc9205766805aaa91da2ef258
Author: Justin Harris <jharris(a)redhat.com>
Date: Fri Nov 20 18:34:52 2009 -0500
Adding save button to plugin details page.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
index f6eee0d..fac4661 100644
--- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
+++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/plugin/InstalledPluginUIBean.java
@@ -65,6 +65,21 @@ public class InstalledPluginUIBean {
return this.scheduledJobsDefinition;
}
+ public void updatePlugin() {
+ ServerPluginsLocal serverPlugins = LookupUtil.getServerPlugins();
+
+ try {
+ serverPlugins.updatePluginExceptContent(EnterpriseFacesContextUtility.getSubject(), plugin);
+
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO,
+ "Configuration settings saved.");
+ } catch (Exception e) {
+ log.error("Error updating the plugin configurations.", e);
+ FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR,
+ "There was an error changing the configuration settings.", e);
+ }
+ }
+
private void lookupPlugin() {
hasPermission();
String pluginName = FacesContextUtility.getRequiredRequestParameter("plugin", String.class);
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
index 3921b8e..fa46dc8 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/plugin/plugin-details.xhtml
@@ -76,24 +76,32 @@
</rich:panel>
- <rich:panel>
+
+ <rich:panel rendered="#{InstalledPluginUIBean.plugin.pluginConfiguration != null}">
<f:facet name="header">
<h:outputText value="Plugin Configuration"/>
</f:facet>
<onc:config
configurationDefinition="#{InstalledPluginUIBean.pluginConfigurationDefinition}"
- configuration="#{InstalledPluginUIBean.plugin.pluginConfiguration}"
- readOnly="true" />
+ configuration="#{InstalledPluginUIBean.plugin.pluginConfiguration}" />
</rich:panel>
- <rich:panel>
+ <rich:panel rendered="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration != null}">
<f:facet name="header">
<h:outputText value="Scheduled Jobs"/>
</f:facet>
<onc:config
configurationDefinition="#{InstalledPluginUIBean.scheduledJobsDefinition}"
- configuration="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration}"
- readOnly="true" />
+ configuration="#{InstalledPluginUIBean.plugin.scheduledJobsConfiguration}" />
+ </rich:panel>
+
+ <input type="hidden" name="plugin" value="#{param.plugin}"/>
+ <input type="hidden" name="pluginType" value="#{param.pluginType}"/>
+
+ <rich:panel rendered="#{InstalledPluginUIBean.plugin.pluginConfiguration != null ||
+ InstalledPluginUIBean.plugin.scheduledJobsConfiguration != null}">
+ <h:commandButton value="OK" type="submit" action="#{InstalledPluginUIBean.updatePlugin}"
+ alt="Click to Save Plugin" styleClass="buttonmed" />
</rich:panel>
</rich:panel>
commit e144f9a55590182e130ae768b9b494b13f03c2a6
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 22 22:42:30 2009 -0500
convert CRLF to LF
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
index a7c0cbc..2c47b0a 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
@@ -1,397 +1,397 @@
-<%@ page import="java.io.ByteArrayOutputStream" %>
-<%@ page import="java.io.PrintStream" %>
-
-<%@ page import="org.rhq.core.domain.auth.Subject" %>
-<%@ page import="org.rhq.core.domain.util.PersistenceUtility" %>
-
-<%@ page import="org.rhq.enterprise.gui.legacy.util.SessionUtils"%>
-<%@ page import="org.rhq.enterprise.gui.util.WebUtility"%>
-
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences" %>
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences.MetricRangePreferences" %>
-
-<%@ page import="org.rhq.enterprise.server.test.CoreTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.DiscoveryTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.MeasurementTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.SubjectRoleTestBeanLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.AlertTemplateTestLocal" %>
-<%@ page import="org.rhq.enterprise.server.cloud.instance.ServerManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementBaselineManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.core.AgentManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.system.SystemManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.auth.SubjectManagerLocal" %>
-<%@ page import="org.rhq.enterprise.server.support.SupportManagerLocal" %>
-<%@page import="org.rhq.enterprise.server.plugin.ServerPluginsLocal"%><html>
-<%@ page import="org.rhq.enterprise.server.util.LookupUtil" %>
-<%@ page import="org.rhq.enterprise.server.scheduler.jobs.DataPurgeJob"%>
-
-<%@ page import="org.rhq.enterprise.server.resource.ResourceTypeManagerRemote"%>
-<%@ page import="org.rhq.core.domain.criteria.ResourceTypeCriteria"%>
-<%@ page import="org.rhq.core.domain.resource.ResourceType"%>
-
-<%@ page import="javax.naming.NamingException" %>
-
-<%@ page contentType="text/html;charset=UTF-8" language="java" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-
-<html>
-<head><title>RHQ Test Control Page</title></head>
-<body>
-
-<jsp:include page="/admin/include/adminTestLinks.html" flush="true" />
-
-<%
- CoreTestLocal coreTestBean;
- DiscoveryTestLocal discoveryTestBean;
- MeasurementTestLocal measurementTestBean;
- ResourceGroupTestBeanLocal resourceGroupTestBean;
- SubjectRoleTestBeanLocal subjectRoleTestBean;
- ServerManagerLocal serverManager;
- AlertTemplateTestLocal alertTemplateTestBean;
- MeasurementBaselineManagerLocal measurementBaselineManager;
- MeasurementScheduleManagerLocal measurementScheduleManager;
- AgentManagerLocal agentManager;
- SystemManagerLocal systemManager;
- SubjectManagerLocal subjectManager;
- SupportManagerLocal supportManager;
- ResourceTypeManagerRemote typeManager;
- ServerPluginsLocal serverPlugins;
-
- coreTestBean = LookupUtil.getCoreTest();
- discoveryTestBean = LookupUtil.getDiscoveryTest();
- measurementTestBean = LookupUtil.getMeasurementTest();
- resourceGroupTestBean = LookupUtil.getResourceGroupTestBean();
- subjectRoleTestBean = LookupUtil.getSubjectRoleTestBean();
- serverManager = LookupUtil.getServerManager();
- alertTemplateTestBean = LookupUtil.getAlertTemplateTestBean();
- measurementBaselineManager = LookupUtil.getMeasurementBaselineManager();
- measurementScheduleManager = LookupUtil.getMeasurementScheduleManager();
- agentManager = LookupUtil.getAgentManager();
- systemManager = LookupUtil.getSystemManager();
- subjectManager = LookupUtil.getSubjectManager();
- supportManager = LookupUtil.getSupportManager();
- typeManager = LookupUtil.getResourceTypeManagerRemote();
- serverPlugins = LookupUtil.getServerPlugins();
-
- String result = null;
- String mode = pageContext.getRequest().getParameter("mode");
- String failure = null;
- try
- {
- if ("registerTestAgent".equals(mode))
- {
- coreTestBean.registerTestAgent();
- }
- else if ("registerTestPluginAndTypeInfo".equals(mode))
- {
- discoveryTestBean.registerTestPluginAndTypeInfo();
- }
- else if ("removeTestPluginAndTypeInfo".equals(mode))
- {
- discoveryTestBean.removeTestPluginAndTypeInfo();
- }
- else if ("sendTestFullInventoryReport".equals(mode))
- {
- discoveryTestBean.sendTestFullInventoryReport();
- }
- else if ("sendTestRuntimeInventoryReport".equals(mode))
- {
- discoveryTestBean.sendTestRuntimeInventoryReport();
- }
- else if ("sendTestMeasurementReport".equals(mode))
- {
- measurementTestBean.sendTestMeasurementReport();
- }
- else if ("sendNewPlatform".equals(mode))
- {
- String address = request.getParameter("address");
- int servers = Integer.parseInt(request.getParameter("servers"));
- int servicesPerServer = Integer.parseInt(request.getParameter("servicesPerServer"));
- discoveryTestBean.sendNewPlatform(address, servers, servicesPerServer);
- }
- else if ("setupCompatibleGroups".equals(mode))
- {
- resourceGroupTestBean.setupCompatibleGroups();
- }
- else if ("setupUberMixedGroup".equals(mode))
- {
- resourceGroupTestBean.setupUberMixedGroup();
- }
- else if ("startStats".equals(mode))
- {
- coreTestBean.enableHibernateStatistics();
- }
- else if ("addProblemResource".equals(mode))
- {
- measurementTestBean.addProblemResource();
- }
- else if ("setAgentCurrentlyScheduledMetrics".equals(mode))
- {
- String value = pageContext.getRequest().getParameter("v");
- measurementTestBean.setAgentCurrentlyScheduledMetrics(Double.valueOf(value));
- }
- else if ("addSubjectsAndRoles".equals(mode))
- {
- String roleCount = pageContext.getRequest().getParameter("roleCount");
- String usersInRoleCount = pageContext.getRequest().getParameter("usersInRoleCount");
- subjectRoleTestBean.createRolesAndUsers(Integer.parseInt(roleCount), Integer.parseInt(usersInRoleCount));
- }
- else if ("clusterGetIdentity".equals(mode))
- {
- String serverName = serverManager.getIdentity();
- pageContext.setAttribute("serverName", "(serverName = " + serverName + ")");
- }
- else if ("cloneAlertTemplate".equals(mode))
- {
- String alertTemplateId = pageContext.getRequest().getParameter("alertTemplateId");
- String numberOfClones = pageContext.getRequest().getParameter("numberOfClones");
- alertTemplateTestBean.cloneAlertTemplate(Integer.parseInt(alertTemplateId), Integer.parseInt(numberOfClones));
- }
- else if ("calculateAutoBaselines".equals(mode))
- {
- // for now, baselines aren't calculated until we hit our day limit, we force it here
- java.util.Properties props = systemManager.getSystemConfiguration();
- props.put("CAM_BASELINE_LASTTIME", "0");
- systemManager.setSystemConfiguration(subjectManager.getOverlord(), props,true);
-
- measurementBaselineManager.calculateAutoBaselines();
- }
- else if ("calculateOOBs".equals(mode))
- {
- DataPurgeJob dpj = new DataPurgeJob();
- dpj.calculateOOBs();
- }
- else if ("checkForSuspectAgents".equals(mode))
- {
- agentManager.checkForSuspectAgents();
- }
- else if ("dataPurgeJob".equals(mode))
- {
- DataPurgeJob.purgeNow();
- }
- else if ("dbMaintenance".equals(mode))
- {
- systemManager.vacuum(subjectManager.getOverlord());
- systemManager.reindex(subjectManager.getOverlord());
- systemManager.analyze(subjectManager.getOverlord());
- }
- else if ("metricDisplayRange".equals(mode))
- {
- int lastHours = Integer.parseInt(pageContext.getRequest().getParameter("lastHours"));
- Subject subject = WebUtility.getSubject(request);
- MeasurementPreferences prefs = new MeasurementPreferences(subject);
- MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
- rangePrefs.lastN = lastHours;
- prefs.setMetricRangePreferences(rangePrefs);
- }
- else if ("errorCorrectSchedules".equals("mode"))
- {
- measurementScheduleManager.errorCorrectSchedules();
- }
- else if ("generateSnapshotReport".equals(mode))
- {
- int resourceId = Integer.parseInt(request.getParameter("resourceId"));
- String name = request.getParameter("name");
- String description = request.getParameter("description");
- java.net.URL url = supportManager.getSnapshotReport(subjectManager.getOverlord(), resourceId, name, description);
- result = "Snapshot Report is located here: " + url.toString();
- }
- else if ("purgeServerPlugin".equals(mode))
- {
- String serverPluginName = request.getParameter("serverPluginName");
- serverPlugins.purgeServerPlugin(subjectManager.getOverlord(), serverPluginName);
- result = "OK - you can now try to re-register a plugin with the name [" + serverPluginName + "]";
- }
- else if ("typeManagerRemote".equals(mode))
- {
- int typeId = Integer.parseInt(request.getParameter("typeId"));
- ResourceTypeCriteria criteria = new ResourceTypeCriteria();
- criteria.addFilterId(typeId);
- criteria.fetchMetricDefinitions(true);
- java.util.List<ResourceType> types = typeManager.findResourceTypesByCriteria(subjectManager.getOverlord(), criteria);
- result = "";
- for (ResourceType type : types) {
- result += type.getName() + " has " + (type.getMetricDefinitions() != null ? type.getMetricDefinitions().size() : "empty") + " metric definitions";
- }
- }
- }
- catch (Exception e)
- {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- e.printStackTrace(new PrintStream(baos));
- failure = baos.toString();
- }
-
- pageContext.setAttribute("executed", mode);
- pageContext.setAttribute("result", result);
- pageContext.setAttribute("failure", failure);
- pageContext.setAttribute("testAgentReported", Boolean.valueOf(coreTestBean.isTestAgentReported()));
-
-%>
-
-<c:if test="${executed != null}">
- <b>Executed <c:out value="${executed}"/>: </b> <c:out value="${result}"/><br>
- <c:if test="${failure != null}">
- <pre style="background-color: yellow;"><c:out value="${failure}"/></pre>
- </c:if>
-</c:if>
-
-<h2>Administration</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
-Add Lots of Users and Roles
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="addSubjectsAndRoles"/>
- Number of Roles: <input type="text" name="roleCount" size="5"/><br/>
- Number of Users in each Role: <input type="text" name="usersInRoleCount" size="5"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
- <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
-</ul>
-
-<h2>Core</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestAgent"/>
- <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
- <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=dbMaintenance"/>
- <a href="<c:out value="${url}"/>">Perform All Database Maintenance Now</a></li>
-</ul>
-
-<h2>Cluster</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=clusterGetIdentity"/>
- <a href="<c:out value="${url}"/>">Get Identity</a> <c:out value="${serverName}"/></li>
-</ul>
-
-<h2>Inventory</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestFullInventoryReport"/>
- <a href="<c:out value="${url}"/>">Send Full Inventory Report</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestRuntimeInventoryReport"/>
- <a href="<c:out value="${url}"/>">Send Runtime Inventory Report</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setupCompatibleGroups"/>
- <a href="<c:out value="${url}"/>">Setup Compatible Groups</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setupUberMixedGroup"/>
- <a href="<c:out value="${url}"/>">Setup Uber Mixed Group</a></li>
-</ul>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=sendNewPlatform"/>
-Send New Platform Inventory Report
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="sendNewPlatform"/>
- Address: <input type="text" name="address" size="30"/><br/>
- Servers: <input type="text" name="servers" size="5"/><br/>
- Services Per Server: <input type="text" name="servicesPerServer" size="5"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-
-<h2>Measurement</h2>
-
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateAutoBaselines"/>
- <a href="<c:out value="${url}"/>">Calculate Auto Baselines</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestMeasurementReport"/>
- <a href="<c:out value="${url}"/>">Send Measurement Report</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=addProblemResource"/>
- <a href="<c:out value="${url}"/>">Add problem Resource</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=100"/>
- <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 100</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=50"/>
- <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 50</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=checkForSuspectAgents"/>
- <a href="<c:out value="${url}"/>">Check For Suspect Agents</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=dataPurgeJob"/>
- <a href="<c:out value="${url}"/>">Force Data Purge Now</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateOOBs"/>
- <a href="<c:out value="${url}"/>">Force calculation of OOBs</a></li>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=errorCorrectSchedules"/>
- <a href="<c:out value="${url}"/>">Error-Correct Measurement Schedules</a></li>
-</ul>
-
-<h2>Alerts</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=cloneAlertTemplate"/>
-Template Cloning
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="cloneAlertTemplate"/>
- Alert Template ID: <input type="text" name="alertTemplateId" size="5"/><br/>
- Number of Clones: <input type="text" name="numberOfClones" size="5"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-<h2>Utilities</h2>
-<ul>
- <li><c:url var="url" value="/admin/test/control.jsp?mode=startStats"/>
- <a href="<c:out value="${url}"/>">Start Hibernate Statistics Collection</a></li>
-</ul>
-
-
-<h2>User Preferences</h2>
-<%
- Subject subject = WebUtility.getSubject(request);
- MeasurementPreferences prefs = new MeasurementPreferences(subject);
- MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
- pageContext.setAttribute("lastHours", String.valueOf(rangePrefs.lastN));
-%>
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="metricDisplayRange"/>
- Last X hours: <input type="text" name="lastHours" size="5" value="<c:out value="${lastHours}"/>"/><br/>
- <input type="submit" value="Send" name="Send"/>
-</form>
-
-<h2>Snapshot Report</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=generateSnapshotReport"/>
-Generate Snapshot Report
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="generateSnapshotReport"/>
- Resource ID: <input type="text" name="resourceId" size="10"/><br/>
- Name: <input type="text" name="name" size="30"/><br/>
- Description: <input type="text" name="description" size="100"/><br/>
- <input type="submit" value="Generate Snapshot" name="Generate Snapshot"/>
-</form>
-
-<h2>Server Plugins</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=purgeServerPlugin"/>
-Purge Server Plugin (allowing you to re-register it again later)
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="purgeServerPlugin"/>
- ServerPluginName: <input type="text" name="serverPluginName" size="30"/><br/>
- <input type="submit" value="Purge Server Plugin" name="Purge Server Plugin"/>
-</form>
-
-<h2>Resource Type Criteria</h2>
-
-<c:url var="url" value="/admin/test/control.jsp?mode=typeManagerRemote"/>
-Query ResourceTypes by Criteria
-<form action="<c:out value="${url}"/>" method="get">
- <input type="hidden" name="mode" value="typeManagerRemote"/>
- ResourceType ID: <input type="text" name="typeId" size="10"/><br/>
- <input type="submit" value="Query by Criteria" name="Query by Criteria"/>
-</form>
-
-
-
-</body>
-</html>
+<%@ page import="java.io.ByteArrayOutputStream" %>
+<%@ page import="java.io.PrintStream" %>
+
+<%@ page import="org.rhq.core.domain.auth.Subject" %>
+<%@ page import="org.rhq.core.domain.util.PersistenceUtility" %>
+
+<%@ page import="org.rhq.enterprise.gui.legacy.util.SessionUtils"%>
+<%@ page import="org.rhq.enterprise.gui.util.WebUtility"%>
+
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences" %>
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementPreferences.MetricRangePreferences" %>
+
+<%@ page import="org.rhq.enterprise.server.test.CoreTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.DiscoveryTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.MeasurementTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.SubjectRoleTestBeanLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.AlertTemplateTestLocal" %>
+<%@ page import="org.rhq.enterprise.server.cloud.instance.ServerManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.test.ResourceGroupTestBeanLocal" %>
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementBaselineManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.measurement.MeasurementScheduleManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.core.AgentManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.system.SystemManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.auth.SubjectManagerLocal" %>
+<%@ page import="org.rhq.enterprise.server.support.SupportManagerLocal" %>
+<%@page import="org.rhq.enterprise.server.plugin.ServerPluginsLocal"%><html>
+<%@ page import="org.rhq.enterprise.server.util.LookupUtil" %>
+<%@ page import="org.rhq.enterprise.server.scheduler.jobs.DataPurgeJob"%>
+
+<%@ page import="org.rhq.enterprise.server.resource.ResourceTypeManagerRemote"%>
+<%@ page import="org.rhq.core.domain.criteria.ResourceTypeCriteria"%>
+<%@ page import="org.rhq.core.domain.resource.ResourceType"%>
+
+<%@ page import="javax.naming.NamingException" %>
+
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
+<html>
+<head><title>RHQ Test Control Page</title></head>
+<body>
+
+<jsp:include page="/admin/include/adminTestLinks.html" flush="true" />
+
+<%
+ CoreTestLocal coreTestBean;
+ DiscoveryTestLocal discoveryTestBean;
+ MeasurementTestLocal measurementTestBean;
+ ResourceGroupTestBeanLocal resourceGroupTestBean;
+ SubjectRoleTestBeanLocal subjectRoleTestBean;
+ ServerManagerLocal serverManager;
+ AlertTemplateTestLocal alertTemplateTestBean;
+ MeasurementBaselineManagerLocal measurementBaselineManager;
+ MeasurementScheduleManagerLocal measurementScheduleManager;
+ AgentManagerLocal agentManager;
+ SystemManagerLocal systemManager;
+ SubjectManagerLocal subjectManager;
+ SupportManagerLocal supportManager;
+ ResourceTypeManagerRemote typeManager;
+ ServerPluginsLocal serverPlugins;
+
+ coreTestBean = LookupUtil.getCoreTest();
+ discoveryTestBean = LookupUtil.getDiscoveryTest();
+ measurementTestBean = LookupUtil.getMeasurementTest();
+ resourceGroupTestBean = LookupUtil.getResourceGroupTestBean();
+ subjectRoleTestBean = LookupUtil.getSubjectRoleTestBean();
+ serverManager = LookupUtil.getServerManager();
+ alertTemplateTestBean = LookupUtil.getAlertTemplateTestBean();
+ measurementBaselineManager = LookupUtil.getMeasurementBaselineManager();
+ measurementScheduleManager = LookupUtil.getMeasurementScheduleManager();
+ agentManager = LookupUtil.getAgentManager();
+ systemManager = LookupUtil.getSystemManager();
+ subjectManager = LookupUtil.getSubjectManager();
+ supportManager = LookupUtil.getSupportManager();
+ typeManager = LookupUtil.getResourceTypeManagerRemote();
+ serverPlugins = LookupUtil.getServerPlugins();
+
+ String result = null;
+ String mode = pageContext.getRequest().getParameter("mode");
+ String failure = null;
+ try
+ {
+ if ("registerTestAgent".equals(mode))
+ {
+ coreTestBean.registerTestAgent();
+ }
+ else if ("registerTestPluginAndTypeInfo".equals(mode))
+ {
+ discoveryTestBean.registerTestPluginAndTypeInfo();
+ }
+ else if ("removeTestPluginAndTypeInfo".equals(mode))
+ {
+ discoveryTestBean.removeTestPluginAndTypeInfo();
+ }
+ else if ("sendTestFullInventoryReport".equals(mode))
+ {
+ discoveryTestBean.sendTestFullInventoryReport();
+ }
+ else if ("sendTestRuntimeInventoryReport".equals(mode))
+ {
+ discoveryTestBean.sendTestRuntimeInventoryReport();
+ }
+ else if ("sendTestMeasurementReport".equals(mode))
+ {
+ measurementTestBean.sendTestMeasurementReport();
+ }
+ else if ("sendNewPlatform".equals(mode))
+ {
+ String address = request.getParameter("address");
+ int servers = Integer.parseInt(request.getParameter("servers"));
+ int servicesPerServer = Integer.parseInt(request.getParameter("servicesPerServer"));
+ discoveryTestBean.sendNewPlatform(address, servers, servicesPerServer);
+ }
+ else if ("setupCompatibleGroups".equals(mode))
+ {
+ resourceGroupTestBean.setupCompatibleGroups();
+ }
+ else if ("setupUberMixedGroup".equals(mode))
+ {
+ resourceGroupTestBean.setupUberMixedGroup();
+ }
+ else if ("startStats".equals(mode))
+ {
+ coreTestBean.enableHibernateStatistics();
+ }
+ else if ("addProblemResource".equals(mode))
+ {
+ measurementTestBean.addProblemResource();
+ }
+ else if ("setAgentCurrentlyScheduledMetrics".equals(mode))
+ {
+ String value = pageContext.getRequest().getParameter("v");
+ measurementTestBean.setAgentCurrentlyScheduledMetrics(Double.valueOf(value));
+ }
+ else if ("addSubjectsAndRoles".equals(mode))
+ {
+ String roleCount = pageContext.getRequest().getParameter("roleCount");
+ String usersInRoleCount = pageContext.getRequest().getParameter("usersInRoleCount");
+ subjectRoleTestBean.createRolesAndUsers(Integer.parseInt(roleCount), Integer.parseInt(usersInRoleCount));
+ }
+ else if ("clusterGetIdentity".equals(mode))
+ {
+ String serverName = serverManager.getIdentity();
+ pageContext.setAttribute("serverName", "(serverName = " + serverName + ")");
+ }
+ else if ("cloneAlertTemplate".equals(mode))
+ {
+ String alertTemplateId = pageContext.getRequest().getParameter("alertTemplateId");
+ String numberOfClones = pageContext.getRequest().getParameter("numberOfClones");
+ alertTemplateTestBean.cloneAlertTemplate(Integer.parseInt(alertTemplateId), Integer.parseInt(numberOfClones));
+ }
+ else if ("calculateAutoBaselines".equals(mode))
+ {
+ // for now, baselines aren't calculated until we hit our day limit, we force it here
+ java.util.Properties props = systemManager.getSystemConfiguration();
+ props.put("CAM_BASELINE_LASTTIME", "0");
+ systemManager.setSystemConfiguration(subjectManager.getOverlord(), props,true);
+
+ measurementBaselineManager.calculateAutoBaselines();
+ }
+ else if ("calculateOOBs".equals(mode))
+ {
+ DataPurgeJob dpj = new DataPurgeJob();
+ dpj.calculateOOBs();
+ }
+ else if ("checkForSuspectAgents".equals(mode))
+ {
+ agentManager.checkForSuspectAgents();
+ }
+ else if ("dataPurgeJob".equals(mode))
+ {
+ DataPurgeJob.purgeNow();
+ }
+ else if ("dbMaintenance".equals(mode))
+ {
+ systemManager.vacuum(subjectManager.getOverlord());
+ systemManager.reindex(subjectManager.getOverlord());
+ systemManager.analyze(subjectManager.getOverlord());
+ }
+ else if ("metricDisplayRange".equals(mode))
+ {
+ int lastHours = Integer.parseInt(pageContext.getRequest().getParameter("lastHours"));
+ Subject subject = WebUtility.getSubject(request);
+ MeasurementPreferences prefs = new MeasurementPreferences(subject);
+ MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
+ rangePrefs.lastN = lastHours;
+ prefs.setMetricRangePreferences(rangePrefs);
+ }
+ else if ("errorCorrectSchedules".equals("mode"))
+ {
+ measurementScheduleManager.errorCorrectSchedules();
+ }
+ else if ("generateSnapshotReport".equals(mode))
+ {
+ int resourceId = Integer.parseInt(request.getParameter("resourceId"));
+ String name = request.getParameter("name");
+ String description = request.getParameter("description");
+ java.net.URL url = supportManager.getSnapshotReport(subjectManager.getOverlord(), resourceId, name, description);
+ result = "Snapshot Report is located here: " + url.toString();
+ }
+ else if ("purgeServerPlugin".equals(mode))
+ {
+ String serverPluginName = request.getParameter("serverPluginName");
+ serverPlugins.purgeServerPlugin(subjectManager.getOverlord(), serverPluginName);
+ result = "OK - you can now try to re-register a plugin with the name [" + serverPluginName + "]";
+ }
+ else if ("typeManagerRemote".equals(mode))
+ {
+ int typeId = Integer.parseInt(request.getParameter("typeId"));
+ ResourceTypeCriteria criteria = new ResourceTypeCriteria();
+ criteria.addFilterId(typeId);
+ criteria.fetchMetricDefinitions(true);
+ java.util.List<ResourceType> types = typeManager.findResourceTypesByCriteria(subjectManager.getOverlord(), criteria);
+ result = "";
+ for (ResourceType type : types) {
+ result += type.getName() + " has " + (type.getMetricDefinitions() != null ? type.getMetricDefinitions().size() : "empty") + " metric definitions";
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ e.printStackTrace(new PrintStream(baos));
+ failure = baos.toString();
+ }
+
+ pageContext.setAttribute("executed", mode);
+ pageContext.setAttribute("result", result);
+ pageContext.setAttribute("failure", failure);
+ pageContext.setAttribute("testAgentReported", Boolean.valueOf(coreTestBean.isTestAgentReported()));
+
+%>
+
+<c:if test="${executed != null}">
+ <b>Executed <c:out value="${executed}"/>: </b> <c:out value="${result}"/><br>
+ <c:if test="${failure != null}">
+ <pre style="background-color: yellow;"><c:out value="${failure}"/></pre>
+ </c:if>
+</c:if>
+
+<h2>Administration</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
+Add Lots of Users and Roles
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="addSubjectsAndRoles"/>
+ Number of Roles: <input type="text" name="roleCount" size="5"/><br/>
+ Number of Users in each Role: <input type="text" name="usersInRoleCount" size="5"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=addSubjectsAndRoles"/>
+ <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
+</ul>
+
+<h2>Core</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestAgent"/>
+ <a href="<c:out value="${url}"/>">Report Test Agent</a> (done = <c:out value="${testAgentReported}"/>)</li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=registerTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Register test plugin metadata</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=removeTestPluginAndTypeInfo"/>
+ <a href="<c:out value="${url}"/>">Remove test plugin metadata</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=dbMaintenance"/>
+ <a href="<c:out value="${url}"/>">Perform All Database Maintenance Now</a></li>
+</ul>
+
+<h2>Cluster</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=clusterGetIdentity"/>
+ <a href="<c:out value="${url}"/>">Get Identity</a> <c:out value="${serverName}"/></li>
+</ul>
+
+<h2>Inventory</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestFullInventoryReport"/>
+ <a href="<c:out value="${url}"/>">Send Full Inventory Report</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestRuntimeInventoryReport"/>
+ <a href="<c:out value="${url}"/>">Send Runtime Inventory Report</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setupCompatibleGroups"/>
+ <a href="<c:out value="${url}"/>">Setup Compatible Groups</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setupUberMixedGroup"/>
+ <a href="<c:out value="${url}"/>">Setup Uber Mixed Group</a></li>
+</ul>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=sendNewPlatform"/>
+Send New Platform Inventory Report
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="sendNewPlatform"/>
+ Address: <input type="text" name="address" size="30"/><br/>
+ Servers: <input type="text" name="servers" size="5"/><br/>
+ Services Per Server: <input type="text" name="servicesPerServer" size="5"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+
+<h2>Measurement</h2>
+
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateAutoBaselines"/>
+ <a href="<c:out value="${url}"/>">Calculate Auto Baselines</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=sendTestMeasurementReport"/>
+ <a href="<c:out value="${url}"/>">Send Measurement Report</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=addProblemResource"/>
+ <a href="<c:out value="${url}"/>">Add problem Resource</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=100"/>
+ <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 100</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=setAgentCurrentlyScheduledMetrics&v=50"/>
+ <a href="<c:out value="${url}"/>">Set RHQ Agent 'CurrentlyScheduleMetrics' to 50</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=checkForSuspectAgents"/>
+ <a href="<c:out value="${url}"/>">Check For Suspect Agents</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=dataPurgeJob"/>
+ <a href="<c:out value="${url}"/>">Force Data Purge Now</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=calculateOOBs"/>
+ <a href="<c:out value="${url}"/>">Force calculation of OOBs</a></li>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=errorCorrectSchedules"/>
+ <a href="<c:out value="${url}"/>">Error-Correct Measurement Schedules</a></li>
+</ul>
+
+<h2>Alerts</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=cloneAlertTemplate"/>
+Template Cloning
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="cloneAlertTemplate"/>
+ Alert Template ID: <input type="text" name="alertTemplateId" size="5"/><br/>
+ Number of Clones: <input type="text" name="numberOfClones" size="5"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+<h2>Utilities</h2>
+<ul>
+ <li><c:url var="url" value="/admin/test/control.jsp?mode=startStats"/>
+ <a href="<c:out value="${url}"/>">Start Hibernate Statistics Collection</a></li>
+</ul>
+
+
+<h2>User Preferences</h2>
+<%
+ Subject subject = WebUtility.getSubject(request);
+ MeasurementPreferences prefs = new MeasurementPreferences(subject);
+ MetricRangePreferences rangePrefs = prefs.getMetricRangePreferences();
+ pageContext.setAttribute("lastHours", String.valueOf(rangePrefs.lastN));
+%>
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="metricDisplayRange"/>
+ Last X hours: <input type="text" name="lastHours" size="5" value="<c:out value="${lastHours}"/>"/><br/>
+ <input type="submit" value="Send" name="Send"/>
+</form>
+
+<h2>Snapshot Report</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=generateSnapshotReport"/>
+Generate Snapshot Report
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="generateSnapshotReport"/>
+ Resource ID: <input type="text" name="resourceId" size="10"/><br/>
+ Name: <input type="text" name="name" size="30"/><br/>
+ Description: <input type="text" name="description" size="100"/><br/>
+ <input type="submit" value="Generate Snapshot" name="Generate Snapshot"/>
+</form>
+
+<h2>Server Plugins</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=purgeServerPlugin"/>
+Purge Server Plugin (allowing you to re-register it again later)
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="purgeServerPlugin"/>
+ ServerPluginName: <input type="text" name="serverPluginName" size="30"/><br/>
+ <input type="submit" value="Purge Server Plugin" name="Purge Server Plugin"/>
+</form>
+
+<h2>Resource Type Criteria</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=typeManagerRemote"/>
+Query ResourceTypes by Criteria
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="typeManagerRemote"/>
+ ResourceType ID: <input type="text" name="typeId" size="10"/><br/>
+ <input type="submit" value="Query by Criteria" name="Query by Criteria"/>
+</form>
+
+
+
+</body>
+</html>
commit f04ef82719012571ecfa157eb270c6b0424ad0ac
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 22 22:39:34 2009 -0500
mistakenly deleted the html tag, put it back
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
index 4d5cfd5..a7c0cbc 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
@@ -38,7 +38,7 @@
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-
+<html>
<head><title>RHQ Test Control Page</title></head>
<body>
commit a5fcd064dc1d1eea47c2806754c3244e1c000235
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Sun Nov 22 01:59:12 2009 -0500
since there is no current way to "revive" a undeployed plugin from the real GUI, at least provide _some_ way to get back to a state that will let you re-register a plugin again using the test control.jsp page
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
index f3f0a35..4d5cfd5 100644
--- a/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
+++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/test/control.jsp
@@ -24,6 +24,7 @@
<%@ page import="org.rhq.enterprise.server.system.SystemManagerLocal" %>
<%@ page import="org.rhq.enterprise.server.auth.SubjectManagerLocal" %>
<%@ page import="org.rhq.enterprise.server.support.SupportManagerLocal" %>
+<%@page import="org.rhq.enterprise.server.plugin.ServerPluginsLocal"%><html>
<%@ page import="org.rhq.enterprise.server.util.LookupUtil" %>
<%@ page import="org.rhq.enterprise.server.scheduler.jobs.DataPurgeJob"%>
@@ -37,7 +38,7 @@
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-<html>
+
<head><title>RHQ Test Control Page</title></head>
<body>
@@ -58,6 +59,7 @@
SubjectManagerLocal subjectManager;
SupportManagerLocal supportManager;
ResourceTypeManagerRemote typeManager;
+ ServerPluginsLocal serverPlugins;
coreTestBean = LookupUtil.getCoreTest();
discoveryTestBean = LookupUtil.getDiscoveryTest();
@@ -73,6 +75,7 @@
subjectManager = LookupUtil.getSubjectManager();
supportManager = LookupUtil.getSupportManager();
typeManager = LookupUtil.getResourceTypeManagerRemote();
+ serverPlugins = LookupUtil.getServerPlugins();
String result = null;
String mode = pageContext.getRequest().getParameter("mode");
@@ -197,6 +200,12 @@
java.net.URL url = supportManager.getSnapshotReport(subjectManager.getOverlord(), resourceId, name, description);
result = "Snapshot Report is located here: " + url.toString();
}
+ else if ("purgeServerPlugin".equals(mode))
+ {
+ String serverPluginName = request.getParameter("serverPluginName");
+ serverPlugins.purgeServerPlugin(subjectManager.getOverlord(), serverPluginName);
+ result = "OK - you can now try to re-register a plugin with the name [" + serverPluginName + "]";
+ }
else if ("typeManagerRemote".equals(mode))
{
int typeId = Integer.parseInt(request.getParameter("typeId"));
@@ -362,6 +371,16 @@ Generate Snapshot Report
<input type="submit" value="Generate Snapshot" name="Generate Snapshot"/>
</form>
+<h2>Server Plugins</h2>
+
+<c:url var="url" value="/admin/test/control.jsp?mode=purgeServerPlugin"/>
+Purge Server Plugin (allowing you to re-register it again later)
+<form action="<c:out value="${url}"/>" method="get">
+ <input type="hidden" name="mode" value="purgeServerPlugin"/>
+ ServerPluginName: <input type="text" name="serverPluginName" size="30"/><br/>
+ <input type="submit" value="Purge Server Plugin" name="Purge Server Plugin"/>
+</form>
+
<h2>Resource Type Criteria</h2>
<c:url var="url" value="/admin/test/control.jsp?mode=typeManagerRemote"/>
14 years, 5 months
[rhq] Branch 'pc' - modules/core modules/enterprise
by mazz
modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java | 20 ---
modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java | 52 +++++---
modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java | 59 ++++------
3 files changed, 58 insertions(+), 73 deletions(-)
New commits:
commit db605e78ebfb82d01f0ce4130f327c45170540c7
Author: John Mazzitelli <mazz(a)redhat.com>
Date: Wed Nov 25 17:18:29 2009 -0500
get rid of the update query we don't need anymore
fix tests so they don't rely on that old update query
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
index eda26d8..4047d10 100644
--- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
+++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/Plugin.java
@@ -187,25 +187,6 @@ import org.rhq.core.util.MessageDigestGenerator;
+ " LEFT JOIN p.scheduledJobsConfiguration " //
+ " WHERE p.deployment = 'SERVER' AND p.status = 'INSTALLED' "), //
- // this query does not update the content blob or ctime
- @NamedQuery(name = Plugin.UPDATE_ALL_BUT_CONTENT, query = "" //
- + "UPDATE Plugin p " //
- + " SET p.name = :name, " //
- + " p.displayName = :displayName, " //
- + " p.description = :description, " //
- + " p.enabled = :enabled, " //
- + " p.status = :status, " //
- + " p.help = :help, " //
- + " p.version = :version, " //
- + " p.ampsVersion = :ampsVersion," //
- + " p.deployment = :deployment, " //
- + " p.pluginConfiguration = :pluginConfiguration, " //
- + " p.scheduledJobsConfiguration = :scheduledJobsConfiguration, " //
- + " p.path = :path, " //
- + " p.md5 = :md5, " //
- + " p.mtime = :mtime " //
- + " WHERE p.id = :id"),
-
// this query is how you enable and disable plugins
@NamedQuery(name = Plugin.UPDATE_PLUGINS_ENABLED_BY_IDS, query = "" //
+ "UPDATE Plugin p " //
@@ -256,7 +237,6 @@ public class Plugin implements Serializable {
public static final String QUERY_FIND_BY_IDS_AND_TYPE = "Plugin.findByIdsAndType";
public static final String QUERY_GET_NAMES_BY_ENABLED_AND_TYPE = "Plugin.findByEnabledAndType";
public static final String QUERY_GET_STATUS_BY_NAME_AND_TYPE = "Plugin.getStatusByNameAndType";
- public static final String UPDATE_ALL_BUT_CONTENT = "Plugin.updateAllButContent";
public static final String UPDATE_PLUGINS_ENABLED_BY_IDS = "Plugin.updatePluginsEnabledByIds";
@Column(name = "ID", nullable = false)
diff --git a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
index 07f8f97..729f7c2 100644
--- a/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
+++ b/modules/core/domain/src/test/java/org/rhq/core/domain/resource/test/PluginTest.java
@@ -131,23 +131,39 @@ public class PluginTest extends AbstractEJB3Test {
em.persist(jobsConfig);
em.flush(); // gotta get those two persists to flush to the DB
- q = em.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
- q.setParameter("id", id); // same as the one we just persisted
- q.setParameter("name", name);
- q.setParameter("path", path);
- q.setParameter("displayName", displayName);
- q.setParameter("enabled", enabled);
- q.setParameter("status", status);
- q.setParameter("md5", md5);
- q.setParameter("version", version);
- q.setParameter("ampsVersion", ampsVersion);
- q.setParameter("deployment", deployment);
- q.setParameter("pluginConfiguration", pluginConfig);
- q.setParameter("scheduledJobsConfiguration", jobsConfig);
- q.setParameter("description", description);
- q.setParameter("help", help);
- q.setParameter("mtime", System.currentTimeMillis());
- assert q.executeUpdate() == 1 : "Failed to update the plugin";
+ // do what ServerPluginsBean/ResourceMetadataManagerBean.updateServerPluginExceptContent does
+ Configuration config = plugin.getPluginConfiguration();
+ if (config != null) {
+ config = em.merge(config);
+ plugin.setPluginConfiguration(config);
+ }
+ config = plugin.getScheduledJobsConfiguration();
+ if (config != null) {
+ config = em.merge(config);
+ plugin.setScheduledJobsConfiguration(config);
+ }
+
+ Plugin pluginEntity = em.getReference(Plugin.class, plugin.getId());
+ pluginEntity.setName(name);
+ pluginEntity.setPath(path);
+ pluginEntity.setDisplayName(displayName);
+ pluginEntity.setEnabled(enabled);
+ pluginEntity.setStatus(status);
+ pluginEntity.setMd5(md5);
+ pluginEntity.setVersion(version);
+ pluginEntity.setAmpsVersion(ampsVersion);
+ pluginEntity.setDeployment(deployment);
+ pluginEntity.setPluginConfiguration(pluginConfig);
+ pluginEntity.setScheduledJobsConfiguration(jobsConfig);
+ pluginEntity.setDescription(description);
+ pluginEntity.setHelp(help);
+ pluginEntity.setMtime(System.currentTimeMillis());
+
+ try {
+ em.flush(); // make sure we push this out to the DB now
+ } catch (Exception e) {
+ throw new Exception("Failed to update a plugin that matches [" + plugin + "]", e);
+ }
em.close();
getTransactionManager().commit(); // must commit now
@@ -163,7 +179,7 @@ public class PluginTest extends AbstractEJB3Test {
assert plugin.isEnabled() == enabled;
assert plugin.getMD5().equals(md5);
assert plugin.getVersion().equals(version);
- q.setParameter("ampsVersion", ampsVersion);
+ assert plugin.getAmpsVersion().equals(ampsVersion);
assert plugin.getDescription().equals(description);
assert plugin.getDeployment() == PluginDeploymentType.SERVER;
assert plugin.getPluginConfiguration().equals(pluginConfig);
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
index 9c971e0..d502f4e 100644
--- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
+++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBean.java
@@ -198,49 +198,38 @@ public class ResourceMetadataManagerBean implements ResourceMetadataManagerLocal
entityManager.persist(plugin);
} else {
// agent plugins don't support these configs, but if/when they do in the future, this will support it
- boolean needFlush = false;
+ // make sure we create (if necessary) and attach the configs
Configuration config = plugin.getPluginConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setPluginConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
+ config = entityManager.merge(config);
+ plugin.setPluginConfiguration(config);
}
config = plugin.getScheduledJobsConfiguration();
if (config != null) {
- if (config.getId() > 0) {
- config = entityManager.getReference(Configuration.class, config.getId());
- plugin.setScheduledJobsConfiguration(config);
- } else {
- entityManager.persist(config);
- needFlush = true;
- }
- }
- if (needFlush) {
- entityManager.flush(); // must be flushed to the DB so the JPQL update below works
+ config = entityManager.merge(config);
+ plugin.setScheduledJobsConfiguration(config);
}
// update all the fields except content
- Query q = entityManager.createNamedQuery(Plugin.UPDATE_ALL_BUT_CONTENT);
- q.setParameter("id", plugin.getId());
- q.setParameter("name", plugin.getName());
- q.setParameter("path", plugin.getPath());
- q.setParameter("displayName", plugin.getDisplayName());
- q.setParameter("enabled", plugin.isEnabled());
- q.setParameter("status", plugin.getStatus());
- q.setParameter("md5", plugin.getMD5());
- q.setParameter("version", plugin.getVersion());
- q.setParameter("ampsVersion", plugin.getAmpsVersion());
- q.setParameter("deployment", plugin.getDeployment());
- q.setParameter("pluginConfiguration", plugin.getPluginConfiguration());
- q.setParameter("scheduledJobsConfiguration", plugin.getScheduledJobsConfiguration());
- q.setParameter("description", plugin.getDescription());
- q.setParameter("help", plugin.getHelp());
- q.setParameter("mtime", plugin.getMtime());
- if (q.executeUpdate() != 1) {
+ Plugin pluginEntity = entityManager.getReference(Plugin.class, plugin.getId());
+ pluginEntity.setName(plugin.getName());
+ pluginEntity.setPath(plugin.getPath());
+ pluginEntity.setDisplayName(plugin.getDisplayName());
+ pluginEntity.setEnabled(plugin.isEnabled());
+ pluginEntity.setStatus(plugin.getStatus());
+ pluginEntity.setMd5(plugin.getMD5());
+ pluginEntity.setVersion(plugin.getVersion());
+ pluginEntity.setAmpsVersion(plugin.getAmpsVersion());
+ pluginEntity.setDeployment(plugin.getDeployment());
+ pluginEntity.setPluginConfiguration(plugin.getPluginConfiguration());
+ pluginEntity.setScheduledJobsConfiguration(plugin.getScheduledJobsConfiguration());
+ pluginEntity.setDescription(plugin.getDescription());
+ pluginEntity.setHelp(plugin.getHelp());
+ pluginEntity.setMtime(plugin.getMtime());
+
+ try {
+ entityManager.flush(); // make sure we push this out to the DB now
+ } catch (Exception e) {
throw new Exception("Failed to update a plugin that matches [" + plugin + "]");
}
}
14 years, 5 months