modules/core/dbutils/src/main/java/org/rhq/core/db/DatabaseType.java | 37 modules/core/dbutils/src/main/java/org/rhq/core/db/ant/DbAntI18NResourceKeys.java | 10 modules/core/dbutils/src/main/java/org/rhq/core/db/ant/dbupgrade/SST_JavaTask.java | 102 ++ modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/CustomAlertSenderUpgradeTask.java | 219 +++++ modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DatabaseUpgradeTask.java | 34 modules/core/dbutils/src/main/resources/db-ant-tasks.properties | 1 modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml | 23 modules/core/dbutils/src/main/scripts/dbsetup/authz-schema.xml | 2 modules/core/dbutils/src/main/scripts/dbsetup/search-data.xml | 8 modules/core/dbutils/src/main/scripts/dbsetup/search-schema.xml | 1 modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml | 180 ++-- modules/core/domain/src/main/java/org/rhq/core/domain/alert/Alert.java | 34 modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java | 4 modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java | 89 -- modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationTemplate.java | 177 ---- modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionEnumeration.java | 16 modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionSimple.java | 20 modules/core/domain/src/main/java/org/rhq/core/domain/criteria/AlertDefinitionCriteria.java | 10 modules/core/domain/src/main/java/org/rhq/core/domain/plugin/AbstractPlugin.java | 3 modules/core/domain/src/main/java/org/rhq/core/domain/search/SavedSearch.java | 39 modules/core/domain/src/main/java/org/rhq/core/domain/search/SearchSubsystem.java | 14 modules/core/domain/src/main/java/org/rhq/core/domain/search/SearchSuggestion.java | 94 ++ modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java | 32 modules/enterprise/gui/alert-migration/README.txt | 18 modules/enterprise/gui/alert-migration/etc/dumpAlertDefinitions.js | 14 modules/enterprise/gui/alert-migration/pom.xml | 254 ----- modules/enterprise/gui/alert-migration/src/main/java/org/rhq/helpers/alertMigration/Alert13Parser.java | 202 ---- modules/enterprise/gui/alert-migration/src/main/java/org/rhq/helpers/alertMigration/MigrationServlet.java | 100 -- modules/enterprise/gui/alert-migration/src/main/java/org/rhq/helpers/alertMigration/RestoreAlerts.java | 71 - modules/enterprise/gui/alert-migration/src/main/webapp/WEB-INF/web.xml | 27 modules/enterprise/gui/alert-migration/src/main/webapp/index.html | 17 modules/enterprise/gui/alert-migration/src/test/java/Alert13ParserTest.java | 83 - modules/enterprise/gui/alert-migration/src/test/resources/alertDef.csv | 13 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java | 66 - modules/enterprise/gui/pom.xml | 1 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/alert/AlertNotificationTemplateDetailsUIBean.java | 90 -- modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/alert/ListAlertNotificationTemplatesUIBean.java | 76 - modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/alert/NewAlertNotificationTemplateUIBean.java | 86 -- modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsAction.java | 8 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsFormPrepareAction.java | 143 +++ modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/RemoveLdapGroupsAction.java | 6 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/ViewAction.java | 13 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/user/RegisterAction.java | 44 - modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/AlertNotificationStoreUIBean.java | 72 - modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/AlertNotificationsUIBean.java | 26 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/CustomContentUIBean.java | 6 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/DefinitionNotificationsUIBean.java | 105 -- modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/framework/UserPreferencesUIBean.java | 62 + modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PagedListDataModel.java | 4 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java | 6 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/NewGroupDefinitionGeneralPropertiesUIBean.java | 2 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/inventory/browse/BrowseGroupsUIBean.java | 29 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/inventory/browse/BrowseResourcesUIBean.java | 48 - modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/WebUserPreferences.java | 10 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/AckAlertAction.java | 19 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/hub/ResourceHubPortalAction.java | 40 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/startup/StartupServlet.java | 11 modules/enterprise/gui/portal-war/src/main/webapp/admin/role/AddLdapRoleGroups.jsp | 2 modules/enterprise/gui/portal-war/src/main/webapp/admin/role/RoleLdapGroupsForm.jsp | 263 ++++++ modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/alert/template/notification/details.xhtml | 136 --- modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/alert/template/notification/list.xhtml | 146 --- modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/alert/template/notification/new.xhtml | 74 - modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/alert/notification/details.xhtml | 84 - modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/menu/menu.xhtml | 23 modules/enterprise/gui/portal-war/src/main/webapp/rhq/definition/group/list.xhtml | 2 modules/enterprise/gui/portal-war/src/main/webapp/rhq/inventory/browseGroups.xhtml | 8 modules/enterprise/gui/portal-war/src/main/webapp/rhq/inventory/browseResources.xhtml | 46 - modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listAlertHistory.xhtml | 6 modules/enterprise/server/ear/pom.xml | 14 modules/enterprise/server/jar/src/main/antlr3/org/rhq/enterprise/server/search/RHQL.g | 3 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java | 168 +-- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerLocal.java | 7 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java | 255 ----- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerLocal.java | 80 - modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java | 103 -- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerLocal.java | 11 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java | 54 - modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java | 10 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/CustomAlertSenderBackingBean.java | 9 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManager.java | 302 ------- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java | 426 ++++++++++ modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerLocal.java | 53 + modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/SavedSearchResultCountRecalculationJob.java | 101 ++ modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/AbstractSearchAssistant.java | 12 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/ResourceSearchAssistant.java | 2 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/SearchAssistant.java | 10 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchAssistManager.java | 115 ++ modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchSuggestion.java | 52 - modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchTranslationManager.java | 26 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/translation/SearchTranslatorFactory.java | 2 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java | 26 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/LookupUtil.java | 6 modules/enterprise/server/jar/src/main/resources/single-line-rhql.txt | 10 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/authz/test/RoleManagerBeanTest.java | 5 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/SubcategoryTest.java | 18 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java | 321 +++---- modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateEventsSubsystemTest.java | 17 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateSubsytemTestBase.java | 4 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/GenericSearchAssistTest.java | 5 modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/TestAutoCompletionManager.java | 8 modules/enterprise/server/jar/src/test/resources/log4j.xml | 5 modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsBackingBean.java | 21 modules/plugins/postgres/src/main/java/org/rhq/plugins/postgres/PostgresTableComponent.java | 10 modules/plugins/sshd/src/main/java/org/rhq/plugins/sshd/OpenSSHDComponent.java | 2 104 files changed, 2542 insertions(+), 3442 deletions(-)
New commits: commit de211f8fc7cbee6258b7dde44a602e9734036b23 Author: John Sanda jsanda@redhat.com Date: Wed Apr 28 16:09:48 2010 -0400
[BZ 544353] Modifying ui backing bean for edit page so stale values are not used
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java index 09837ec..262c173 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/EditGroupDefinitionGeneralPropertiesUIBean.java @@ -103,6 +103,8 @@ public class EditGroupDefinitionGeneralPropertiesUIBean { }
public String update() { + HttpSession session = FacesContextUtility.getRequest().getSession(); + try { GroupDefinition groupDefinition = GroupDefinitionUIBean.lookupGroupDefinition();
@@ -120,8 +122,6 @@ public class EditGroupDefinitionGeneralPropertiesUIBean { groupDefinition.setExpression(expression.replaceAll("\r", "\n").replaceAll("\f", "\n").replaceAll("\n+", "\n"));
- HttpSession session = FacesContextUtility.getRequest().getSession(); - session.setAttribute(TEMPORARY_EDIT_MARKER, "marker"); session.setAttribute(TEMPORARY_EXPRESSION_ATTRIBUTE, expression); session.setAttribute(TEMPORARY_NAME_ATTRIBUTE, name); @@ -148,6 +148,8 @@ public class EditGroupDefinitionGeneralPropertiesUIBean { return OUTCOME_FAILURE; }
+ session.removeAttribute(TEMPORARY_EDIT_MARKER); + FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "General properties updated."); return OUTCOME_SUCCESS; } diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/NewGroupDefinitionGeneralPropertiesUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/NewGroupDefinitionGeneralPropertiesUIBean.java index ef3c90d..587ed1b 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/NewGroupDefinitionGeneralPropertiesUIBean.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/definition/group/NewGroupDefinitionGeneralPropertiesUIBean.java @@ -99,7 +99,7 @@ public class NewGroupDefinitionGeneralPropertiesUIBean { return OUTCOME_FAILURE; }
- session.setAttribute(TEMPORARY_CREATE_MARKER, null); + session.removeAttribute(TEMPORARY_CREATE_MARKER);
FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Definition created successfully. Add conditions below.");
commit 303467aeda8d90b48cb68581d53211c774a82fd5 Author: Joseph Marques joseph@redhat.com Date: Wed Apr 28 10:06:54 2010 -0400
BA-586918 - fix for ClassCastException when using AlertDefinitionCriteria when filtering by either alertTemplateParentId or alertTemplateResourceTypeId
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/AlertDefinitionCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/AlertDefinitionCriteria.java index c3992cb..e553ca8 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/AlertDefinitionCriteria.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/AlertDefinitionCriteria.java @@ -29,8 +29,8 @@ import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement;
-import org.rhq.core.domain.alert.AlertPriority; import org.rhq.core.domain.alert.AlertDefinition; +import org.rhq.core.domain.alert.AlertPriority; import org.rhq.core.domain.util.PageOrdering;
/** @@ -46,8 +46,8 @@ public class AlertDefinitionCriteria extends Criteria { private String filterName; private String filterDescription; private AlertPriority filterPriority; - private String filterAlertTemplateParentId; // requires overrides - private String filterAlertTemplateResourceTypeId; // requires overrides + private Integer filterAlertTemplateParentId; // requires overrides + private Integer filterAlertTemplateResourceTypeId; // requires overrides private String filterAlertTemplateResourceTypeName; // requires overrides private List<Integer> filterResourceIds; // requires overrides private Boolean filterEnabled; @@ -90,11 +90,11 @@ public class AlertDefinitionCriteria extends Criteria { this.filterPriority = filterPriority; }
- public void addFilterAlertTemplateParentId(String filterAlertTemplateParentId) { + public void addFilterAlertTemplateParentId(Integer filterAlertTemplateParentId) { this.filterAlertTemplateParentId = filterAlertTemplateParentId; }
- public void addFilterAlertTemplateResourceTypeId(String filterAlertTemplateResourceTypeId) { + public void addFilterAlertTemplateResourceTypeId(Integer filterAlertTemplateResourceTypeId) { this.filterAlertTemplateResourceTypeId = filterAlertTemplateResourceTypeId; }
commit 1851fe41127d4fb136b88184189efc37439f8677 Author: Joseph Marques joseph@redhat.com Date: Wed Apr 28 03:12:49 2010 -0400
BZ-586676: fix for alert>history sub-tab as a result of changes to dbsetup
* alert entity no longer refers to the subject entity via foreign key relationship, update Facelet accordingly
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listAlertHistory.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listAlertHistory.xhtml index b708ab7..0d0a46d 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listAlertHistory.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listAlertHistory.xhtml @@ -174,16 +174,16 @@ <f:facet name="header"> <h:outputText styleClass="headerText" value="Ack by" /> </f:facet> - <h:outputText value="#{item.alert.ackBy.name}" title="#{item.alert.ackBy.firstName} #{item.alert.ackBy.lastName}"/> + <h:outputText value="#{item.alert.acknowledgingSubject}" /> </rich:column>
rich:column <f:facet name="header"> - <onc:sortableColumnHeader sort="a.ackTime"> + <onc:sortableColumnHeader sort="a.acknowledgeTime"> <h:outputText styleClass="headerText" value="Ack date" /> </onc:sortableColumnHeader> </f:facet> - <h:outputText value="#{item.alert.ackTime}"> + <h:outputText value="#{item.alert.acknowledgeTime}"> <f:converter converterId="RelativeDurationConverter" /> </h:outputText> </rich:column>
commit 605b051d37b98be46f183e3d2bce214d256507f5 Author: Joseph Marques joseph@redhat.com Date: Wed Apr 28 01:29:18 2010 -0400
move logging message to DEBUG level
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/WebUserPreferences.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/WebUserPreferences.java index c0abd7e..e2414a7 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/WebUserPreferences.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/WebUserPreferences.java @@ -777,7 +777,7 @@ public class WebUserPreferences extends SubjectPreferencesBase { pageControlProperties.add(field.getOrdering().toString()); pageControlProperties.add(field.getField()); } - System.out.println("setPageControl(" + view + ", " + pageControl + ")"); + log.debug("setPageControl(" + view + ", " + pageControl + ")");
setPreference(view.toString(), pageControlProperties); }
commit 20fe0ece0175e24f2a8905c3a666011802decea5 Author: Simeon Pinder spinder@redhat.com Date: Tue Apr 27 18:44:32 2010 -0400
BZ 584355: i)refactored ldap auth classes to be more consitently defined.ii)modified exception handling.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsAction.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsAction.java index fe91d46..036f8c1 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsAction.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsAction.java @@ -35,13 +35,16 @@ import org.rhq.enterprise.gui.legacy.action.BaseAction; import org.rhq.enterprise.gui.legacy.action.BaseValidatorForm; import org.rhq.enterprise.gui.legacy.util.RequestUtils; import org.rhq.enterprise.gui.legacy.util.SessionUtils; -import org.rhq.enterprise.server.authz.RoleManagerLocal; +import org.rhq.enterprise.server.resource.group.LdapGroupManagerLocal; import org.rhq.enterprise.server.util.LookupUtil;
/** * An Action that adds resource groups for a role. */ public class AddLdapGroupsAction extends BaseAction { + + LdapGroupManagerLocal ldapManager = LookupUtil.getLdapGroupManager(); + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { Log log = LogFactory.getLog(AddLdapGroupsAction.class.getName()); @@ -75,8 +78,7 @@ public class AddLdapGroupsAction extends BaseAction { log.debug("adding group [" + id + "] for role [" + roleId + "]"); }
- RoleManagerLocal roleManager = LookupUtil.getRoleManager(); - roleManager.addLdapGroupsToRole(RequestUtils.getSubject(request), roleId, pendingGroupIds); + ldapManager.addLdapGroupsToRole(RequestUtils.getSubject(request), roleId, pendingGroupIds);
log.debug("removing pending group list"); SessionUtils.removeList(session, Constants.PENDING_RESGRPS_SES_ATTR); diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsFormPrepareAction.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsFormPrepareAction.java index 39fe62e..6cbbfce 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsFormPrepareAction.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsFormPrepareAction.java @@ -28,6 +28,7 @@ import java.util.Properties; import java.util.Set; import java.util.TreeMap;
+import javax.ejb.EJBException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;
@@ -55,7 +56,7 @@ import org.rhq.enterprise.server.RHQConstants; import org.rhq.enterprise.server.authz.RoleManagerLocal; import org.rhq.enterprise.server.exception.LdapCommunicationException; import org.rhq.enterprise.server.exception.LdapFilterException; -import org.rhq.enterprise.server.resource.group.LdapGroupManager; +import org.rhq.enterprise.server.resource.group.LdapGroupManagerLocal; import org.rhq.enterprise.server.system.SystemManagerLocal; import org.rhq.enterprise.server.util.LookupUtil;
@@ -65,6 +66,9 @@ import org.rhq.enterprise.server.util.LookupUtil; public class AddLdapGroupsFormPrepareAction extends TilesAction { final String LDAP_GROUP_CACHE = "ldapGroupCache";
+ RoleManagerLocal roleManager = LookupUtil.getRoleManager(); + LdapGroupManagerLocal ldapManager = LookupUtil.getLdapGroupManager(); + public ActionForward execute(ComponentContext context, ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { Log log = LogFactory.getLog(AddLdapGroupsFormPrepareAction.class.getName()); @@ -111,16 +115,16 @@ public class AddLdapGroupsFormPrepareAction extends TilesAction { try { //defend against ldap communication runtime difficulties.
if (cachedAvailableLdapGroups == null) { - allGroups = LdapGroupManager.getInstance().findAvailableGroups(); + // allGroups = LdapGroupManagerBean.getInstance().findAvailableGroups(); + allGroups = ldapManager.findAvailableGroups(); } else {//reuse cached. allGroups = cachedAvailableLdapGroups; } //store unmodified list in session. cachedAvailableLdapGroups = allGroups;
- RoleManagerLocal roleManager = LookupUtil.getRoleManager(); //retrieve currently assigned groups - assignedList = roleManager.findLdapGroupsByRole(role.getId(), PageControl.getUnlimitedInstance()); + assignedList = ldapManager.findLdapGroupsByRole(role.getId(), PageControl.getUnlimitedInstance());
//trim already defined from all groups returned. allGroups = filterExisting(assignedList, allGroups); @@ -217,6 +221,30 @@ public class AddLdapGroupsFormPrepareAction extends TilesAction { availableGroups.setTotalSize(groupLookup.size()); availableGroups.setPageControl(pca);
+ } catch (EJBException ejx) { + //this is the exception type thrown now that we use SLSB.Local methods + // mine out other exceptions + Exception cause = ejx.getCausedByException(); + if (cause == null) { + ActionMessages actionMessages = new ActionMessages(); + actionMessages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("errors.cam.general")); + saveErrors(request, actionMessages); + } else { + if (cause instanceof LdapFilterException) { + ActionMessages actionMessages = new ActionMessages(); + actionMessages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + "admin.role.LdapGroupFilterMessage")); + saveErrors(request, actionMessages); + } else if (cause instanceof LdapCommunicationException) { + ActionMessages actionMessages = new ActionMessages(); + SystemManagerLocal manager = LookupUtil.getSystemManager(); + Properties options = manager.getSystemConfiguration(); + String providerUrl = options.getProperty(RHQConstants.LDAPUrl, "(unavailable)"); + actionMessages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + "admin.role.LdapCommunicationMessage", providerUrl)); + saveErrors(request, actionMessages); + } + } } catch (LdapFilterException lce) { ActionMessages actionMessages = new ActionMessages(); actionMessages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("admin.role.LdapGroupFilterMessage")); diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/RemoveLdapGroupsAction.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/RemoveLdapGroupsAction.java index fb359c6..48ab1c5 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/RemoveLdapGroupsAction.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/RemoveLdapGroupsAction.java @@ -31,12 +31,16 @@ import org.rhq.core.util.collection.ArrayUtils; import org.rhq.enterprise.gui.legacy.Constants; import org.rhq.enterprise.gui.legacy.action.BaseAction; import org.rhq.enterprise.gui.legacy.util.RequestUtils; +import org.rhq.enterprise.server.resource.group.LdapGroupManagerLocal; import org.rhq.enterprise.server.util.LookupUtil;
/** * An Action that retrieves data to facilitate display of the form for removing groups to a role. */ public class RemoveLdapGroupsAction extends BaseAction { + + LdapGroupManagerLocal ldapManager = LookupUtil.getLdapGroupManager(); + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { Log log = LogFactory.getLog(RemoveLdapGroupsAction.class.getName()); @@ -46,7 +50,7 @@ public class RemoveLdapGroupsAction extends BaseAction { int[] groupIds = ArrayUtils.unwrapArray(rmForm.getLdapGroups());
log.debug("removing groups " + groupIds + "] for role [" + roleId + "]"); - LookupUtil.getRoleManager().removeLdapGroupsFromRole(RequestUtils.getSubject(request), roleId, groupIds); + ldapManager.removeLdapGroupsFromRole(RequestUtils.getSubject(request), roleId, groupIds);
RequestUtils.setConfirmation(request, "admin.role.confirm.RemoveLdapGroups"); return returnSuccess(request, mapping, Constants.ROLE_PARAM, roleId); diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/ViewAction.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/ViewAction.java index 3414dab..b2e884e 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/ViewAction.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/ViewAction.java @@ -45,6 +45,7 @@ import org.rhq.enterprise.gui.legacy.action.WorkflowPrepareAction; import org.rhq.enterprise.gui.legacy.util.RequestUtils; import org.rhq.enterprise.gui.util.WebUtility; import org.rhq.enterprise.server.authz.RoleManagerLocal; +import org.rhq.enterprise.server.resource.group.LdapGroupManagerLocal; import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal; import org.rhq.enterprise.server.util.LookupUtil;
@@ -52,6 +53,11 @@ import org.rhq.enterprise.server.util.LookupUtil; * An Action that retrieves a specific role. This is executed when you view a specific role. */ public class ViewAction extends WorkflowPrepareAction { + + LdapGroupManagerLocal ldapManager = LookupUtil.getLdapGroupManager(); + RoleManagerLocal roleManager = LookupUtil.getRoleManager(); + ResourceGroupManagerLocal groupManager = LookupUtil.getResourceGroupManager(); + /** */ public ActionForward workflow(ComponentContext context, ActionMapping mapping, ActionForm form, @@ -75,8 +81,8 @@ public class ViewAction extends WorkflowPrepareAction { log.trace("group page control: " + pcg); log.trace("ldap group page control: " + pcldap);
- RoleManagerLocal roleManager = LookupUtil.getRoleManager(); - ResourceGroupManagerLocal groupManager = LookupUtil.getResourceGroupManager(); + // RoleManagerLocal roleManager = LookupUtil.getRoleManager(); + // ResourceGroupManagerLocal groupManager = LookupUtil.getResourceGroupManager();
// get all the role permissions Set<Permission> permissions = roleManager.getPermissions(roleId); @@ -91,6 +97,7 @@ public class ViewAction extends WorkflowPrepareAction {
// get the subjects attached to the role log.trace("getting users for role [" + roleId + "]"); + // PageList<Subject> users = roleManager.findSubjectsByRole(roleId, pcu); PageList<Subject> users = roleManager.findSubjectsByRole(roleId, pcu); request.setAttribute(Constants.ROLE_USERS_ATTR, users);
@@ -104,7 +111,7 @@ public class ViewAction extends WorkflowPrepareAction { request.setAttribute(Constants.NUM_RESGRPS_ATTR, new Integer(groups.getTotalSize())); }
- PageList<LdapGroup> ldapGroups = roleManager.findLdapGroupsByRole(roleId, pcldap); + PageList<LdapGroup> ldapGroups = ldapManager.findLdapGroupsByRole(roleId, pcldap); request.setAttribute(Constants.ROLE_LDAPGRPS_ATTR, ldapGroups); if (ldapGroups == null) { request.setAttribute(Constants.NUM_LDAPGRPS_ATTR, new Integer(0)); diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/user/RegisterAction.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/user/RegisterAction.java index 9d4ec7a..91980ad 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/user/RegisterAction.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/user/RegisterAction.java @@ -23,6 +23,7 @@ import java.util.HashMap; import java.util.List; import java.util.Properties;
+import javax.ejb.EJBException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @@ -44,10 +45,9 @@ import org.rhq.enterprise.gui.legacy.util.RequestUtils; import org.rhq.enterprise.gui.legacy.util.SessionUtils; import org.rhq.enterprise.server.RHQConstants; import org.rhq.enterprise.server.auth.SubjectManagerLocal; -import org.rhq.enterprise.server.authz.RoleManagerLocal; import org.rhq.enterprise.server.exception.LdapCommunicationException; import org.rhq.enterprise.server.exception.LdapFilterException; -import org.rhq.enterprise.server.resource.group.LdapGroupManager; +import org.rhq.enterprise.server.resource.group.LdapGroupManagerLocal; import org.rhq.enterprise.server.system.SystemManagerLocal; import org.rhq.enterprise.server.util.LookupUtil;
@@ -55,6 +55,11 @@ import org.rhq.enterprise.server.util.LookupUtil; * Registers a user. Triggered when authenticated via LDAP. */ public class RegisterAction extends BaseAction { + + SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager(); + SystemManagerLocal systemManager = LookupUtil.getSystemManager(); + LdapGroupManagerLocal ldapManager = LookupUtil.getLdapGroupManager(); + /** * Create the user with the attributes specified in the given <code>NewForm</code> and save it into the session * attribute <code>Constants.USER_ATTR</code>. @@ -96,7 +101,6 @@ public class RegisterAction extends BaseAction { String password = (String) session.getAttribute(Constants.PASSWORD_SES_ATTR); session.removeAttribute(Constants.PASSWORD_SES_ATTR);
- SubjectManagerLocal subjectManager = LookupUtil.getSubjectManager(); Subject superuser = subjectManager.getOverlord();
// create the subject, but don't add a principal since LDAP will handle authentication @@ -118,8 +122,7 @@ public class RegisterAction extends BaseAction { parms.put(Constants.USER_PARAM, newSubject.getId());
//BZ-580127: only do group authz check if one or both of group filter fields is set - SystemManagerLocal manager = LookupUtil.getSystemManager(); - Properties options = manager.getSystemConfiguration(); + Properties options = systemManager.getSystemConfiguration(); String groupFilter = (String) options.getProperty(RHQConstants.LDAPGroupFilter, ""); String groupMember = (String) options.getProperty(RHQConstants.LDAPGroupMember, ""); if ((groupFilter.trim().length() > 0) || (groupMember.trim().length() > 0)) { @@ -127,11 +130,32 @@ public class RegisterAction extends BaseAction { String provider = LookupUtil.getSystemManager().getSystemConfiguration().getProperty( RHQConstants.JAASProvider); if (RHQConstants.LDAPJAASProvider.equals(provider)) { - List<String> groupNames = new ArrayList(LdapGroupManager.getInstance().findAvailableGroupsFor( - newSubject.getName())); - RoleManagerLocal roleManager = LookupUtil.getRoleManager(); - roleManager.assignRolesToLdapSubject(newSubject.getId(), groupNames); - + List<String> groupNames = new ArrayList(ldapManager.findAvailableGroupsFor(newSubject.getName())); + ldapManager.assignRolesToLdapSubject(newSubject.getId(), groupNames); + } + } catch (EJBException ejx) { + //this is the exception type thrown now that we use SLSB.Local methods + // mine out other exceptions + Exception cause = ejx.getCausedByException(); + if (cause == null) { + ActionMessages actionMessages = new ActionMessages(); + actionMessages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("errors.cam.general")); + saveErrors(request, actionMessages); + } else { + if (cause instanceof LdapFilterException) { + ActionMessages actionMessages = new ActionMessages(); + actionMessages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + "admin.role.LdapGroupFilterMessage")); + saveErrors(request, actionMessages); + } else if (cause instanceof LdapCommunicationException) { + ActionMessages actionMessages = new ActionMessages(); + SystemManagerLocal manager = LookupUtil.getSystemManager(); + options = manager.getSystemConfiguration(); + String providerUrl = options.getProperty(RHQConstants.LDAPUrl, "(unavailable)"); + actionMessages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage( + "admin.role.LdapCommunicationMessage", providerUrl)); + saveErrors(request, actionMessages); + } } } catch (LdapFilterException lce) { ActionMessages actionMessages = new ActionMessages(); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java index 8e4d96e..00d4c31 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerBean.java @@ -20,9 +20,7 @@ package org.rhq.enterprise.server.authz;
import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashSet; -import java.util.LinkedList; import java.util.List; import java.util.Set;
@@ -40,7 +38,6 @@ import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.authz.Role; import org.rhq.core.domain.criteria.RoleCriteria; -import org.rhq.core.domain.resource.group.LdapGroup; import org.rhq.core.domain.resource.group.ResourceGroup; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; @@ -91,29 +88,6 @@ public class RoleManagerBean implements RoleManagerLocal, RoleManagerRemote { return roles; }
- @Override - public PageList<LdapGroup> findLdapGroupsByRole(int roleId, PageControl pageControl) { - Role role = entityManager.find(Role.class, roleId); - if (role == null) { - throw new IllegalArgumentException("Could not find role[" + roleId + "] to lookup ldap Groups on"); - } - return new PageList<LdapGroup>(role.getLdapGroups(), role.getLdapGroups().size(), pageControl); - } - - public PageList<LdapGroup> findLdapGroups(PageControl pc) { - - pc.initDefaultOrderingField("g.name"); - - String queryName = LdapGroup.QUERY_FIND_ALL; - Query queryCount = PersistenceUtility.createCountQuery(entityManager, queryName); - Query query = PersistenceUtility.createQueryWithOrderBy(entityManager, queryName, pc); - - long count = (Long) queryCount.getSingleResult(); - // List<Role> roles = query.getResultList(); - List<LdapGroup> groups = query.getResultList(); - return new PageList<LdapGroup>(groups, (int) count, pc); - } - /** * @see org.rhq.enterprise.server.authz.RoleManagerLocal#findRoles(PageControl) */ @@ -466,83 +440,6 @@ public class RoleManagerBean implements RoleManagerLocal, RoleManagerRemote { } }
- /** - * @see org.rhq.enterprise.server.authz.RoleManagerLocal#addResourceGroupsToRole(Subject, int, int[]) - */ - @RequiredPermission(Permission.MANAGE_SECURITY) - public void addLdapGroupsToRole(Subject subject, int roleId, List<String> groupIds) { - if ((groupIds != null) && (groupIds.size() > 0)) { - Role role = entityManager.find(Role.class, roleId); - if (role == null) { - throw new IllegalArgumentException("Could not find role[" + roleId + "] to add resourceGroups to"); - } - role.getLdapGroups().size(); // load them in - - for (String groupId : groupIds) { - LdapGroup group = new LdapGroup(); - group.setName(groupId); - if (role == null) { - throw new IllegalArgumentException("Tried to add ldapGroup[" + groupId + "] to role[" + roleId - + "], but resourceGroup was not found"); - } - role.addLdapGroup(group); - } - } - } - - /** - * @see org.rhq.enterprise.server.authz.RoleManagerLocal#removeLdapGroupsFromRole(Subject, int, int[]) - */ - - @RequiredPermission(Permission.MANAGE_SECURITY) - public void removeLdapGroupsFromRole(Subject subject, int roleId, int[] groupIds) { - if ((groupIds != null) && (groupIds.length > 0)) { - Role role = entityManager.find(Role.class, roleId); - if (role == null) { - throw new IllegalArgumentException("Could not find role[" + roleId + "] to remove resourceGroups from"); - } - role.getLdapGroups().size(); // load them in - - for (Integer groupId : groupIds) { - LdapGroup doomedGroup = entityManager.find(LdapGroup.class, groupId); - if (doomedGroup == null) { - throw new IllegalArgumentException("Tried to remove doomedGroup[" + groupId + "] from role[" - + roleId + "], but subject was not found"); - } - role.removeLdapGroup(doomedGroup); - } - - Query purgeQuery = entityManager.createNamedQuery(LdapGroup.DELETE_BY_ID); - - List<Integer> ids = new LinkedList<Integer>(); - for (int i : groupIds) { - ids.add(i); - } - purgeQuery.setParameter("ids", ids); - purgeQuery.executeUpdate(); - } - } - - private List<Role> findRolesByLdapGroupNames(List<String> ldapGroupNames) { - if (ldapGroupNames.isEmpty()) { - return Collections.EMPTY_LIST; - } - Query query = entityManager.createNamedQuery(LdapGroup.FIND_BY_ROLES_GROUP_NAMES); - query.setParameter("names", ldapGroupNames); - return (List<Role>) query.getResultList(); - } - - public void assignRolesToLdapSubject(int subjectId, List<String> ldapGroupNames) { - Subject sub = entityManager.find(Subject.class, subjectId); - List<Role> roles = findRolesByLdapGroupNames(ldapGroupNames); - sub.getRoles().clear(); - sub.getLdapRoles().clear(); - for (Role role : roles) { - sub.addRole(role); - sub.addLdapRole(role); - } - } - private void processDependentPermissions(Role role) { /* * if you can control user/roles, then you can give yourself permissions, too; so we might as well diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerLocal.java index b89020f..58f962a 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/authz/RoleManagerLocal.java @@ -18,7 +18,6 @@ */ package org.rhq.enterprise.server.authz;
-import java.util.List; import java.util.Set;
import javax.ejb.Local; @@ -27,7 +26,6 @@ import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.authz.Role; import org.rhq.core.domain.criteria.RoleCriteria; -import org.rhq.core.domain.resource.group.LdapGroup; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList;
@@ -161,8 +159,6 @@ public interface RoleManagerLocal {
Role getRole(Subject subject, int roleId);
- PageList<LdapGroup> findLdapGroupsByRole(int roleId, PageControl pageControl); - PageList<Role> findSubjectAssignedRoles(Subject subject, int subjectId, PageControl pc);
//This is a proxy of getAvailableRolesForSubject but without pendingRoleIds as required by remote spec @@ -202,8 +198,6 @@ public interface RoleManagerLocal {
void addRolesToResourceGroup(Subject subject, int groupId, int[] roleIds);
- void addLdapGroupsToRole(Subject subject, int roleId, List<String> groupIds); - /** * Removes the given resource groups from the given role. * @@ -215,11 +209,6 @@ public interface RoleManagerLocal {
void removeRolesFromResourceGroup(Subject subject, int groupId, int[] roleIds);
- void removeLdapGroupsFromRole(Subject subject, int roleId, int[] groupIds); - PageList<Role> findRolesByCriteria(Subject subject, RoleCriteria criteria);
- void assignRolesToLdapSubject(int subjectId, List<String> ldapGroupNames); - - PageList<LdapGroup> findLdapGroups(PageControl pc); } \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java index d6fcaa7..d6e6ae8 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/core/jaas/LdapLoginModule.java @@ -45,7 +45,7 @@ import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; import org.rhq.enterprise.server.auth.SubjectManagerLocal; import org.rhq.enterprise.server.authz.RoleManagerLocal; -import org.rhq.enterprise.server.resource.group.LdapGroupManager; +import org.rhq.enterprise.server.resource.group.LdapGroupManagerLocal; import org.rhq.enterprise.server.util.LookupUtil; import org.rhq.enterprise.server.util.security.UntrustedSSLSocketFactory;
@@ -94,6 +94,8 @@ import org.rhq.enterprise.server.util.security.UntrustedSSLSocketFactory; public class LdapLoginModule extends UsernamePasswordLoginModule { private Log log = LogFactory.getLog(LdapLoginModule.class);
+ LdapGroupManagerLocal ldapManager = LookupUtil.getLdapGroupManager(); + // The delimimiter to use when specifiying multiple BaseDN's. private static final String BASEDN_DELIMITER = ";";
@@ -218,11 +220,11 @@ public class LdapLoginModule extends UsernamePasswordLoginModule { //BUT still must always return true as authz is handled by RHQ if roles/groups correct
//retrieve all ldap groups that this user is authorized for based on ldap group filter and group member settings - Set<String> authorizedLdapGroups = LdapGroupManager.getInstance().findAvailableGroupsFor(userName); + Set<String> authorizedLdapGroups = ldapManager.findAvailableGroupsFor(userName); RoleManagerLocal roleManager = LookupUtil.getRoleManager();
//find all currently mapped ldap groups - PageList<LdapGroup> allCurrentLdapGroupsRegistered = roleManager.findLdapGroups(PageControl + PageList<LdapGroup> allCurrentLdapGroupsRegistered = ldapManager.findLdapGroups(PageControl .getUnlimitedInstance());
//find all roles for currently mapped ldap groups. @@ -239,7 +241,7 @@ public class LdapLoginModule extends UsernamePasswordLoginModule { //else add this subject back to all AuthoriziedLdapGroups //lookup all roles that map to the authorizedLdapGroup names List authorizedList = new ArrayList(authorizedLdapGroups); - roleManager.assignRolesToLdapSubject(ldapSubject.getId(), authorizedList); + ldapManager.assignRolesToLdapSubject(ldapSubject.getId(), authorizedList); } return true; } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManager.java deleted file mode 100644 index e372777..0000000 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManager.java +++ /dev/null @@ -1,304 +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.resource.group; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import javax.naming.Context; -import javax.naming.NamingEnumeration; -import javax.naming.NamingException; -import javax.naming.directory.Attribute; -import javax.naming.directory.InvalidSearchFilterException; -import javax.naming.directory.SearchControls; -import javax.naming.directory.SearchResult; -import javax.naming.ldap.InitialLdapContext; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.rhq.enterprise.server.RHQConstants; -import org.rhq.enterprise.server.exception.LdapCommunicationException; -import org.rhq.enterprise.server.exception.LdapFilterException; -import org.rhq.enterprise.server.system.SystemManagerLocal; -import org.rhq.enterprise.server.util.LookupUtil; -import org.rhq.enterprise.server.util.security.UntrustedSSLSocketFactory; - -/** - * @author paji - */ -public class LdapGroupManager { - private static final LdapGroupManager INSTANCE = new LdapGroupManager(); - private static final String BASEDN_DELIMITER = ";"; - private Log log = LogFactory.getLog(LdapGroupManager.class); - - private LdapGroupManager() { - } - - public static LdapGroupManager getInstance() { - return INSTANCE; - } - - public Set<Map<String, String>> findAvailableGroups() { - SystemManagerLocal manager = LookupUtil.getSystemManager(); - - Properties options = manager.getSystemConfiguration(); - String groupFilter = (String) options.get(RHQConstants.LDAPGroupFilter); - String filter = String.format("(%s)", groupFilter); - - return buildGroup(options, filter); - } - - public Set<String> findAvailableGroupsFor(String userName) { - SystemManagerLocal manager = LookupUtil.getSystemManager(); - Properties options = manager.getSystemConfiguration(); - String groupFilter = (String) options.getProperty(RHQConstants.LDAPGroupFilter, ""); - String groupMember = (String) options.getProperty(RHQConstants.LDAPGroupMember, ""); - String userDN = getUserDN(options, userName); - //TODO: spinder 4/21/10 put in error/debug logging messages for badly formatted filter combinations - String filter = ""; - //form assumes examples where groupFilter is like 'objecclass=groupOfNames' and groupMember is 'member' - // to produce ldaf filter like (&(objecclass=groupOfNames)(member=cn=Administrator,ou=People,dc=test,dc=com)) - filter = String.format("(&(%s)(%s=%s))", groupFilter, groupMember, userDN); - - Set<Map<String, String>> matched = buildGroup(options, filter); - - Set<String> ldapSet = new HashSet<String>(); - for (Map<String, String> match : matched) { - ldapSet.add(match.get("id")); - } - return ldapSet; - } - - private String getUserDN(Properties options, String userName) { - // Load our LDAP specific properties - Properties env = getProperties(options); - - // Load the BaseDN - // Load the BaseDN - String baseDN = (String) options.get(RHQConstants.LDAPBaseDN); - - // Load the LoginProperty - String loginProperty = (String) options.get(RHQConstants.LDAPLoginProperty); - if (loginProperty == null) { - // Use the default - loginProperty = "cn"; - } - // Load any information we may need to bind - String bindDN = (String) options.get(RHQConstants.LDAPBindDN); - String bindPW = (String) options.get(RHQConstants.LDAPBindPW); - - // Load any search filter - String searchFilter = (String) options.get(RHQConstants.LDAPFilter); - if (bindDN != null) { - env.setProperty(Context.SECURITY_PRINCIPAL, bindDN); - env.setProperty(Context.SECURITY_CREDENTIALS, bindPW); - env.setProperty(Context.SECURITY_AUTHENTICATION, "simple"); - } - - try { - InitialLdapContext ctx = new InitialLdapContext(env, null); - SearchControls searchControls = getSearchControls(); - - // Add the search filter if specified. This only allows for a single search filter.. i.e. foo=bar. - String filter; - if ((searchFilter != null) && (searchFilter.length() != 0)) { - filter = "(&(" + loginProperty + "=" + userName + ")" + "(" + searchFilter + "))"; - } else { - filter = "(" + loginProperty + "=" + userName + ")"; - } - - log.debug("Using LDAP filter=" + filter); - - // Loop through each configured base DN. It may be useful - // in the future to allow for a filter to be configured for - // each BaseDN, but for now the filter will apply to all. - String[] baseDNs = baseDN.split(BASEDN_DELIMITER); - for (int x = 0; x < baseDNs.length; x++) { - NamingEnumeration answer = ctx.search(baseDNs[x], filter, searchControls); - if (!answer.hasMoreElements()) { //BZ:582471- ldap api bug change - log.debug("User " + userName + " not found for BaseDN " + baseDNs[x]); - // Nothing found for this DN, move to the next one if we have one. - continue; - } - - // We use the first match - SearchResult si = (SearchResult) answer.next(); - - // Construct the UserDN - String userDN = si.getName() + "," + baseDNs[x]; - return userDN; - } - - // If we try all the BaseDN's and have not found a match, return false - return ""; - } catch (NamingException e) { - throw new RuntimeException(e); - } - } - - /** - * @throws NamingException - * @see org.jboss.security.auth.spi.UsernamePasswordLoginModule#validatePassword(java.lang.String,java.lang.String) - */ - protected Set<Map<String, String>> buildGroup(Properties options, String filter) { - Set<Map<String, String>> ret = new HashSet<Map<String, String>>(); - // Load our LDAP specific properties - Properties env = getProperties(options); - - // Load the BaseDN - String baseDN = (String) options.get(RHQConstants.LDAPBaseDN); - - // Load the LoginProperty - String loginProperty = (String) options.get(RHQConstants.LDAPLoginProperty); - if (loginProperty == null) { - // Use the default - loginProperty = "cn"; - } - // Load any information we may need to bind - String bindDN = (String) options.get(RHQConstants.LDAPBindDN); - String bindPW = (String) options.get(RHQConstants.LDAPBindPW); - if (bindDN != null) { - env.setProperty(Context.SECURITY_PRINCIPAL, bindDN); - env.setProperty(Context.SECURITY_CREDENTIALS, bindPW); - env.setProperty(Context.SECURITY_AUTHENTICATION, "simple"); - } - try { - InitialLdapContext ctx = new InitialLdapContext(env, null); - SearchControls searchControls = getSearchControls(); - /*String filter = "(&(objectclass=groupOfUniqueNames)(uniqueMember=uid=" + userName - + ",ou=People, dc=rhndev, dc=redhat, dc=com))";*/ - - // Loop through each configured base DN. It may be useful - // in the future to allow for a filter to be configured for - // each BaseDN, but for now the filter will apply to all. - String[] baseDNs = baseDN.split(BASEDN_DELIMITER); - - for (int x = 0; x < baseDNs.length; x++) { - NamingEnumeration answer = ctx.search(baseDNs[x], filter, searchControls); - boolean ldapApiEnumerationBugEncountered = false; - while ((!ldapApiEnumerationBugEncountered) && answer.hasMoreElements()) {//BZ:582471- ldap api bug change - // We use the first match - SearchResult si = null; - try { - si = (SearchResult) answer.next(); - } catch (NullPointerException npe) { - ldapApiEnumerationBugEncountered = true; - break; - } - Map<String, String> entry = new HashMap<String, String>(); - String name = (String) si.getAttributes().get("cn").get(); - name = name.trim(); - Attribute desc = si.getAttributes().get("description"); - String description = desc != null ? (String) desc.get() : ""; - description = description.trim(); - entry.put("id", name); - entry.put("name", name); - entry.put("description", description); - ret.add(entry); - } - } - } catch (NamingException e) { - if (e instanceof InvalidSearchFilterException) { - InvalidSearchFilterException fException = (InvalidSearchFilterException) e; - String message = "The ldap group filter defined is invalid "; - log.error(message, fException); - throw new LdapFilterException(message + " " + fException.getMessage()); - } - //TODO: check for ldap connection/unavailable/etc. exceptions. - else { - log.error("LDAP communication error: " + e.getMessage(), e); - throw new LdapCommunicationException(e); - } - } - - return ret; - } - - /** - * Load a default set of properties to use when connecting to the LDAP server. If basic authentication is needed, - * the caller must set Context.SECURITY_PRINCIPAL, Context.SECURITY_CREDENTIALS and Context.SECURITY_AUTHENTICATION - * appropriately. - * - * @return properties that are to be used when connecting to LDAP server - */ - private Properties getProperties(Properties options) { - Properties env = new Properties(options); - // Set our default factory name if one is not given - String factoryName = env.getProperty(RHQConstants.LDAPFactory); - env.setProperty(Context.INITIAL_CONTEXT_FACTORY, factoryName); - - // Setup SSL if requested - String protocol = env.getProperty(RHQConstants.LDAPProtocol); - if ((protocol != null) && protocol.equals("ssl")) { - String ldapSocketFactory = env.getProperty("java.naming.ldap.factory.socket"); - if (ldapSocketFactory == null) { - env.put("java.naming.ldap.factory.socket", UntrustedSSLSocketFactory.class.getName()); - } - env.put(Context.SECURITY_PROTOCOL, "ssl"); - } - - // Set the LDAP url - String providerUrl = env.getProperty(RHQConstants.LDAPUrl); - if (providerUrl == null) { - providerUrl = "ldap://localhost:" + (((protocol != null) && protocol.equals("ssl")) ? "636" : "389"); - } - - env.setProperty(Context.PROVIDER_URL, providerUrl); - - // Follow referrals automatically - env.setProperty(Context.REFERRAL, "ignore"); //BZ:582471- active directory query change - - return env; - } - - /** - * A simple method to construct a SearchControls object for use when doing LDAP searches. All of the defaults are - * used, with the exception of the scope, which is set to SUBTREE rather than the default of ONE_LEVEL - * - * @return controls what is searched in LDAP - */ - private SearchControls getSearchControls() { - // Set the scope to subtree, default is one-level - int scope = SearchControls.SUBTREE_SCOPE; - - // No limit on the time waiting for a response - int timeLimit = 0; - - // No limit on the number of entries returned - long countLimit = 0; - - // Attributes to return. - String[] returnedAttributes = null; - - // Don't return the object - boolean returnObject = false; - - // No dereferencing during the search - boolean deference = false; - - SearchControls constraints = new SearchControls(scope, countLimit, timeLimit, returnedAttributes, returnObject, - deference); - return constraints; - } -} diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java new file mode 100644 index 0000000..63e36db --- /dev/null +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerBean.java @@ -0,0 +1,426 @@ +/* + * 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.resource.group; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import javax.ejb.EJB; +import javax.ejb.Stateless; +import javax.naming.Context; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.Attribute; +import javax.naming.directory.InvalidSearchFilterException; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; +import javax.naming.ldap.InitialLdapContext; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; +import javax.persistence.Query; + +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.authz.Role; +import org.rhq.core.domain.resource.group.LdapGroup; +import org.rhq.core.domain.util.PageControl; +import org.rhq.core.domain.util.PageList; +import org.rhq.core.server.PersistenceUtility; +import org.rhq.enterprise.server.RHQConstants; +import org.rhq.enterprise.server.auth.SubjectManagerLocal; +import org.rhq.enterprise.server.authz.RequiredPermission; +import org.rhq.enterprise.server.exception.LdapCommunicationException; +import org.rhq.enterprise.server.exception.LdapFilterException; +import org.rhq.enterprise.server.system.SystemManagerLocal; +import org.rhq.enterprise.server.util.security.UntrustedSSLSocketFactory; + +/** + * This bean provides functionality to manipulate the ldap auth/authz funcitonality. + * That is, adding/modifying/deleting ldap group/users and their + * associated subjects and permissions are performed by this manager. + * @author paji + * @author Simeon Pinder + */ +@Stateless +public class LdapGroupManagerBean implements LdapGroupManagerLocal { + + // private static final LdapGroupManagerBean INSTANCE = new LdapGroupManagerBean(); + private Log log = LogFactory.getLog(LdapGroupManagerBean.class); + + private static final String BASEDN_DELIMITER = ";"; + + @PersistenceContext(unitName = RHQConstants.PERSISTENCE_UNIT_NAME) + private EntityManager entityManager; + + @EJB + private SubjectManagerLocal subjectManager; + + @EJB + private SystemManagerLocal systemManager; + + public Set<Map<String, String>> findAvailableGroups() { + Properties options = systemManager.getSystemConfiguration(); + String groupFilter = (String) options.get(RHQConstants.LDAPGroupFilter); + String filter = String.format("(%s)", groupFilter); + + return buildGroup(options, filter); + } + + public Set<String> findAvailableGroupsFor(String userName) { + Properties options = systemManager.getSystemConfiguration(); + String groupFilter = (String) options.getProperty(RHQConstants.LDAPGroupFilter, ""); + String groupMember = (String) options.getProperty(RHQConstants.LDAPGroupMember, ""); + String userDN = getUserDN(options, userName); + //TODO: spinder 4/21/10 put in error/debug logging messages for badly formatted filter combinations + String filter = ""; + //form assumes examples where groupFilter is like 'objecclass=groupOfNames' and groupMember is 'member' + // to produce ldaf filter like (&(objecclass=groupOfNames)(member=cn=Administrator,ou=People,dc=test,dc=com)) + filter = String.format("(&(%s)(%s=%s))", groupFilter, groupMember, userDN); + + Set<Map<String, String>> matched = buildGroup(options, filter); + + Set<String> ldapSet = new HashSet<String>(); + for (Map<String, String> match : matched) { + ldapSet.add(match.get("id")); + } + return ldapSet; + } + + /** + * @see org.rhq.enterprise.server.authz.RoleManagerLocal#addResourceGroupsToRole(Subject, int, int[]) + */ + @RequiredPermission(Permission.MANAGE_SECURITY) + public void addLdapGroupsToRole(Subject subject, int roleId, List<String> groupIds) { + if ((groupIds != null) && (groupIds.size() > 0)) { + Role role = entityManager.find(Role.class, roleId); + if (role == null) { + throw new IllegalArgumentException("Could not find role[" + roleId + "] to add resourceGroups to"); + } + role.getLdapGroups().size(); // load them in + + for (String groupId : groupIds) { + LdapGroup group = new LdapGroup(); + group.setName(groupId); + if (role == null) { + throw new IllegalArgumentException("Tried to add ldapGroup[" + groupId + "] to role[" + roleId + + "], but resourceGroup was not found"); + } + role.addLdapGroup(group); + } + } + } + + /** + * @see org.rhq.enterprise.server.authz.RoleManagerLocal#removeLdapGroupsFromRole(Subject, int, int[]) + */ + + @RequiredPermission(Permission.MANAGE_SECURITY) + public void removeLdapGroupsFromRole(Subject subject, int roleId, int[] groupIds) { + if ((groupIds != null) && (groupIds.length > 0)) { + Role role = entityManager.find(Role.class, roleId); + if (role == null) { + throw new IllegalArgumentException("Could not find role[" + roleId + "] to remove resourceGroups from"); + } + role.getLdapGroups().size(); // load them in + + for (Integer groupId : groupIds) { + LdapGroup doomedGroup = entityManager.find(LdapGroup.class, groupId); + if (doomedGroup == null) { + throw new IllegalArgumentException("Tried to remove doomedGroup[" + groupId + "] from role[" + + roleId + "], but subject was not found"); + } + role.removeLdapGroup(doomedGroup); + } + + Query purgeQuery = entityManager.createNamedQuery(LdapGroup.DELETE_BY_ID); + + List<Integer> ids = new LinkedList<Integer>(); + for (int i : groupIds) { + ids.add(i); + } + purgeQuery.setParameter("ids", ids); + purgeQuery.executeUpdate(); + } + } + + private List<Role> findRolesByLdapGroupNames(List<String> ldapGroupNames) { + if (ldapGroupNames.isEmpty()) { + return Collections.EMPTY_LIST; + } + Query query = entityManager.createNamedQuery(LdapGroup.FIND_BY_ROLES_GROUP_NAMES); + query.setParameter("names", ldapGroupNames); + return (List<Role>) query.getResultList(); + } + + public void assignRolesToLdapSubject(int subjectId, List<String> ldapGroupNames) { + Subject sub = entityManager.find(Subject.class, subjectId); + List<Role> roles = findRolesByLdapGroupNames(ldapGroupNames); + sub.getRoles().clear(); + sub.getLdapRoles().clear(); + for (Role role : roles) { + sub.addRole(role); + sub.addLdapRole(role); + } + } + + @Override + public PageList<LdapGroup> findLdapGroupsByRole(int roleId, PageControl pageControl) { + Role role = entityManager.find(Role.class, roleId); + if (role == null) { + throw new IllegalArgumentException("Could not find role[" + roleId + "] to lookup ldap Groups on"); + } + return new PageList<LdapGroup>(role.getLdapGroups(), role.getLdapGroups().size(), pageControl); + } + + public PageList<LdapGroup> findLdapGroups(PageControl pc) { + + pc.initDefaultOrderingField("g.name"); + + String queryName = LdapGroup.QUERY_FIND_ALL; + Query queryCount = PersistenceUtility.createCountQuery(entityManager, queryName); + Query query = PersistenceUtility.createQueryWithOrderBy(entityManager, queryName, pc); + + long count = (Long) queryCount.getSingleResult(); + // List<Role> roles = query.getResultList(); + List<LdapGroup> groups = query.getResultList(); + return new PageList<LdapGroup>(groups, (int) count, pc); + } + + private String getUserDN(Properties options, String userName) { + // Load our LDAP specific properties + Properties env = getProperties(options); + + // Load the BaseDN + // Load the BaseDN + String baseDN = (String) options.get(RHQConstants.LDAPBaseDN); + + // Load the LoginProperty + String loginProperty = (String) options.get(RHQConstants.LDAPLoginProperty); + if (loginProperty == null) { + // Use the default + loginProperty = "cn"; + } + // Load any information we may need to bind + String bindDN = (String) options.get(RHQConstants.LDAPBindDN); + String bindPW = (String) options.get(RHQConstants.LDAPBindPW); + + // Load any search filter + String searchFilter = (String) options.get(RHQConstants.LDAPFilter); + if (bindDN != null) { + env.setProperty(Context.SECURITY_PRINCIPAL, bindDN); + env.setProperty(Context.SECURITY_CREDENTIALS, bindPW); + env.setProperty(Context.SECURITY_AUTHENTICATION, "simple"); + } + + try { + InitialLdapContext ctx = new InitialLdapContext(env, null); + SearchControls searchControls = getSearchControls(); + + // Add the search filter if specified. This only allows for a single search filter.. i.e. foo=bar. + String filter; + if ((searchFilter != null) && (searchFilter.length() != 0)) { + filter = "(&(" + loginProperty + "=" + userName + ")" + "(" + searchFilter + "))"; + } else { + filter = "(" + loginProperty + "=" + userName + ")"; + } + + log.debug("Using LDAP filter=" + filter); + + // Loop through each configured base DN. It may be useful + // in the future to allow for a filter to be configured for + // each BaseDN, but for now the filter will apply to all. + String[] baseDNs = baseDN.split(BASEDN_DELIMITER); + for (int x = 0; x < baseDNs.length; x++) { + NamingEnumeration answer = ctx.search(baseDNs[x], filter, searchControls); + if (!answer.hasMoreElements()) { //BZ:582471- ldap api bug change + log.debug("User " + userName + " not found for BaseDN " + baseDNs[x]); + // Nothing found for this DN, move to the next one if we have one. + continue; + } + + // We use the first match + SearchResult si = (SearchResult) answer.next(); + + // Construct the UserDN + String userDN = si.getName() + "," + baseDNs[x]; + return userDN; + } + + // If we try all the BaseDN's and have not found a match, return false + return ""; + } catch (NamingException e) { + throw new RuntimeException(e); + } + } + + /** + * @throws NamingException + * @see org.jboss.security.auth.spi.UsernamePasswordLoginModule#validatePassword(java.lang.String,java.lang.String) + */ + protected Set<Map<String, String>> buildGroup(Properties options, String filter) { + Set<Map<String, String>> ret = new HashSet<Map<String, String>>(); + // Load our LDAP specific properties + Properties env = getProperties(options); + + // Load the BaseDN + String baseDN = (String) options.get(RHQConstants.LDAPBaseDN); + + // Load the LoginProperty + String loginProperty = (String) options.get(RHQConstants.LDAPLoginProperty); + if (loginProperty == null) { + // Use the default + loginProperty = "cn"; + } + // Load any information we may need to bind + String bindDN = (String) options.get(RHQConstants.LDAPBindDN); + String bindPW = (String) options.get(RHQConstants.LDAPBindPW); + if (bindDN != null) { + env.setProperty(Context.SECURITY_PRINCIPAL, bindDN); + env.setProperty(Context.SECURITY_CREDENTIALS, bindPW); + env.setProperty(Context.SECURITY_AUTHENTICATION, "simple"); + } + try { + InitialLdapContext ctx = new InitialLdapContext(env, null); + SearchControls searchControls = getSearchControls(); + /*String filter = "(&(objectclass=groupOfUniqueNames)(uniqueMember=uid=" + userName + + ",ou=People, dc=rhndev, dc=redhat, dc=com))";*/ + + // Loop through each configured base DN. It may be useful + // in the future to allow for a filter to be configured for + // each BaseDN, but for now the filter will apply to all. + String[] baseDNs = baseDN.split(BASEDN_DELIMITER); + + for (int x = 0; x < baseDNs.length; x++) { + NamingEnumeration answer = ctx.search(baseDNs[x], filter, searchControls); + boolean ldapApiEnumerationBugEncountered = false; + while ((!ldapApiEnumerationBugEncountered) && answer.hasMoreElements()) {//BZ:582471- ldap api bug change + // We use the first match + SearchResult si = null; + try { + si = (SearchResult) answer.next(); + } catch (NullPointerException npe) { + ldapApiEnumerationBugEncountered = true; + break; + } + Map<String, String> entry = new HashMap<String, String>(); + String name = (String) si.getAttributes().get("cn").get(); + name = name.trim(); + Attribute desc = si.getAttributes().get("description"); + String description = desc != null ? (String) desc.get() : ""; + description = description.trim(); + entry.put("id", name); + entry.put("name", name); + entry.put("description", description); + ret.add(entry); + } + } + } catch (NamingException e) { + if (e instanceof InvalidSearchFilterException) { + InvalidSearchFilterException fException = (InvalidSearchFilterException) e; + String message = "The ldap group filter defined is invalid "; + log.error(message, fException); + throw new LdapFilterException(message + " " + fException.getMessage()); + } + //TODO: check for ldap connection/unavailable/etc. exceptions. + else { + log.error("LDAP communication error: " + e.getMessage(), e); + throw new LdapCommunicationException(e); + } + } + + return ret; + } + + /** + * Load a default set of properties to use when connecting to the LDAP server. If basic authentication is needed, + * the caller must set Context.SECURITY_PRINCIPAL, Context.SECURITY_CREDENTIALS and Context.SECURITY_AUTHENTICATION + * appropriately. + * + * @return properties that are to be used when connecting to LDAP server + */ + private Properties getProperties(Properties options) { + Properties env = new Properties(options); + // Set our default factory name if one is not given + String factoryName = env.getProperty(RHQConstants.LDAPFactory); + env.setProperty(Context.INITIAL_CONTEXT_FACTORY, factoryName); + + // Setup SSL if requested + String protocol = env.getProperty(RHQConstants.LDAPProtocol); + if ((protocol != null) && protocol.equals("ssl")) { + String ldapSocketFactory = env.getProperty("java.naming.ldap.factory.socket"); + if (ldapSocketFactory == null) { + env.put("java.naming.ldap.factory.socket", UntrustedSSLSocketFactory.class.getName()); + } + env.put(Context.SECURITY_PROTOCOL, "ssl"); + } + + // Set the LDAP url + String providerUrl = env.getProperty(RHQConstants.LDAPUrl); + if (providerUrl == null) { + providerUrl = "ldap://localhost:" + (((protocol != null) && protocol.equals("ssl")) ? "636" : "389"); + } + + env.setProperty(Context.PROVIDER_URL, providerUrl); + + // Follow referrals automatically + env.setProperty(Context.REFERRAL, "ignore"); //BZ:582471- active directory query change + + return env; + } + + /** + * A simple method to construct a SearchControls object for use when doing LDAP searches. All of the defaults are + * used, with the exception of the scope, which is set to SUBTREE rather than the default of ONE_LEVEL + * + * @return controls what is searched in LDAP + */ + private SearchControls getSearchControls() { + // Set the scope to subtree, default is one-level + int scope = SearchControls.SUBTREE_SCOPE; + + // No limit on the time waiting for a response + int timeLimit = 0; + + // No limit on the number of entries returned + long countLimit = 0; + + // Attributes to return. + String[] returnedAttributes = null; + + // Don't return the object + boolean returnObject = false; + + // No dereferencing during the search + boolean deference = false; + + SearchControls constraints = new SearchControls(scope, countLimit, timeLimit, returnedAttributes, returnObject, + deference); + return constraints; + } +} diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerLocal.java new file mode 100644 index 0000000..6709b32 --- /dev/null +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManagerLocal.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 as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.server.resource.group; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.ejb.Local; + +import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.resource.group.LdapGroup; +import org.rhq.core.domain.util.PageControl; +import org.rhq.core.domain.util.PageList; + +/** + * A manager that provides methods for creating, updating, deleting, and querying {@link LdapGroup}s. + * + * @author Simeon Pinder + */ +@Local +public interface LdapGroupManagerLocal { + + PageList<LdapGroup> findLdapGroupsByRole(int roleId, PageControl pageControl); + + PageList<LdapGroup> findLdapGroups(PageControl pc); + + void addLdapGroupsToRole(Subject subject, int roleId, List<String> groupIds); + + void removeLdapGroupsFromRole(Subject subject, int roleId, int[] groupIds); + + void assignRolesToLdapSubject(int subjectId, List<String> ldapGroupNames); + + Set<Map<String, String>> findAvailableGroups(); + + Set<String> findAvailableGroupsFor(String userName); +} \ No newline at end of file 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 c21526a..e5171e9 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 @@ -155,6 +155,8 @@ import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal; import org.rhq.enterprise.server.resource.ResourceTypeManagerRemote; import org.rhq.enterprise.server.resource.cluster.ClusterManagerBean; import org.rhq.enterprise.server.resource.cluster.ClusterManagerLocal; +import org.rhq.enterprise.server.resource.group.LdapGroupManagerBean; +import org.rhq.enterprise.server.resource.group.LdapGroupManagerLocal; import org.rhq.enterprise.server.resource.group.ResourceGroupManagerBean; import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal; import org.rhq.enterprise.server.resource.group.definition.GroupDefinitionExpressionBuilderManagerBean; @@ -655,4 +657,8 @@ public final class LookupUtil { return lookupLocal(DataAccessManagerBean.class); }
+ public static LdapGroupManagerLocal getLdapGroupManager() { + return lookupLocal(LdapGroupManagerBean.class); + } + } \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/authz/test/RoleManagerBeanTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/authz/test/RoleManagerBeanTest.java index 2315ee8..c0ae4d9 100644 --- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/authz/test/RoleManagerBeanTest.java +++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/authz/test/RoleManagerBeanTest.java @@ -33,6 +33,7 @@ import org.rhq.core.domain.util.PageList; import org.rhq.enterprise.server.auth.SubjectManagerLocal; import org.rhq.enterprise.server.authz.PermissionException; import org.rhq.enterprise.server.authz.RoleManagerLocal; +import org.rhq.enterprise.server.resource.group.LdapGroupManagerLocal; import org.rhq.enterprise.server.test.AbstractEJB3Test; import org.rhq.enterprise.server.util.LookupUtil;
@@ -43,6 +44,7 @@ import org.rhq.enterprise.server.util.LookupUtil; public class RoleManagerBeanTest extends AbstractEJB3Test { private SubjectManagerLocal subjectManager; private RoleManagerLocal roleManager; + private LdapGroupManagerLocal ldapManager;
/** * Prepares things for the entire test class. @@ -51,6 +53,7 @@ public class RoleManagerBeanTest extends AbstractEJB3Test { public void beforeClass() { roleManager = LookupUtil.getRoleManager(); subjectManager = LookupUtil.getSubjectManager(); + ldapManager = LookupUtil.getLdapGroupManager(); }
/** @@ -263,7 +266,7 @@ public class RoleManagerBeanTest extends AbstractEJB3Test { LdapGroup group = new LdapGroup(); group.setName("Foo"); role.addLdapGroup(group); - assert roleManager.findLdapGroupsByRole(role.getId(), PageControl.getUnlimitedInstance()).size() == 1 : "Ldap Group Foo Should be assigned"; + assert ldapManager.findLdapGroupsByRole(role.getId(), PageControl.getUnlimitedInstance()).size() == 1 : "Ldap Group Foo Should be assigned"; } finally { getTransactionManager().rollback(); }
commit 03be63bc157f46c0c6192e25063da5fcf6b76e73 Author: Joseph Marques joseph@redhat.com Date: Tue Apr 27 16:35:00 2010 -0400
oops, referring to a table that no longer exists
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml index 145b8e2..1837d73 100644 --- a/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml +++ b/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml @@ -124,7 +124,6 @@ <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/> <column name="ALERT_DEFINITION_ID" required="false" type="INTEGER" references="RHQ_ALERT_DEFINITION(ID)"/> - <column name="TEMPLATE_ID" required="false" type="INTEGER" references="RHQ_ALERT_NOTIF_TEMPL(ID)"/> <column name="SENDER_CONFIG_ID" required="false" type="INTEGER" references="RHQ_CONFIG(ID)"/> <column name="SENDER_NAME" required="true" size="100" type="VARCHAR2" /> </table>
commit e2e2e300fa0fe5441b962cd7c109e13a2c2f8eb9 Author: Joseph Marques joseph@redhat.com Date: Tue Apr 27 16:25:52 2010 -0400
improve debug logging for pagination/sorting issues, so that root cause can more readily be determined in the future
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/WebUserPreferences.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/WebUserPreferences.java index a939ab4..c0abd7e 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/WebUserPreferences.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/WebUserPreferences.java @@ -693,16 +693,21 @@ public class WebUserPreferences extends SubjectPreferencesBase { }
public PageControl getPageControl(PageControlView view) { - return getPageControl(view, 15); + PageControl results = getPageControl(view, 15); + log.debug("getPageControl(" + view + ") " + results); + return results; }
public PageControl getPageControl(PageControlView view, int defaultPageSize) { if (view == PageControlView.NONE) { + log.debug("getPageControl(" + view + ") -> PageControl.getUnlimitedInstance()"); return PageControl.getUnlimitedInstance(); }
List<String> pageControlProperties = getPreferenceAsList(view.toString()); + log.debug("getPageControl(" + view + ") -> pageControlProperties: " + pageControlProperties); if (pageControlProperties.size() == 0) { + log.debug("getPageControl(" + view + ") -> getDefaultPageControl for empty properties"); PageControl defaultControl = getDefaultPageControl(view, defaultPageSize); return defaultControl; } else { @@ -722,6 +727,7 @@ public class WebUserPreferences extends SubjectPreferencesBase {
i += 2; } + log.debug("getPageControl(" + view + ") -> " + pageControl);
if (view.isUnlimited() && pageSize != PageControl.SIZE_UNLIMITED) { // make sure pageSize for an unlimited view is actually unlimited @@ -739,6 +745,7 @@ public class WebUserPreferences extends SubjectPreferencesBase { * persist and load just fine because the logic in this method and its counterpart * setPageControl are kept in sync */ + log.debug("getPageControl(" + view + ") -> getDefaultPageControl for exception: " + t.getMessage()); pageControl = getDefaultPageControl(view, defaultPageSize); } return pageControl; @@ -770,6 +777,7 @@ public class WebUserPreferences extends SubjectPreferencesBase { pageControlProperties.add(field.getOrdering().toString()); pageControlProperties.add(field.getField()); } + System.out.println("setPageControl(" + view + ", " + pageControl + ")");
setPreference(view.toString(), pageControlProperties); }
commit 85f04f40d6ca346279b916804e3c23a486ba98a8 Author: Joseph Marques joseph@redhat.com Date: Tue Apr 27 16:25:19 2010 -0400
do now swallow the error message when their appears to be an error handling PageControl data
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PagedListDataModel.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PagedListDataModel.java index adbc7cf..ca3f353 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PagedListDataModel.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/paging/PagedListDataModel.java @@ -340,9 +340,7 @@ public abstract class PagedListDataModel<T> extends DataModel { * ordering (though the underlying SLSB may add a default ordering downstream). */ resetToDefaults(pc); - if (log.isTraceEnabled()) { - log.trace(pageControlView + ": Received error[" + t.getMessage() + "], resetting to " + pc); - } + log.error(pageControlView + ": Received error[" + t.getMessage() + "], resetting to " + pc); tryQueryAgain = true; }
commit d568a683944cbb81c717589f7c8c1a341a0ae433 Author: Joseph Marques joseph@redhat.com Date: Tue Apr 27 16:24:38 2010 -0400
BZ-584149 fix for broken sorting on the inventory browser (resources and groups)
* CriteriaQueryGenerator now automatically prepends the alias to the ordering fields when building the query * needed to remove explicit alias identifier from the sortableColumnHeader definitions * also, updated CriteriaQueryGenerator to support sorting by column ordinals (required by group browser's availability columns)
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/inventory/browseGroups.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/inventory/browseGroups.xhtml index 65be544..70d9821 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/inventory/browseGroups.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/inventory/browseGroups.xhtml @@ -144,7 +144,7 @@
rich:column <f:facet name="header"> - <onc:sortableColumnHeader sort="rg.name"> + <onc:sortableColumnHeader sort="name"> <h:outputText styleClass="headerText" value="Name" /> </onc:sortableColumnHeader> </f:facet> @@ -157,7 +157,7 @@
rich:column <f:facet name="header"> - <onc:sortableColumnHeader sort="rg.resourceType.name"> + <onc:sortableColumnHeader sort="resourceType.name"> <h:outputText styleClass="headerText" value="Group Type" /> </onc:sortableColumnHeader> </f:facet> @@ -167,7 +167,7 @@
rich:column <f:facet name="header"> - <onc:sortableColumnHeader sort="rg.resourceType.plugin"> + <onc:sortableColumnHeader sort="resourceType.plugin"> <h:outputText styleClass="headerText" value="Plugin" /> </onc:sortableColumnHeader> </f:facet> @@ -177,7 +177,7 @@
rich:column <f:facet name="header"> - <onc:sortableColumnHeader sort="rg.description"> + <onc:sortableColumnHeader sort="description"> <h:outputText styleClass="headerText" value="Description" /> </onc:sortableColumnHeader> </f:facet> diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/inventory/browseResources.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/inventory/browseResources.xhtml index 90d45c0..3a4c7ea 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/inventory/browseResources.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/inventory/browseResources.xhtml @@ -157,7 +157,7 @@
rich:column <f:facet name="header"> - <onc:sortableColumnHeader sort="r.name"> + <onc:sortableColumnHeader sort="name"> <h:outputText styleClass="headerText" value="Name" /> </onc:sortableColumnHeader> </f:facet> @@ -178,7 +178,7 @@
rich:column <f:facet name="header"> - <onc:sortableColumnHeader sort="r.resourceType.category"> + <onc:sortableColumnHeader sort="resourceType.category"> <h:outputText styleClass="headerText" value="Category" /> </onc:sortableColumnHeader> </f:facet> @@ -188,7 +188,7 @@
rich:column <f:facet name="header"> - <onc:sortableColumnHeader sort="r.resourceType.name"> + <onc:sortableColumnHeader sort="resourceType.name"> <h:outputText styleClass="headerText" value="Type" /> </onc:sortableColumnHeader> </f:facet> @@ -198,7 +198,7 @@
rich:column <f:facet name="header"> - <onc:sortableColumnHeader sort="r.resourceType.plugin"> + <onc:sortableColumnHeader sort="resourceType.plugin"> <h:outputText styleClass="headerText" value="Plugin" /> </onc:sortableColumnHeader> </f:facet> @@ -208,7 +208,7 @@
rich:column <f:facet name="header"> - <onc:sortableColumnHeader sort="r.description"> + <onc:sortableColumnHeader sort="description"> <h:outputText styleClass="headerText" value="Description" /> </onc:sortableColumnHeader> </f:facet> @@ -218,7 +218,7 @@
rich:column <f:facet name="header"> - <onc:sortableColumnHeader sort="r.currentAvailability.availabilityType"> + <onc:sortableColumnHeader sort="currentAvailability.availabilityType"> <h:outputText styleClass="headerText" value="Availability" /> </onc:sortableColumnHeader> </f:facet> diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java index ff71760..2272f12 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java @@ -302,15 +302,15 @@ public final class CriteriaQueryGenerator {
String fieldName = orderingField.getField(); String override = criteria.getJPQLSortOverride(fieldName); - if (override == null) { - override = alias + "." + fieldName; - } else { - override = alias + "." + override; - } + String suffix = (override == null) ? fieldName : override; + + // if the suffix is numerical, do not prefix the alias + // this allows us to sort by column ordinal, which is required for availability on the group browser + String sortFragment = (isNumber(suffix)) ? suffix : (alias + "." + suffix);
PageOrdering ordering = orderingField.getOrdering();
- results.append(override).append(' ').append(ordering); + results.append(sortFragment).append(' ').append(ordering); } } results.append(NL); @@ -319,6 +319,18 @@ public final class CriteriaQueryGenerator { return results.toString(); }
+ private boolean isNumber(String input) { + if (input == null) { + return false; + } + for (char next : input.toCharArray()) { + if (Character.isDigit(next) == false) { + return false; + } + } + return true; + } + public List<String> getFetchFields(Criteria criteria) { List<String> results = new ArrayList<String>(); for (Field fetchField : getFields(criteria, Criteria.Type.FETCH)) {
commit dbd83ebec16eafff8561e524cd089998c98ba356 Author: Joseph Marques joseph@redhat.com Date: Tue Apr 27 15:08:41 2010 -0400
fix sorting bug on the group definitions list page
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/definition/group/list.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/definition/group/list.xhtml index 41f8728..61f9d89 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/definition/group/list.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/definition/group/list.xhtml @@ -26,8 +26,6 @@ <ui:define name="content">
<h:form id="groupDefinitionsListForm"> - <input type="hidden" name="id" value="${param.id}"/> - <h:panelGrid columns="1" styleClass="data-table">
<ui:param name="groupDefinitionsDataModel" value="#{ListGroupDefinitionsUIBean.dataModel}"/>
commit 051595ca85f346a5f4f673632b2be17c62c2af25 Author: Joseph Marques joseph@redhat.com Date: Tue Apr 27 13:23:22 2010 -0400
suppress debugging statement
diff --git a/modules/enterprise/server/jar/src/main/antlr3/org/rhq/enterprise/server/search/RHQL.g b/modules/enterprise/server/jar/src/main/antlr3/org/rhq/enterprise/server/search/RHQL.g index 4fa879e..6816a1e 100644 --- a/modules/enterprise/server/jar/src/main/antlr3/org/rhq/enterprise/server/search/RHQL.g +++ b/modules/enterprise/server/jar/src/main/antlr3/org/rhq/enterprise/server/search/RHQL.g @@ -75,7 +75,7 @@ tokens { */
searchExpression - : conditionalExpression { System.out.println($conditionalExpression.tree.toStringTree()); } + : conditionalExpression { /* System.out.println($conditionalExpression.tree.toStringTree()); */ } ;
conditionalExpression
commit b3751bd05aca5af3d7fdf12971953231ffe491ac Author: Joseph Marques joseph@redhat.com Date: Tue Apr 27 13:03:37 2010 -0400
if possible, use the resource-specific ancestry to populate relative resource drop-down
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/CustomContentUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/CustomContentUIBean.java index eb7d500..64bf25a 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/CustomContentUIBean.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/CustomContentUIBean.java @@ -77,6 +77,8 @@ public class CustomContentUIBean extends EnterpriseFacesContextUIBean { customBackingBean.setWebUser(getSubject()); customBackingBean.setContext(FacesContextUtility.getRequiredRequestParameter("context")); customBackingBean.setContextId(FacesContextUtility.getRequiredRequestParameter("contextId")); + customBackingBean.setContextSubId(FacesContextUtility.getOptionalRequestParameter("contextSubId", + (String) null)); customBackingBean.loadView(); outjectBean(backingBeanName, customBackingBean); } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/CustomAlertSenderBackingBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/CustomAlertSenderBackingBean.java index 2f8b323..848765f 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/CustomAlertSenderBackingBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/CustomAlertSenderBackingBean.java @@ -36,6 +36,7 @@ public class CustomAlertSenderBackingBean { protected Subject webUser; protected String context; protected String contextId; + protected String contextSubId;
public Configuration getAlertParameters() { return alertParameters; @@ -69,6 +70,14 @@ public class CustomAlertSenderBackingBean { this.contextId = contextId; }
+ public String getContextSubId() { + return contextSubId; + } + + public void setContextSubId(String contextSubId) { + this.contextSubId = contextSubId; + } + public void loadView() { }
diff --git a/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsBackingBean.java b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsBackingBean.java index 7fd8cc1..2880800 100644 --- a/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsBackingBean.java +++ b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsBackingBean.java @@ -18,6 +18,7 @@ */ package org.rhq.enterprise.server.plugins.alertOperations;
+import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; @@ -100,8 +101,24 @@ public class OperationsBackingBean extends CustomAlertSenderBackingBean { descendantTypeId = get(OperationInfo.Constants.RELATIVE_DESCENDANT_TYPE_ID, "none");
ResourceType contextType = computeResourceTypeFromContext(); // should not be null - List<ResourceType> ancestors = LookupUtil.getResourceTypeManager().getResourceTypeAncestorsWithOperations( - getOverlord(), contextType.getId()); + List<ResourceType> ancestors = null; + if (context.equals("resource")) { + try { + List<Resource> ancestry = LookupUtil.getResourceManager().getResourceLineage( + Integer.parseInt(contextSubId)); + ancestors = new ArrayList<ResourceType>(); + for (Resource next : ancestry) { + ancestors.add(next.getResourceType()); + } + } catch (Throwable t) { + // ignore, we'll default to a different loading style below + } + } + + if (ancestors == null) { // if not in the resource content or fallback if resource ancestry loading bombs + ancestors = LookupUtil.getResourceTypeManager().getResourceTypeAncestorsWithOperations(getOverlord(), + contextType.getId()); + } load(ancestorTypeOptions, ancestors);
if (ancestorTypeId.equals("none") == false) {
commit 901a44092dd5031653ac056bd9fd925dc97ab43e Author: John Mazzitelli mazz@redhat.com Date: Wed Apr 21 13:36:48 2010 -0400
bz535436 - removed all usages of collection.toArray in InventoryManager to avoid concurrency bug. now using synchronized block that should protect against this. (cherry picked from commit ac4460c69494fc6720de5d9ba03af5c6b89ed989)
diff --git a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java index f4785f8..8b6cf68 100644 --- a/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java +++ b/modules/core/plugin-container/src/main/java/org/rhq/core/pc/inventory/InventoryManager.java @@ -1821,7 +1821,9 @@ public class InventoryManager extends AgentService implements ContainerService, * @param listener instance to notify of change events */ public void addInventoryEventListener(InventoryEventListener listener) { - this.inventoryEventListeners.add(listener); + synchronized (this.inventoryEventListeners) { + this.inventoryEventListeners.add(listener); + } }
/** @@ -1830,7 +1832,21 @@ public class InventoryManager extends AgentService implements ContainerService, * @param listener instance to remove from event notification */ public void removeInventoryEventListener(InventoryEventListener listener) { - this.inventoryEventListeners.remove(listener); + synchronized (this.inventoryEventListeners) { + this.inventoryEventListeners.remove(listener); + } + } + + /** + * Always use this before accessing the event listeners because this ensures + * thread safety. + * + * @return all inventory event listeners + */ + private Set<InventoryEventListener> getInventoryEventListeners() { + synchronized (this.inventoryEventListeners) { + return new HashSet<InventoryEventListener>(this.inventoryEventListeners); + } }
/** @@ -1844,8 +1860,7 @@ public class InventoryManager extends AgentService implements ContainerService, return; }
- InventoryEventListener[] iteratorSafeListeners = new InventoryEventListener[inventoryEventListeners.size()]; - iteratorSafeListeners = inventoryEventListeners.toArray(iteratorSafeListeners); + Set<InventoryEventListener> iteratorSafeListeners = getInventoryEventListeners(); for (InventoryEventListener listener : iteratorSafeListeners) { // Catch anything to make sure we don't stop firing to other listeners try { @@ -1868,8 +1883,7 @@ public class InventoryManager extends AgentService implements ContainerService, log.debug("Firing activated for resource: " + resource); }
- InventoryEventListener[] iteratorSafeListeners = new InventoryEventListener[inventoryEventListeners.size()]; - iteratorSafeListeners = inventoryEventListeners.toArray(iteratorSafeListeners); + Set<InventoryEventListener> iteratorSafeListeners = getInventoryEventListeners(); for (InventoryEventListener listener : iteratorSafeListeners) { // Catch anything to make sure we don't stop firing to other listeners try { @@ -1893,8 +1907,7 @@ public class InventoryManager extends AgentService implements ContainerService, log.debug("Firing deactivated for resource: " + resource); }
- InventoryEventListener[] iteratorSafeListeners = new InventoryEventListener[inventoryEventListeners.size()]; - iteratorSafeListeners = inventoryEventListeners.toArray(iteratorSafeListeners); + Set<InventoryEventListener> iteratorSafeListeners = getInventoryEventListeners(); for (InventoryEventListener listener : iteratorSafeListeners) { // Catch anything to make sure we don't stop firing to other listeners try { @@ -1917,8 +1930,7 @@ public class InventoryManager extends AgentService implements ContainerService, return; }
- InventoryEventListener[] iteratorSafeListeners = new InventoryEventListener[inventoryEventListeners.size()]; - iteratorSafeListeners = inventoryEventListeners.toArray(iteratorSafeListeners); + Set<InventoryEventListener> iteratorSafeListeners = getInventoryEventListeners(); for (InventoryEventListener listener : iteratorSafeListeners) { // Catch anything to make sure we don't stop firing to other listeners try {
commit bdbc5d990cd959005e9a7355fc1ba5c1296187d7 Author: Simeon Pinder spinder@redhat.com Date: Tue Apr 27 12:49:48 2010 -0400
BZ 584994:i)pagination fix ii)added ldapgroupform iii)cache ldap group list
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsFormPrepareAction.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsFormPrepareAction.java index bd38c20..39fe62e 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsFormPrepareAction.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/role/AddLdapGroupsFormPrepareAction.java @@ -19,11 +19,14 @@ package org.rhq.enterprise.gui.admin.role;
import java.util.ArrayList; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.NavigableSet; import java.util.Properties; import java.util.Set; +import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -43,6 +46,7 @@ import org.rhq.core.domain.authz.Role; import org.rhq.core.domain.resource.group.LdapGroup; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; +import org.rhq.core.domain.util.PageOrdering; import org.rhq.enterprise.gui.legacy.Constants; import org.rhq.enterprise.gui.legacy.util.RequestUtils; import org.rhq.enterprise.gui.legacy.util.SessionUtils; @@ -59,6 +63,8 @@ import org.rhq.enterprise.server.util.LookupUtil; * An Action that retrieves data to facilitate display of the form for adding groups to a role. */ public class AddLdapGroupsFormPrepareAction extends TilesAction { + final String LDAP_GROUP_CACHE = "ldapGroupCache"; + public ActionForward execute(ComponentContext context, ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { Log log = LogFactory.getLog(AddLdapGroupsFormPrepareAction.class.getName()); @@ -76,6 +82,9 @@ public class AddLdapGroupsFormPrepareAction extends TilesAction { RequestUtils.setError(request, Constants.ERR_ROLE_NOT_FOUND); return null; } + //use cached LDAP group list to avoid hitting ldap server each time ui pref changed. + Set<Map<String, String>> cachedAvailableLdapGroups = null; + cachedAvailableLdapGroups = (Set<Map<String, String>>) request.getSession().getAttribute(LDAP_GROUP_CACHE);
addForm.setR(role.getId());
@@ -93,21 +102,31 @@ public class AddLdapGroupsFormPrepareAction extends TilesAction { PageList<Map<String, String>> pendingGroups = new PageList<Map<String, String>>(pendingSet, 0, pcp); PageList<Map<String, String>> availableGroups = new PageList<Map<String, String>>(availableGroupsSet, 0, pca); /* pending groups are those on the right side of the "add - * to list" widget- awaiting association with the rolewhen the form's "ok" button is clicked. */ + * to list" widget- awaiting association with the role when the form's "ok" button is clicked. */ pendingGroupIds = SessionUtils.getListAsListStr(request.getSession(), Constants.PENDING_RESGRPS_SES_ATTR);
log.trace("getting pending groups for role [" + roleId + ")"); String name = "foo";
try { //defend against ldap communication runtime difficulties. - allGroups = LdapGroupManager.getInstance().findAvailableGroups(); - RoleManagerLocal roleManager = LookupUtil.getRoleManager();
+ if (cachedAvailableLdapGroups == null) { + allGroups = LdapGroupManager.getInstance().findAvailableGroups(); + } else {//reuse cached. + allGroups = cachedAvailableLdapGroups; + } + //store unmodified list in session. + cachedAvailableLdapGroups = allGroups; + + RoleManagerLocal roleManager = LookupUtil.getRoleManager(); + //retrieve currently assigned groups assignedList = roleManager.findLdapGroupsByRole(role.getId(), PageControl.getUnlimitedInstance());
+ //trim already defined from all groups returned. allGroups = filterExisting(assignedList, allGroups); Set<String> pendingIds = new HashSet<String>(pendingGroupIds);
+ //retrieve pending information pendingSet = findPendingGroups(pendingIds, allGroups); pendingGroups = new PageList<Map<String, String>>(pendingSet, pendingSet.size(), pcp);
@@ -118,6 +137,86 @@ public class AddLdapGroupsFormPrepareAction extends TilesAction {
availableGroupsSet = findAvailableGroups(pendingIds, allGroups); availableGroups = new PageList<Map<String, String>>(availableGroupsSet, availableGroupsSet.size(), pca); + + //We cannot reuse the PageControl mechanism as there are no database calls to retrieve list + // must replicate paging using existing web params, formula etc. + + //determine count to return up to 15|30|45 and page index + int returnAmount = pca.getPageSize(); + int returnIndex = pca.getPageNumber(); + + //determine sort order + PageOrdering sortOrder = pca.getPrimarySortOrder(); + if (sortOrder == null) { + sortOrder = PageOrdering.ASC; + pca.setPrimarySortOrder(sortOrder);//reset on pc + } + + //determine which column to sort on + String sortColumn = pca.getPrimarySortColumn(); + if (sortColumn == null) { + sortColumn = "lg.name"; + pca.setPrimarySort(sortColumn, sortOrder);//reset on pc + } + + //now sort based off these values and populate sizedAvailableGroups accordingly + ArrayList<Map<String, String>> groupsValues = availableGroups.getValues(); + + //store maps based off the keys and sort() + Map<Integer, Map> groupLookup = new HashMap<Integer, Map>(); + TreeMap<String, Integer> groupNames = new TreeMap<String, Integer>(); + TreeMap<String, Integer> groupDescriptions = new TreeMap<String, Integer>(); + for (int i = 0; i < groupsValues.size(); i++) { + Map<String, String> entry = groupsValues.get(i); + Integer key = Integer.valueOf(i); + groupLookup.put(key, entry); + groupNames.put(entry.get("name"), key); + groupDescriptions.put(entry.get("description"), key); + } + + //do calculations to determine how many sorted values to return. + int start, end; + start = (int) (returnIndex * returnAmount); + end = start + returnAmount; + PageList<Map<String, String>> sizedAvailableGroups = new PageList<Map<String, String>>(); + + //detect sort order + boolean descending = false; + if (sortOrder.DESC == sortOrder) { + descending = true; + } + //use sort column to determine which list to use + if (sortColumn.equalsIgnoreCase("lg.name")) { + int i = 0; + NavigableSet<String> keyList = groupNames.navigableKeySet(); + if (descending) { + keyList = groupNames.descendingKeySet(); + } + for (String key : keyList) { + if ((i >= start) && (i < end)) { + sizedAvailableGroups.add(groupLookup.get(groupNames.get(key))); + } + i++; + } + } else { + int i = 0; + NavigableSet<String> keyList = groupDescriptions.navigableKeySet(); + if (descending) { + keyList = groupNames.descendingKeySet(); + } + for (String key : keyList) { + if ((i >= start) && (i < end)) { + sizedAvailableGroups.add(groupLookup.get(groupDescriptions.get(key))); + } + i++; + } + } + //make sizedAvailableGroup the new reference to return. + availableGroups = sizedAvailableGroups; + //populate pagination elements for loaded elements. + availableGroups.setTotalSize(groupLookup.size()); + availableGroups.setPageControl(pca); + } catch (LdapFilterException lce) { ActionMessages actionMessages = new ActionMessages(); actionMessages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("admin.role.LdapGroupFilterMessage")); @@ -136,7 +235,9 @@ public class AddLdapGroupsFormPrepareAction extends TilesAction { request.setAttribute(Constants.PENDING_RESGRPS_ATTR, pendingGroups); request.setAttribute(Constants.NUM_PENDING_RESGRPS_ATTR, new Integer(pendingGroups.getTotalSize())); request.setAttribute(Constants.AVAIL_RESGRPS_ATTR, availableGroups); - request.setAttribute(Constants.NUM_AVAIL_RESGRPS_ATTR, new Integer(availableGroups.getTotalSize())); + request.setAttribute(Constants.NUM_AVAIL_RESGRPS_ATTR, new Integer(allGroups.size())); + //store cachedAvailableGroups in session so trim down ldap communication chatter. + request.getSession().setAttribute(LDAP_GROUP_CACHE, cachedAvailableLdapGroups);
return null; } @@ -175,4 +276,4 @@ public class AddLdapGroupsFormPrepareAction extends TilesAction { } return ret; } -} \ No newline at end of file +} diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/role/AddLdapRoleGroups.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/role/AddLdapRoleGroups.jsp index 93ec22e..4341a5e 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/admin/role/AddLdapRoleGroups.jsp +++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/role/AddLdapRoleGroups.jsp @@ -13,7 +13,7 @@
<tiles:insert definition=".portlet.error"/>
-<tiles:insert page="/admin/role/RoleGroupsForm.jsp"> +<tiles:insert page="/admin/role/RoleLdapGroupsForm.jsp"> <tiles:put name="availableResGrps" beanName="AvailableResGrps"/> <tiles:put name="numAvailableResGrps" beanName="NumAvailableResGrps"/> <tiles:put name="pendingResGrps" beanName="PendingResGrps"/> diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/admin/role/RoleLdapGroupsForm.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/admin/role/RoleLdapGroupsForm.jsp new file mode 100644 index 0000000..2880f22 --- /dev/null +++ b/modules/enterprise/gui/portal-war/src/main/webapp/admin/role/RoleLdapGroupsForm.jsp @@ -0,0 +1,263 @@ +<%@ page language="java" %> +<%@ page errorPage="/common/Error.jsp" %> +<%@ taglib uri="http://jakarta.apache.org/struts/tags-html-el" prefix="html" %> +<%@ taglib uri="http://jakarta.apache.org/struts/tags-tiles" prefix="tiles" %> +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib uri="/WEB-INF/tld/display.tld" prefix="display" %> + +<tiles:importAttribute name="availableResGrps"/> +<tiles:importAttribute name="numAvailableResGrps"/> +<tiles:importAttribute name="pendingResGrps"/> +<tiles:importAttribute name="numPendingResGrps"/> + +<script language="JavaScript" src="<html:rewrite page="/js/addRemoveWidget.js"/>" type="text/javascript"></script> +<c:set var="widgetInstanceName" value="addGroups"/> + +<script type="text/javascript"> +var pageData = new Array(); +initializeWidgetProperties('<c:out value="${widgetInstanceName}"/>'); +widgetProperties = getWidgetProperties('<c:out value="${widgetInstanceName}"/>'); +</script> + +<c:url var="selfPnaAction" value="/admin/role/RoleAdmin.do"> + <c:param name="mode" value="addLdapGroups"/> + <c:param name="r" value="${Role.id}"/> + <c:if test="${not empty param.psa}"> + <c:param name="psa" value="${param.psa}"/> + </c:if> + <c:if test="${not empty param.soa}"> + <c:param name="soa" value="${param.soa}"/> + </c:if> + <c:if test="${not empty param.sca}"> + <c:param name="sca" value="${param.sca}"/> + </c:if> + <c:if test="${not empty param.psp}"> + <c:param name="psp" value="${param.psp}"/> + </c:if> + <c:if test="${not empty param.pnp}"> + <c:param name="pnp" value="${param.pnp}"/> + </c:if> + <c:if test="${not empty param.sop}"> + <c:param name="sop" value="${param.sop}"/> + </c:if> + <c:if test="${not empty param.scp}"> + <c:param name="scp" value="${param.scp}"/> + </c:if> +</c:url> + +<c:url var="selfPnpAction" value="/admin/role/RoleAdmin.do"> + <c:param name="mode" value="addLdapGroups"/> + <c:param name="r" value="${Role.id}"/> + <c:if test="${not empty param.psa}"> + <c:param name="psa" value="${param.psa}"/> + </c:if> + <c:if test="${not empty param.pna}"> + <c:param name="pna" value="${param.pna}"/> + </c:if> + <c:if test="${not empty param.soa}"> + <c:param name="soa" value="${param.soa}"/> + </c:if> + <c:if test="${not empty param.sca}"> + <c:param name="sca" value="${param.sca}"/> + </c:if> + <c:if test="${not empty param.psp}"> + <c:param name="psp" value="${param.psp}"/> + </c:if> + <c:if test="${not empty param.sop}"> + <c:param name="sop" value="${param.sop}"/> + </c:if> + <c:if test="${not empty param.scp}"> + <c:param name="scp" value="${param.scp}"/> + </c:if> +</c:url> + +<c:url var="selfPsaAction" value="/admin/role/RoleAdmin.do"> + <c:param name="mode" value="addLdapGroups"/> + <c:param name="r" value="${Role.id}"/> + <c:if test="${not empty param.pna}"> + <c:param name="pna" value="${param.pna}"/> + </c:if> + <c:if test="${not empty param.soa}"> + <c:param name="soa" value="${param.soa}"/> + </c:if> + <c:if test="${not empty param.sca}"> + <c:param name="sca" value="${param.sca}"/> + </c:if> + <c:if test="${not empty param.pnp}"> + <c:param name="pnp" value="${param.pnp}"/> + </c:if> + <c:if test="${not empty param.psp}"> + <c:param name="psp" value="${param.psp}"/> + </c:if> + <c:if test="${not empty param.sop}"> + <c:param name="sop" value="${param.sop}"/> + </c:if> + <c:if test="${not empty param.scp}"> + <c:param name="scp" value="${param.scp}"/> + </c:if> +</c:url> + + +<c:url var="selfPspAction" value="/admin/role/RoleAdmin.do"> + <c:param name="mode" value="addLdapGroups"/> + <c:param name="r" value="${Role.id}"/> + <c:if test="${not empty param.pna}"> + <c:param name="pna" value="${param.pna}"/> + </c:if> + <c:if test="${not empty param.psa}"> + <c:param name="psa" value="${param.psa}"/> + </c:if> + <c:if test="${not empty param.soa}"> + <c:param name="soa" value="${param.soa}"/> + </c:if> + <c:if test="${not empty param.sca}"> + <c:param name="sca" value="${param.sca}"/> + </c:if> + <c:if test="${not empty param.pnp}"> + <c:param name="pnp" value="${param.pnp}"/> + </c:if> + <c:if test="${not empty param.sop}"> + <c:param name="sop" value="${param.sop}"/> + </c:if> + <c:if test="${not empty param.scp}"> + <c:param name="scp" value="${param.scp}"/> + </c:if> +</c:url> + +<c:url var="selfPaAction" value="/admin/role/RoleAdmin.do"> + <c:param name="mode" value="addLdapGroups"/> + <c:param name="r" value="${Role.id}"/> + <c:if test="${not empty param.pna}"> + <c:param name="pna" value="${param.pna}"/> + </c:if> + <c:if test="${not empty param.psa}"> + <c:param name="psa" value="${param.psa}"/> + </c:if> + <c:if test="${not empty param.pnp}"> + <c:param name="pnp" value="${param.pnp}"/> + </c:if> + <c:if test="${not empty param.psp}"> + <c:param name="psp" value="${param.psp}"/> + </c:if> + <c:if test="${not empty param.sop}"> + <c:param name="sop" value="${param.sop}"/> + </c:if> + <c:if test="${not empty param.scp}"> + <c:param name="scp" value="${param.scp}"/> + </c:if> +</c:url> + +<c:url var="selfPpAction" value="/admin/role/RoleAdmin.do"> + <c:param name="mode" value="addLdapGroups"/> + <c:param name="r" value="${Role.id}"/> + <c:if test="${not empty param.pna}"> + <c:param name="pna" value="${param.pna}"/> + </c:if> + <c:if test="${not empty param.psa}"> + <c:param name="psa" value="${param.psa}"/> + </c:if> + <c:if test="${not empty param.soa}"> + <c:param name="soa" value="${param.soa}"/> + </c:if> + <c:if test="${not empty param.sca}"> + <c:param name="sca" value="${param.sca}"/> + </c:if> + <c:if test="${not empty param.pnp}"> + <c:param name="pnp" value="${param.pnp}"/> + </c:if> + <c:if test="${not empty param.psp}"> + <c:param name="psp" value="${param.psp}"/> + </c:if> +</c:url> + + +<!-- SELECT & ADD --> +<table width="100%" cellpadding="0" cellspacing="0" border="0"> + <tr> + <td width="50%" valign="top"> + +<tiles:insert definition=".header.tab"> + <tiles:put name="tabKey" value="admin.role.groups.GroupsTab"/> + <tiles:put name="useFromSideBar" value="true"/> +</tiles:insert> + + </td> + <td><html:img page="/images/spacer.gif" width="40" height="1" border="0"/></td> + <td> + +<tiles:insert definition=".header.tab"> + <tiles:put name="tabKey" value="admin.role.groups.AssignToRoleTab"/> + <tiles:put name="useToSideBar" value="true"/> +</tiles:insert> + + </td> + </tr> + <tr> + <!-- SELECT COLUMN --> + <td width="50%" valign="top"> + <!-- TABLED LIST CONTENTS (SELECT COLUMN) --> + <div id="<c:out value="${widgetInstanceName}"/>FromDiv"> + + <display:table padRows="true" rightSidebar="true" items="${AvailableResGrps}" var="group" action="${selfPaAction}" + postfix="a" + styleId="fromTable" width="100%" cellpadding="0" cellspacing="0" border="0"> + <display:column width="1%" property="id" title="<input type="checkbox" onclick="ToggleAll(this, widgetProperties)" name="fromToggleAll">" isLocalizedTitle="false" styleClass="ListCellCheckbox" headerStyleClass="ListHeaderCheckbox"> + <display:checkboxdecorator name="availableGroup" onclick="ToggleSelection(this, widgetProperties)" styleClass="availableListMember"/> + </display:column> + <display:column property="name" title="common.header.Group" sortAttr="lg.name" width="50%"/> + <display:column property="description" title="common.header.Description" sortAttr="lg.description" width="50%"/> + </display:table> + + </div> + <!-- / --> + +<tiles:insert definition=".toolbar.new"> + <tiles:put name="useFromSideBar" value="true"/> + <tiles:put name="pageList" beanName="AvailableResGrps"/> + <tiles:put name="pageAction" beanName="selfPsaAction"/> + <tiles:put name="postfix" value="a"/> +</tiles:insert> + + </td> + <!-- / SELECT COLUMN --> + + <!-- ADD/REMOVE COLUMN --> + <td id="<c:out value="${widgetInstanceName}"/>AddRemoveButtonTd"> + <div id="AddButtonDiv" align="left"><html:img page="/images/fb_addarrow_gray.gif" border="0" titleKey="AddToList.ClickToAdd"/></div> + <br> <br> + <div id="RemoveButtonDiv" align="right"><html:img page="/images/fb_removearrow_gray.gif" border="0" titleKey="AddToList.ClickToRemove"/></div> + </td> + <!-- / ADD/REMOVE COLUMN --> + + <!-- ADD COLUMN --> + <td width="50%" valign="top"> + <!-- TABLED LIST CONTENTS (SELECT COLUMN) --> + <div id='<c:out value="${widgetInstanceName}"/>ToDiv'> + + <display:table padRows="true" leftSidebar="true" items="${PendingResGrps}" var="group" action="${selfPpAction}" + postfix="p" + styleId="toTable" width="100%" cellpadding="0" cellspacing="0" border="0"> + <display:column width="1%" property="id" title="<input type="checkbox" onclick="ToggleAll(this, widgetProperties)" name="toToggleAll">" isLocalizedTitle="false" styleClass="ListCellCheckbox" headerStyleClass="ListHeaderCheckbox"> + <display:checkboxdecorator name="pendingGroup" onclick="ToggleSelection(this, widgetProperties)" styleClass="pendingListMember"/> + </display:column> + <display:column property="name" title="common.header.Group" sortAttr="lg.name" width="50%"/> + <display:column property="description" title="common.header.Description" width="50%" sortAttr="lg.description"/> + </display:table> + + </div> + <!-- / --> + +<tiles:insert definition=".toolbar.new"> + <tiles:put name="newButtonKey" value="admin.role.groups.NewResourceGroupButton"/> + <tiles:put name="useToSideBar" value="true"/> + <tiles:put name="pageList" beanName="PendingResGrps"/> + <tiles:put name="pageAction" beanName="selfPspAction"/> + <tiles:put name="postfix" value="p"/> +</tiles:insert> + + </td> + <!-- / ADD COLUMN --> + + </tr> +</table> +<!-- / SELECT & ADD --> diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManager.java index 0478fd8..e372777 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManager.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/group/LdapGroupManager.java @@ -208,8 +208,10 @@ public class LdapGroupManager { } Map<String, String> entry = new HashMap<String, String>(); String name = (String) si.getAttributes().get("cn").get(); + name = name.trim(); Attribute desc = si.getAttributes().get("description"); String description = desc != null ? (String) desc.get() : ""; + description = description.trim(); entry.put("id", name); entry.put("name", name); entry.put("description", description);
commit 33247dceb1a722507ae16190333ffe9f2b09180b Author: Joseph Marques joseph@redhat.com Date: Tue Apr 27 12:32:55 2010 -0400
fix NPE seen during very first recalculation of saved search result counts
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/SavedSearchResultCountRecalculationJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/SavedSearchResultCountRecalculationJob.java index 0e015e3..db826de 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/SavedSearchResultCountRecalculationJob.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/SavedSearchResultCountRecalculationJob.java @@ -67,7 +67,10 @@ public class SavedSearchResultCountRecalculationJob extends AbstractStatefulJob PageList<Resource> results = resourceManager.findResourcesByCriteria(overlord, criteria); totalMillis += System.currentTimeMillis();
- if (results.getTotalSize() != next.getResultCount()) { + // TODO: should recent count be computed at the time of update/save for this saved search? + // it would obviate the need for null checking here as well as in the UI for conditional + // display of the result count + if (next.getResultCount() == null || results.getTotalSize() != next.getResultCount()) { next.setResultCount((long) results.getTotalSize()); savedSearchManager.updateSavedSearch(overlord, next); updated++; @@ -76,7 +79,7 @@ public class SavedSearchResultCountRecalculationJob extends AbstractStatefulJob } catch (Throwable t) { // TODO: mark this saved search as "broken" so that future computation is suppressed for it errors++; - LOG.error("Could not calculate result count for SavedSearch[name=" + next.getName() + ", patter='" + LOG.error("Could not calculate result count for SavedSearch[name=" + next.getName() + ", pattern='" + next.getPattern() + "']"); } }
commit 8bdaceac79897f786743a3607f287581565c9b6d Author: Joseph Marques joseph@redhat.com Date: Tue Apr 27 12:32:37 2010 -0400
removal of alert notification templates
* charles explained they will not be released in their current form * reuse occurs at the alert definitions level (resource/group/type), not a component thereof
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml index b2db5f0..145b8e2 100644 --- a/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml +++ b/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml @@ -119,16 +119,6 @@ </index> </table>
- <table name="RHQ_ALERT_NOTIF_TEMPL" tablespace="@@@LARGE_TABLESPACE_FOR_DATA@@@" - storage-options="freelists 5" cache="true" logging="false"> - <column name="ID" default="sequence-only" initial="10001" - primarykey="true" required="true" type="INTEGER"/> - <column name="CTIME" required="true" type="LONG"/> - <column name="MTIME" required="true" type="LONG"/> - <column name="NAME" required="true" size="100" type="VARCHAR2"/> - <column name="DESCRIPTION" required="false" size="250" type="VARCHAR2"/> - </table> - <table name="RHQ_ALERT_NOTIFICATION" tablespace="@@@LARGE_TABLESPACE_FOR_DATA@@@" storage-options="freelists 5" cache="true" logging="false"> <column name="ID" default="sequence-only" initial="10001" 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 d028a43..d97a230 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -2058,8 +2058,9 @@
<schemaSpec version="2.70"> <schema-addColumn table="RHQ_ALERT" column="ACK_TIME" columnType="LONG" /> - <!-- TODO: this needs to change to ack_subject_name --> <schema-addColumn table="RHQ_ALERT" column="ACK_SUBJECT" precision="100" columnType="VARCHAR2" /> + </schemaSpec> + <schemaSpec version="2.70.1"> <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="SENDER_NAME" precision="100" columnType="VARCHAR2" /> <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="SENDER_CONFIG_ID" columnType="INTEGER" /> <schema-directSQL> @@ -2071,35 +2072,7 @@ </statement> </schema-directSQL> </schemaSpec> - <schemaSpec version="2.70.1"> - <schema-createSequence name="RHQ_ALERT_NOTIF_TEMPL_ID_SEQ" initial="10001" /> - <schema-directSQL> - <statement desc="Creating table RHQ_ALERT_NOTIF_TEMPL"> - CREATE TABLE RHQ_ALERT_NOTIF_TEMPL ( ID INTEGER PRIMARY KEY ) - </statement> - </schema-directSQL> - <schema-alterColumn table="RHQ_ALERT_NOTIF_TEMPL" column="ID" nullable="false" /> - <schema-addColumn table="RHQ_ALERT_NOTIF_TEMPL" column="CTIME" columnType="LONG" /> - <schema-alterColumn table="RHQ_ALERT_NOTIF_TEMPL" column="CTIME" nullable="false" /> - <schema-addColumn table="RHQ_ALERT_NOTIF_TEMPL" column="MTIME" columnType="LONG" /> - <schema-alterColumn table="RHQ_ALERT_NOTIF_TEMPL" column="MTIME" nullable="false" /> - <schema-addColumn table="RHQ_ALERT_NOTIF_TEMPL" column="NAME" precision="100" columnType="VARCHAR2" /> - <schema-alterColumn table="RHQ_ALERT_NOTIF_TEMPL" column="NAME" nullable="false" /> - <schema-addColumn table="RHQ_ALERT_NOTIF_TEMPL" column="DESCRIPTION" precision="250" columnType="VARCHAR2" /> - </schemaSpec> <schemaSpec version="2.70.2"> - <!-- add structures for alert notification templates --> - <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="TEMPLATE_ID" columnType="INTEGER" /> - <schema-directSQL> - <statement> - ALTER TABLE RHQ_ALERT_NOTIFICATION - ADD CONSTRAINT RHQ_AN_TEMPLATE_ID_FK - FOREIGN KEY (TEMPLATE_ID) - REFERENCES RHQ_ALERT_NOTIF_TEMPL (ID) - </statement> - </schema-directSQL> - </schemaSpec> - <schemaSpec version="2.70.3"> <!-- turn first-class notification data into configuration objects for custom alert senders --> <schema-alterColumn table="RHQ_ALERT_NOTIFICATION" column="NOTIFICATION_TYPE" nullable="TRUE" /> <schema-javaTask className="CustomAlertSenderUpgradeTask" /> @@ -2110,7 +2083,7 @@ </schema-directSQL> <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="NOTIFICATION_TYPE" /> </schemaSpec> - <schemaSpec version="2.70.4"> + <schemaSpec version="2.70.3"> <!-- remove first-class alert notification structures from definition side of the model--> <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="snmp_host" /> <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="snmp_port" /> @@ -2120,19 +2093,19 @@ <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="subject_id" /> <schema-deleteColumn table="RHQ_ALERT_DEFINITION" column="operation_def_id" /> </schemaSpec> - <schemaSpec version="2.70.5"> + <schemaSpec version="2.70.4"> <schema-deleteColumn table="RHQ_ALERT_NOTIF_LOG" column="roles" /> <schema-deleteColumn table="RHQ_ALERT_NOTIF_LOG" column="subjects" /> <schema-deleteColumn table="RHQ_ALERT_NOTIF_LOG" column="emails" /> </schemaSpec> - <schemaSpec version="2.70.6"> + <schemaSpec version="2.70.5"> <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="SENDER" columnType="VARCHAR2" precision="200" /> <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="RESULT_STATE" columnType="VARCHAR2" precision="20" /> <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="MESSAGE" columnType="VARCHAR2" precision="255" /> <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="ALL_EMAILS" columnType="VARCHAR2" precision="4000" /> <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="EMAILS_FAILED" columnType="VARCHAR2" precision="4000" /> </schemaSpec> - <schemaSpec version="2.70.7"> + <schemaSpec version="2.70.6"> <schema-directSQL> <statement> DROP INDEX RHQ_ALERT_IDX_ALERT diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java index b77d8b0..b9c0401 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java @@ -49,7 +49,7 @@ import org.rhq.core.domain.configuration.Configuration; @NamedQueries( { @NamedQuery(name = AlertNotification.DELETE_BY_ID, query = "DELETE FROM AlertNotification an WHERE an.id IN ( :ids )"), @NamedQuery(name = AlertNotification.QUERY_DELETE_BY_RESOURCES, query = "DELETE FROM AlertNotification an WHERE an.alertDefinition IN ( SELECT ad FROM AlertDefinition ad WHERE ad.resource.id IN ( :resourceIds ) )"), - @NamedQuery(name = AlertNotification.QUERY_DELETE_ORPHANED, query = "DELETE FROM AlertNotification an WHERE an.alertDefinition IS NULL AND an.alertNotificationTemplate IS NULL") }) + @NamedQuery(name = AlertNotification.QUERY_DELETE_ORPHANED, query = "DELETE FROM AlertNotification an WHERE an.alertDefinition IS NULL") }) @SequenceGenerator(name = "RHQ_ALERT_NOTIFICATION_ID_SEQ", sequenceName = "RHQ_ALERT_NOTIFICATION_ID_SEQ") @Table(name = "RHQ_ALERT_NOTIFICATION") public class AlertNotification implements Serializable { @@ -74,10 +74,6 @@ public class AlertNotification implements Serializable { @ManyToOne private AlertDefinition alertDefinition;
- @JoinColumn(name = "TEMPLATE_ID") - @ManyToOne - private AlertNotificationTemplate alertNotificationTemplate; - @JoinColumn(name = "SENDER_CONFIG_ID", referencedColumnName = "ID") @OneToOne(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER) private Configuration configuration; @@ -162,14 +158,6 @@ public class AlertNotification implements Serializable { this.configuration = configuration; }
- public AlertNotificationTemplate getAlertNotificationTemplate() { - return alertNotificationTemplate; - } - - public void setAlertNotificationTemplate(AlertNotificationTemplate alertNotificationTemplate) { - this.alertNotificationTemplate = alertNotificationTemplate; - } - public int getAlertDefinitionId() { return alertDefinitionId; } @@ -185,7 +173,6 @@ public class AlertNotification implements Serializable { sb.append("{alertDefinitionId=").append(alertDefinitionId); sb.append(", alertNotificationId=").append(alertNotificationId); sb.append(", id=").append(id); - sb.append(", notificationTemplate=").append(alertNotificationTemplate); sb.append(", senderName='").append(senderName).append('''); sb.append('}'); return sb.toString(); diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationTemplate.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationTemplate.java deleted file mode 100644 index df64a54..0000000 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationTemplate.java +++ /dev/null @@ -1,177 +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.core.domain.alert.notification; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.NamedQueries; -import javax.persistence.NamedQuery; -import javax.persistence.OneToMany; -import javax.persistence.PrePersist; -import javax.persistence.PreUpdate; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; - -import org.rhq.core.domain.alert.AlertDefinition; -import org.rhq.core.domain.resource.Resource; -import org.rhq.core.domain.resource.ResourceType; -import org.rhq.core.domain.resource.group.ResourceGroup; - -/** - * An {@link AlertNotificationTemplate} is a group of {@link AlertNotification}. This can be used to create - * pre-configured sets of notifications which can then be applied to all types of {@link AlertDefinition}s - - * those at the {@link Resource}-level, {@link ResourceGroup}-level, and {@link ResourceType}-level (a.k.a - * Alert Template). - * - * @author Heiko W. Rupp - */ - -@NamedQueries( { - @NamedQuery(name = AlertNotificationTemplate.FIND_BY_NAME, query = "SELECT t FROM AlertNotificationTemplate t WHERE t.name = :name"), - @NamedQuery(name = AlertNotificationTemplate.FIND_ALL, query = "SELECT t FROM AlertNotificationTemplate AS t") }) -@Entity -@Table(name = "RHQ_ALERT_NOTIF_TEMPL") -@SequenceGenerator(name = "RHQ_ALERT_NOTIF_TEMPL_ID_SEQ", sequenceName = "RHQ_ALERT_NOTIF_TEMPL_ID_SEQ") -public class AlertNotificationTemplate implements Serializable { - - private static final long serialVersionUID = 1L; - - public static final String FIND_BY_NAME = "AlertNotificationTemplate.findByName"; - public static final String FIND_ALL = "AlertNotificationTemplate.findAll"; - - @Column(name = "ID", nullable = false) - @GeneratedValue(generator = "RHQ_ALERT_NOTIF_TEMPL_ID_SEQ") - @Id - private int id; - - @Column(name = "CTIME") - private long ctime; - - @Column(name = "MTIME") - private long mtime; - - @Column(name = "NAME") - private String name; - - @Column(name = "DESCRIPTION") - private String description; - - @OneToMany(mappedBy = "alertNotificationTemplate", cascade = CascadeType.ALL) - List<AlertNotification> notifications = new ArrayList<AlertNotification>(); - - protected AlertNotificationTemplate() { - // for JPA - } - - public AlertNotificationTemplate(String name, String description) { - this.name = name; - this.description = description; - } - - public int getId() { - return this.id; - } - - public long getCtime() { - return ctime; - } - - public long getMtime() { - return mtime; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return this.description; - } - - public void setDescription(String description) { - this.description = description; - } - - public List<AlertNotification> getNotifications() { - return notifications; - } - - public void setNotifications(List<AlertNotification> notifications) { - this.notifications = notifications; - } - - public List<AlertNotification> addNotification(AlertNotification notification) { - this.notifications.add(notification); - return this.notifications; - } - - @PrePersist - void onPersist() { - this.mtime = this.ctime = System.currentTimeMillis(); - } - - @PreUpdate - void onPreUpdate() { - this.mtime = System.currentTimeMillis(); - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - - AlertNotificationTemplate that = (AlertNotificationTemplate) o; - - if (description != null ? !description.equals(that.description) : that.description != null) - return false; - return name.equals(that.name); - - } - - @Override - public int hashCode() { - int result = name.hashCode(); - result = 31 * result + (description != null ? description.hashCode() : 0); - return result; - } - - @Override - public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append("NotificationTemplate"); - sb.append("{id=").append(id); - sb.append(", name='").append(name).append('''); - sb.append(", description='").append(description).append('''); - sb.append('}'); - return sb.toString(); - } -} diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/alert/AlertNotificationTemplateDetailsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/alert/AlertNotificationTemplateDetailsUIBean.java deleted file mode 100644 index c3bad26..0000000 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/alert/AlertNotificationTemplateDetailsUIBean.java +++ /dev/null @@ -1,90 +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.gui.admin.alert; - -import javax.faces.application.FacesMessage; - -import org.jboss.seam.ScopeType; -import org.jboss.seam.annotations.In; -import org.jboss.seam.annotations.Name; -import org.jboss.seam.annotations.Scope; - -import org.rhq.core.domain.alert.notification.AlertNotificationTemplate; -import org.rhq.core.gui.util.FacesContextUtility; -import org.rhq.enterprise.gui.common.framework.EnterpriseFacesContextUIBean; -import org.rhq.enterprise.server.alert.AlertNotificationManagerLocal; - -@Scope(ScopeType.PAGE) -@Name("AlertNotificationTemplateDetailsUIBean") -public class AlertNotificationTemplateDetailsUIBean extends EnterpriseFacesContextUIBean { - - @In - private AlertNotificationManagerLocal alertNotificationManager; - - private AlertNotificationTemplate template; - - private void loadTemplate() { - if (template == null) { - int templateId = FacesContextUtility.getRequiredRequestParameter("templateId", Integer.class); - template = alertNotificationManager.getAlertNotificationTemplate(getSubject(), templateId); - } - } - - public AlertNotificationTemplate getTemplate() { - loadTemplate(); - - return template; - } - - public int getNotificationCount() { - loadTemplate(); - - return template.getNotifications().size(); - } - - public String edit() { - return OUTCOME_EDIT; - } - - public String editNotifications() { - return OUTCOME_EDIT; - } - - public String save() { - try { - alertNotificationManager.updateNotificationTemplate(getSubject(), template.getId(), template.getName(), - template.getDescription()); - FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, - "Alert notification template was successfully modified."); - } catch (Throwable t) { - FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, - "Error while saving alert notification template: " + t.getMessage()); - } - - return OUTCOME_SAVE; - } - - public String cancel() { - FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, - "Alert notification template modifications were cancelled."); - - return OUTCOME_CANCELLED; - } - -} diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/alert/ListAlertNotificationTemplatesUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/alert/ListAlertNotificationTemplatesUIBean.java deleted file mode 100644 index dd63d29..0000000 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/alert/ListAlertNotificationTemplatesUIBean.java +++ /dev/null @@ -1,76 +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.gui.admin.alert; - -import java.util.List; - -import javax.faces.application.FacesMessage; - -import org.jboss.seam.ScopeType; -import org.jboss.seam.annotations.In; -import org.jboss.seam.annotations.Name; -import org.jboss.seam.annotations.Scope; - -import org.rhq.core.domain.alert.notification.AlertNotificationTemplate; -import org.rhq.core.domain.auth.Subject; -import org.rhq.core.domain.util.PageControl; -import org.rhq.core.domain.util.PageList; -import org.rhq.core.gui.util.FacesContextUtility; -import org.rhq.core.gui.util.StringUtility; -import org.rhq.enterprise.gui.common.framework.EnterpriseFacesContextUIBean; -import org.rhq.enterprise.server.alert.AlertNotificationManagerLocal; - -@Scope(ScopeType.PAGE) -@Name("ListAlertNotificationTemplatesUIBean") -public class ListAlertNotificationTemplatesUIBean extends EnterpriseFacesContextUIBean { - - @In - private AlertNotificationManagerLocal alertNotificationManager; - - public PageList<AlertNotificationTemplate> getAlertNotificationTemplates() { - List<AlertNotificationTemplate> templates = alertNotificationManager.listNotificationTemplates(getSubject()); - return new PageList<AlertNotificationTemplate>(templates, new PageControl(0, templates.size())); - } - - public String deleteSelectedAlertNotificationTemplates() { - try { - Subject subject = getSubject(); - String[] selectedNotificationTemplates = getSelectedNotificationTemplates(); - Integer[] selectedNotificationTemplateIds = StringUtility.getIntegerArray(selectedNotificationTemplates); - int deleted = alertNotificationManager - .deleteNotificationTemplates(subject, selectedNotificationTemplateIds); - FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Deleted " + deleted - + " alert notification templates"); - } catch (Throwable t) { - FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, "Deletion failed: " + t.getMessage()); - } - - return OUTCOME_SUCCESS; - } - - public String createNewAlertNotificationTemplate() { - return OUTCOME_CREATE; - } - - private String[] getSelectedNotificationTemplates() { - String[] results = FacesContextUtility.getRequest().getParameterValues("selectedNotificationTemplates"); - return results; - } - -} diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/alert/NewAlertNotificationTemplateUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/alert/NewAlertNotificationTemplateUIBean.java deleted file mode 100644 index b2e0b07..0000000 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/admin/alert/NewAlertNotificationTemplateUIBean.java +++ /dev/null @@ -1,86 +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.gui.admin.alert; - -import java.util.ArrayList; - -import javax.faces.application.FacesMessage; - -import org.jboss.seam.ScopeType; -import org.jboss.seam.annotations.In; -import org.jboss.seam.annotations.Name; -import org.jboss.seam.annotations.Scope; - -import org.rhq.core.domain.alert.notification.AlertNotification; -import org.rhq.core.domain.alert.notification.AlertNotificationTemplate; -import org.rhq.core.gui.util.FacesContextUtility; -import org.rhq.enterprise.gui.common.framework.EnterpriseFacesContextUIBean; -import org.rhq.enterprise.server.alert.AlertNotificationManagerLocal; - -@Scope(ScopeType.PAGE) -@Name("NewAlertNotificationTemplateUIBean") -public class NewAlertNotificationTemplateUIBean extends EnterpriseFacesContextUIBean { - - @In - private AlertNotificationManagerLocal alertNotificationManager; - - private String name; - private String description; - - private int createdTemplateId; // will be set as a result of create(), used for JSF navigation rules - - public String create() { - try { - AlertNotificationTemplate template = alertNotificationManager.createNotificationTemplate(this.name, - this.description, new ArrayList<AlertNotification>(), true); - createdTemplateId = template.getId(); - FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Created new alert notification template"); - } catch (Throwable t) { - FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, "Creation failed: " + t.getMessage()); - } - - return OUTCOME_SUCCESS; - } - - public String cancel() { - FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Template creation cancelled."); - return OUTCOME_CANCELLED; - } - - public int getCreatedTemplateId() { - return createdTemplateId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - -} diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/CustomContentUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/CustomContentUIBean.java index 758383a..eb7d500 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/CustomContentUIBean.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/CustomContentUIBean.java @@ -59,13 +59,15 @@ public class CustomContentUIBean extends EnterpriseFacesContextUIBean {
AlertNotification activeNotification = alertNotificationManager.getAlertNotification(getSubject(), alertNotificationId); + if (activeNotification == null) { + return; // this was just removed on the previous request + } String senderName = activeNotification.getSenderName();
AlertSenderInfo info = alertNotificationManager.getAlertInfoForSender(senderName);
if (info != null && info.getUiSnippetUrl() != null) { this.contentUrl = info.getUiSnippetUrl().toString(); - //this.contentUrl = "rhq/custom/plugin/alert/" + senderName + "/" + info.getUiSnippetShortPath(); }
String backingBeanName = alertNotificationManager.getBackingBeanNameForSender(senderName); diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/DefinitionNotificationsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/DefinitionNotificationsUIBean.java deleted file mode 100644 index 5b7cbeb..0000000 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/DefinitionNotificationsUIBean.java +++ /dev/null @@ -1,105 +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.gui.alert.common; - -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -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.domain.alert.notification.AlertNotificationTemplate; -import org.rhq.core.gui.util.FacesContextUtility; -import org.rhq.enterprise.gui.common.framework.EnterpriseFacesContextUIBean; -import org.rhq.enterprise.server.alert.AlertNotificationManagerLocal; - -@Scope(ScopeType.EVENT) -@Name("definitionNotificationsUIBean") -public class DefinitionNotificationsUIBean extends EnterpriseFacesContextUIBean { - - @In - private AlertNotificationsUIBean alertNotificationsUIBean; - @In - private AlertNotificationManagerLocal alertNotificationManager; - - private String selectedTemplate; - private Boolean clearExistingNotifications; - private Map<String, String> notificationTemplates; - - public String getSelectedTemplate() { - return selectedTemplate; - } - - public void setSelectedTemplate(String selectedTemplate) { - this.selectedTemplate = selectedTemplate; - } - - public Boolean getClearExistingNotifications() { - return clearExistingNotifications; - } - - public void setClearExistingNotifications(Boolean clearExistingNotifications) { - this.clearExistingNotifications = clearExistingNotifications; - } - - public Map<String, String> getNotificationTemplates() { - return this.notificationTemplates; - } - - public String addAlertSenderFromTemplate() { - int alertDefinitionId = FacesContextUtility.getRequiredRequestParameter("ad", Integer.class); - this.alertNotificationManager.applyNotificationTemplateToAlertDefinition(getSelectedTemplate(), - alertDefinitionId, getClearExistingNotifications()); - this.alertNotificationsUIBean.reloadAlertNotifications(); - return "success"; - } - - @Create - public void init() { - this.notificationTemplates = lookupNotificationTemplates(); - } - - private Map<String, String> lookupNotificationTemplates() { - Map<String, String> result = new TreeMap<String, String>(); - List<AlertNotificationTemplate> templates = this.alertNotificationManager - .listNotificationTemplates(getSubject()); - - for (AlertNotificationTemplate template : templates) { - String displayName = getNotificationDisplayName(template); - result.put(displayName, template.getName()); // displayed text, option value - } - - return result; - } - - private String getNotificationDisplayName(AlertNotificationTemplate template) { - StringBuilder builder = new StringBuilder(template.getName()); - - builder.append(" ("); - builder.append(template.getDescription()); - builder.append(")"); - - return builder.toString(); - } - -} \ No newline at end of file diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/alert/template/notification/details.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/alert/template/notification/details.xhtml deleted file mode 100644 index 69bfcb3..0000000 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/alert/template/notification/details.xhtml +++ /dev/null @@ -1,136 +0,0 @@ -<?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="https://ajax4jsf.dev.java.net/ajax" - xmlns:rich="http://richfaces.ajax4jsf.org/rich%22%3E - -<ui:composition template="/rhq/layout/main.xhtml"> - - <ui:param name="pageTitle" value="Alert Notification Template Details"/> - - <ui:define name="breadcrumbs"> - <h:outputLink value="/rhq/admin/alert/template/notification/list.xhtml"> - <h:outputText value="Alert Notification Templates" /> - </h:outputLink> - <h:outputText value=" > " /> - <h:outputLink value="/rhq/admin/alert/template/notification/details.xhtml"> - <f:param name="templateId" value="#{AlertNotificationTemplateDetailsUIBean.template.id}" /> - <f:param name="mode" value="view" /> - <h:outputText value="Details for '#{AlertNotificationTemplateDetailsUIBean.template.name}'" /> - </h:outputLink> - </ui:define> - - <ui:define name="body"> - - <ui:param name="mode" value="#{param.mode}" /> - - <br/> - <h:messages showDetail="true" - globalOnly="true" - infoClass="InfoBlock" - warnClass="WarnBlock" - errorClass="ErrorBlock" - fatalClass="FatalBlock" - layout="table" /> - - <h:form id="alertNotificationTemplateDetailsForm"> - - <input type="hidden" name="templateId" value="#{param.templateId}" /> - <input type="hidden" name="mode" value="#{param.mode}" /> - - rich:panel - <f:facet name="header"> - General Properties - </f:facet> - <table width="100%"> - <tr> - <td align="right" style="white-space: no-wrap;"><b>Name<span class="required-marker-text">*</span>:</b></td> - <td align="left"> - <h:inputText rendered="${mode eq 'edit'}" value="#{AlertNotificationTemplateDetailsUIBean.template.name}" /> - <h:outputText rendered="${mode ne 'edit'}" value="#{AlertNotificationTemplateDetailsUIBean.template.name}" /> - </td> - </tr> - <tr> - <td align="right" style="white-space: no-wrap;"><b>Description:</b></td> - <td align="left"> - <h:inputText rendered="${mode eq 'edit'}" value="#{AlertNotificationTemplateDetailsUIBean.template.description}" /> - <h:outputText rendered="${mode ne 'edit'}" value="#{AlertNotificationTemplateDetailsUIBean.template.description}" /> - </td> - </tr> - <tr> - <td align="right" style="white-space: no-wrap;"><b>Date Created:</b></td> - <td align="left"> - <h:outputText value="#{AlertNotificationTemplateDetailsUIBean.template.ctime}"> - <f:converter converterId="UserDateTimeConverter" /> - </h:outputText> - </td> - </tr> - <tr> - <td align="right" style="white-space: no-wrap;"><b>Last Modified:</b></td> - <td align="left"> - <h:outputText value="#{AlertNotificationTemplateDetailsUIBean.template.mtime}"> - <f:converter converterId="UserDateTimeConverter" /> - </h:outputText> - </td> - </tr> - </table> - <h:panelGroup layout="block"> - <h:panelGrid columns="3" styleClass="buttons-table" columnClasses="button-cell" > - <h:commandButton action="#{AlertNotificationTemplateDetailsUIBean.edit}" - value="EDIT" styleClass="buttonmed" id="editPropertiesButton" - rendered="${mode ne 'edit'}"/> - <h:commandButton action="#{AlertNotificationTemplateDetailsUIBean.save}" - value="SAVE" styleClass="buttonmed" id="saveButton" - rendered="${mode eq 'edit'}"/> - <h:commandButton action="#{AlertNotificationTemplateDetailsUIBean.cancel}" - value="CANCEL" styleClass="buttonmed" id="cancelButton" immediate="true" - rendered="${mode eq 'edit'}"/> - </h:panelGrid> - </h:panelGroup> - </rich:panel> - <br/> - <rich:panel rendered="${mode ne 'edit'}"> - <f:facet name="header"> - Notification Actions - </f:facet> - <table width="100%"> - <tr> - <td align="right" style="white-space: no-wrap;" width="20%"><b>Sender Info:</b></td> - <td align="left"> - <h:outputText value="#{AlertNotificationTemplateDetailsUIBean.notificationCount} " /> - <h:outputText value="${msg['alert.current.detail.notify.Message']}" /> - </td> - </tr> - </table> - <h:panelGroup layout="block"> - <h:panelGrid columns="3" styleClass="buttons-table" columnClasses="button-cell" > - <h:commandButton action="#{AlertNotificationTemplateDetailsUIBean.editNotifications}" - value="EDIT" styleClass="buttonmed" id="editNotificationsButton" /> - </h:panelGrid> - </h:panelGroup> - </rich:panel> - - ui:remove - <ui:include src="/rhq/common/alert/notification/details.xhtml" - rendered="${mode eq 'edit'}"> - <ui:param name="redirect" value="/rhq/admin/alert/template/notification/details.xhtml?mode=view&templateId=#{param.templateId}" /> - </ui:include> - </ui:remove> - - </h:form> - - </ui:define> - -</ui:composition> - -</html> diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/alert/template/notification/list.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/alert/template/notification/list.xhtml deleted file mode 100644 index 3b2c868..0000000 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/alert/template/notification/list.xhtml +++ /dev/null @@ -1,146 +0,0 @@ -<?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:a4j="http://richfaces.org/a4j" - xmlns:rich="http://richfaces.ajax4jsf.org/rich%22%3E - -<ui:composition template="/rhq/layout/main.xhtml"> - - <ui:param name="pageTitle" value="List Alert Notification Templates"/> - - <ui:define name="metaHeaders"> - <style> - #senderName { - display: none; - } - </style> - </ui:define> - - <ui:define name="breadcrumbs"> - <h:outputLink value="/rhq/admin/alert/template/notification/list.xhtml"> - <h:outputText value="Alert Notification Templates" /> - </h:outputLink> - </ui:define> - - <ui:define name="body"> - <br/> - <h:messages showDetail="true" - globalOnly="true" - infoClass="InfoBlock" - warnClass="WarnBlock" - errorClass="ErrorBlock" - fatalClass="FatalBlock" - layout="table" /> - - <h:form id="listAlertNotificationTemplatesForm"> - rich:panel - <f:facet name="header"> - <h:outputText value="Alert Notification Templates"/> - </f:facet> - - <h:panelGrid columns="1" styleClass="data-table"> - <h:outputText value="*Templates are groups of notifications that can be applied to alert definitions en masse" /> - <br/> - - <ui:param name="notificationTemplateDataModel" value="#{ListAlertNotificationTemplatesUIBean.alertNotificationTemplates}"/> - <rich:dataTable id="notificationTemplateDataModel" - rows="0" - value="#{notificationTemplateDataModel}" - var="notificationTemplate" - width="100%" - columnsWidth="1%, 30%, 40%, 15%, 15%" - styleClass="resources-table" - headerClass="tableRowHeader" - footerClass="on-pager-footer" - onRowMouseOver="this.style.backgroundColor='#E7E7E7'" - onRowMouseOut="this.style.backgroundColor='#{a4jSkin.tableBackgroundColor}'"> - - <f:facet name="PageControlView"> - <onc:paginationControl id="NONE" /> - </f:facet> - - rich:column - <f:facet name="header"> - <onc:allSelect target="selectedNotificationTemplates" /> - </f:facet> - - <onc:select name="selectedNotificationTemplates" value="#{notificationTemplate.id}" /> - </rich:column> - - rich:column - <f:facet name="header"> - <onc:sortableColumnHeader sort="name"> - <h:outputText styleClass="headerText" value="Name" /> - </onc:sortableColumnHeader> - </f:facet> - - <h:outputLink value="/rhq/admin/alert/template/notification/details.xhtml"> - <f:param name="templateId" value="#{notificationTemplate.id}" /> - <f:param name="mode" value="view" /> - <h:outputText value="#{notificationTemplate.name}" /> - </h:outputLink> - </rich:column> - - rich:column - <f:facet name="header"> - <onc:sortableColumnHeader sort="description"> - <h:outputText styleClass="headerText" value="Description" /> - </onc:sortableColumnHeader> - </f:facet> - - <h:outputText value="#{notificationTemplate.description}" /> - </rich:column> - - rich:column - <f:facet name="header"> - <onc:sortableColumnHeader sort="ctime"> - <h:outputText styleClass="headerText" value="Created" /> - </onc:sortableColumnHeader> - </f:facet> - - <h:outputText value="#{notificationTemplate.ctime}"> - <f:converter converterId="UserDateTimeConverter" /> - </h:outputText> - </rich:column> - - rich:column - <f:facet name="header"> - <onc:sortableColumnHeader sort="mtime"> - <h:outputText styleClass="headerText" value="Last Modified" /> - </onc:sortableColumnHeader> - </f:facet> - - <h:outputText value="#{notificationTemplate.mtime}"> - <f:converter converterId="UserDateTimeConverter" /> - </h:outputText> - </rich:column> - - <f:facet name="footer"> - rich:columnGroup - <rich:column colspan="5" width="100%"> - <h:commandButton action="#{ListAlertNotificationTemplatesUIBean.createNewAlertNotificationTemplate}" - value="CREATE NEW" styleClass="on-pager-button buttonsmall" - rendered="#{GlobalPermissionsUIBean.inventory}" /> - <onc:selectCommandButton action="#{ListAlertNotificationTemplatesUIBean.deleteSelectedAlertNotificationTemplates}" - value="DELETE SELECTED" target="selectedNotificationTemplates" styleClass="on-pager-button buttonsmall" - rendered="#{GlobalPermissionsUIBean.inventory}" /> - </rich:column> - </rich:columnGroup> - </f:facet> - - <h:outputText value="Templates are groups of preconfigured alert notifications that can later be applied to alert definitions" /> - - </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/admin/alert/template/notification/new.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/alert/template/notification/new.xhtml deleted file mode 100644 index 25862c1..0000000 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/alert/template/notification/new.xhtml +++ /dev/null @@ -1,74 +0,0 @@ -<?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="https://ajax4jsf.dev.java.net/ajax" - xmlns:rich="http://richfaces.ajax4jsf.org/rich%22%3E - -<ui:composition template="/rhq/layout/main.xhtml"> - - <ui:param name="pageTitle" value="Create New Alert Notification Template"/> - - <ui:define name="breadcrumbs"> - <h:outputLink value="/rhq/admin/alert/template/notification/list.xhtml"> - <h:outputText value="Alert Notification Templates" /> - </h:outputLink> - <h:outputText value=" > " /> - <h:outputLink value="/rhq/admin/alert/template/notification/new.xhtml"> - <h:outputText value="Create New" /> - </h:outputLink> - </ui:define> - - <ui:define name="body"> - - <h:form> - - rich:panel - - <f:facet name="header"> - General Properties - </f:facet> - - <table> - <tr> - <td align="right"><b>Name<span class="required-marker-text">*</span>:</b></td> - <td align="left"> - <h:inputText value="#{NewAlertNotificationTemplateUIBean.name}" size="60" maxlength="100" /> - </td> - </tr> - <tr> - <td align="right"><b>Description:</b></td> - <td align="left"> - <h:inputText value="#{NewAlertNotificationTemplateUIBean.description}" size="60" maxlength="250" /> - </td> - </tr> - </table> - - </rich:panel> - - <h:panelGroup layout="block" styleClass="BlockContent"> - <h:panelGrid columns="2" styleClass="buttons-table" columnClasses="button-cell"> - <h:commandButton action="#{NewAlertNotificationTemplateUIBean.create}" - value="CREATE" styleClass="buttonmed"/> - <h:commandButton action="#{NewAlertNotificationTemplateUIBean.cancel}" - immediate="true" - value="CANCEL" styleClass="buttonmed"/> - </h:panelGrid> - </h:panelGroup> - - </h:form> - - </ui:define> - -</ui:composition> - -</html> diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/alert/notification/details.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/alert/notification/details.xhtml index 74b978e..0c25391 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/alert/notification/details.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/alert/notification/details.xhtml @@ -27,10 +27,8 @@
<ui:define name="body"> <a4j:keepAlive beanName="AlertNotificationContextUIBean" /> - <a4j:keepAlive beanName="alertNotificationStoreUIBean" /> <a4j:keepAlive beanName="alertNotificationsUIBean" /> <a4j:keepAlive beanName="customContentUIBean" /> - <a4j:keepAlive beanName="definitionNotificationsUIBean" />
<rich:panel id="existingAlertsPanel">
@@ -98,15 +96,6 @@ operation="show" event="onclick" /> </h:outputLink> - ui:remove - <h:outputLink id="addAlertTemplateLink" styleClass="buttonmed" value="#" rendered="#{param.context ne 'template'}"> - <h:outputText value="Import Templates" /> - <rich:componentControl for="addAlertFromTemplatePanel" - attachTo="addAlertTemplateLink" - operation="show" - event="onclick" /> - </h:outputLink> - </ui:remove> <h:commandButton id="removeAlertButton" value="Remove Selected" action="#{alertNotificationsUIBean.removeSelected}" @@ -185,55 +174,6 @@ </h:form> </rich:panel> </rich:modalPanel> - - - <rich:modalPanel id="addAlertFromTemplatePanel" moveable="false" autosized="true"> - <rich:panel id="importTemplatesPanel"> - <f:facet name="header"> - <h:outputText value="Import Notifications From Template" style="white-space: nowrap;"/> - </f:facet> - - <h:form id="newNotificationsFromTemplateForm"> - <input type="hidden" name="ad" value="#{param.contextId}"/> - <input type="hidden" name="context" value="#{param.context}"/> - <input type="hidden" name="contextId" value="#{param.contextId}"/> - <input type="hidden" name="contextSubId" value="#{param.contextSubId}"/> - - <rich:panel rendered="#{definitionNotificationsUIBean.notificationTemplates.size ne 0}"> - <div style="height: 100px;"> - <h:selectOneMenu id="templateList" value="#{definitionNotificationsUIBean.selectedTemplate}"> - <f:selectItems value="#{definitionNotificationsUIBean.notificationTemplates}"/> - </h:selectOneMenu> - - <br/> - - <h:selectBooleanCheckbox title="clearExisting" value="#{definitionNotificationsUIBean.clearExistingNotifications}"/> - <h:outputText value="Clear existing notifications"/> - </div> - </rich:panel> - - <rich:panel rendered="#{definitionNotificationsUIBean.notificationTemplates.size eq 0}"> - <div style="height: 100px;"> - No Alert Notification Templates have been defined yet.<br/> - Please create some in Administration -> System Configuration -> Alert Notification Templates - </div> - </rich:panel> - - <h:panelGrid columns="4" styleClass="buttons-table" columnClasses="button-cell"> - <a4j:commandButton value="OK" action="#{definitionNotificationsUIBean.addAlertSenderFromTemplate}" - styleClass="buttonmed" id="addTemplateButton" - reRender="sendersList" - rendered="#{definitionNotificationsUIBean.notificationTemplates.size ne 0}"> - <rich:componentControl for="addAlertFromTemplatePanel" attachTo="addTemplateButton" operation="hide" event="onclick" /> - </a4j:commandButton> - <h:outputLink id="alertTemplateCancelLink" styleClass="buttonmed" value="#" style="float: right; margin: 10px;"> - <h:outputText value="Cancel" /> - <rich:componentControl for="addAlertFromTemplatePanel" attachTo="alertTemplateCancelLink" operation="hide" event="onclick" /> - </h:outputLink> - </h:panelGrid> - </h:form> - </rich:panel> - </rich:modalPanel>
</ui:define>
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java index 0897dc7..3a9a56c 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java @@ -27,7 +27,6 @@ import java.util.Set; import javax.ejb.EJB; import javax.ejb.Stateless; import javax.persistence.EntityManager; -import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; import javax.persistence.Query;
@@ -38,7 +37,6 @@ import org.rhq.core.clientapi.agent.metadata.ConfigurationMetadataParser; import org.rhq.core.domain.alert.AlertDefinition; import org.rhq.core.domain.alert.AlertDefinitionContext; import org.rhq.core.domain.alert.notification.AlertNotification; -import org.rhq.core.domain.alert.notification.AlertNotificationTemplate; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.authz.Permission; import org.rhq.core.domain.configuration.Configuration; @@ -48,7 +46,6 @@ 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.ServerPluginsLocal; import org.rhq.enterprise.server.plugin.pc.alert.AlertSenderInfo; import org.rhq.enterprise.server.plugin.pc.alert.AlertSenderPluginManager; @@ -152,7 +149,9 @@ public class AlertNotificationManagerBean implements AlertNotificationManagerLoc try { bb.internalCleanup(); } catch (Throwable t) { - LOG.error("removeNotifications, calling backingBean.internalCleanup() resulted in " + t.getMessage()); + LOG + .error("removeNotifications, calling backingBean.internalCleanup() resulted in " + t.getMessage(), + t); } }
@@ -163,30 +162,6 @@ public class AlertNotificationManagerBean implements AlertNotificationManagerLoc return removed; }
- public int removeNotificationsFromTemplate(Subject subject, int templateId, Integer[] notificationIds) { - if ((notificationIds == null) || (notificationIds.length == 0)) { - return 0; - } - - AlertNotificationTemplate templ = entityManager.find(AlertNotificationTemplate.class, templateId); - Set<Integer> notificationIdSet = new HashSet<Integer>(Arrays.asList(notificationIds)); - List<AlertNotification> notifications = templ.getNotifications(); - List<AlertNotification> toBeRemoved = new ArrayList<AlertNotification>(); - - int removed = 0; - for (AlertNotification notification : notifications) { - if (notificationIdSet.contains(notification.getId())) { - toBeRemoved.add(notification); - removed--; - } - } - - templ.getNotifications().removeAll(toBeRemoved); - - return removed; - - } - public int purgeOrphanedAlertNotifications() { Query purgeQuery = entityManager.createNamedQuery(AlertNotification.QUERY_DELETE_ORPHANED); return purgeQuery.executeUpdate(); @@ -350,191 +325,15 @@ public class AlertNotificationManagerBean implements AlertNotificationManagerLoc entityManager.flush(); }
- /** - * Take the passed NotificationTemplate and apply its Notifications to the passed AlertDefinition - * @param templateName name of a pre-defined alert NotificationTemplate - * @param alertDefinitionId id of an AlertDefinition on which the template should be applied - * @param removeOldNotifications Shall old Notifications on the Definition be removed? - */ - public void applyNotificationTemplateToAlertDefinition(String templateName, int alertDefinitionId, - boolean removeOldNotifications) { - - AlertNotificationTemplate template = getNotificationTemplateByName(templateName); - - AlertDefinition definition = getDetachedAlertDefinition(alertDefinitionId); - - applyNotificationTemplateToAlertDefinition(template, definition, removeOldNotifications); - } - - private AlertNotificationTemplate getNotificationTemplateByName(String templateName) { - Query q = entityManager.createNamedQuery(AlertNotificationTemplate.FIND_BY_NAME); - q.setParameter("name", templateName); - AlertNotificationTemplate template; - try { - template = (AlertNotificationTemplate) q.getSingleResult(); - } catch (NoResultException nre) { - LOG.info("There is no alert notification template with name '" + templateName + "'"); - template = new AlertNotificationTemplate("dummy", null); - } - return template; - } - - /** - * Take the passed NotificationTemplate and apply its Notifications to the passed AlertDefinition - * @param template NotificationTemplate to apply - * @param def AlertDefinition to apply the template to - * @param removeOldNotifications Shall old Notifications on the Definition be removed? - */ - public void applyNotificationTemplateToAlertDefinition(AlertNotificationTemplate template, AlertDefinition def, - boolean removeOldNotifications) { - - if (removeOldNotifications) - def.getAlertNotifications().clear(); - - for (AlertNotification notif : template.getNotifications()) { - AlertNotification notification = new AlertNotification(notif, true); - notification.setAlertDefinition(notif.getAlertDefinition()); - entityManager.persist(notification.getConfiguration()); - entityManager.persist(notification); - def.addAlertNotification(notification); // Attach a copy, as the ones in the template should not be shared - } - } - - /** - * Create a new NotificationTemplate from the passed parameters. The passed AlertNotification objects need to have the - * name and sender and any configuration properties already set; alert definitions must not be set. - * @param name name of this notification template. Must be unique - * @param description description of the template - * @param notifications notifications that make up the template - * @param copyNotifications - * @return the newly created template - * @throws IllegalArgumentException when a template with the passed name already exists - */ - @SuppressWarnings("unchecked") - @RequiredPermission(Permission.MANAGE_INVENTORY) - public AlertNotificationTemplate createNotificationTemplate(String name, String description, - List<AlertNotification> notifications, boolean copyNotifications) throws IllegalArgumentException { - - Query q = entityManager.createNamedQuery(AlertNotificationTemplate.FIND_BY_NAME); - q.setParameter("name", name); - List<AlertNotificationTemplate> tmp = q.getResultList(); - if (tmp.size() > 0) { - throw new IllegalArgumentException("AlertNotificationTemplate with name [" + name + "] already exists"); - } - - AlertNotificationTemplate templ = new AlertNotificationTemplate(name, description); - entityManager.persist(templ); - for (AlertNotification n : notifications) { - if (copyNotifications) { - // AlertNotification alNo = n.copyWithAlertDefintion() TODO implement / fix this - } else { - n.setAlertNotificationTemplate(templ); - templ.addNotification(n); - entityManager.persist(n); - } - - } - return templ; - } - - @RequiredPermission(Permission.MANAGE_INVENTORY) - public void updateNotificationTemplate(Subject subject, int templateId, String newName, String newDescription) { - AlertNotificationTemplate template = getAlertNotificationTemplate(subject, templateId); - template.setName(newName); - template.setDescription(newDescription); - entityManager.merge(template); - } - - /** - * Delete the passed Notification Templates - * @param subject subject of the caller - * @param templateIds ids of the templates to delete - * @return number of templates deleted - */ - public int deleteNotificationTemplates(Subject subject, Integer[] templateIds) { - if (templateIds.length == 0) - return 0; - - int num = 0; - for (int id : templateIds) { - AlertNotificationTemplate templ = entityManager.find(AlertNotificationTemplate.class, id); - if (templ == null) { - LOG.warn("No notification template found with id [" + id + "]"); - continue; - } - entityManager.remove(templ); - num++; - } - - return num; - } - - /** - * Add a new alert Notification to a template - * @param user subject of the caller - * @param templateName name of the NotificationTemplate to use - * @param sender the alert sender to use - * @param notificationName the name of this notification - * @param notificationConfiguration the configuration of this AlertNotification - * @return the new AlertNotification - */ - public AlertNotification addAlertNotificationToTemplate(Subject user, int templateId, String sender, - String notificationName, Configuration notificationConfiguration) { - - AlertNotificationTemplate template = entityManager.find(AlertNotificationTemplate.class, templateId); - - entityManager.persist(notificationConfiguration); - AlertNotification alertNotification = new AlertNotification(sender); - alertNotification.setConfiguration(notificationConfiguration); - alertNotification.setAlertNotificationTemplate(template); - entityManager.persist(alertNotification); - template.addNotification(alertNotification); - - return alertNotification; - - } - - public List<AlertNotification> getNotificationsForTemplate(Subject subject, int templateId) { - - AlertNotificationTemplate template = entityManager.find(AlertNotificationTemplate.class, templateId); - if (template == null) { - LOG.error("DId not find notification template for id [" + templateId + "]"); - return new ArrayList<AlertNotification>(); - } - - List<AlertNotification> notifications = template.getNotifications(); - for (AlertNotification notification : notifications) { - notification.getConfiguration().getProperties().size(); // eager load - } - - return notifications; - } - - /** - * Get all defined notification templates in the system along with their AlertNotifications - * @param user Subject of the caller - * @return List of all defined alert notification templates - */ - @SuppressWarnings("unchecked") - public List<AlertNotificationTemplate> listNotificationTemplates(Subject user) { - - Query q = entityManager.createNamedQuery(AlertNotificationTemplate.FIND_ALL); - List<AlertNotificationTemplate> ret = q.getResultList(); - - return ret; - } - public AlertNotification getAlertNotification(Subject user, int alertNotificationId) { AlertNotification notification = entityManager.find(AlertNotification.class, alertNotificationId); - notification.getConfiguration().getProperties().size(); // eager load the alert properties + if (notification == null) { + return null; + } + if (notification.getConfiguration() != null) { // an "incomplete" notification might not have a config yet + notification.getConfiguration().getProperties().size(); // eager load the alert properties + } return notification; }
- public AlertNotificationTemplate getAlertNotificationTemplate(Subject user, int alertNotificationTemplateId) { - AlertNotificationTemplate template = entityManager.find(AlertNotificationTemplate.class, - alertNotificationTemplateId); - template.getNotifications().size(); // eager load the children alert notifications - return template; - } - } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerLocal.java index 9db80cc..bfa4dbf 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerLocal.java @@ -22,9 +22,7 @@ import java.util.List;
import javax.ejb.Local;
-import org.rhq.core.domain.alert.AlertDefinition; import org.rhq.core.domain.alert.notification.AlertNotification; -import org.rhq.core.domain.alert.notification.AlertNotificationTemplate; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; @@ -93,15 +91,6 @@ public interface AlertNotificationManagerLocal { AlertSenderInfo getAlertInfoForSender(String shortName);
/** - * Take the passed NotificationTemplate and apply its Notifications to the passed AlertDefinition - * @param template NotificationTemplate to apply - * @param def AlertDefinition to apply the template to - * @param removeOldNotifications Shall old Notifications on the Definition be removed? - */ - void applyNotificationTemplateToAlertDefinition(AlertNotificationTemplate template, AlertDefinition def, - boolean removeOldNotifications); - - /** * Return the backing bean for the AlertSender with the passed shortNama * @param shortName name of a sender * @param alertNotificationId @@ -111,62 +100,5 @@ public interface AlertNotificationManagerLocal {
String getBackingBeanNameForSender(String shortName);
- /** - * Create a new NotificationTemplate from the passed parameters. The passed AlertNotification objects need to have the - * name and sender and any configuration properties already set; alert definitions must not be set. - * @param name name of this notification template. Must be unique - * @param description description of the template - * @param notifications notifications that make up the template - * @param copyNotifications - * @return the newly created template - * @throws IllegalArgumentException when a template with the passed name already exists - */ - AlertNotificationTemplate createNotificationTemplate(String name, String description, - List<AlertNotification> notifications, boolean copyNotifications) throws IllegalArgumentException; - - void updateNotificationTemplate(Subject subject, int templateId, String newName, String newDescription); - - /** - * Get all defined notification templates in the system along with their AlertNotifications - * @param user Subject of the caller - * @return List of all defined alert notification templates - */ - List<AlertNotificationTemplate> listNotificationTemplates(Subject user); - AlertNotification getAlertNotification(Subject user, int alertNotificationId); - - AlertNotificationTemplate getAlertNotificationTemplate(Subject user, int alertNotificationTemplateId); - - /** - * Take the passed NotificationTemplate and apply its Notifications to the passed AlertDefinition - * @param templateName name of a pre-defined alert NotificationTemplate - * @param alertDefinitionId id of an AlertDefinition on which the template should be applied - * @param removeOldNotifications Shall old Notifications on the Definition be removed? - */ - void applyNotificationTemplateToAlertDefinition(String templateName, int alertDefinitionId, - boolean removeOldNotifications); - - /** - * Add a new alert Notification to a template - * @param user subject of the caller - * @param templateName name of the NotificationTemplate to use - * @param sender the alert sender to use - * @param notificationName the name of this notification - * @param notificationConfiguration the configuration of this AlertNotification - * @return the new AlertNotification - */ - AlertNotification addAlertNotificationToTemplate(Subject user, int templateId, String sender, - String notificationName, Configuration notificationConfiguration); - - int removeNotificationsFromTemplate(Subject subject, int templateId, Integer[] notificationIds); - - List<AlertNotification> getNotificationsForTemplate(Subject subject, int templateId); - - /** - * Delete the passed Notification Templates - * @param subject subject of the caller - * @param templateIds ids of the templates to delete - * @return number of templates deleted - */ - int deleteNotificationTemplates(Subject subject, Integer[] templateIds); }
commit e782aced9325fee8159672fb037eb96c3da74050 Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Apr 27 11:09:57 2010 -0400
Additional check for proper prop def merging
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java index 238c3c6..e4c608c 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java @@ -445,13 +445,20 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa * @param newProperty the new prop that should replace the existing prop */ private void replaceListPropertyMemberDefinition(PropertyDefinitionList exList, PropertyDefinitionList newList) { - PropertyDefinition doomedMember = exList.getMemberDefinition(); + PropertyDefinition doomedMember = null; + + // only remove the existing member if it is a different entity + if (exList.getMemberDefinition().getId() != newList.getMemberDefinition().getId()) { + doomedMember = exList.getMemberDefinition(); + }
exList.setMemberDefinition(newList.getMemberDefinition()); exList.setMax(newList.getMax()); exList.setMin(newList.getMin());
- entityManager.remove(doomedMember); + if (null != doomedMember) { + entityManager.remove(doomedMember); + } entityManager.merge(exList); entityManager.flush(); }
commit 36b1e605cad08f003af34fb8d51733142637534e Merge: 229a6c4... cc8f2db... Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Apr 27 10:34:00 2010 -0400
Merge branch 'master' into master-jay
commit cc8f2db67869ec32176c5160bc2adb195fdbb678 Author: Joseph Marques joseph@redhat.com Date: Tue Apr 27 09:46:42 2010 -0400
small fix to dbsetup script data
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/search-data.xml b/modules/core/dbutils/src/main/scripts/dbsetup/search-data.xml index da98622..380ef0f 100644 --- a/modules/core/dbutils/src/main/scripts/dbsetup/search-data.xml +++ b/modules/core/dbutils/src/main/scripts/dbsetup/search-data.xml @@ -5,18 +5,18 @@ <!-- overlord-created, global, default saved searches --> <table name="RHQ_SAVED_SEARCH"> <data ID="1" - CONTEXT="Resource" + CONTEXT="RESOURCE" NAME="Downed Platforms" DESCRIPTION="All downed machines across the entire enterprise" - PATTERN="down platform" + PATTERN="availability=down category=platform" LAST_COMPUTE_TIME="0" SUBJECT_ID="1" GLOBAL="TRUE" /> <data ID="2" - CONTEXT="Resource" + CONTEXT="RESOURCE" NAME="Downed Servers" DESCRIPTION="All downed servers across the entire enterprise" - PATTERN="down server" + PATTERN="availability=down category=server" LAST_COMPUTE_TIME="0" SUBJECT_ID="1" GLOBAL="TRUE" />
commit 229a6c47e809481ea9011698dc46a58ca574875f Merge: d3fa4b8... d3cc735... Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Apr 27 09:45:34 2010 -0400
Merge branch 'master' into master-jay
commit d3fa4b8aceb726dc8eda7c6164e4693cb415512c Author: Jay Shaughnessy jshaughn@redhat.com Date: Tue Apr 27 09:43:59 2010 -0400
Test failure showed some bad behavior with respect to the handling of PropDefEnumerations, their cleanup and their order indexing. To resolve I've basically moved ordering logic from the PDE to the PropDefSimple, which uses the enumerated values. In more detail: - remove the PrePersist/PreUpdate orderIndex setting from PDE. this didn't always work, and was the source of the test failure, it relied on the encompassing PDS being fully formed, which it may not be. - Add logic to PDS to assign sane orderIndexes at the time the enumerations are set/added/removed. - update the config metadata update logic analogously, and improve cleanup of obsolete config defs. - updated and reenabled the previously failing tests
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionEnumeration.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionEnumeration.java index 3781d13..fbcabb4 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionEnumeration.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionEnumeration.java @@ -31,8 +31,6 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; -import javax.persistence.PrePersist; -import javax.persistence.PreUpdate; import javax.persistence.SequenceGenerator; import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; @@ -63,7 +61,7 @@ public class PropertyDefinitionEnumeration implements Serializable { private String value;
@Column(name = "ORDER_INDEX", nullable = false) - private int orderIndex; + private int orderIndex = -1;
@Column(name = "IS_DEFAULT") private boolean isDefault; @@ -87,11 +85,13 @@ public class PropertyDefinitionEnumeration implements Serializable { this.isDefault = isDefault; }
- @PrePersist - @PreUpdate - public void updateOrder() { - this.orderIndex = this.propertyDefinitionSimple.getEnumeratedValues().indexOf(this); - } + // @PrePersist + // @PreUpdate + // public void updateOrder() { + // if (this.orderIndex < 0) { + // this.orderIndex = this.propertyDefinitionSimple.getEnumeratedValues().indexOf(this); + // } + // }
public PropertyDefinitionSimple getPropertyDefinitionSimple() { return propertyDefinitionSimple; diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionSimple.java b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionSimple.java index 3a7be2c..a27b677 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionSimple.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/configuration/definition/PropertyDefinitionSimple.java @@ -157,12 +157,30 @@ public class PropertyDefinitionSimple extends PropertyDefinition { public void setEnumeratedValues(List<PropertyDefinitionEnumeration> enumeratedValues, boolean allowCustomEnumValue) { this.enumeratedValues = enumeratedValues; this.allowCustomEnumeratedValue = allowCustomEnumValue; + ensureOrdering(); }
public void addEnumeratedValues(PropertyDefinitionEnumeration... enumerations) { for (PropertyDefinitionEnumeration enumeration : enumerations) { - getEnumeratedValues().add(enumeration); enumeration.setPropertyDefinitionSimple(this); + getEnumeratedValues().add(enumeration); + } + ensureOrdering(); + } + + public void removeEnumeratedValues(PropertyDefinitionEnumeration... enumerations) { + for (PropertyDefinitionEnumeration enumeration : enumerations) { + getEnumeratedValues().remove(enumeration); + } + ensureOrdering(); + } + + private void ensureOrdering() { + if (null == this.enumeratedValues) { + return; + } + for (int i = 0, size = getEnumeratedValues().size(); (i < size); ++i) { + getEnumeratedValues().get(i).setOrderIndex(i); } }
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java index 4abf76f..238c3c6 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/configuration/metadata/ConfigurationMetadataManagerBean.java @@ -30,6 +30,7 @@ import javax.persistence.PersistenceContext;
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.Property; import org.rhq.core.domain.configuration.PropertySimple; @@ -274,8 +275,7 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa * @param existingProperties list of existing properties to inspect for potential removal */ private void removeNoLongerUsedProperties(ConfigurationDefinition newConfigDef, - ConfigurationDefinition existingConfigDef, - List<PropertyDefinition> existingProperties) { + ConfigurationDefinition existingConfigDef, List<PropertyDefinition> existingProperties) { List<PropertyDefinition> propDefsToDelete = new ArrayList<PropertyDefinition>(); for (PropertyDefinition existingPropDef : existingProperties) { PropertyDefinition newPropDef = newConfigDef.get(existingPropDef.getName()); @@ -350,14 +350,8 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa PropertyDefinitionList exList = (PropertyDefinitionList) existingProperty; if (newProperty instanceof PropertyDefinitionList) { PropertyDefinitionList newList = (PropertyDefinitionList) newProperty; - exList.setMemberDefinition(newList.getMemberDefinition()); - exList.setMax(newList.getMax()); - exList.setMin(newList.getMax()); - // what about parentPropertyListDefinition ? - - // TODO recursively update the member ? - } else // simple property or map-property - { + replaceListPropertyMemberDefinition(exList, newList); + } else { // simple property or map-property replaceProperty(existingProperty, newProperty); } } else if (existingProperty instanceof PropertyDefinitionSimple) { @@ -374,12 +368,11 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa List<PropertyDefinitionEnumeration> toDelete = missingInFirstList(newOptions, existingOptions); List<PropertyDefinitionEnumeration> changed = intersection(existingOptions, newOptions);
- // TODO GH: This still doesn't properly reorder options, but at least it doesn't leave any nulls - // and therefore doesn't blow up the renderer - // delete old ones (first so we don't leave index holes later) + // sync the enumerated values and then merge the changes into the PDS, I think this + // solves previous issues with orderIndex values. + // First remove obsolete values for (PropertyDefinitionEnumeration pde : toDelete) { - existingOptions.remove(pde); - entityManager.remove(pde); + existingPDS.removeEnumeratedValues(pde); }
// save new ones @@ -388,16 +381,16 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa entityManager.persist(pde); }
+ // update others for (PropertyDefinitionEnumeration pde : changed) { for (PropertyDefinitionEnumeration nPde : newOptions) { if (nPde.equals(pde)) { pde.setDefault(nPde.isDefault()); - pde.setOrderIndex(nPde.getOrderIndex()); pde.setValue(nPde.getValue()); - entityManager.merge(pde); } } } + entityManager.merge(existingPDS);
// handle <constraint> [0..*]
@@ -444,6 +437,26 @@ public class ConfigurationMetadataManagerBean implements ConfigurationMetadataMa }
/** + * This replaces the member property for the list. If it is a nested structure the whole thing + * is replaced from the top. The previous member property is removed. cascading should remove a nested + * structure. + * + * @param existingProperty the existing prop + * @param newProperty the new prop that should replace the existing prop + */ + private void replaceListPropertyMemberDefinition(PropertyDefinitionList exList, PropertyDefinitionList newList) { + PropertyDefinition doomedMember = exList.getMemberDefinition(); + + exList.setMemberDefinition(newList.getMemberDefinition()); + exList.setMax(newList.getMax()); + exList.setMin(newList.getMin()); + + entityManager.remove(doomedMember); + entityManager.merge(exList); + entityManager.flush(); + } + + /** * Return a list containing those element that are in reference, but not in first. Both input lists are not modified * * @param first diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java index 0dc958a..4a07bb7 100644 --- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java +++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateConfigurationSubsystemTest.java @@ -581,187 +581,176 @@ public class UpdateConfigurationSubsystemTest extends UpdateSubsytemTestBase { } }
- // TODO (jshaughn) For some reason this test is creating a ConfigDef that Hibernate chokes on. Need - // to come back and figure out why. Perhaps it's oracle specific... Also, if activated update - // cleanup routine in TestBase to delete myPlatform6. - @Test(enabled = false) - public void testListProperty() throws Exception { - // Note, plugins are registered in new transactions. for tests, this means - // you can't do everything in a trans and roll back at the end. You must clean up - // manually. + @Test(enabled = ENABLED) + public void testListOfLists() throws Exception { try { - { // extra block for variable scoping purposes - registerPlugin("propertyList-v1.xml"); - ResourceType platform = getResourceType("myPlatform6"); - getTransactionManager().begin(); - EntityManager em = getEntityManager(); - platform = em.find(ResourceType.class, platform.getId()); - - ConfigurationDefinition cd = platform.getResourceConfigurationDefinition(); - Map<String, PropertyDefinition> propDefs = cd.getPropertyDefinitions(); - assert propDefs.size() == 4 : "Expected to see 4 <list-property>s in v1, but got " + propDefs.size(); - for (PropertyDefinition def : propDefs.values()) { - assert def instanceof PropertyDefinitionList : "PropertyDefinition " + def.getName() - + " is no list-property in v1"; - PropertyDefinitionList pdl = (PropertyDefinitionList) def; - PropertyDefinition member = pdl.getMemberDefinition(); - - if (pdl.getName().equals("myList1")) { - assert pdl.getDescription().equals("Just a simple list"); - assert member instanceof PropertyDefinitionSimple : "Expected the member of myList1 to be a simple property in v1"; - PropertyDefinitionSimple pds = (PropertyDefinitionSimple) member; - assert pds.getName().equals("foo"); - } else if (pdl.getName().equals("myList2")) { - assert member instanceof PropertyDefinitionList : "Expected the member of myList2 to be a list property in v1"; - } else if (pdl.getName().equals("myList3")) { - assert member instanceof PropertyDefinitionSimple : "Expected the member of myList3 to be a simple property in v1"; - PropertyDefinitionSimple pds = (PropertyDefinitionSimple) member; - assert pds.getName().equals("baz"); - } else if (pdl.getName().equals("rec1")) { - assert member instanceof PropertyDefinitionList : "Expected the member of rc1 to be a list property in v1"; - PropertyDefinitionList pdl2 = (PropertyDefinitionList) member; - - // TODO check min/max for the lists on the way. Commented out. See JBNADM-1595 - assert pdl2.getName().equals("rec2"); - - // assert pdl2.getMin()==2 : "Expected rec2:min to be 2, but it was " + pdl2.getMin(); - // assert pdl2.getMax()==20; - pdl2 = (PropertyDefinitionList) pdl2.getMemberDefinition(); - assert pdl2.getName().equals("rec3"); - - // assert pdl2.getMin()==3; - // assert pdl2.getMax()==30; - pdl2 = (PropertyDefinitionList) pdl2.getMemberDefinition(); - assert pdl2.getName().equals("rec4"); - - // assert pdl2.getMin()==4; - // assert pdl2.getMax()==40; - assert pdl2.getMemberDefinition() instanceof PropertyDefinitionSimple; - PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pdl2.getMemberDefinition(); - assert pds.getName().equals("rec5"); - assert pds.getDescription().equals("Deeply nested"); - List<PropertyDefinitionEnumeration> options = pds.getEnumeratedValues(); - assert options.size() == 4; - int found = 0; - String[] optionVals = new String[] { "a", "b", "c", "d" }; - for (PropertyDefinitionEnumeration option : options) { - if (containedIn(option.getValue(), optionVals)) { - found++; - } + // extra block for variable scoping purposes + registerPlugin("propertyList-v1.xml"); + ResourceType platform = getResourceType("myPlatform6"); + getTransactionManager().begin(); + EntityManager em = getEntityManager(); + platform = em.find(ResourceType.class, platform.getId()); + ConfigurationDefinition cd = platform.getResourceConfigurationDefinition(); + Map<String, PropertyDefinition> propDefs = cd.getPropertyDefinitions(); + assert propDefs.size() == 4 : "Expected to see 4 <list-property>s in v1, but got " + propDefs.size(); + for (PropertyDefinition def : propDefs.values()) { + assert def instanceof PropertyDefinitionList : "PropertyDefinition " + def.getName() + + " is no list-property in v1"; + PropertyDefinitionList pdl = (PropertyDefinitionList) def; + PropertyDefinition member = pdl.getMemberDefinition(); + + if (pdl.getName().equals("myList1")) { + assert pdl.getDescription().equals("Just a simple list"); + assert member instanceof PropertyDefinitionSimple : "Expected the member of myList1 to be a simple property in v1"; + PropertyDefinitionSimple pds = (PropertyDefinitionSimple) member; + assert pds.getName().equals("foo"); + } else if (pdl.getName().equals("myList2")) { + assert member instanceof PropertyDefinitionList : "Expected the member of myList2 to be a list property in v1"; + } else if (pdl.getName().equals("myList3")) { + assert member instanceof PropertyDefinitionSimple : "Expected the member of myList3 to be a simple property in v1"; + PropertyDefinitionSimple pds = (PropertyDefinitionSimple) member; + assert pds.getName().equals("baz"); + } else if (pdl.getName().equals("rec1")) { + assert member instanceof PropertyDefinitionList : "Expected the member of rc1 to be a list property in v1"; + PropertyDefinitionList pdl2 = (PropertyDefinitionList) member; + + // TODO check min/max for the lists on the way. Commented out. See JBNADM-1595 + assert pdl2.getName().equals("rec2"); + + // assert pdl2.getMin()==2 : "Expected rec2:min to be 2, but it was " + pdl2.getMin(); + // assert pdl2.getMax()==20; + pdl2 = (PropertyDefinitionList) pdl2.getMemberDefinition(); + assert pdl2.getName().equals("rec3"); + + // assert pdl2.getMin()==3; + // assert pdl2.getMax()==30; + pdl2 = (PropertyDefinitionList) pdl2.getMemberDefinition(); + assert pdl2.getName().equals("rec4"); + + // assert pdl2.getMin()==4; + // assert pdl2.getMax()==40; + assert pdl2.getMemberDefinition() instanceof PropertyDefinitionSimple; + PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pdl2.getMemberDefinition(); + assert pds.getName().equals("rec5"); + assert pds.getDescription().equals("Deeply nested"); + List<PropertyDefinitionEnumeration> options = pds.getEnumeratedValues(); + assert options.size() == 4; + int found = 0; + String[] optionVals = new String[] { "a", "b", "c", "d" }; + for (PropertyDefinitionEnumeration option : options) { + if (containedIn(option.getValue(), optionVals)) { + found++; } - - assert found == 4; - Set<Constraint> constraints = pds.getConstraints(); - assert constraints.size() == 1; - } else { - assert true == false : "Unknown list-definition in v1: " + pdl.getName(); } + + assert found == 4; + Set<Constraint> constraints = pds.getConstraints(); + assert constraints.size() == 1; + } else { + assert true == false : "Unknown list-definition in v1: " + pdl.getName(); } - getTransactionManager().rollback(); } + getTransactionManager().rollback();
/* * Deploy v2 of the plugin */ - { // extra block for variable scoping purposes - registerPlugin("propertyList-v2.xml"); - ResourceType platform = getResourceType("myPlatform6"); - getTransactionManager().begin(); - EntityManager em = getEntityManager(); - platform = em.find(ResourceType.class, platform.getId()); - - ConfigurationDefinition cd = platform.getResourceConfigurationDefinition(); - Map<String, PropertyDefinition> propDefs = cd.getPropertyDefinitions(); - assert propDefs.size() == 4 : "Expected to see 4 <list-property>s in v2, but got " + propDefs.size(); - for (PropertyDefinition def : propDefs.values()) { - assert def instanceof PropertyDefinitionList : "PropertyDefinition " + def.getName() - + " is no list-property in v2"; - PropertyDefinitionList pdl = (PropertyDefinitionList) def; - PropertyDefinition member = pdl.getMemberDefinition(); - - if (pdl.getName().equals("myList2")) { - assert member instanceof PropertyDefinitionList : "Expected the member of myList2 to be a list property in v2"; - } else if (pdl.getName().equals("myList3")) { - assert member instanceof PropertyDefinitionList : "Expected the member of myList3 to be a list property in v2"; - PropertyDefinitionList pds = (PropertyDefinitionList) member; - assert pds.getName().equals("baz"); - assert pds.getDescription().equals("myList3:baz"); - assert pds.getMemberDefinition() instanceof PropertyDefinitionSimple : "Expected the member of list3:baz to be a simple property in v2"; - } else if (pdl.getName().equals("myList4")) { - assert pdl.getDescription().equals("Just a simple list"); - assert member instanceof PropertyDefinitionSimple : "Expected the member of myList4 to be a simple property in v2"; - PropertyDefinitionSimple pds = (PropertyDefinitionSimple) member; - assert pds.getName().equals("foo"); - } else if (pdl.getName().equals("rec1")) { - assert member instanceof PropertyDefinitionList : "Expected the member of rec1 to be a list property in v2"; - PropertyDefinitionList pdl2 = (PropertyDefinitionList) member; - assert pdl2.getName().equals("rec2"); - - /* - * PropertyDefinitionList.getMin()/getMax() are commented out. See JBNADM1595 - */ + registerPlugin("propertyList-v2.xml"); + platform = getResourceType("myPlatform6"); + getTransactionManager().begin(); + em = getEntityManager(); + platform = em.find(ResourceType.class, platform.getId());
- // assert pdl2.getMin()==12 : "Expected rec2:min to be 12, but it was " + pdl2.getMin(); - // assert pdl2.getMax()==200; - pdl2 = (PropertyDefinitionList) pdl2.getMemberDefinition(); - assert pdl2.getName().equals("rec3+"); - - // assert pdl2.getMin()==13; - // assert pdl2.getMax()==300; - pdl2 = (PropertyDefinitionList) pdl2.getMemberDefinition(); - assert pdl2.getName().equals("rec4"); - - // assert pdl2.getMin()==14; - // assert pdl2.getMax()==400; - assert pdl2.getMemberDefinition() instanceof PropertyDefinitionSimple; - PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pdl2.getMemberDefinition(); - assert pds.getName().equals("rec5"); - assert pds.getDescription().equals("Nested deeply"); - List<PropertyDefinitionEnumeration> options = pds.getEnumeratedValues(); - assert options.size() == 5; - int found = 0; - String[] optionVals = new String[] { "b", "c", "d", "x", "z" }; - for (PropertyDefinitionEnumeration option : options) { - if (containedIn(option.getValue(), optionVals)) { - found++; - } + cd = platform.getResourceConfigurationDefinition(); + propDefs = cd.getPropertyDefinitions(); + assert propDefs.size() == 4 : "Expected to see 4 <list-property>s in v2, but got " + propDefs.size(); + for (PropertyDefinition def : propDefs.values()) { + assert def instanceof PropertyDefinitionList : "PropertyDefinition " + def.getName() + + " is no list-property in v2"; + PropertyDefinitionList pdl = (PropertyDefinitionList) def; + PropertyDefinition member = pdl.getMemberDefinition(); + + if (pdl.getName().equals("myList2")) { + assert member instanceof PropertyDefinitionList : "Expected the member of myList2 to be a list property in v2"; + } else if (pdl.getName().equals("myList3")) { + assert member instanceof PropertyDefinitionList : "Expected the member of myList3 to be a list property in v2"; + PropertyDefinitionList pds = (PropertyDefinitionList) member; + assert pds.getName().equals("baz"); + assert pds.getDescription().equals("myList3:baz"); + assert pds.getMemberDefinition() instanceof PropertyDefinitionSimple : "Expected the member of list3:baz to be a simple property in v2"; + } else if (pdl.getName().equals("myList4")) { + assert pdl.getDescription().equals("Just a simple list"); + assert member instanceof PropertyDefinitionSimple : "Expected the member of myList4 to be a simple property in v2"; + PropertyDefinitionSimple pds = (PropertyDefinitionSimple) member; + assert pds.getName().equals("foo"); + } else if (pdl.getName().equals("rec1")) { + assert member instanceof PropertyDefinitionList : "Expected the member of rec1 to be a list property in v2"; + PropertyDefinitionList pdl2 = (PropertyDefinitionList) member; + assert pdl2.getName().equals("rec2"); + + /* + * PropertyDefinitionList.getMin()/getMax() are commented out. See JBNADM1595 + */ + + // assert pdl2.getMin()==12 : "Expected rec2:min to be 12, but it was " + pdl2.getMin(); + // assert pdl2.getMax()==200; + pdl2 = (PropertyDefinitionList) pdl2.getMemberDefinition(); + assert pdl2.getName().equals("rec3+"); + + // assert pdl2.getMin()==13; + // assert pdl2.getMax()==300; + pdl2 = (PropertyDefinitionList) pdl2.getMemberDefinition(); + assert pdl2.getName().equals("rec4"); + + // assert pdl2.getMin()==14; + // assert pdl2.getMax()==400; + assert pdl2.getMemberDefinition() instanceof PropertyDefinitionSimple; + PropertyDefinitionSimple pds = (PropertyDefinitionSimple) pdl2.getMemberDefinition(); + assert pds.getName().equals("rec5"); + assert pds.getDescription().equals("Nested deeply"); + List<PropertyDefinitionEnumeration> options = pds.getEnumeratedValues(); + assert options.size() == 5; + int found = 0; + String[] optionVals = new String[] { "b", "c", "d", "x", "z" }; + for (PropertyDefinitionEnumeration option : options) { + if (containedIn(option.getValue(), optionVals)) { + found++; } + }
- assert found == optionVals.length; - Set<Constraint> constraints = pds.getConstraints(); - assert constraints.size() == 2; - for (Constraint constraint : constraints) { - if (constraint instanceof IntegerRangeConstraint) { - IntegerRangeConstraint irc = (IntegerRangeConstraint) constraint; - assert irc != null : "Integer-constraint was null, but should not be"; - // See JBNADM-1596/97 - assert irc.getDetails().equals("-2#10"); - // TODO (ips, 3/31/10): The below is a workaround for IntegerRangeConstraint.onLoad() not being called by Hibernate. - irc.setDetails(irc.getDetails()); - assert irc.getMaximum() == 10; - assert irc.getMinimum() == -2; - } else if (constraint instanceof FloatRangeConstraint) { - FloatRangeConstraint frc = (FloatRangeConstraint) constraint; - assert frc != null : "Float-constraint was null, but should not be"; - // See JBNADM-1596/97 - assert frc.getDetails().equals("10.0#5.0"); - // TODO (ips, 3/31/10): The below is a workaround for FloatRangeConstraint.onLoad() not being called by Hibernate. - frc.setDetails(frc.getDetails()); - assert frc.getMinimum() == 10; // TODO change when JBNADM-1597 is being worked on - assert frc.getMaximum() == 5; - - } else { - assert true == false : "Unknown constraint type encountered"; - } + assert found == optionVals.length; + Set<Constraint> constraints = pds.getConstraints(); + assert constraints.size() == 2; + for (Constraint constraint : constraints) { + if (constraint instanceof IntegerRangeConstraint) { + IntegerRangeConstraint irc = (IntegerRangeConstraint) constraint; + assert irc != null : "Integer-constraint was null, but should not be"; + // See JBNADM-1596/97 + assert irc.getDetails().equals("-2#10"); + // TODO (ips, 3/31/10): The below is a workaround for IntegerRangeConstraint.onLoad() not being called by Hibernate. + irc.setDetails(irc.getDetails()); + assert irc.getMaximum() == 10; + assert irc.getMinimum() == -2; + } else if (constraint instanceof FloatRangeConstraint) { + FloatRangeConstraint frc = (FloatRangeConstraint) constraint; + assert frc != null : "Float-constraint was null, but should not be"; + // See JBNADM-1596/97 + assert frc.getDetails().equals("10.0#5.0"); + // TODO (ips, 3/31/10): The below is a workaround for FloatRangeConstraint.onLoad() not being called by Hibernate. + frc.setDetails(frc.getDetails()); + assert frc.getMinimum() == 10; // TODO change when JBNADM-1597 is being worked on + assert frc.getMaximum() == 5; + + } else { + assert true == false : "Unknown constraint type encountered"; } - } else { - assert true == false : "Unknown list-definition in v2: " + pdl.getName(); } - getTransactionManager().rollback(); + } else { + assert true == false : "Unknown list-definition in v2: " + pdl.getName(); } - - // done with v2 } + getTransactionManager().rollback(); + } finally { if (Status.STATUS_NO_TRANSACTION != getTransactionManager().getStatus()) { getTransactionManager().rollback(); @@ -771,7 +760,7 @@ public class UpdateConfigurationSubsystemTest extends UpdateSubsytemTestBase { try { cleanupTest(); } catch (Exception e) { - System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testListProperty"); + System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + ".testListOfLists"); } } } diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateSubsytemTestBase.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateSubsytemTestBase.java index cb3f029..6b5c627 100644 --- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateSubsytemTestBase.java +++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateSubsytemTestBase.java @@ -125,6 +125,7 @@ public class UpdateSubsytemTestBase extends AbstractEJB3Test { Subject overlord = LookupUtil.getSubjectManager().getOverlord();
ResourceTypeCriteria resourceTypeCriteria = new ResourceTypeCriteria(); + resourceTypeCriteria.setStrict(true); resourceTypeCriteria.addFilterName(typeName); resourceTypeCriteria.addFilterPluginName(pluginName);
@@ -274,7 +275,7 @@ public class UpdateSubsytemTestBase extends AbstractEJB3Test { cleanupResourceType("myPlatform3"); cleanupResourceType("myPlatform4"); cleanupResourceType("myPlatform5"); - //cleanupResourceType("myPlatform6"); + cleanupResourceType("myPlatform6"); cleanupResourceType("myPlatform7"); cleanupResourceType("ops"); cleanupResourceType("testApp1"); @@ -323,6 +324,7 @@ public class UpdateSubsytemTestBase extends AbstractEJB3Test {
// delete any resources first ResourceCriteria c = new ResourceCriteria(); + c.setStrict(true); c.addFilterResourceTypeId(rt.getId()); c.addFilterInventoryStatus(InventoryStatus.NEW); List<Resource> doomedResources = resourceManager.findResourcesByCriteria(overlord, c);
commit d2ce45f0122e499162151ef8e927d9d5086dc5ed Author: Joseph Marques joseph@redhat.com Date: Mon Apr 26 17:32:52 2010 -0400
remove name field from alert notifications
diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/CustomAlertSenderUpgradeTask.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/CustomAlertSenderUpgradeTask.java index 0fa4ee8..07c7590 100644 --- a/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/CustomAlertSenderUpgradeTask.java +++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/CustomAlertSenderUpgradeTask.java @@ -75,9 +75,8 @@ public class CustomAlertSenderUpgradeTask implements DatabaseUpgradeTask {
String propertyName = "subjectId"; String senderName = "System Users"; - String name = "User Notifications";
- persist(data, propertyName, senderName, name); + persist(data, propertyName, senderName); }
private void upgradeRoleNotifications() throws SQLException { @@ -91,9 +90,8 @@ public class CustomAlertSenderUpgradeTask implements DatabaseUpgradeTask {
String propertyName = "roleId"; String senderName = "System Roles"; - String name = "Role Notifications";
- persist(data, propertyName, senderName, name); + persist(data, propertyName, senderName); }
private void upgradeEmailNotifications() throws SQLException { @@ -107,9 +105,8 @@ public class CustomAlertSenderUpgradeTask implements DatabaseUpgradeTask {
String propertyName = "emailAddress"; String senderName = "Direct Emails"; - String name = "Email Notifications";
- persist(data, propertyName, senderName, name); + persist(data, propertyName, senderName); }
private void upgradeSNMPNotifications() throws SQLException { @@ -129,7 +126,7 @@ public class CustomAlertSenderUpgradeTask implements DatabaseUpgradeTask {
// buffer will be 0 the very first time, since definitionId is initially -1 int configId = persistConfiguration("host", host, "port", port, "oid", oid); - persistNotification(alertDefinitionId, configId, "SNMP Traps", "SNMP Notifications"); + persistNotification(alertDefinitionId, configId, "SNMP Traps"); } }
@@ -147,11 +144,11 @@ public class CustomAlertSenderUpgradeTask implements DatabaseUpgradeTask { // buffer will be 0 the very first time, since definitionId is initially -1 int configId = persistConfiguration("operation-definition-id", operationDefinitionId, "selection-mode", "SELF"); - persistNotification(alertDefinitionId, configId, "Resource Operations", "Operation Invocation"); + persistNotification(alertDefinitionId, configId, "Resource Operations"); } }
- private void persist(List<Object[]> data, String propertyName, String sender, String name) throws SQLException { + private void persist(List<Object[]> data, String propertyName, String sender) throws SQLException { int definitionId = -1; StringBuilder buffer = new StringBuilder(); for (Object[] next : data) { @@ -162,7 +159,7 @@ public class CustomAlertSenderUpgradeTask implements DatabaseUpgradeTask { if (buffer.length() != 0) { // buffer will be 0 the very first time, since definitionId is initially -1 int configId = persistConfiguration(propertyName, buffer.toString()); - persistNotification(definitionId, configId, sender, name); + persistNotification(definitionId, configId, sender); } buffer = new StringBuilder(); // reset for the next definitionId } @@ -176,7 +173,7 @@ public class CustomAlertSenderUpgradeTask implements DatabaseUpgradeTask {
if (buffer.length() != 0) { int configId = persistConfiguration(propertyName, buffer.toString()); - persistNotification(definitionId, configId, sender, name); + persistNotification(definitionId, configId, sender); } }
@@ -197,9 +194,9 @@ public class CustomAlertSenderUpgradeTask implements DatabaseUpgradeTask { return configId; }
- private void persistNotification(int definitionId, int configId, String sender, String name) throws SQLException { + private void persistNotification(int definitionId, int configId, String sender) throws SQLException { int notificationId = databaseType.getNextSequenceValue(connection, "rhq_alert_notification", "id"); - String insertNotificationSQL = getInsertNotificationSQL(notificationId, definitionId, configId, sender, name); + String insertNotificationSQL = getInsertNotificationSQL(notificationId, definitionId, configId, sender);
databaseType.executeSql(connection, insertNotificationSQL); } @@ -214,9 +211,9 @@ public class CustomAlertSenderUpgradeTask implements DatabaseUpgradeTask { + " VALUES ( " + id + ", " + configId + ", '" + name + "', '" + value + "', 'property' ) "; }
- private String getInsertNotificationSQL(int id, int definitionId, int configId, String sender, String name) { - return "INSERT INTO rhq_alert_notification ( id, alert_definition_id, sender_config_id, sender_name, display_name )" // - + " VALUES ( " + id + ", " + definitionId + ", " + configId + ", '" + sender + "', '" + name + "' ) "; + private String getInsertNotificationSQL(int id, int definitionId, int configId, String sender) { + return "INSERT INTO rhq_alert_notification ( id, alert_definition_id, sender_config_id, sender_name )" // + + " VALUES ( " + id + ", " + definitionId + ", " + configId + ", '" + sender + "' ) "; }
} diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml index 9617057..b2db5f0 100644 --- a/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml +++ b/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml @@ -137,7 +137,6 @@ <column name="TEMPLATE_ID" required="false" type="INTEGER" references="RHQ_ALERT_NOTIF_TEMPL(ID)"/> <column name="SENDER_CONFIG_ID" required="false" type="INTEGER" references="RHQ_CONFIG(ID)"/> <column name="SENDER_NAME" required="true" size="100" type="VARCHAR2" /> - <column name="DISPLAY_NAME" type="VARCHAR2" size="100" /> </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 6974780..d028a43 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -2060,7 +2060,6 @@ <schema-addColumn table="RHQ_ALERT" column="ACK_TIME" columnType="LONG" /> <!-- TODO: this needs to change to ack_subject_name --> <schema-addColumn table="RHQ_ALERT" column="ACK_SUBJECT" precision="100" columnType="VARCHAR2" /> - <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="DISPLAY_NAME" precision="100" columnType="VARCHAR2" /> <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="SENDER_NAME" precision="100" columnType="VARCHAR2" /> <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="SENDER_CONFIG_ID" columnType="INTEGER" /> <schema-directSQL> diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java index 1a7be46..b77d8b0 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java @@ -85,9 +85,6 @@ public class AlertNotification implements Serializable { @Column(name = "SENDER_NAME") private String senderName;
- @Column(name = "DISPLAY_NAME") - private String displayName; - protected AlertNotification() { } // JPA spec
@@ -115,7 +112,6 @@ public class AlertNotification implements Serializable { } else { this.configuration = source.configuration.deepCopy(false); } - this.displayName = source.displayName; this.senderName = source.senderName; }
@@ -129,8 +125,7 @@ public class AlertNotification implements Serializable { this.alertNotificationId = alertNotificationId; }
- public AlertNotification(String displayName, String sender) { - this.displayName = displayName; + public AlertNotification(String sender) { this.senderName = sender; }
@@ -147,22 +142,6 @@ public class AlertNotification implements Serializable { this.alertDefinition = alertDefinition; }
- public AlertNotification copyWithAlertDefintion(AlertDefinition alertDefinition, boolean copyIds) { - Configuration config; - if (copyIds) { - config = this.configuration; - } else { - config = this.configuration.deepCopy(false); - } - AlertNotification notification = new AlertNotification(alertDefinition, config); - if (copyIds) { - notification.id = this.id; - } - notification.setDisplayName(this.displayName); - notification.setSenderName(this.senderName); - return notification; - } - public void prepareForOrphanDelete() { this.alertDefinition = null; } @@ -183,14 +162,6 @@ public class AlertNotification implements Serializable { this.configuration = configuration; }
- public String getDisplayName() { - return displayName; - } - - public void setDisplayName(String displayName) { - this.displayName = displayName; - } - public AlertNotificationTemplate getAlertNotificationTemplate() { return alertNotificationTemplate; } @@ -216,7 +187,6 @@ public class AlertNotification implements Serializable { sb.append(", id=").append(id); sb.append(", notificationTemplate=").append(alertNotificationTemplate); sb.append(", senderName='").append(senderName).append('''); - sb.append(", displayName='").append(displayName).append('''); sb.append('}'); return sb.toString(); } diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/AlertNotificationStoreUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/AlertNotificationStoreUIBean.java deleted file mode 100644 index 05e254e..0000000 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/AlertNotificationStoreUIBean.java +++ /dev/null @@ -1,72 +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.gui.alert.common; - -import java.util.List; - -import org.jboss.seam.ScopeType; -import org.jboss.seam.annotations.Name; -import org.jboss.seam.annotations.Scope; -import org.jboss.seam.annotations.web.RequestParameter; - -import org.rhq.core.domain.alert.notification.AlertNotification; -import org.rhq.core.domain.auth.Subject; -import org.rhq.core.domain.configuration.Configuration; -import org.rhq.enterprise.server.alert.AlertNotificationManagerLocal; -import org.rhq.enterprise.server.util.LookupUtil; - -@Scope(ScopeType.EVENT) -@Name("alertNotificationStoreUIBean") -public class AlertNotificationStoreUIBean { - - @RequestParameter("context") - private String context; - - @RequestParameter("contextId") - private Integer contextId; - - private AlertNotificationManagerLocal alertNotificationManager = LookupUtil.getAlertNotificationManager(); - - public List<AlertNotification> lookupNotifications(Subject subject) { - if (context.equals("template")) { - return this.alertNotificationManager.getNotificationsForTemplate(subject, contextId); - } else { - return this.alertNotificationManager.getNotificationsForAlertDefinition(subject, contextId); - } - } - - public AlertNotification addNotification(Subject subject, String senderType, String notificationName, - Configuration configuration) { - if (context.equals("template")) { - return alertNotificationManager.addAlertNotificationToTemplate(subject, contextId, senderType, - notificationName, configuration); - } else { - return this.alertNotificationManager.addAlertNotification(subject, contextId, senderType, notificationName, - configuration); - } - } - - public void removeNotifications(Subject subject, Integer[] notificationIds) { - if (context.equals("template")) { - this.alertNotificationManager.removeNotificationsFromTemplate(subject, contextId, notificationIds); - } else { - this.alertNotificationManager.removeNotifications(subject, contextId, notificationIds); - } - } -} diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/AlertNotificationsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/AlertNotificationsUIBean.java index f696c3c..80cc829 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/AlertNotificationsUIBean.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/common/AlertNotificationsUIBean.java @@ -49,14 +49,16 @@ public class AlertNotificationsUIBean extends EnterpriseFacesContextUIBean {
@RequestParameter("nid") private Integer notificationId; + @RequestParameter("context") + private String context; + @RequestParameter("contextId") + private Integer contextId; + @In private AlertNotificationManagerLocal alertNotificationManager; - @In(create = true) - private AlertNotificationStoreUIBean alertNotificationStoreUIBean;
private List<AlertNotification> alertNotifications; private Set<AlertNotification> selectedNotifications; - private String newAlertName; private String selectedNewSender; private AlertNotification activeNotification; private ConfigurationDefinition activeConfigDefinition; @@ -79,14 +81,6 @@ public class AlertNotificationsUIBean extends EnterpriseFacesContextUIBean { this.selectedNotifications = selectedNotifications; }
- public String getNewAlertName() { - return newAlertName; - } - - public void setNewAlertName(String newAlertName) { - this.newAlertName = newAlertName; - } - public String getSelectedNewSender() { return selectedNewSender; } @@ -136,7 +130,8 @@ public class AlertNotificationsUIBean extends EnterpriseFacesContextUIBean { }
public void reloadAlertNotifications() { - this.alertNotifications = this.alertNotificationStoreUIBean.lookupNotifications(getSubject()); + this.alertNotifications = this.alertNotificationManager.getNotificationsForAlertDefinition(getSubject(), + contextId); }
// Sets the initial state of the bean given the requrest parameters, this allows @@ -175,8 +170,9 @@ public class AlertNotificationsUIBean extends EnterpriseFacesContextUIBean { newSenderConfig = new Configuration(); }
- AlertNotification newlyCreated = this.alertNotificationStoreUIBean.addNotification(getSubject(), - this.selectedNewSender, this.newAlertName, newSenderConfig); + AlertNotification newlyCreated = this.alertNotificationManager.addAlertNotification(getSubject(), + this.contextId, this.selectedNewSender, newSenderConfig); + this.alertNotifications.add(newlyCreated); // only add if no errors this.activeNotification = newlyCreated; this.selectedNotifications.clear(); @@ -194,7 +190,7 @@ public class AlertNotificationsUIBean extends EnterpriseFacesContextUIBean { }
public String removeSelected() { - this.alertNotificationStoreUIBean.removeNotifications(getSubject(), getSelectedIds()); + this.alertNotificationManager.removeNotifications(getSubject(), contextId, getSelectedIds()); this.alertNotifications.removeAll(this.selectedNotifications); // only remove if no errors this.activeNotification = null;
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/alert/notification/details.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/alert/notification/details.xhtml index fd83f96..74b978e 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/alert/notification/details.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/alert/notification/details.xhtml @@ -52,19 +52,13 @@ fastOrderControlsVisible="false" orderControlsVisible="false" id="sendersList"> - <rich:column width="20%"> - <f:facet name="header"> - <h:outputText value="Name" /> - </f:facet> - <h:outputText value="#{alertNotification.displayName}" /> - </rich:column> - <rich:column width="20%"> + <rich:column width="25%"> <f:facet name="header"> <h:outputText value="Type" /> </f:facet> <h:outputText value="#{alertNotification.senderName}" /> </rich:column> - <rich:column width="60%"> + <rich:column width="75%"> <f:facet name="header"> <h:outputText value="Configuration" /> </f:facet> @@ -170,20 +164,6 @@ <input type="hidden" name="contextSubId" value="#{param.contextSubId}"/>
<div style="height: 100px;"> - <h:outputLabel for="alertNameInput" value="Alert Notification Name:" /> - <br /> - <h:inputText id="alertNameInput" - value="#{alertNotificationsUIBean.newAlertName}" - maxlength="100" - required="true" /> - - <h:message for="alertNameInput" - infoClass="InfoBlock" - warnClass="WarnBlock" - errorClass="ErrorBlock" - fatalClass="FatalBlock" /> - <br /><br /> - <h:outputLabel for="senderList" value="Alert Sender Type:" /> <br /> <h:selectOneMenu id="senderList" value="#{alertNotificationsUIBean.selectedNewSender}"> diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java index 0e7682a..0897dc7 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java @@ -296,7 +296,7 @@ public class AlertNotificationManagerBean implements AlertNotificationManagerLoc * {@inheritDoc} */ public AlertNotification addAlertNotification(Subject user, int alertDefinitionId, String senderName, - String alertName, Configuration configuration) { + Configuration configuration) {
AlertDefinition definition = alertDefinitionManager.getAlertDefinition(user, alertDefinitionId); if (definition == null) { @@ -307,7 +307,6 @@ public class AlertNotificationManagerBean implements AlertNotificationManagerLoc entityManager.persist(configuration); AlertNotification notif = new AlertNotification(definition); notif.setSenderName(senderName); - notif.setDisplayName(alertName); notif.setConfiguration(configuration); entityManager.persist(notif); definition.getAlertNotifications().add(notif); @@ -485,7 +484,7 @@ public class AlertNotificationManagerBean implements AlertNotificationManagerLoc AlertNotificationTemplate template = entityManager.find(AlertNotificationTemplate.class, templateId);
entityManager.persist(notificationConfiguration); - AlertNotification alertNotification = new AlertNotification(notificationName, sender); + AlertNotification alertNotification = new AlertNotification(sender); alertNotification.setConfiguration(notificationConfiguration); alertNotification.setAlertNotificationTemplate(template); entityManager.persist(alertNotification); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerLocal.java index 56f1c20..9db80cc 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerLocal.java @@ -65,10 +65,9 @@ public interface AlertNotificationManagerLocal { * @param user subject of the caller * @param alertDefinitionId Id of the alert definition * @param senderName shortName of the {@link AlertSender} - * @param alertName name of the new {@link AlertNotification} * @param configuration Properties for this alert sender. */ - AlertNotification addAlertNotification(Subject user, int alertDefinitionId, String senderName, String alertName, + AlertNotification addAlertNotification(Subject user, int alertDefinitionId, String senderName, Configuration configuration);
/**
commit d3cc735b22ba4548e5eef68b1dae73bf51335649 Author: Joseph Marques joseph@redhat.com Date: Mon Apr 26 17:00:14 2010 -0400
BZ-562816: fix for stack trace when trying to edit general properties or conditions for an alert definition
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java index afa5671..5a3aeba 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java @@ -448,8 +448,7 @@ public class AlertDefinition implements Serializable {
Set<AlertNotification> copiedNotifications = new HashSet<AlertNotification>(); for (AlertNotification oldNotification : new HashSet<AlertNotification>(alertDef.getAlertNotifications())) { - AlertNotification newNotification = oldNotification.copy(copyIds); - newNotification.setAlertDefinition(this); + AlertNotification newNotification = new AlertNotification(oldNotification, copyIds); copiedNotifications.add(newNotification); } this.removeAllAlertNotifications(); diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java index 1f14aad..1a7be46 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java @@ -79,7 +79,7 @@ public class AlertNotification implements Serializable { private AlertNotificationTemplate alertNotificationTemplate;
@JoinColumn(name = "SENDER_CONFIG_ID", referencedColumnName = "ID") - @OneToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY) + @OneToOne(cascade = { CascadeType.ALL }, fetch = FetchType.EAGER) private Configuration configuration;
@Column(name = "SENDER_NAME") @@ -108,6 +108,17 @@ public class AlertNotification implements Serializable { this.configuration = config.deepCopy(); }
+ public AlertNotification(AlertNotification source, boolean copyIds) { + if (copyIds) { + this.id = source.id; + this.configuration = source.configuration; + } else { + this.configuration = source.configuration.deepCopy(false); + } + this.displayName = source.displayName; + this.senderName = source.senderName; + } + /** * Constructor only for transient usage * @param alertDefinitionId @@ -136,31 +147,22 @@ public class AlertNotification implements Serializable { this.alertDefinition = alertDefinition; }
- public AlertNotification copy(boolean copyIds) { - AlertNotification results = copy(); - if (copyIds) { - results.id = this.id; - } - return results; - } - - public AlertNotification copyWithAlertDefintion(AlertDefinition alertDefinition, boolean cloneConfiguration) { + public AlertNotification copyWithAlertDefintion(AlertDefinition alertDefinition, boolean copyIds) { Configuration config; - if (cloneConfiguration) { - config = this.configuration.deepCopy(false); - } else { + if (copyIds) { config = this.configuration; + } else { + config = this.configuration.deepCopy(false); } AlertNotification notification = new AlertNotification(alertDefinition, config); + if (copyIds) { + notification.id = this.id; + } notification.setDisplayName(this.displayName); notification.setSenderName(this.senderName); return notification; }
- protected AlertNotification copy() { - return new AlertNotification(this.alertDefinition, this.configuration); - } - public void prepareForOrphanDelete() { this.alertDefinition = null; } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java index 8a4bb98..0e7682a 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java @@ -393,7 +393,8 @@ public class AlertNotificationManagerBean implements AlertNotificationManagerLoc def.getAlertNotifications().clear();
for (AlertNotification notif : template.getNotifications()) { - AlertNotification notification = notif.copyWithAlertDefintion(def, true); + AlertNotification notification = new AlertNotification(notif, true); + notification.setAlertDefinition(notif.getAlertDefinition()); entityManager.persist(notification.getConfiguration()); entityManager.persist(notification); def.addAlertNotification(notification); // Attach a copy, as the ones in the template should not be shared
commit deef32fd46d29fa6bf9145ac360c9b1d59b2826a Author: Joseph Marques joseph@redhat.com Date: Mon Apr 26 16:28:38 2010 -0400
only print statistics for saved search result count recalculation if updates were non-zero
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/SavedSearchResultCountRecalculationJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/SavedSearchResultCountRecalculationJob.java index a1e53b3..0e015e3 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/SavedSearchResultCountRecalculationJob.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/SavedSearchResultCountRecalculationJob.java @@ -80,7 +80,10 @@ public class SavedSearchResultCountRecalculationJob extends AbstractStatefulJob + next.getPattern() + "']"); } } - LOG.info("Statistics: updated " + updated + " in " + totalMillis + " ms (" + errors + " errors)"); + if (updated > 0) { + // only print non-zero stats + LOG.info("Statistics: updated " + updated + " in " + totalMillis + " ms (" + errors + " errors)"); + } }
private List<SavedSearch> getSavedSearchesNeedingRecomputation() {
commit 9937c0a8336afcf18245fe8614ad3fe413d178bc Author: Joseph Marques joseph@redhat.com Date: Mon Apr 26 15:52:28 2010 -0400
fix failure unit tests for saved searches subsystem
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchAssistManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchAssistManager.java index 2cb808c..97f44dd 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchAssistManager.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchAssistManager.java @@ -31,7 +31,7 @@ public class SearchAssistManager { private static List<String> booleanOperators = Arrays.asList("and", "or", "|");
private Subject subject; - private AbstractSearchAssistant completor; + private SearchSubsystem searchSubsystem;
/* * states: @@ -278,10 +278,11 @@ public class SearchAssistManager {
public SearchAssistManager(Subject subject, SearchSubsystem searchSubsystem) { this.subject = subject; - this.completor = getAutoCompletor(searchSubsystem); + this.searchSubsystem = searchSubsystem; + }
- protected AbstractSearchAssistant getAutoCompletor(SearchSubsystem searchSubsystem) { + protected AbstractSearchAssistant getSearchAssistant() { if (searchSubsystem == SearchSubsystem.RESOURCE) { return new ResourceSearchAssistant(); } else { @@ -290,8 +291,8 @@ public class SearchAssistManager { }
public List<String> getAllContexts() { - List<String> results = new ArrayList<String>(completor.getSimpleContexts()); - for (String parameterized : completor.getParameterizedContexts()) { + List<String> results = new ArrayList<String>(getSearchAssistant().getSimpleContexts()); + for (String parameterized : getSearchAssistant().getParameterizedContexts()) { results.add(parameterized + "["); } return results; @@ -299,7 +300,7 @@ public class SearchAssistManager {
public List<SearchSuggestion> getSuggestions(String expression, int caretPos) { //List<SearchSuggestion> simple = getSimpleSuggestions(expression, caretPos); - List<SearchSuggestion> advanced = getAdvancedSuggestions(expression, caretPos, SearchSuggestion.Kind.Advanced); + List<SearchSuggestion> advanced = getAdvancedSuggestions(expression, caretPos); List<SearchSuggestion> userSavedSearches = getUserSavedSearchSuggestions(expression); List<SearchSuggestion> globalSavedSearches = getGlobalSavedSearchSuggestions(expression);
@@ -313,11 +314,12 @@ public class SearchAssistManager { }
public List<SearchSuggestion> getSimpleSuggestions(String expression, int caretPos) { + AbstractSearchAssistant completor = getSearchAssistant(); + List<SearchSuggestion> results = new ArrayList<SearchSuggestion>(); for (String nextContext : completor.getSimpleContexts()) { String intermediateExpression = nextContext + "=" + expression; - List<SearchSuggestion> suggestions = getAdvancedSuggestions(intermediateExpression, caretPos, - SearchSuggestion.Kind.Simple); + List<SearchSuggestion> suggestions = getAdvancedSuggestions(intermediateExpression, caretPos); results.addAll(suggestions); } Collections.sort(results); @@ -328,8 +330,9 @@ public class SearchAssistManager { } }
- public List<SearchSuggestion> getAdvancedSuggestions(String expression, int caretPos, - SearchSuggestion.Kind targetKind) { + public List<SearchSuggestion> getAdvancedSuggestions(String expression, int caretPos) { + AbstractSearchAssistant completor = getSearchAssistant(); + debug("getAdvancedSuggestions: START"); long id = HibernatePerformanceMonitor.get().start(); SearchTermAssistant assistant = new SearchTermAssistant(expression, caretPos); @@ -339,7 +342,7 @@ public class SearchAssistManager {
if (tokens.length == 0) { debug("getAdvancedSuggestions: no terms"); - return convert(getAllContexts(), targetKind); // no terms yet defined + return convert(getAllContexts()); // no terms yet defined }
String beforeCaret = assistant.getFragmentBeforeCaret(); @@ -352,26 +355,26 @@ public class SearchAssistManager { if (parsed.context.equals("")) { if (tokens.length == 1) { debug("getAdvancedSuggestions: no terms yet, suggesting contexts"); - return convert(getAllContexts(), targetKind); + return convert(getAllContexts()); } else if (isBooleanTerm(assistant.getPreviousToken())) { debug("getAdvancedSuggestions: previous term was boolean, suggesting contexts"); - return convert(getAllContexts(), targetKind); + return convert(getAllContexts()); } else { debug("getAdvancedSuggestions: previous term was not boolean, suggesting boolean"); - return convert(booleanOperators, targetKind); + return convert(booleanOperators); } } else if (isBooleanTerm(parsed.context)) { debug("getAdvancedSuggestions: beforeCaret is whole boolean operator"); - return convert(getAllContexts(), targetKind); // TODO: should we tell user to type a space first? + return convert(getAllContexts()); // TODO: should we tell user to type a space first? } else { // check if this context is complete or not if (completor.getSimpleContexts().contains(parsed.context)) { debug("getAdvancedSuggestions: search term is simple context, wants operator"); - return convert(pad(parsed.context, comparisonOperators, ""), targetKind); + return convert(pad(parsed.context, comparisonOperators, "")); } if (completor.getParameterizedContexts().contains(parsed.context)) { debug("getAdvancedSuggestions: search term is parameterized context, wants open bracket"); - return convert(Arrays.asList(parsed.context + "["), targetKind); + return convert(Arrays.asList(parsed.context + "[")); }
debug("getAdvancedSuggestions: search term wants context completion"); @@ -386,12 +389,11 @@ public class SearchAssistManager { startsWithContexts.add(context + "["); } } - return convert(startsWithContexts, targetKind); + return convert(startsWithContexts); } case PARAM: debug("getAdvancedSuggestions: param state"); - return convert(pad(parsed.context + "[", completor.getParameters(parsed.context, parsed.param), "]"), - targetKind); + return convert(pad(parsed.context + "[", completor.getParameters(parsed.context, parsed.param), "]")); case OPERATOR: debug("getAdvancedSuggestions: operator state"); if (comparisonOperators.contains(parsed.operator)) { @@ -399,11 +401,11 @@ public class SearchAssistManager { List<String> valueSuggestions = pad(""", completor.getValues(parsed.context, parsed.param, ""), """); if (completor.getSimpleContexts().contains(parsed.context)) { debug("getAdvancedSuggestions: suggesting value completions for a simple context"); - return convert(pad(parsed.context + parsed.operator, valueSuggestions, ""), targetKind); + return convert(pad(parsed.context + parsed.operator, valueSuggestions, "")); } else { debug("getAdvancedSuggestions: suggesting value completions for a parameterized context"); return convert(pad(parsed.context + "[" + parsed.param + "]" + parsed.operator, valueSuggestions, - ""), targetKind); + "")); } }
@@ -416,9 +418,9 @@ public class SearchAssistManager {
debug("getAdvancedSuggestions: providing suggestions for comparison operators"); if (completor.getSimpleContexts().contains(parsed.context)) { - return convert(pad(parsed.context, operatorSuggestions, ""), targetKind); + return convert(pad(parsed.context, operatorSuggestions, "")); } else { - return convert(pad(parsed.context + "[" + parsed.param + "]", operatorSuggestions, ""), targetKind); + return convert(pad(parsed.context + "[" + parsed.param + "]", operatorSuggestions, "")); } case VALUE: debug("getAdvancedSuggestions: value state"); @@ -426,11 +428,10 @@ public class SearchAssistManager { """); if (completor.getSimpleContexts().contains(parsed.context)) { debug("getAdvancedSuggestions: suggesting value completions for a simple context"); - return convert(pad(parsed.context + parsed.operator, valueSuggestions, ""), targetKind); + return convert(pad(parsed.context + parsed.operator, valueSuggestions, "")); } else { debug("getAdvancedSuggestions: suggesting value completions for a parameterized context"); - return convert(pad(parsed.context + "[" + parsed.param + "]" + parsed.operator, valueSuggestions, ""), - targetKind); + return convert(pad(parsed.context + "[" + parsed.param + "]" + parsed.operator, valueSuggestions, "")); } default: return Collections.emptyList(); @@ -440,6 +441,7 @@ public class SearchAssistManager { public List<SearchSuggestion> getUserSavedSearchSuggestions(String expression) { SavedSearchCriteria criteria = new SavedSearchCriteria(); criteria.addFilterSubjectId(subject.getId()); + criteria.addFilterSearchContext(searchSubsystem); if (expression != null && expression.trim().equals("")) { criteria.addFilterName(expression); } @@ -494,10 +496,10 @@ public class SearchAssistManager { return false; }
- private List<SearchSuggestion> convert(List<String> suggestions, SearchSuggestion.Kind targetKind) { + private List<SearchSuggestion> convert(List<String> suggestions) { List<SearchSuggestion> results = new ArrayList<SearchSuggestion>(suggestions.size()); for (String suggestion : suggestions) { - results.add(new SearchSuggestion(targetKind, suggestion)); + results.add(new SearchSuggestion(Kind.Advanced, suggestion)); } return results; } diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/GenericSearchAssistTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/GenericSearchAssistTest.java index 5d51d10..0a28dee 100644 --- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/GenericSearchAssistTest.java +++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/GenericSearchAssistTest.java @@ -36,7 +36,7 @@ public class GenericSearchAssistTest extends AbstractEJB3Test { }
count++; - List<SearchSuggestion> results = new TestAutoCompletionManager().getSuggestions(expression, + List<SearchSuggestion> results = new TestAutoCompletionManager().getAdvancedSuggestions(expression, expression.length()); List<String> expectedResults = Arrays.asList(expected.split(" "));
@@ -51,7 +51,8 @@ public class GenericSearchAssistTest extends AbstractEJB3Test { } System.out.println("Tested " + count + " expressions for assist"); } catch (Exception e) { - System.out.println("Error testing single line RHQL: " + e); + System.out.println("Error testing GenericSearchAssistTest: " + e); + e.printStackTrace(System.out); throw e; } finally { if (reader != null) { diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/TestAutoCompletionManager.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/TestAutoCompletionManager.java index 28a11a7..704146b 100644 --- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/TestAutoCompletionManager.java +++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/TestAutoCompletionManager.java @@ -9,6 +9,7 @@ import java.util.Map; import org.rhq.core.domain.search.SearchSubsystem; import org.rhq.enterprise.server.search.assist.AbstractSearchAssistant; import org.rhq.enterprise.server.search.execution.SearchAssistManager; +import org.rhq.enterprise.server.util.LookupUtil;
public class TestAutoCompletionManager extends SearchAssistManager { public static class TestAutoCompletor extends AbstractSearchAssistant { @@ -61,10 +62,12 @@ public class TestAutoCompletionManager extends SearchAssistManager { }
public TestAutoCompletionManager() { - super(null, null); + super(LookupUtil.getSubjectManager().getOverlord(), null); }
- protected AbstractSearchAssistant getAutoCompletor(SearchSubsystem searchContext) { + @Override + protected AbstractSearchAssistant getSearchAssistant() { return new TestAutoCompletor(); + } }
commit 7064ea6ab73f1899567ed6bd6e48ee86aaf3f2cc Author: Joseph Marques joseph@redhat.com Date: Mon Apr 26 13:04:08 2010 -0400
BZ-562816: fix regression in custom alert sender UI
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/alert/notification/details.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/alert/notification/details.xhtml index b8ae721..fd83f96 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/alert/notification/details.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/alert/notification/details.xhtml @@ -56,7 +56,7 @@ <f:facet name="header"> <h:outputText value="Name" /> </f:facet> - <h:outputText value="#{alertNotification.name}" /> + <h:outputText value="#{alertNotification.displayName}" /> </rich:column> <rich:column width="20%"> <f:facet name="header">
commit 8f4b79421c74e3d50abb3d8ab209168912e4c8fa Author: Joseph Marques joseph@redhat.com Date: Mon Apr 26 13:03:16 2010 -0400
continuing development on search subsystem:
add support for simple search terms (as opposed to context=value advanced expressions) fixed search portlet on the dashboard to point to the JSF-based inventory browser added display of global and user-specific saved searches to the resources menu support for loading saved searches from the menu bar, pre-populating the search textbox support for loading saved searches from the search suggestion, pre-populating the search textbox
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/search-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/search-schema.xml index 14634b6..7910f84 100644 --- a/modules/core/dbutils/src/main/scripts/dbsetup/search-schema.xml +++ b/modules/core/dbutils/src/main/scripts/dbsetup/search-schema.xml @@ -12,7 +12,6 @@ <column name="DESCRIPTION" type="VARCHAR2" size="500" required="false"/> <column name="PATTERN" type="VARCHAR2" size="1000" required="true"/>
- <column name="JPQL_TRANSLATION" type="VARCHAR2" size="4000" required="false"/> <column name="LAST_COMPUTE_TIME" type="LONG" required="true"/> <column name="RESULT_COUNT" type="LONG" required="false"/>
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/AbstractPlugin.java b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/AbstractPlugin.java index d056fbb..e64c22b 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/AbstractPlugin.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/plugin/AbstractPlugin.java @@ -23,7 +23,6 @@
package org.rhq.core.domain.plugin;
-import java.io.ByteArrayInputStream; import java.io.Serializable;
import javax.persistence.Column; @@ -40,8 +39,6 @@ import javax.persistence.PrePersist; import javax.persistence.SequenceGenerator; import javax.persistence.Table;
-import org.rhq.core.util.MessageDigestGenerator; - /** * Base plugin implementation that agent and server plugin implementations extend. * diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/search/SavedSearch.java b/modules/core/domain/src/main/java/org/rhq/core/domain/search/SavedSearch.java index a9d4ff1..147942b 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/search/SavedSearch.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/search/SavedSearch.java @@ -22,13 +22,18 @@ */ package org.rhq.core.domain.search;
+import java.io.Serializable; + 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.ManyToOne; import javax.persistence.SequenceGenerator; import javax.persistence.Table;
@@ -55,7 +60,9 @@ import org.rhq.core.domain.auth.Subject; @Entity @SequenceGenerator(name = "id", sequenceName = "RHQ_SAVED_SEARCH_ID_SEQ") @Table(name = "RHQ_SAVED_SEARCH") -public class SavedSearch { +public class SavedSearch implements Serializable { + + private static final long serialVersionUID = 1L;
@Id @Column(name = "ID", nullable = false) @@ -75,16 +82,14 @@ public class SavedSearch { @Column(name = "PATTERN", nullable = false) private String pattern;
- @Column(name = "JPQL_TRANSLATION") - private String jpqlTranslation; - @Column(name = "LAST_COMPUTE_TIME", nullable = false) private long lastComputeTime;
@Column(name = "RESULT_COUNT") private Long resultCount;
- @Column(name = "SUBJECT_ID", nullable = false) + @JoinColumn(name = "SUBJECT_ID", nullable = false) + @ManyToOne(fetch = FetchType.LAZY) private Subject subject;
@Column(name = "SUBJECT_ID", insertable = false, updatable = false) @@ -105,7 +110,6 @@ public class SavedSearch { setName(name); // name can be null, to allow for saving searches quickly
this.description = null; - this.jpqlTranslation = null; // null value for pre-computed JPQL implies computation is needed this.lastComputeTime = 0; // further imply that computation needs to occur this.resultCount = null; // NULL resultCount implies either computation failed or hasn't begun yet this.global = false; // user must promote saved search to be a global after creation @@ -157,14 +161,6 @@ public class SavedSearch { this.pattern = pattern; }
- public String getJpqlTranslation() { - return jpqlTranslation; - } - - public void setJpqlTransation(String jpqlTranslation) { - this.jpqlTranslation = jpqlTranslation; - } - public long getLastComputeTime() { return lastComputeTime; } @@ -250,4 +246,19 @@ public class SavedSearch {
return true; } + + @Override + public String toString() { + return "SavedSearch [" // + + "id=" + id // + + ", context=" + context // + + ", description=" + description // + + ", global=" + global // + + ", lastComputeTime=" + lastComputeTime // + + ", name=" + name // + + ", pattern=" + pattern // + + ", resultCount=" + resultCount // + + ", subjectId=" + subjectId + "]"; + } + } diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/search/SearchSubsystem.java b/modules/core/domain/src/main/java/org/rhq/core/domain/search/SearchSubsystem.java index a834833..cc489f8 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/search/SearchSubsystem.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/search/SearchSubsystem.java @@ -25,6 +25,7 @@ package org.rhq.core.domain.search; import java.util.HashMap; import java.util.Map;
+import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.group.ResourceGroup;
/** @@ -40,8 +41,8 @@ import org.rhq.core.domain.resource.group.ResourceGroup; */ public enum SearchSubsystem {
- Resource(org.rhq.core.domain.resource.Resource.class), // - Group(ResourceGroup.class); + RESOURCE(Resource.class), // + GROUP(ResourceGroup.class);
private Class<?> entityClass; private static Map<Class<?>, SearchSubsystem> subsystems; @@ -63,4 +64,13 @@ public enum SearchSubsystem { public static SearchSubsystem get(Class<?> entityClass) { return SearchSubsystem.subsystems.get(entityClass); } + + /** + * A Java bean style getter to allow us to access the enum name from JSP or Facelets pages + * + * @return the enum name + */ + public String getName() { + return name(); + } } diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/search/SearchSuggestion.java b/modules/core/domain/src/main/java/org/rhq/core/domain/search/SearchSuggestion.java new file mode 100644 index 0000000..7e47275 --- /dev/null +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/search/SearchSuggestion.java @@ -0,0 +1,94 @@ +package org.rhq.core.domain.search; + +import java.io.Serializable; + +public class SearchSuggestion implements Serializable, Comparable<SearchSuggestion> { + + private static final long serialVersionUID = 1L; + + public enum Kind { + Unknown(""), // + InstructionalTextComment(""), // + GlobalSavedSearch("GLOBAL"), // + UserSavedSearch("SAVED"), // + AdvancedOperator("SYNTAX"), // + Advanced("QUERY"), // + Simple("TEXT"); + + private String displayName; + + private Kind(String displayName) { + this.displayName = displayName; + } + + public String getDisplayName() { + return displayName; + } + + public String getName() { + return name(); + } + } + + private final Kind kind; + private final String value; + private final String label; + private final int startIndex; + private final int endIndex; + + public SearchSuggestion(Kind kind, String value) { + this(kind, value, 0, 0); + } + + public SearchSuggestion(Kind kind, String value, int startIndex, int length) { + this.kind = kind; + this.label = value; + this.value = value; + this.startIndex = startIndex; + this.endIndex = startIndex + length; + } + + public SearchSuggestion(Kind kind, String label, String value, int startIndex, int length) { + this.kind = kind; + this.label = label; + this.value = value; + this.startIndex = startIndex; + this.endIndex = startIndex + length; + } + + public Kind getKind() { + return kind; + } + + public String getLabel() { + return label; + } + + public String getValue() { + return value; + } + + public int getStartIndex() { + return startIndex; + } + + public int getEndIndex() { + return endIndex; + } + + @Override + public int compareTo(SearchSuggestion other) { + int kindComparision = (this.kind.ordinal() - other.kind.ordinal()); + if (kindComparision != 0) { + return kindComparision; + } + return label.compareTo(other.label); + } + + public String toString() { + String before = label.substring(0, startIndex); + String highlight = label.substring(startIndex, endIndex); + String after = label.substring(endIndex); + return before + "(" + highlight + ")" + after + "->" + value; + } +} diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/framework/UserPreferencesUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/framework/UserPreferencesUIBean.java index 0b87f7f..8fa9e9f 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/framework/UserPreferencesUIBean.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/common/framework/UserPreferencesUIBean.java @@ -19,15 +19,14 @@ package org.rhq.enterprise.gui.common.framework;
import java.util.List; -import java.util.Enumeration; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.criteria.SavedSearchCriteria; import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.resource.group.ResourceGroup; +import org.rhq.core.domain.search.SavedSearch; import org.rhq.core.domain.util.PageControl; +import org.rhq.core.domain.util.PageOrdering; import org.rhq.core.gui.util.FacesContextUtility; import org.rhq.enterprise.gui.legacy.ParamConstants; import org.rhq.enterprise.gui.legacy.WebUser; @@ -35,6 +34,7 @@ import org.rhq.enterprise.gui.legacy.WebUserPreferences; import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility; import org.rhq.enterprise.server.resource.ResourceManagerLocal; import org.rhq.enterprise.server.resource.group.ResourceGroupManagerLocal; +import org.rhq.enterprise.server.search.SavedSearchManagerLocal; import org.rhq.enterprise.server.util.LookupUtil;
/** @@ -42,23 +42,40 @@ import org.rhq.enterprise.server.util.LookupUtil; */ public class UserPreferencesUIBean {
- private final Log log = LogFactory.getLog(UserPreferencesUIBean.class); + //private final Log log = LogFactory.getLog(UserPreferencesUIBean.class);
public static final String LEFT_RESOURCE_NAV_SHOWING = "ui.leftResourceNavShowing"; public static final String SUMMARY_PANEL_DISPLAY_STATE = "ui.summaryPanelDisplayState";
private ResourceManagerLocal resourceManager = LookupUtil.getResourceManager(); private ResourceGroupManagerLocal groupManager = LookupUtil.getResourceGroupManager(); + private SavedSearchManagerLocal savedSearchManager = LookupUtil.getSavedSearchManager(); + private List<Resource> resourceFavorites; private List<ResourceGroup> groupFavorites; + private List<SavedSearch> savedSearches; private String refreshPath;
+ private WebUser webUser; + private Subject subject; + public Subject getSubject() { - return EnterpriseFacesContextUtility.getSubject(); + if (subject == null) { + loadUserInfo(); + } + return subject; }
public WebUser getWebUser() { - return EnterpriseFacesContextUtility.getWebUser(); + if (webUser == null) { + loadUserInfo(); + } + return webUser; + } + + private void loadUserInfo() { + webUser = EnterpriseFacesContextUtility.getWebUser(); + subject = webUser.getSubject(); }
public String getLeftResourceNavState() { @@ -68,8 +85,7 @@ public class UserPreferencesUIBean { }
public void setLeftResourceNavState(String state) { - WebUser webUser = EnterpriseFacesContextUtility.getWebUser(); - WebUserPreferences preferences = webUser.getWebPreferences(); + WebUserPreferences preferences = getWebUser().getWebPreferences(); preferences.setPreference(LEFT_RESOURCE_NAV_SHOWING, state); }
@@ -95,17 +111,13 @@ public class UserPreferencesUIBean { }
public void setPageRefresh(int refresh, String path) { - WebUser webUser = EnterpriseFacesContextUtility.getWebUser(); - WebUserPreferences preferences = webUser.getWebPreferences(); + WebUserPreferences preferences = getWebUser().getWebPreferences();
preferences.setPreference("PATH_REFRESH." + path, refresh); }
- - public int getPageRefresh() { - WebUser webUser = EnterpriseFacesContextUtility.getWebUser(); - WebUserPreferences preferences = webUser.getWebPreferences(); + WebUserPreferences preferences = getWebUser().getWebPreferences();
String path = (String) FacesContextUtility.getRequest().getAttribute("javax.servlet.forward.request_uri"); if (path == null) { @@ -124,13 +136,11 @@ public class UserPreferencesUIBean { }
public String getSummaryPanelDisplayState() { - return EnterpriseFacesContextUtility.getWebUser().getWebPreferences().getPreference( - SUMMARY_PANEL_DISPLAY_STATE, "true"); + return getWebUser().getWebPreferences().getPreference(SUMMARY_PANEL_DISPLAY_STATE, "true"); }
public void setSummaryPanelDisplayState(String state) { - WebUser webUser = EnterpriseFacesContextUtility.getWebUser(); - WebUserPreferences preferences = webUser.getWebPreferences(); + WebUserPreferences preferences = getWebUser().getWebPreferences(); preferences.setPreference(SUMMARY_PANEL_DISPLAY_STATE, state); }
@@ -146,6 +156,20 @@ public class UserPreferencesUIBean { return resourceFavorites; }
+ public List<SavedSearch> getSavedSearches() { + if (savedSearches == null) { + SavedSearchCriteria criteria = new SavedSearchCriteria(); + criteria.addFilterSubjectId(getSubject().getId()); + criteria.addFilterGlobal(true); + criteria.setFiltersOptional(true); // get this user's searches as well as global ones + criteria.addSortGlobal(PageOrdering.DESC); // globals, then user-specified + criteria.addSortName(PageOrdering.ASC); // each sublist is alphabetical + + savedSearches = savedSearchManager.findSavedSearchesByCriteria(getSubject(), criteria); + } + return savedSearches; + } + public List<ResourceGroup> getGroupFavorites() { if (groupFavorites == null) { WebUser user = EnterpriseFacesContextUtility.getWebUser(); diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/inventory/browse/BrowseGroupsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/inventory/browse/BrowseGroupsUIBean.java index 37941e7..aad85f1 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/inventory/browse/BrowseGroupsUIBean.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/inventory/browse/BrowseGroupsUIBean.java @@ -13,6 +13,7 @@ import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.criteria.ResourceGroupCriteria; import org.rhq.core.domain.resource.group.GroupCategory; import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite; +import org.rhq.core.domain.search.SearchSuggestion; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; import org.rhq.core.gui.util.FacesContextUtility; @@ -21,7 +22,6 @@ 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.server.resource.group.ResourceGroupManagerLocal; -import org.rhq.enterprise.server.search.execution.SearchSuggestion; import org.rhq.enterprise.server.util.LookupUtil;
public class BrowseGroupsUIBean extends PagedDataTableUIBean { diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/inventory/browse/BrowseResourcesUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/inventory/browse/BrowseResourcesUIBean.java index 074cd3a..e01a8f2 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/inventory/browse/BrowseResourcesUIBean.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/inventory/browse/BrowseResourcesUIBean.java @@ -13,7 +13,9 @@ import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.criteria.ResourceCriteria; import org.rhq.core.domain.resource.ResourceCategory; import org.rhq.core.domain.resource.composite.ResourceComposite; +import org.rhq.core.domain.search.SavedSearch; import org.rhq.core.domain.search.SearchSubsystem; +import org.rhq.core.domain.search.SearchSuggestion; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; import org.rhq.core.gui.util.FacesContextUtility; @@ -24,8 +26,8 @@ import org.rhq.enterprise.gui.common.paging.PageControlView; import org.rhq.enterprise.gui.common.paging.ResourceNameDisambiguatingPagedListDataModel; import org.rhq.enterprise.gui.util.EnterpriseFacesContextUtility; import org.rhq.enterprise.server.resource.ResourceManagerLocal; +import org.rhq.enterprise.server.search.SavedSearchManagerLocal; import org.rhq.enterprise.server.search.execution.SearchAssistManager; -import org.rhq.enterprise.server.search.execution.SearchSuggestion; import org.rhq.enterprise.server.util.HibernatePerformanceMonitor; import org.rhq.enterprise.server.util.LookupUtil;
@@ -34,10 +36,13 @@ public class BrowseResourcesUIBean extends PagedDataTableUIBean {
public static final String MANAGED_BEAN_NAME = "BrowseResourcesUIBean";
- private String filter; - private HtmlInputText filterInput; + private String search; + private HtmlInputText searchInput; private ResourceCategory category;
+ private ResourceManagerLocal resourceManager = LookupUtil.getResourceManager(); + private SavedSearchManagerLocal savedSearchManager = LookupUtil.getSavedSearchManager(); + private static final IntExtractor<ResourceComposite> RESOURCE_ID_EXTRATOR = new IntExtractor<ResourceComposite>() { public int extract(ResourceComposite object) { return object.getResource().getId(); @@ -54,15 +59,21 @@ public class BrowseResourcesUIBean extends PagedDataTableUIBean { category = ResourceCategory.SERVICE; }
- filter = FacesContextUtility.getOptionalRequestParameter("filter"); + String searchId = FacesContextUtility.getOptionalRequestParameter("searchId"); + if (searchId != null) { + SavedSearch savedSearch = savedSearchManager.getSavedSearchById(getSubject(), Integer.valueOf(searchId)); + search = savedSearch.getPattern(); + } else { + search = FacesContextUtility.getOptionalRequestParameter("search"); + } }
- public String getFilter() { - return this.filter; + public String getSearch() { + return this.search; }
- public void setFilter(String filter) { - this.filter = filter; + public void setSearch(String search) { + this.search = search; }
public ResourceCategory getCategory() { @@ -77,8 +88,6 @@ public class BrowseResourcesUIBean extends PagedDataTableUIBean { return dataModel; }
- private ResourceManagerLocal resourceManager = LookupUtil.getResourceManager(); - private class ResultsDataModel extends ResourceNameDisambiguatingPagedListDataModel<ResourceComposite> {
public ResultsDataModel(PageControlView view, String beanName) { @@ -86,14 +95,14 @@ public class BrowseResourcesUIBean extends PagedDataTableUIBean { }
public PageList<ResourceComposite> fetchDataForPage(PageControl pc) { - String filter = getFilter(); + String search = getSearch(); ResourceCategory category = getCategory();
ResourceCriteria criteria = new ResourceCriteria(); criteria.setPageControl(pc); criteria.addFilterResourceCategory(category); - if (filter != null && !filter.trim().equals("")) { - criteria.setSearchExpression(filter); + if (search != null && !search.trim().equals("")) { + criteria.setSearchExpression(search); } criteria.fetchParentResource(true);
@@ -127,25 +136,24 @@ public class BrowseResourcesUIBean extends PagedDataTableUIBean { return FacesContextUtility.getRequest().getParameterValues("selectedItems"); }
- SearchAssistManager searchAssist = new SearchAssistManager(SearchSubsystem.Resource); + SearchAssistManager searchAssist = new SearchAssistManager(getSubject(), SearchSubsystem.RESOURCE);
public List<SearchSuggestion> autocomplete(Object suggest) { String currentInputText = (String) suggest;
// assume caret at the end of the input long id = HibernatePerformanceMonitor.get().start(); - List<SearchSuggestion> suggestions = searchAssist.getAdvancedSuggestions(currentInputText, currentInputText - .length()); + List<SearchSuggestion> suggestions = searchAssist.getSuggestions(currentInputText, currentInputText.length()); HibernatePerformanceMonitor.get().stop(id, "ResourceSuggestions"); return suggestions; }
- public HtmlInputText getFilterInput() { - return filterInput; + public HtmlInputText getSearchInput() { + return searchInput; }
- public void setFilterInput(HtmlInputText filterInput) { - this.filterInput = filterInput; + public void setSearchInput(HtmlInputText searchInput) { + this.searchInput = searchInput; }
} diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/hub/ResourceHubPortalAction.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/hub/ResourceHubPortalAction.java index f3d14be..1c775c8 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/hub/ResourceHubPortalAction.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/hub/ResourceHubPortalAction.java @@ -36,6 +36,7 @@ import org.jetbrains.annotations.NotNull;
import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.plugin.Plugin; +import org.rhq.core.domain.resource.InventorySummary; import org.rhq.core.domain.resource.ResourceCategory; import org.rhq.core.domain.resource.composite.ResourceComposite; import org.rhq.core.domain.util.PageList; @@ -48,7 +49,6 @@ import org.rhq.enterprise.gui.legacy.util.HubUtils; import org.rhq.enterprise.gui.legacy.util.RequestUtils; import org.rhq.enterprise.gui.legacy.util.SessionUtils; import org.rhq.enterprise.gui.util.WebUtility; -import org.rhq.core.domain.resource.InventorySummary; import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal; import org.rhq.enterprise.server.util.LookupUtil;
@@ -86,29 +86,23 @@ public class ResourceHubPortalAction extends BaseAction { messages = getResources(request); ResourceHubForm hubForm = (ResourceHubForm) form;
- /* - * once search functionality is complete, this will redirect to the new inventory manager; - * until then, keep it working against the old ResourceHub - */ - if (false) { - String filter = hubForm.getKeywords(); - if (filter.equals("Resource Name")) { - filter = null; // user didn't type a filter, just selected a category and clicked 'GO' - } - String category = hubForm.getResourceCategory(); - String subtab = "all"; - try { - ResourceCategory.valueOf(category.toUpperCase()); - subtab = category.toLowerCase(); - } catch (Exception e) { - subtab = "hub"; - } - String url = "/rhq/inventory/browseResources.xhtml?subtab=" + subtab; - if (filter != null && !filter.trim().equals("")) { - url += "&filter=" + filter; - } - response.sendRedirect(url); + String searchExpression = hubForm.getKeywords(); + if (searchExpression.equals("Resource Name")) { + searchExpression = null; // user didn't type a filter, just selected a category and clicked 'GO' + } + String category = hubForm.getResourceCategory(); + String subtab = "all"; + try { + ResourceCategory.valueOf(category.toUpperCase()); + subtab = category.toLowerCase(); + } catch (Exception e) { + subtab = "hub"; + } + String url = "/rhq/inventory/browseResources.xhtml?subtab=" + subtab; + if (searchExpression != null && !searchExpression.trim().equals("")) { + url += "&search=name=" + searchExpression; } + response.sendRedirect(url);
org.rhq.core.domain.util.PageControl pageControl = WebUtility.getPageControl(request); Subject subject = RequestUtils.getSubject(request); 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 d6cb267..51107b2 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 @@ -59,6 +59,7 @@ import org.rhq.enterprise.server.plugin.pc.ServerPluginServiceManagement; import org.rhq.enterprise.server.resource.ResourceTypeManagerLocal; import org.rhq.enterprise.server.scheduler.SchedulerLocal; import org.rhq.enterprise.server.scheduler.jobs.AsyncResourceDeleteJob; +import org.rhq.enterprise.server.scheduler.jobs.SavedSearchResultCountRecalculationJob; import org.rhq.enterprise.server.scheduler.jobs.CheckForSuspectedAgentsJob; import org.rhq.enterprise.server.scheduler.jobs.CheckForTimedOutConfigUpdatesJob; import org.rhq.enterprise.server.scheduler.jobs.CheckForTimedOutContentRequestsJob; @@ -325,6 +326,16 @@ public class StartupServlet extends HttpServlet { LookupUtil.getSystemManager().scheduleConfigCacheReloader();
try { + // Do not check until we are up at least 1 min, and every minute thereafter. + final long initialDelay = 1000L * 60; + final long interval = 1000L * 60; + scheduler.scheduleSimpleRepeatingJob(SavedSearchResultCountRecalculationJob.class, true, false, initialDelay, + interval); + } catch (Exception e) { + log("Cannot schedule asynchronous resource deletion job: " + e.getMessage()); + } + + try { // Do not check until we are up at least 1 min, and every 5 minutes thereafter. final long initialDelay = 1000L * 60; final long interval = 1000L * 60 * 5; diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/menu/menu.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/menu/menu.xhtml index 232974b..8e016de 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/menu/menu.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/menu/menu.xhtml @@ -124,6 +124,21 @@ </c:if> </c:forEach> </rich:menuGroup> + + ui:remove***** Resources > SAVED SEARCHES *****</ui:remove> + <rich:menuGroup value="Saved Searches" icon="/images/bookmark.png"> + <c:forEach var="savedSearch" items="#{UserPreferencesUIBean.savedSearches}"> + <c:if test="#{savedSearch.context.name == 'RESOURCE'}"> + <rich:menuItem submitMode="none" + icon="/images/icons/Flag_#{savedSearch.global ? 'yellow' : 'blue'}_16.png" + onclick="window.location = '/rhq/inventory/browseResources.xhtml?subtab=all&searchId=#{savedSearch.id}'"> + <h:outputText value="#{savedSearch.name}" /> + <h:outputText value=" (#{savedSearch.resultCount})" + rendered="#{not empty savedSearch.resultCount}" /> + </rich:menuItem> + </c:if> + </c:forEach> + </rich:menuGroup>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/inventory/browseResources.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/inventory/browseResources.xhtml index ac11225..90d45c0 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/inventory/browseResources.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/inventory/browseResources.xhtml @@ -31,17 +31,23 @@ <a4j:keepAlive beanName="BrowseResourcesUIBean"/>
<h:form id="browseResourcesForm"> - <input type="hidden" name="subtab" value="${param.subtab}"/> + <input type="hidden" name="subtab" value="${param.subtab}" />
<p/> <h:panelGroup> - <h:outputLabel for="filter" value="Search: " /> - <h:inputText id="filter" - binding="#{BrowseResourcesUIBean.filterInput}" - value="#{BrowseResourcesUIBean.filter}" + <h:outputLabel for="search" value="Search: " /> + <h:inputText id="search" + binding="#{BrowseResourcesUIBean.searchInput}" + value="#{BrowseResourcesUIBean.search}" onkeypress="return ignoreEnterKey(event);" - style="width: 600px;" /> - <rich:suggestionbox id="suggest" for="filter" + style="width: 600px;"> + ui:remove + <a4j:support event="onfocus" reRender="suggest" + disableDefault="true" status="commonStatus" limitToList="true" + ajaxSingle="true" oncomplete="#{rich:component('suggest')}.show(event, {})"/> + </ui:remove> + </h:inputText> + <rich:suggestionbox id="suggest" for="search" width="600" height="400" border="1" cellpadding="1" cellspacing="1" minChars="0" @@ -56,7 +62,19 @@ eventsQueue="resourceSearchSuggestions" ignoreDupResponses="true" rendered="true"> <!-- disable until auto-completer is added --> - <h:column> + <h:column width="10%"> + <h:outputText value="#{suggestItem.kind.displayName}" style="font-variant: small-caps; color: gray;" + rendered="#{suggestItem.kind.name eq 'Simple'}" /> + <h:outputText value="#{suggestItem.kind.displayName}" style="font-variant: small-caps; " + rendered="#{suggestItem.kind.name eq 'Advanced'}" /> + <h:outputText value="#{suggestItem.kind.displayName}" style="font-variant: small-caps; color: yellow" + rendered="#{suggestItem.kind.name eq 'AdvancedOperator'}" /> + <h:outputText value="#{suggestItem.kind.displayName}" style="font-variant: small-caps; color: green;" + rendered="#{suggestItem.kind.name eq 'UserSavedSearch'}" /> + <h:outputText value="#{suggestItem.kind.displayName}" style="font-variant: small-caps; color: orange;" + rendered="#{suggestItem.kind.name eq 'GlobalSavedSearch'}" /> + </h:column> + <h:column width="90%"> <h:outputText value="#{suggestItem.label}" /> </h:column> </rich:suggestionbox> diff --git a/modules/enterprise/server/jar/src/main/antlr3/org/rhq/enterprise/server/search/RHQL.g b/modules/enterprise/server/jar/src/main/antlr3/org/rhq/enterprise/server/search/RHQL.g index b8ff97e..4fa879e 100644 --- a/modules/enterprise/server/jar/src/main/antlr3/org/rhq/enterprise/server/search/RHQL.g +++ b/modules/enterprise/server/jar/src/main/antlr3/org/rhq/enterprise/server/search/RHQL.g @@ -95,6 +95,7 @@ conditionalPrimary
simpleConditionalExpression : c=context WS* op=comparisonOperator WS* ident=identifier -> ^($op $c ^(VALUE $ident)) + | ident=identifier ; // rewrite tree output so operator is always the root -- ignore captured WS
context diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/SavedSearchResultCountRecalculationJob.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/SavedSearchResultCountRecalculationJob.java new file mode 100644 index 0000000..a1e53b3 --- /dev/null +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/scheduler/jobs/SavedSearchResultCountRecalculationJob.java @@ -0,0 +1,95 @@ +/* + * 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.scheduler.jobs; + +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; + +import org.rhq.core.domain.auth.Subject; +import org.rhq.core.domain.criteria.ResourceCriteria; +import org.rhq.core.domain.criteria.SavedSearchCriteria; +import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.search.SavedSearch; +import org.rhq.core.domain.search.SearchSubsystem; +import org.rhq.core.domain.util.PageList; +import org.rhq.enterprise.server.resource.ResourceManagerLocal; +import org.rhq.enterprise.server.search.SavedSearchManagerLocal; +import org.rhq.enterprise.server.util.LookupUtil; + +/** + * + * + * @author Joseph Marques + */ +public class SavedSearchResultCountRecalculationJob extends AbstractStatefulJob { + + private final static Log LOG = LogFactory.getLog(SavedSearchResultCountRecalculationJob.class); + + private SavedSearchManagerLocal savedSearchManager = LookupUtil.getSavedSearchManager(); + private ResourceManagerLocal resourceManager = LookupUtil.getResourceManager(); + + private Subject overlord = LookupUtil.getSubjectManager().getOverlord(); + + @Override + public void executeJobCode(JobExecutionContext context) throws JobExecutionException { + List<SavedSearch> staleSavedSearches = getSavedSearchesNeedingRecomputation(); + + int errors = 0; + int updated = 0; + long totalMillis = 0; + for (SavedSearch next : staleSavedSearches) { + try { + if (next.getContext() == SearchSubsystem.RESOURCE) { + ResourceCriteria criteria = new ResourceCriteria(); + criteria.setSearchExpression(next.getPattern()); + + totalMillis -= System.currentTimeMillis(); + PageList<Resource> results = resourceManager.findResourcesByCriteria(overlord, criteria); + totalMillis += System.currentTimeMillis(); + + if (results.getTotalSize() != next.getResultCount()) { + next.setResultCount((long) results.getTotalSize()); + savedSearchManager.updateSavedSearch(overlord, next); + updated++; + } + } + } catch (Throwable t) { + // TODO: mark this saved search as "broken" so that future computation is suppressed for it + errors++; + LOG.error("Could not calculate result count for SavedSearch[name=" + next.getName() + ", patter='" + + next.getPattern() + "']"); + } + } + LOG.info("Statistics: updated " + updated + " in " + totalMillis + " ms (" + errors + " errors)"); + } + + private List<SavedSearch> getSavedSearchesNeedingRecomputation() { + long fiveMinutesAgo = System.currentTimeMillis() - (5 * 60 * 1000); + + SavedSearchCriteria criteria = new SavedSearchCriteria(); + criteria.addFilterLastComputeTimeMax(fiveMinutesAgo); + + List<SavedSearch> results = savedSearchManager.findSavedSearchesByCriteria(overlord, criteria); + return results; + } +} diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/AbstractSearchAssistant.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/AbstractSearchAssistant.java index 90c790f..05b39e1 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/AbstractSearchAssistant.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/AbstractSearchAssistant.java @@ -12,6 +12,16 @@ import org.rhq.enterprise.server.util.LookupUtil;
public abstract class AbstractSearchAssistant implements SearchAssistant {
+ private int maxResultCount = 20; + + public int getMaxResultCount() { + return maxResultCount; + } + + public void setMaxResultCount(int maxResultCount) { + this.maxResultCount = maxResultCount; + } + @Override public List<String> getSimpleContexts() { return Collections.emptyList(); @@ -46,7 +56,7 @@ public abstract class AbstractSearchAssistant implements SearchAssistant { @SuppressWarnings("unchecked") protected final List<String> execute(String jpql) { Query query = LookupUtil.getEntityManager().createQuery(jpql); - query.setMaxResults(20); + query.setMaxResults(maxResultCount); List<String> results = query.getResultList(); return results; } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/ResourceSearchAssistant.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/ResourceSearchAssistant.java index 94dcb7f..0e2b3df 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/ResourceSearchAssistant.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/ResourceSearchAssistant.java @@ -21,7 +21,7 @@ public class ResourceSearchAssistant extends AbstractSearchAssistant {
@Override public SearchSubsystem getSearchSubsystem() { - return SearchSubsystem.Resource; + return SearchSubsystem.RESOURCE; }
@Override diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/SearchAssistant.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/SearchAssistant.java index 804e0bb..4314e06 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/SearchAssistant.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/assist/SearchAssistant.java @@ -6,14 +6,14 @@ import org.rhq.core.domain.search.SearchSubsystem;
public interface SearchAssistant {
- public SearchSubsystem getSearchSubsystem(); + SearchSubsystem getSearchSubsystem();
- public List<String> getSimpleContexts(); + List<String> getSimpleContexts();
- public List<String> getParameterizedContexts(); + List<String> getParameterizedContexts();
- public List<String> getParameters(String context, String filter); + List<String> getParameters(String context, String filter);
- public List<String> getValues(String context, String param, String filter); + List<String> getValues(String context, String param, String filter);
} diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchAssistManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchAssistManager.java index e500449..2cb808c 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchAssistManager.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchAssistManager.java @@ -9,19 +9,29 @@ 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.criteria.SavedSearchCriteria; +import org.rhq.core.domain.search.SavedSearch; import org.rhq.core.domain.search.SearchSubsystem; +import org.rhq.core.domain.search.SearchSuggestion; +import org.rhq.core.domain.search.SearchSuggestion.Kind; +import org.rhq.core.domain.util.PageOrdering; +import org.rhq.enterprise.server.search.SavedSearchManagerLocal; +import org.rhq.enterprise.server.search.assist.AbstractSearchAssistant; import org.rhq.enterprise.server.search.assist.ResourceSearchAssistant; -import org.rhq.enterprise.server.search.assist.SearchAssistant; import org.rhq.enterprise.server.util.HibernatePerformanceMonitor; +import org.rhq.enterprise.server.util.LookupUtil;
public class SearchAssistManager {
private static final Log LOG = LogFactory.getLog(SearchAssistManager.class); + private SavedSearchManagerLocal savedSearchManager = LookupUtil.getSavedSearchManager();
private static List<String> comparisonOperators = Arrays.asList("!==", "!=", "==", "="); - private static List<String> booleanOperators = Arrays.asList("and", "or"); + private static List<String> booleanOperators = Arrays.asList("and", "or", "|");
- private SearchAssistant completor; + private Subject subject; + private AbstractSearchAssistant completor;
/* * states: @@ -266,12 +276,13 @@ public class SearchAssistManager { } }
- public SearchAssistManager(SearchSubsystem searchSubsystem) { + public SearchAssistManager(Subject subject, SearchSubsystem searchSubsystem) { + this.subject = subject; this.completor = getAutoCompletor(searchSubsystem); }
- protected SearchAssistant getAutoCompletor(SearchSubsystem searchSubsystem) { - if (searchSubsystem == SearchSubsystem.Resource) { + protected AbstractSearchAssistant getAutoCompletor(SearchSubsystem searchSubsystem) { + if (searchSubsystem == SearchSubsystem.RESOURCE) { return new ResourceSearchAssistant(); } else { throw new IllegalArgumentException("No SearchAssistant found for SearchSubsystem[" + searchSubsystem + "]"); @@ -286,7 +297,39 @@ public class SearchAssistManager { return results; }
- public List<SearchSuggestion> getAdvancedSuggestions(String expression, int caretPos) { + public List<SearchSuggestion> getSuggestions(String expression, int caretPos) { + //List<SearchSuggestion> simple = getSimpleSuggestions(expression, caretPos); + List<SearchSuggestion> advanced = getAdvancedSuggestions(expression, caretPos, SearchSuggestion.Kind.Advanced); + List<SearchSuggestion> userSavedSearches = getUserSavedSearchSuggestions(expression); + List<SearchSuggestion> globalSavedSearches = getGlobalSavedSearchSuggestions(expression); + + List<SearchSuggestion> results = new ArrayList<SearchSuggestion>(); + //results.addAll(simple); + results.addAll(advanced); + results.addAll(userSavedSearches); + results.addAll(globalSavedSearches); + Collections.sort(results); + return results; + } + + public List<SearchSuggestion> getSimpleSuggestions(String expression, int caretPos) { + List<SearchSuggestion> results = new ArrayList<SearchSuggestion>(); + for (String nextContext : completor.getSimpleContexts()) { + String intermediateExpression = nextContext + "=" + expression; + List<SearchSuggestion> suggestions = getAdvancedSuggestions(intermediateExpression, caretPos, + SearchSuggestion.Kind.Simple); + results.addAll(suggestions); + } + Collections.sort(results); + if (results.size() > completor.getMaxResultCount()) { + return results.subList(0, completor.getMaxResultCount()); + } else { + return results; + } + } + + public List<SearchSuggestion> getAdvancedSuggestions(String expression, int caretPos, + SearchSuggestion.Kind targetKind) { debug("getAdvancedSuggestions: START"); long id = HibernatePerformanceMonitor.get().start(); SearchTermAssistant assistant = new SearchTermAssistant(expression, caretPos); @@ -296,7 +339,7 @@ public class SearchAssistManager {
if (tokens.length == 0) { debug("getAdvancedSuggestions: no terms"); - return convert(getAllContexts()); // no terms yet defined + return convert(getAllContexts(), targetKind); // no terms yet defined }
String beforeCaret = assistant.getFragmentBeforeCaret(); @@ -309,26 +352,26 @@ public class SearchAssistManager { if (parsed.context.equals("")) { if (tokens.length == 1) { debug("getAdvancedSuggestions: no terms yet, suggesting contexts"); - return convert(getAllContexts()); + return convert(getAllContexts(), targetKind); } else if (isBooleanTerm(assistant.getPreviousToken())) { debug("getAdvancedSuggestions: previous term was boolean, suggesting contexts"); - return convert(getAllContexts()); + return convert(getAllContexts(), targetKind); } else { debug("getAdvancedSuggestions: previous term was not boolean, suggesting boolean"); - return convert(booleanOperators); + return convert(booleanOperators, targetKind); } } else if (isBooleanTerm(parsed.context)) { debug("getAdvancedSuggestions: beforeCaret is whole boolean operator"); - return convert(getAllContexts()); // TODO: should we tell user to type a space first? + return convert(getAllContexts(), targetKind); // TODO: should we tell user to type a space first? } else { // check if this context is complete or not if (completor.getSimpleContexts().contains(parsed.context)) { debug("getAdvancedSuggestions: search term is simple context, wants operator"); - return convert(pad(parsed.context, comparisonOperators, "")); + return convert(pad(parsed.context, comparisonOperators, ""), targetKind); } if (completor.getParameterizedContexts().contains(parsed.context)) { debug("getAdvancedSuggestions: search term is parameterized context, wants open bracket"); - return convert(Arrays.asList(parsed.context + "[")); + return convert(Arrays.asList(parsed.context + "["), targetKind); }
debug("getAdvancedSuggestions: search term wants context completion"); @@ -343,11 +386,12 @@ public class SearchAssistManager { startsWithContexts.add(context + "["); } } - return convert(startsWithContexts); + return convert(startsWithContexts, targetKind); } case PARAM: debug("getAdvancedSuggestions: param state"); - return convert(pad(parsed.context + "[", completor.getParameters(parsed.context, parsed.param), "]")); + return convert(pad(parsed.context + "[", completor.getParameters(parsed.context, parsed.param), "]"), + targetKind); case OPERATOR: debug("getAdvancedSuggestions: operator state"); if (comparisonOperators.contains(parsed.operator)) { @@ -355,11 +399,11 @@ public class SearchAssistManager { List<String> valueSuggestions = pad(""", completor.getValues(parsed.context, parsed.param, ""), """); if (completor.getSimpleContexts().contains(parsed.context)) { debug("getAdvancedSuggestions: suggesting value completions for a simple context"); - return convert(pad(parsed.context + parsed.operator, valueSuggestions, "")); + return convert(pad(parsed.context + parsed.operator, valueSuggestions, ""), targetKind); } else { debug("getAdvancedSuggestions: suggesting value completions for a parameterized context"); return convert(pad(parsed.context + "[" + parsed.param + "]" + parsed.operator, valueSuggestions, - "")); + ""), targetKind); } }
@@ -372,9 +416,9 @@ public class SearchAssistManager {
debug("getAdvancedSuggestions: providing suggestions for comparison operators"); if (completor.getSimpleContexts().contains(parsed.context)) { - return convert(pad(parsed.context, operatorSuggestions, "")); + return convert(pad(parsed.context, operatorSuggestions, ""), targetKind); } else { - return convert(pad(parsed.context + "[" + parsed.param + "]", operatorSuggestions, "")); + return convert(pad(parsed.context + "[" + parsed.param + "]", operatorSuggestions, ""), targetKind); } case VALUE: debug("getAdvancedSuggestions: value state"); @@ -382,16 +426,65 @@ public class SearchAssistManager { """); if (completor.getSimpleContexts().contains(parsed.context)) { debug("getAdvancedSuggestions: suggesting value completions for a simple context"); - return convert(pad(parsed.context + parsed.operator, valueSuggestions, "")); + return convert(pad(parsed.context + parsed.operator, valueSuggestions, ""), targetKind); } else { debug("getAdvancedSuggestions: suggesting value completions for a parameterized context"); - return convert(pad(parsed.context + "[" + parsed.param + "]" + parsed.operator, valueSuggestions, "")); + return convert(pad(parsed.context + "[" + parsed.param + "]" + parsed.operator, valueSuggestions, ""), + targetKind); } default: return Collections.emptyList(); } }
+ public List<SearchSuggestion> getUserSavedSearchSuggestions(String expression) { + SavedSearchCriteria criteria = new SavedSearchCriteria(); + criteria.addFilterSubjectId(subject.getId()); + if (expression != null && expression.trim().equals("")) { + criteria.addFilterName(expression); + } + + criteria.setCaseSensitive(false); + criteria.addSortName(PageOrdering.ASC); + + List<SavedSearch> savedSearchResults = savedSearchManager.findSavedSearchesByCriteria(subject, criteria); + + List<SearchSuggestion> results = new ArrayList<SearchSuggestion>(); + for (SavedSearch next : savedSearchResults) { + String label = next.getName(); + String value = next.getPattern(); + int index = next.getName().toLowerCase().indexOf(expression); + SearchSuggestion suggestion = new SearchSuggestion(Kind.UserSavedSearch, label, value, index, expression + .length()); + results.add(suggestion); + } + return results; + } + + public List<SearchSuggestion> getGlobalSavedSearchSuggestions(String expression) { + SavedSearchCriteria criteria = new SavedSearchCriteria(); + criteria.addFilterGlobal(true); + if (expression != null && expression.trim().equals("")) { + criteria.addFilterName(expression); + } + + criteria.setCaseSensitive(false); + criteria.addSortName(PageOrdering.ASC); + + List<SavedSearch> savedSearchResults = savedSearchManager.findSavedSearchesByCriteria(subject, criteria); + + List<SearchSuggestion> results = new ArrayList<SearchSuggestion>(); + for (SavedSearch next : savedSearchResults) { + String label = next.getName(); + String value = next.getPattern(); + int index = next.getName().toLowerCase().indexOf(expression); + SearchSuggestion suggestion = new SearchSuggestion(Kind.GlobalSavedSearch, label, value, index, expression + .length()); + results.add(suggestion); + } + return results; + } + private boolean isBooleanTerm(String term) { for (String op : booleanOperators) { if (op.equals(term)) { @@ -401,10 +494,10 @@ public class SearchAssistManager { return false; }
- private List<SearchSuggestion> convert(List<String> suggestions) { + private List<SearchSuggestion> convert(List<String> suggestions, SearchSuggestion.Kind targetKind) { List<SearchSuggestion> results = new ArrayList<SearchSuggestion>(suggestions.size()); for (String suggestion : suggestions) { - results.add(new SearchSuggestion(SearchSuggestion.SearchCategory.Advanced, suggestion)); + results.add(new SearchSuggestion(targetKind, suggestion)); } return results; } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchSuggestion.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchSuggestion.java deleted file mode 100644 index e69090d..0000000 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchSuggestion.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.rhq.enterprise.server.search.execution; - -public class SearchSuggestion { - public enum SearchCategory { - Simple, Advanced, SavedSearch, InstructionalTextComment, Unknown; - } - - private final SearchCategory category; - private final String value; - private final String label; - private final int startIndex; - private final int endIndex; - - public SearchSuggestion(SearchCategory category, String value) { - this(category, value, 0, 0); - } - - public SearchSuggestion(SearchCategory category, String value, int startIndex, int length) { - this.category = category; - this.label = value; - this.value = value; - this.startIndex = startIndex; - this.endIndex = startIndex + length; - } - - public SearchCategory getCategory() { - return category; - } - - public String getLabel() { - return label; - } - - public String getValue() { - return value; - } - - public int getStartIndex() { - return startIndex; - } - - public int getEndIndex() { - return endIndex; - } - - public String toString() { - String before = label.substring(0, startIndex); - String highlight = label.substring(startIndex, endIndex); - String after = label.substring(endIndex); - return before + "(" + highlight + ")" + after + "->" + value; - } -} diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchTranslationManager.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchTranslationManager.java index 806987f..812bc57 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchTranslationManager.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/execution/SearchTranslationManager.java @@ -57,19 +57,19 @@ public class SearchTranslationManager {
public String getJPQLSelectStatement() throws Exception { String jpql = "SELECT " + alias + " FROM " + entity + " " + alias + " WHERE " + getJPQLWhereFragment(); - System.out.println("JPQL was:"); + //System.out.println("JPQL was:"); PrintUtils.printJPQL(jpql.split(" ")); - System.out.println(); + //System.out.println(); return jpql; }
public String getJPQLWhereFragment() throws Exception { RHQLParser.searchExpression_return searchAST = parser.searchExpression();
- System.out.println("Search was: " + expression); + //System.out.println("Search was: " + expression); CommonTree searchExpressionTree = (CommonTree) searchAST.getTree(); - System.out.println("Errors found: " + adaptor.getErrorMessages()); - System.out.println("Tree was:"); + //System.out.println("Errors found: " + adaptor.getErrorMessages()); + //System.out.println("Tree was:"); PrintUtils.print(searchExpressionTree, ""); String fragment = generateJPQL(searchExpressionTree); return fragment; @@ -193,12 +193,12 @@ public class SearchTranslationManager { }
if (lineBreakers.contains(next)) { - System.out.println(); - System.out.print(indent); + //System.out.println(); + //System.out.print(indent); }
- System.out.print(next); - System.out.print(" "); + //System.out.print(next); + //System.out.print(" ");
if (next.equals(")")) { indent = indent.substring(3); @@ -228,11 +228,11 @@ public class SearchTranslationManager { return; }
- System.out.print(indent + token.getText()); + //System.out.print(indent + token.getText()); if (isStringNode(token)) { - System.out.println(collapseStringChildren(tree)); + //System.out.println(collapseStringChildren(tree)); } else { - System.out.println(); + //System.out.println(); for (int childIndex = 0; childIndex < tree.getChildCount(); childIndex++) { CommonTree child = (CommonTree) tree.getChild(childIndex); print(child, indent + " "); @@ -261,7 +261,7 @@ public class SearchTranslationManager { }
public static void main(String[] args) throws Exception { - SearchTranslationManager manager = new SearchTranslationManager(SearchSubsystem.Resource); + SearchTranslationManager manager = new SearchTranslationManager(SearchSubsystem.RESOURCE); manager.setExpression("(name = rhq and category = server) or plugin = jbossas"); String jpql = manager.getJPQLSelectStatement(); } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/translation/SearchTranslatorFactory.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/translation/SearchTranslatorFactory.java index fa8d626..ee8ecda 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/translation/SearchTranslatorFactory.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/search/translation/SearchTranslatorFactory.java @@ -8,7 +8,7 @@ public class SearchTranslatorFactory { }
public static SearchTranslator getTranslator(SearchSubsystem searchContext) { - if (searchContext == SearchSubsystem.Resource) { + if (searchContext == SearchSubsystem.RESOURCE) { return new ResourceSearchTranslator(); } throw new IllegalArgumentException("No SearchTranslator found for SearchContext[" + searchContext + "]"); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java index 0e1a789..ff71760 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java @@ -398,7 +398,7 @@ public final class CriteriaQueryGenerator {
// translate first, if there was an error we won't add the dangling 'AND' to the where clause String translatedJPQL = searchManager.getJPQLWhereFragment(); - LOG.info("Translated JPQL Fragment was: " + translatedJPQL); + LOG.debug("Translated JPQL Fragment was: " + translatedJPQL); if (translatedJPQL != null) { searchExpressionWhereClause = translatedJPQL; } diff --git a/modules/enterprise/server/jar/src/main/resources/single-line-rhql.txt b/modules/enterprise/server/jar/src/main/resources/single-line-rhql.txt index 8793fb1..265071b 100644 --- a/modules/enterprise/server/jar/src/main/resources/single-line-rhql.txt +++ b/modules/enterprise/server/jar/src/main/resources/single-line-rhql.txt @@ -94,4 +94,12 @@ context = value1 | ((context = value2)) ((context = value1)) context = value2 (context = value1) (context = value2) (context = value1 (context = value2)) -context = value1 ((context = value2)) \ No newline at end of file +context = value1 ((context = value2)) + +# simple terms +hello +hello world +"hello world" 'foo bar' +'hello world' "foo bar" +hello | world +context=value | world \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/GenericSearchAssistTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/GenericSearchAssistTest.java index 867ee78..5d51d10 100644 --- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/GenericSearchAssistTest.java +++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/GenericSearchAssistTest.java @@ -10,7 +10,7 @@ import java.util.List;
import org.testng.annotations.Test;
-import org.rhq.enterprise.server.search.execution.SearchSuggestion; +import org.rhq.core.domain.search.SearchSuggestion; import org.rhq.enterprise.server.test.AbstractEJB3Test;
public class GenericSearchAssistTest extends AbstractEJB3Test { @@ -36,7 +36,7 @@ public class GenericSearchAssistTest extends AbstractEJB3Test { }
count++; - List<SearchSuggestion> results = new TestAutoCompletionManager().getAdvancedSuggestions(expression, + List<SearchSuggestion> results = new TestAutoCompletionManager().getSuggestions(expression, expression.length()); List<String> expectedResults = Arrays.asList(expected.split(" "));
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/TestAutoCompletionManager.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/TestAutoCompletionManager.java index 89cb5ff..28a11a7 100644 --- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/TestAutoCompletionManager.java +++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/search/TestAutoCompletionManager.java @@ -8,7 +8,6 @@ import java.util.Map;
import org.rhq.core.domain.search.SearchSubsystem; import org.rhq.enterprise.server.search.assist.AbstractSearchAssistant; -import org.rhq.enterprise.server.search.assist.SearchAssistant; import org.rhq.enterprise.server.search.execution.SearchAssistManager;
public class TestAutoCompletionManager extends SearchAssistManager { @@ -62,10 +61,10 @@ public class TestAutoCompletionManager extends SearchAssistManager { }
public TestAutoCompletionManager() { - super(null); + super(null, null); }
- protected SearchAssistant getAutoCompletor(SearchSubsystem searchContext) { + protected AbstractSearchAssistant getAutoCompletor(SearchSubsystem searchContext) { return new TestAutoCompletor(); } }
commit 4fd30d06a5ad9001591e4a573a3051ef657c1ae8 Merge: 7bb4095... e529883... Author: Heiko W. Rupp hwr@redhat.com Date: Mon Apr 26 14:21:51 2010 +0200
Merge branch 'master' of ssh://git.fedorahosted.org/git/rhq/rhq
commit 7bb40954466ae844f2135f8062d4cd4ad0385bd2 Author: Heiko W. Rupp hwr@redhat.com Date: Mon Apr 26 14:05:17 2010 +0200
BZ 548172 pg_relation_size() no longer understands names in postgres 8.4+ Also prevent a NPE from unboxing.
diff --git a/modules/plugins/postgres/src/main/java/org/rhq/plugins/postgres/PostgresTableComponent.java b/modules/plugins/postgres/src/main/java/org/rhq/plugins/postgres/PostgresTableComponent.java index c69496f..ff21e78 100644 --- a/modules/plugins/postgres/src/main/java/org/rhq/plugins/postgres/PostgresTableComponent.java +++ b/modules/plugins/postgres/src/main/java/org/rhq/plugins/postgres/PostgresTableComponent.java @@ -55,7 +55,7 @@ public class PostgresTableComponent implements DatabaseComponent<PostgresDatabas private static final List<String> PG_STAT_USER_TABLE_STATS = Arrays.asList("seq_scan", "seq_tup_read", "idx_scan", "idx_tup_fetch", "n_tup_ins", "n_tup_upd", "n_tup_del", "table_size", "total_size");
- public static final String PG_STAT_USER_TABLES_QUERY = "SELECT ts.*, pg_relation_size(ts.relname) AS table_size, pg_total_relation_size(ts.relname) AS total_size, \n" + public static final String PG_STAT_USER_TABLES_QUERY = "SELECT ts.*, pg_relation_size(ts.relid) AS table_size, pg_total_relation_size(ts.relid) AS total_size, \n" + " ios.heap_blks_read, ios.heap_blks_hit, ios.idx_blks_read, ios.idx_blks_hit, \n" + " ios.toast_blks_read, ios.toast_blks_hit, ios.tidx_blks_read, ios.tidx_blks_hit \n" + "FROM pg_stat_user_tables ts LEFT JOIN pg_statio_user_tables ios on ts.relid = ios.relid \n" @@ -90,7 +90,7 @@ public class PostgresTableComponent implements DatabaseComponent<PostgresDatabas getTableName()); for (MeasurementScheduleRequest request : requests) { String metricName = request.getName(); - double value; + Double value; if (metricName.equals("rows")) { value = DatabaseQueryUtility.getSingleNumericQueryValue(this, PG_COUNT_ROWS + getTableName()); } else if (metricName.equals("rows_approx")) { @@ -99,8 +99,10 @@ public class PostgresTableComponent implements DatabaseComponent<PostgresDatabas value = results.get(metricName); }
- MeasurementDataNumeric mdn = new MeasurementDataNumeric(request, value); - report.addData(mdn); + if (value!=null) { + MeasurementDataNumeric mdn = new MeasurementDataNumeric(request, value); + report.addData(mdn); + } } }
commit 3b0f9d16573db48e4d5f85463a8d550356c79c2b Author: Heiko W. Rupp hwr@redhat.com Date: Mon Apr 26 11:58:20 2010 +0200
Prevent NPE if no sshd is running/found.
diff --git a/modules/plugins/sshd/src/main/java/org/rhq/plugins/sshd/OpenSSHDComponent.java b/modules/plugins/sshd/src/main/java/org/rhq/plugins/sshd/OpenSSHDComponent.java index a2cd1a6..c84beb5 100644 --- a/modules/plugins/sshd/src/main/java/org/rhq/plugins/sshd/OpenSSHDComponent.java +++ b/modules/plugins/sshd/src/main/java/org/rhq/plugins/sshd/OpenSSHDComponent.java @@ -70,7 +70,7 @@ public class OpenSSHDComponent implements ResourceComponent, ConfigurationFacet, }
public AvailabilityType getAvailability() { - return processInfo.isRunning() ? AvailabilityType.UP : AvailabilityType.DOWN; + return (processInfo != null && processInfo.isRunning()) ? AvailabilityType.UP : AvailabilityType.DOWN; }
private void getSSHDProcess() {
commit e5298839fe034f63c45b100c2a1f2e5464794d23 Author: Joseph Marques joseph@redhat.com Date: Fri Apr 23 19:15:39 2010 -0400
BZ-567297 add deletion/removal functionality to the inventory browser group tab
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/inventory/browse/BrowseGroupsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/inventory/browse/BrowseGroupsUIBean.java index 5c39367..37941e7 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/inventory/browse/BrowseGroupsUIBean.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/inventory/browse/BrowseGroupsUIBean.java @@ -3,17 +3,20 @@ package org.rhq.enterprise.gui.inventory.browse; import java.util.ArrayList; import java.util.List;
+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.criteria.ResourceGroupCriteria; import org.rhq.core.domain.resource.group.GroupCategory; import org.rhq.core.domain.resource.group.composite.ResourceGroupComposite; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; import org.rhq.core.gui.util.FacesContextUtility; +import org.rhq.core.gui.util.StringUtility; import org.rhq.enterprise.gui.common.framework.PagedDataTableUIBean; import org.rhq.enterprise.gui.common.paging.PageControlView; import org.rhq.enterprise.gui.common.paging.PagedListDataModel; @@ -93,4 +96,28 @@ public class BrowseGroupsUIBean extends PagedDataTableUIBean { // offer suggestions based on currentInputText return suggestions; } + + public String deleteSelectedGroups() { + try { + Subject subject = getSubject(); + + String[] selectedGroups = getSelectedItems(); + int[] groupIds = StringUtility.getIntArray(selectedGroups); + + for (int nextGroupId : groupIds) { + groupManager.deleteResourceGroup(subject, nextGroupId); + } + + FacesContextUtility.addMessage(FacesMessage.SEVERITY_INFO, "Deleted selected groups"); + } catch (Exception e) { + FacesContextUtility.addMessage(FacesMessage.SEVERITY_ERROR, "Failed to delete all selected groups", e); + } + + return "success"; + } + + private String[] getSelectedItems() { + return FacesContextUtility.getRequest().getParameterValues("selectedItems"); + } + }
commit 190d928d699c43b53b4f794b113fe035c701a10c Author: Joseph Marques joseph@redhat.com Date: Fri Apr 23 19:02:41 2010 -0400
BZ-585255 - fix resource search from the menu bar to properly show disambiguated results
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/menu/menu.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/menu/menu.xhtml index fb41230..232974b 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/menu/menu.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/common/menu/menu.xhtml @@ -136,7 +136,7 @@ <rich:suggestionbox id="resourceSelectBox" for="selectedResource" tokens=",[]" ajaxSingle="true" immediate="true" suggestionAction="#{ResourceSelectUIBean.autocomplete}" - var="result" data="foo" fetchValue="#{result.resource.id}" + var="result" data="foo" fetchValue="#{result.original.resource.id}" nothingLabel="No matching resources found" style="background-color: #cccccc;" onselect="document.location.href='#{onf:getDefaultResourceTabURL()}?id=' + #{rich:element('selectedResource')}.value" @@ -144,15 +144,15 @@ <h:column> <f:facet name="header">Avail</f:facet> <h:graphicImage - value="/images/icons/availability_#{result.availability == 'UP' ? 'green' : 'red'}_16.png"/> + value="/images/icons/availability_#{result.original.availability == 'UP' ? 'green' : 'red'}_16.png"/> </h:column> <h:column> <f:facet name="header">Resource</f:facet> - <h:outputText value="#{result.resource.name}"/> + <h:outputText value="#{result.original.resource.name}"/> </h:column> <h:column> <f:facet name="header">Parent</f:facet> - <h:outputText value="#{result.parent.name}"/> + <h:outputText value="#{result.original.parent.name}"/> </h:column> </rich:suggestionbox> </h:panelGroup>
commit 55e50e5881b78557432e365da3eb05f11f832ff5 Author: Jay Shaughnessy jshaughn@redhat.com Date: Fri Apr 23 17:01:56 2010 -0400
-updated log4j.xml to reduce unit test hibernate verbosity -fixed failing test UpdateEventsSubsystemTest.testDeleteEventStuff() -fixed a log message
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/SubcategoryTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/SubcategoryTest.java index 270fad3..1031f42 100644 --- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/SubcategoryTest.java +++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/SubcategoryTest.java @@ -46,7 +46,7 @@ public class SubcategoryTest extends UpdateSubsytemTestBase { cleanupTest(); } catch (Exception e) { System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName() - + ".testAddDeleteDefaultTemplate"); + + ".testAddResourcTypeWithKnownSubCategory"); } } } diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateEventsSubsystemTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateEventsSubsystemTest.java index 78d2788..4c8ab8a 100644 --- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateEventsSubsystemTest.java +++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/UpdateEventsSubsystemTest.java @@ -45,12 +45,14 @@ import org.rhq.enterprise.server.util.LookupUtil; */ public class UpdateEventsSubsystemTest extends UpdateSubsytemTestBase {
+ static final boolean ENABLED = true; + @Override protected String getSubsystemDirectory() { return "events"; }
- @Test + @Test(enabled = ENABLED) public void testCreateDeleteEvent() throws Exception { System.out.println("= testCreateDeleteEvent"); try { @@ -124,7 +126,7 @@ public class UpdateEventsSubsystemTest extends UpdateSubsytemTestBase { * Simulate just redeploying the plugin with no change in descriptor. * @throws Exception */ - @Test + @Test(enabled = ENABLED) public void testNoOpChange() throws Exception { System.out.println("= testNoOpChange"); try { @@ -172,7 +174,7 @@ public class UpdateEventsSubsystemTest extends UpdateSubsytemTestBase { } }
- @Test + @Test(enabled = ENABLED) public void testDeleteEventStuff() throws Exception { System.out.println("= testDeleteEvent"); EventManagerLocal eventManager = LookupUtil.getEventManager(); @@ -186,8 +188,6 @@ public class UpdateEventsSubsystemTest extends UpdateSubsytemTestBase { registerPlugin("event1-2.xml"); getTransactionManager().begin(); entityManager = getEntityManager(); - getPluginId(entityManager); - platform = getResourceType("events");
testResource = new Resource("-test-", "-test resource", platform); @@ -198,13 +198,13 @@ public class UpdateEventsSubsystemTest extends UpdateSubsytemTestBase {
getTransactionManager().begin(); entityManager = getEntityManager(); - //platform = getResourceType("events"); platform = entityManager.find(ResourceType.class, platform.getId()); testResource = entityManager.find(Resource.class, testResource.getId()); Set<EventDefinition> eDefs = platform.getEventDefinitions(); assert eDefs.size() == 2 : "Did not find the expected 2 eventDefinitions, but " + eDefs.size(); Iterator<EventDefinition> eIter = eDefs.iterator(); boolean found = false; + Map<EventSource, Set<Event>> events = new HashMap<EventSource, Set<Event>>(1); while (eIter.hasNext()) { EventDefinition def = eIter.next(); if (def.getName().equals("hans")) { @@ -212,18 +212,17 @@ public class UpdateEventsSubsystemTest extends UpdateSubsytemTestBase { // We got the definition that will vanish later, so attach some stuff to it EventSource source = new EventSource("test location", def, testResource); entityManager.persist(source); + Event ev = new Event(def.getName(), source.getLocation(), System.currentTimeMillis(), EventSeverity.INFO, "This is a test"); - // entityManager.persist(ev); // We can't do this, as Event.source does not get filled this way :( - Map<EventSource, Set<Event>> events = new HashMap<EventSource, Set<Event>>(1); Set<Event> evSet = new HashSet<Event>(1); evSet.add(ev); events.put(source, evSet); - eventManager.addEventData(events); } } assert found : "Hans was not found"; getTransactionManager().commit(); + eventManager.addEventData(events);
/* * --- done with the setup --- diff --git a/modules/enterprise/server/jar/src/test/resources/log4j.xml b/modules/enterprise/server/jar/src/test/resources/log4j.xml index b9817dd..d721bff 100644 --- a/modules/enterprise/server/jar/src/test/resources/log4j.xml +++ b/modules/enterprise/server/jar/src/test/resources/log4j.xml @@ -44,6 +44,11 @@ </layout> </appender>
+ <!-- Hibernate logs WARNINGS frequent from this class, in test envs. --> + <category name="org.hibernate.hql.ast.QueryTranslatorImpl"> + <priority value="ERROR"/> + </category> + <root> <appender-ref ref="CONSOLE"/> <appender-ref ref="FILE"/>
commit 520863990da701f0ba2c239726fa5bfac992afda Author: Jay Shaughnessy jshaughn@redhat.com Date: Fri Apr 23 16:07:08 2010 -0400
Fix the cleanup of this test.
diff --git a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/SubcategoryTest.java b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/SubcategoryTest.java index 696a25c..270fad3 100644 --- a/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/SubcategoryTest.java +++ b/modules/enterprise/server/jar/src/test/java/org/rhq/enterprise/server/resource/metadata/test/SubcategoryTest.java @@ -18,8 +18,6 @@ */ package org.rhq.enterprise.server.resource.metadata.test;
-import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.testng.annotations.Test;
/** @@ -29,8 +27,6 @@ import org.testng.annotations.Test; */ public class SubcategoryTest extends UpdateSubsytemTestBase {
- private final Log log = LogFactory.getLog(SubcategoryTest.class); - @Override protected String getSubsystemDirectory() { return "resource"; @@ -38,14 +34,20 @@ public class SubcategoryTest extends UpdateSubsytemTestBase {
@Test public void testAddResourcTypeWithKnownSubCategory() throws Exception { - getTransactionManager().begin(); + // Note, plugins are registered in new transactions. for tests, this means + // you can't do everything in a trans and roll back at the end. You must clean up + // manually. try { registerPlugin("test-subcategories.xml"); registerPlugin("test-subcategories3.xml"); - - } finally { - getTransactionManager().rollback(); + // clean up + try { + cleanupTest(); + } catch (Exception e) { + System.out.println("CANNNOT CLEAN UP TEST: " + this.getClass().getSimpleName() + + ".testAddDeleteDefaultTemplate"); + } } }
commit 3259b72fe1efb4b46c0f47e2ef82b2de89b23c09 Author: Jay Shaughnessy jshaughn@redhat.com Date: Fri Apr 23 14:46:17 2010 -0400
Fixed a couple of too-long constraint names for ora.
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 8a89f96..6974780 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -2066,7 +2066,7 @@ <schema-directSQL> <statement> ALTER TABLE RHQ_ALERT_NOTIFICATION - ADD CONSTRAINT RHQ_ALERT_NOTIFICATION_SENDER_CONFIG_ID_FK + ADD CONSTRAINT RHQ_AN_SENDER_CONFIG_ID_FK FOREIGN KEY (SENDER_CONFIG_ID) REFERENCES RHQ_CONFIG (ID) </statement> @@ -2094,7 +2094,7 @@ <schema-directSQL> <statement> ALTER TABLE RHQ_ALERT_NOTIFICATION - ADD CONSTRAINT RHQ_ALERT_NOTIFICATION_TEMPLATE_ID_FK + ADD CONSTRAINT RHQ_AN_TEMPLATE_ID_FK FOREIGN KEY (TEMPLATE_ID) REFERENCES RHQ_ALERT_NOTIF_TEMPL (ID) </statement>
commit 6d0e513b5a6ba7005e5da47c328a55a8104a7f19 Author: Joseph Marques joseph@redhat.com Date: Fri Apr 23 13:17:31 2010 -0400
remove mention of the alert-migration maven module, since it is no longer needed
diff --git a/modules/enterprise/gui/pom.xml b/modules/enterprise/gui/pom.xml index 5a91cab..0c529ba 100644 --- a/modules/enterprise/gui/pom.xml +++ b/modules/enterprise/gui/pom.xml @@ -38,7 +38,6 @@ <module>base-perspective-war</module> <module>webdav-war</module> <module>content_http-war</module> - <module>alert-migration</module> <module>coregui</module> </modules> </profile> diff --git a/modules/enterprise/server/ear/pom.xml b/modules/enterprise/server/ear/pom.xml index 0cc1fb2..eba5172 100644 --- a/modules/enterprise/server/ear/pom.xml +++ b/modules/enterprise/server/ear/pom.xml @@ -80,13 +80,6 @@ <type>war</type> </dependency>
- <dependency> - <groupId>org.rhq.helpers</groupId> - <artifactId>alert-migration</artifactId> - <version>${project.version}</version> - <type>war</type> - </dependency> - <!-- ** SARs --> <!-- <dependency> <groupId>org.rhq</groupId> <artifactId>rhq-enterprise-server-agent-sar</artifactId> @@ -193,13 +186,6 @@ <contextRoot>/content</contextRoot> </webModule>
- <webModule> - <groupId>org.rhq.helpers</groupId> - <artifactId>alert-migration</artifactId> - <bundleFileName>alert-migration.war</bundleFileName> - <contextRoot>/alert-migration</contextRoot> - </webModule> - <!-- ** EJB-JARs -->
<ejbModule>
commit 3d3f6dd4d74aa463dc54208aef82fd127be40a27 Author: Joseph Marques joseph@redhat.com Date: Fri Apr 23 13:14:24 2010 -0400
alert notifications are now db-upgraded using the standard mechanism, this project is no longer needed
diff --git a/modules/enterprise/gui/alert-migration/README.txt b/modules/enterprise/gui/alert-migration/README.txt deleted file mode 100644 index 511720f..0000000 --- a/modules/enterprise/gui/alert-migration/README.txt +++ /dev/null @@ -1,18 +0,0 @@ - -This module is to migrate alert definitions from rhq 1.3.1 to rhq 3 - -You need to follow those steps: - -- have rhq 1.3.1 running -- dump the old alerts (running the scripts need java 1.6 ) - - $ rhq-cli.sh -u rhqadmin -p rhqadmin -f dumpAlertDefinitions.js - - This will dump the alert definitions in to a file called alertDefinitions.csv - in the current directory - -- download rhq 3 and run the installer -- *after* running the installer, direct the - browser to localhost:7080/alert-migration - and upload the alertDefinitions.csv file - diff --git a/modules/enterprise/gui/alert-migration/etc/dumpAlertDefinitions.js b/modules/enterprise/gui/alert-migration/etc/dumpAlertDefinitions.js deleted file mode 100644 index d5c45b3..0000000 --- a/modules/enterprise/gui/alert-migration/etc/dumpAlertDefinitions.js +++ /dev/null @@ -1,14 +0,0 @@ -# -# CLI script to export Alert Definitions -# Writes the dump to a file 'alertDefinitions.csv' in the -# current directory - appends to this file if it already exists. -# call it liek this: "rhq-cli.sh -u rhqadmin -p rhqadmin -f dumpAlertDefinitions.js" -# -criteria = new AlertDefinitionCriteria() -criteria.fetchAlertNotifications(true) - -defs = AlertDefinitionManager.findAlertDefinitionsByCriteria(subject,criteria) - -exporter.setTarget('csv', 'alertDefinitions.csv') -exporter.write(defs) - diff --git a/modules/enterprise/gui/alert-migration/pom.xml b/modules/enterprise/gui/alert-migration/pom.xml deleted file mode 100644 index b7e8205..0000000 --- a/modules/enterprise/gui/alert-migration/pom.xml +++ /dev/null @@ -1,254 +0,0 @@ -<?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-helpers</artifactId> - <groupId>org.rhq.helpers</groupId> - <version>3.0.0-SNAPSHOT</version> - </parent> - <modelVersion>4.0.0</modelVersion> - - <groupId>org.rhq.helpers</groupId> - <artifactId>alert-migration</artifactId> - <packaging>war</packaging> - - <name>RHQ alert migration</name> - <description>Migrate alert notification from RHQ 1.3.1 to RHQ 3 format</description> - - <scm> - <connection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/enterprise/gui/alert-migration</connection> - <developerConnection>scm:git:ssh://git.fedorahosted.org/git/rhq.git/modules/enterprise/gui/alert-migration</developerConnection> - </scm> - - <dependencies> - <dependency> - <groupId>org.rhq</groupId> - <artifactId>rhq-core-domain</artifactId> - <version>${project.version}</version> - <scope>provided</scope> <!-- by ear --> - </dependency> - - <dependency> - <groupId>org.rhq</groupId> - <artifactId>rhq-enterprise-server</artifactId> - <version>${project.version}</version> - <scope>provided</scope> <!-- by rhq.ear (as ejb-jar) --> - </dependency> - - <dependency> - <groupId>org.rhq</groupId> - <artifactId>rhq-core-util</artifactId> - <version>${project.version}</version> - <scope>provided</scope> <!-- by rhq.ear --> - </dependency> - - - <dependency> - <groupId>net.sf.opencsv</groupId> - <artifactId>opencsv</artifactId> - <version>2.0</version> - </dependency> - - <!-- This is a fix for the Javac bug requiring annotations to be - available when compiling dependent classes. --> - <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>jboss.jboss-embeddable-ejb3</groupId> - <artifactId>jboss-ejb3-all</artifactId> - <version>1.0.0.Alpha9</version> - <scope>provided</scope> - </dependency> - - <dependency> - <groupId>javax.servlet</groupId> - <artifactId>servlet-api</artifactId> - <version>2.4</version> - <scope>provided</scope> <!-- by JBossAS --> - </dependency> - - <dependency> - <groupId>commons-fileupload</groupId> - <artifactId>commons-fileupload</artifactId> - <version>1.2</version> - </dependency> - - <dependency> - <groupId>commons-io</groupId> - <artifactId>commons-io</artifactId> - <version>1.3.1</version> - </dependency> - - <dependency> - <groupId>i18nlog</groupId> - <artifactId>i18nlog</artifactId> - <version>1.0.9</version> - <scope>provided</scope> - </dependency> - - </dependencies> - - <build> - <finalName>alert-migration</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>false</filtering> - <directory>${basedir}/src/main/webapp</directory> - <!--<includes>--> - <!--<include>**/*.properties</include>--> - <!--</includes>--> - </resource> - <!--<resource>--> - <!--<filtering>true</filtering>--> - <!--<directory>${basedir}/target/resources</directory>--> - <!--<includes>--> - <!--<include>**/*.properties</include>--> - <!--</includes>--> - <!--</resource>--> - </webResources> - </configuration> - </plugin> - -<!-- - <plugin> - <artifactId>maven-antrun-plugin</artifactId> - <executions> - <execution> - <id>Generate I18N Resource Bundles</id> - <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">- -> - <i18n outputdir="${basedir}/target/resources/WEB-INF/classes" defaultlocale="en" verbose="false" append="false" verify="true"> - <classpath refid="maven.runtime.classpath" /> - <classfileset dir="${project.build.outputDirectory}"> - <include name="**/*I18NResourceKeys.class" /> - </classfileset> - </i18n> - <copy todir="${project.build.outputDirectory}" encoding="UTF-8" outputencoding="UTF-8"> - <fileset dir="${basedir}/target/resources/WEB-INF/classes"> - <include name="InstallerMessages*.properties" /> - </fileset> - <mapper type="glob" from="*" to="*.unfiltered" /> - </copy> - </tasks> - </configuration> - <goals> - <goal>run</goal> - </goals> - </execution> - </executions> - </plugin> ---> - </plugins> - - </build> - - <profiles> - - <profile> - <id>dev</id> - - <properties> - <rhq.rootDir>../../../..</rhq.rootDir> - <rhq.containerDir>${rhq.rootDir}/${rhq.defaultDevContainerPath}</rhq.containerDir> - <rhq.deploymentName>${project.build.finalName}.war</rhq.deploymentName> - <rhq.deploymentDir>${rhq.containerDir}/jbossas/server/default/deploy/${rhq.earName}/${rhq.deploymentName}</rhq.deploymentDir> - </properties> - - <build> - <plugins> - - <plugin> - <artifactId>maven-antrun-plugin</artifactId> - <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}" 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/alert-migration/src/main/java/org/rhq/helpers/alertMigration/Alert13Parser.java b/modules/enterprise/gui/alert-migration/src/main/java/org/rhq/helpers/alertMigration/Alert13Parser.java deleted file mode 100644 index 9107354..0000000 --- a/modules/enterprise/gui/alert-migration/src/main/java/org/rhq/helpers/alertMigration/Alert13Parser.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * RHQ Management Platform - * Copyright (C) 2005-2010 Red Hat, Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -package org.rhq.helpers.alertMigration; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import au.com.bytecode.opencsv.CSVReader; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.rhq.core.domain.alert.notification.AlertNotification; -import org.rhq.core.domain.configuration.Configuration; -import org.rhq.core.domain.configuration.PropertySimple; - -/** - * Parser for a dump of the 1.3 alert structures via CLI - * @author Heiko W. Rupp - */ -public class Alert13Parser { - - private final Log log = LogFactory.getLog(Alert13Parser.class); - File inputFile; - Reader inputReader; - - public static final String RHQ_USERS = "RHQ Users"; - - public Alert13Parser(File input) { - this.inputFile = input; - try { - inputReader = new FileReader(input); - } catch (FileNotFoundException e) { - throw new RuntimeException("File " + input.getAbsolutePath() + " not found"); - } - } - - public Alert13Parser(Reader reader) { - inputReader = reader; - } - - public Alert13Parser(InputStream stream) { - inputReader = new InputStreamReader(stream); - } - - - - public List<AlertNotification> parse() { - - List<AlertNotification> result = new ArrayList<AlertNotification>(); - - List<String[]> lines = null; - try { - CSVReader reader = new CSVReader(inputReader); - lines = reader.readAll(); - reader.close(); - - - boolean isFirst = true; - for (String[] line : lines) { - if (isFirst) { // Skip over first line with headers - isFirst=false; - continue; - } - if (line.length<2) // Skip over empty lines - continue; - - log.debug(Arrays.asList(line)); - String tmp = line[9]; // alert definition id - int alertDefinitionId = Integer.valueOf(tmp); - log.debug(" adefid " + alertDefinitionId); - - tmp = line[1]; // Notifications - CSVReader nr = new CSVReader(new StringReader(tmp)); - String[] notifications = nr.readNext(); - int i = 0; - int pos = 0; - while (i < notifications.length) { - int nid; - String n = notifications[i]; - log.debug(" Notification: " + n); - /* - * A single notification now runs over multiple lines - */ - if (n.startsWith("[") || n.startsWith(" ")) - n = n.substring(1); - - if (n.equals("]")) { - i++; - continue; - } - - nid = Integer.valueOf(getField(n,"id")); - - - AlertNotification alNo = new AlertNotification(alertDefinitionId,nid); - Configuration config = new Configuration(); - alNo.setConfiguration(config); - alNo.setOrder(pos); - - if (n.startsWith("Subject")) { - String subjectId = getField(notifications[i+1],"id"); - String subject = getField(notifications[i+2],"name"); - i+=4; - log.debug("subject: " + subjectId); - config.put(new PropertySimple("subjectId", subjectId)); - alNo.setSenderName(RHQ_USERS); - alNo.setName(subject); - - } else if (n.startsWith("Role")) { - String roleId = getField(notifications[i+1],"id"); - String role = getField(notifications[i+2],"name"); - i+=4; - log.debug("role: " + roleId); - config.put(new PropertySimple("roleId", roleId)); - alNo.setSenderName("Roles"); - alNo.setName(role); - - - } else if (n.startsWith("Snmp")) { - String host = getField(notifications[i+1],"host"); - String port = getField(notifications[i+2],"port"); - String oid = getField(notifications[i+3],"oid"); - i+=5; - log.debug("snmp: " + host + ", " + port + ", " + oid); - config.put(new PropertySimple("host",host)); - config.put(new PropertySimple("port",port)); - config.put(new PropertySimple("OID",oid)); - alNo.setSenderName("SNMP"); - alNo.setName(host+oid); - - } else if (n.startsWith("Email")) { - String emails = getField(notifications[i+1],"emailAddress"); - log.debug("email: " + emails); - config.put(new PropertySimple("emailAddress",emails)); - alNo.setSenderName("Email"); - alNo.setName(emails); - i+=3; - } else { - log.error("Unknown notification :>" + n + "<"); - i++; - } - log.debug(" -- for nid : " + nid); - - result.add(alNo); - pos++; - } - - tmp = line[12]; - nr = new CSVReader(new StringReader(tmp)); - String[] operations = nr.readNext(); -// for (String op: operations) { -// log.debug(" Operation: " + op); -// } - - } - } catch (IOException e) { - e.printStackTrace(); // TODO: Customise this generated block - return result; - } - - return result; - } - - private String getField(String input, String fieldName) { - - String str = fieldName + "="; - int pos = input.indexOf(str); - if (pos==-1) - return ""; - String tmp = input.substring(pos+str.length()); - if (tmp.endsWith("]")) - tmp = tmp.substring(0,tmp.length()-1); - - return tmp; - } -} diff --git a/modules/enterprise/gui/alert-migration/src/main/java/org/rhq/helpers/alertMigration/MigrationServlet.java b/modules/enterprise/gui/alert-migration/src/main/java/org/rhq/helpers/alertMigration/MigrationServlet.java deleted file mode 100644 index 9ac4b25..0000000 --- a/modules/enterprise/gui/alert-migration/src/main/java/org/rhq/helpers/alertMigration/MigrationServlet.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * RHQ Management Platform - * Copyright (C) 2005-2010 Red Hat, Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -package org.rhq.helpers.alertMigration; - -import java.io.IOException; -import java.io.PrintWriter; -import java.util.Iterator; -import java.util.List; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileUploadException; -import org.apache.commons.fileupload.disk.DiskFileItemFactory; -import org.apache.commons.fileupload.servlet.ServletFileUpload; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.rhq.core.domain.alert.notification.AlertNotification; -import org.rhq.core.domain.auth.Subject; -import org.rhq.enterprise.server.alert.AlertNotificationManagerLocal; -import org.rhq.enterprise.server.util.LookupUtil; - -/** - * Simple servlet to upload an rhq 1.3 alert definition dump after - * migrating the database to rhq 3.0 format. - * - * @author Heiko W. Rupp - */ -public class MigrationServlet extends HttpServlet { - - private final Log log = LogFactory.getLog(MigrationServlet.class); - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - - PrintWriter writer; - if (ServletFileUpload.isMultipartContent(req)){ - - ServletFileUpload servletFileUpload = new ServletFileUpload(new DiskFileItemFactory()); - List fileItemsList = null; - try { - fileItemsList = servletFileUpload.parseRequest(req); - } catch (FileUploadException e) { - - writer = resp.getWriter(); - writer.write("<strong>File upload failed: </strong><br/>"); - for (StackTraceElement elem : e.getStackTrace()) - writer.write(elem.toString() + "br/>"); - writer.flush(); - return; - } - - Iterator it = fileItemsList.iterator(); - while (it.hasNext()){ - FileItem fileItem = (FileItem)it.next(); - if (fileItem.isFormField()){ - /* The file item contains a simple name-value pair of a form field */ - // TODO flag as error ? - } - else{ - /* The file item contains an uploaded file */ - - Alert13Parser parser = new Alert13Parser(fileItem.getInputStream()); - List<AlertNotification> notifications = parser.parse(); - AlertNotificationManagerLocal notificationManager = LookupUtil.getAlertNotificationManager(); - Subject overlord = LookupUtil.getSubjectManager().getOverlord(); - - notificationManager.mergeTransientAlertNotifications(overlord,notifications); - - writer = resp.getWriter(); - writer.write("<strong>Alert Definitions have been migrated</strong><p/>"); - writer.write("<a href="/Dashboard.do">To the RHQ Dashboard</a>"); - writer.flush(); - - } - } - } - - } -} diff --git a/modules/enterprise/gui/alert-migration/src/main/java/org/rhq/helpers/alertMigration/RestoreAlerts.java b/modules/enterprise/gui/alert-migration/src/main/java/org/rhq/helpers/alertMigration/RestoreAlerts.java deleted file mode 100644 index 7e9e761..0000000 --- a/modules/enterprise/gui/alert-migration/src/main/java/org/rhq/helpers/alertMigration/RestoreAlerts.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * RHQ Management Platform - * Copyright (C) 2005-2010 Red Hat, Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -package org.rhq.helpers.alertMigration; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.util.ArrayList; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.rhq.core.domain.alert.notification.AlertNotification; - -/** - * Read in a dump file and print the Alert notifications to stdout. - * Only useful for testing. - * - * @author Heiko W. Rupp - */ -public class RestoreAlerts { - - private final Log log = LogFactory.getLog(RestoreAlerts.class); - - - public static void main(String[] args) { - - if (args.length<1) { - usage(); - System.exit(1); - } - - File file = new File(args[0]); - if (!file.canRead()) { - System.err.println("Can not read file " + file.getAbsolutePath()); - System.exit(2); - } - - Alert13Parser parser = new Alert13Parser(file); - List<AlertNotification> notifications = parser.parse(); - - System.out.println("Found " + notifications.size() + " notifications in the dump"); - for (AlertNotification n : notifications) - System.out.println(n); - - } - - - private static void usage() { - System.out.println("Usage:"); - System.out.println(" RestoreAlerts inputFile"); - } - -} diff --git a/modules/enterprise/gui/alert-migration/src/main/webapp/WEB-INF/web.xml b/modules/enterprise/gui/alert-migration/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index ec27207..0000000 --- a/modules/enterprise/gui/alert-migration/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0"?> - -<web-app xmlns="http://java.sun.com/xml/ns/javaee" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_4.xsd" - version="2.4"> - - <display-name>RHQ Alert Migration Helper</display-name> - <description>RHQ Alert Migration Helper. This is uesd to migrate 1.3.1 style alerts to the 3.0 format.</description> - - <servlet> - <servlet-name>Migration Servlet</servlet-name> - <servlet-class>org.rhq.helpers.alertMigration.MigrationServlet</servlet-class> - <load-on-startup>2</load-on-startup> - </servlet> - - <servlet-mapping> - <servlet-name>Migration Servlet</servlet-name> - <url-pattern>/migration</url-pattern> - </servlet-mapping> - - - <welcome-file-list> - <welcome-file>index.html</welcome-file> - </welcome-file-list> - -</web-app> \ No newline at end of file diff --git a/modules/enterprise/gui/alert-migration/src/main/webapp/index.html b/modules/enterprise/gui/alert-migration/src/main/webapp/index.html deleted file mode 100644 index 0650df0..0000000 --- a/modules/enterprise/gui/alert-migration/src/main/webapp/index.html +++ /dev/null @@ -1,17 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" - "http://www.w3.org/TR/html4/loose.dtd"> -<html> -<head> - <title>Alert Migration</title> -</head> -<body> - -<h1>Alert Migration</h1> -<strong>Please supply the dump file</strong> -<form action="migration" method="POST" enctype="multipart/form-data"> - <input name="alertDumpFile" type="file" size="50" maxlength="100000" accept="text/*"> - <br/> - <input type="submit" value="Upload!"> -</form> -</body> -</html> \ No newline at end of file diff --git a/modules/enterprise/gui/alert-migration/src/test/java/Alert13ParserTest.java b/modules/enterprise/gui/alert-migration/src/test/java/Alert13ParserTest.java deleted file mode 100644 index d038f8e..0000000 --- a/modules/enterprise/gui/alert-migration/src/test/java/Alert13ParserTest.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * RHQ Management Platform - * Copyright (C) 2005-2010 Red Hat, Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -import java.io.File; -import java.util.List; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.testng.annotations.Test; - -import org.rhq.core.domain.alert.notification.AlertNotification; -import org.rhq.core.domain.configuration.Configuration; -import org.rhq.helpers.alertMigration.Alert13Parser; - -/** - * Test for the alert13 parser - * @author Heiko W. Rupp - */ -@Test -public class Alert13ParserTest { - - private final Log log = LogFactory.getLog(Alert13ParserTest.class); - - - - public void testParser() throws Exception { - - File input = new File("src/test/resources/alertDef.csv"); - - Alert13Parser parser = new Alert13Parser(input); - List<AlertNotification> notifications = parser.parse(); - - assert notifications != null; - assert notifications.size()==15 : "Did not find 15 notifications, but " + notifications.size(); - - for (AlertNotification n : notifications) { - - switch (n.getAlertNotificationId()) { - case 10001: - assert n.getAlertDefinitionId() == 10001; - assert n.getSenderName().equals(Alert13Parser.RHQ_USERS); - break; - case 10011: - assert n.getAlertDefinitionId() == 10011; - assert n.getSenderName().equals("Roles"); - break; - case 10002: - assert n.getAlertDefinitionId() == 10011; - assert n.getSenderName().equals("Email"); - assert n.getConfiguration().getSimpleValue("emailAddress","").equals("hwr@bsd.de"); - break; - case 10031: - assert n.getAlertDefinitionId() == 10011; - assert n.getSenderName().equals("Email"); - assert n.getConfiguration().getSimpleValue("emailAddress","").equals("hwr@pilhuhn.de"); - break; - case 10032: - assert n.getAlertDefinitionId() == 10051; - assert n.getSenderName().equals("SNMP"); - Configuration c = n.getConfiguration(); - assert c.getSimpleValue("host","").equals("localhost"); - assert c.getSimpleValue("OID","").equals("1.2.3.4.5.6.7"); - - } - } - } -} diff --git a/modules/enterprise/gui/alert-migration/src/test/resources/alertDef.csv b/modules/enterprise/gui/alert-migration/src/test/resources/alertDef.csv deleted file mode 100644 index 4a7bb87..0000000 --- a/modules/enterprise/gui/alert-migration/src/test/resources/alertDef.csv +++ /dev/null @@ -1,13 +0,0 @@ -"alertDampening","alertNotifications","conditionExpression","context","controlFiltered","deleted","description","enabled","groupAlertDefinition","id","name","notifyFiltered","operationDefinition","parentId","priority","readOnly","recoveryId","resource","resourceGroup","resourceType","willRecover" - -"org.rhq.core.domain.alert.AlertDampening[ category=NONE[] ]","[SubjectNotification[id=10001, subject=org.rhq.core.domain.auth.Subject[id=2,name=rhqadmin], ]]","ANY","Resource","false","false","","false","null","10001","test1","false","null","0","!! - Medium","false","0","Resource[id=10001, type=Mac OS X, key=snert-embedded, name=snert-embedded, parent=<null>, version=MacOSX 10.6.2]","null","null","false" -"org.rhq.core.domain.alert.AlertDampening[ category=NONE[] ]","[RoleNotification[id=10011, role=org.rhq.core.domain.authz.Role[id=1, name=Super User Role], ], EmailNotification[id=10031, emailAddress=hwr@pilhuhn.de, ], EmailNotification[id=10002, emailAddress=hwr@bsd.de, ]]","ANY","Resource","false","false","","false","null","10011","test2","false","null","0","!!! - High","false","0","Resource[id=10001, type=Mac OS X, key=snert-embedded, name=snert-embedded, parent=<null>, version=MacOSX 10.6.2]","null","null","false" -"org.rhq.core.domain.alert.AlertDampening[ category=NONE[] ]","[RoleNotification[id=10021, role=org.rhq.core.domain.authz.Role[id=1, name=Super User Role], ], RoleNotification[id=10022, role=org.rhq.core.domain.authz.Role[id=2, name=All Resources Role], ]]","ANY","Group","false","false","","true","null","10041","Group Alert","false","null","0","!! - Medium","false","0","null","ResourceGroup[id=10001, name=ASse, category=COMPATIBLE, type=JBossAS Server, isDynaGroup=false, isClusterGroup=false]","null","true" -"org.rhq.core.domain.alert.AlertDampening[ category=NONE[] ]","[RoleNotification[id=10023, role=org.rhq.core.domain.authz.Role[id=1, name=Super User Role], ], RoleNotification[id=10024, role=org.rhq.core.domain.authz.Role[id=2, name=All Resources Role], ]]","ANY","Resource","false","false","","true","org.rhq.core.domain.alert.AlertDefinition[ id=10041, name=Group Alert, conditionExpression=ANY, priority=!! - Medium, ]","10042","Group Alert","false","null","0","!! - Medium","false","0","Resource[id=10004, type=JBossAS Server, key=/jon/jopr-server-2.3.1/jbossas/server/default, name=snert JBossAS 4.2.3.GA default (snert:2099), parent=snert-embedded, version=4.2.3.GA]","null","null","true" -"org.rhq.core.domain.alert.AlertDampening[ category=NONE[] ]","[RoleNotification[id=10025, role=org.rhq.core.domain.authz.Role[id=1, name=Super User Role], ], RoleNotification[id=10026, role=org.rhq.core.domain.authz.Role[id=2, name=All Resources Role], ]]","ANY","Resource","false","false","","true","org.rhq.core.domain.alert.AlertDefinition[ id=10041, name=Group Alert, conditionExpression=ANY, priority=!! - Medium, ]","10043","Group Alert","false","null","0","!! - Medium","false","0","Resource[id=11034, type=JBossAS Server, key=/devel/jboss-4.0.5.GA/server/default, name=pickeldi JBossAS 4.0.5.GA default (1099), version=4.0.5.GA]","null","null","true" -"org.rhq.core.domain.alert.AlertDampening[ category=NONE[] ]","[SnmpNotification[id=10032, host=localhost, port=162, oid=1.2.3.4.5.6.7, ]]","ANY","Resource","false","false","","true","null","10051","snmp","false","null","0","!! - Medium","false","0","Resource[id=10001, type=Mac OS X, key=snert-embedded, name=snert-embedded, parent=<null>, version=MacOSX 10.6.2]","null","null","true" -"org.rhq.core.domain.alert.AlertDampening[ category=NONE[] ]","[RoleNotification[id=10041, role=org.rhq.core.domain.authz.Role[id=1, name=Super User Role], ], RoleNotification[id=10042, role=org.rhq.core.domain.authz.Role[id=2, name=All Resources Role], ]]","ANY","Type","false","false","","true","null","10061","test-template","false","null","0","!! - Medium","false","0","null","null","Mac OS X","true" -"org.rhq.core.domain.alert.AlertDampening[ category=NONE[] ]","[RoleNotification[id=10043, role=org.rhq.core.domain.authz.Role[id=1, name=Super User Role], ], RoleNotification[id=10044, role=org.rhq.core.domain.authz.Role[id=2, name=All Resources Role], ]]","ANY","Resource","false","false","","true","null","10062","test-template","false","null","10061","!! - Medium","false","0","Resource[id=10001, type=Mac OS X, key=snert-embedded, name=snert-embedded, parent=<null>, version=MacOSX 10.6.2]","null","null","true" -"org.rhq.core.domain.alert.AlertDampening[ category=NONE[] ]","[]","ANY","Resource","false","false","no explicit notification","false","null","10021","Test3","false","null","0","!! - Medium","false","0","Resource[id=10001, type=Mac OS X, key=snert-embedded, name=snert-embedded, parent=<null>, version=MacOSX 10.6.2]","null","null","true" -"org.rhq.core.domain.alert.AlertDampening[ category=NONE[] ]","[]","ANY","Resource","false","false","","false","null","10031","OPs","false","OperationDefinition[id=10016, resourceType=ResourceType[id=10051, category=Platform, name=Mac OS X, plugin=Platforms], name=viewProcessList]","0","!! - Medium","false","0","Resource[id=10001, type=Mac OS X, key=snert-embedded, name=snert-embedded, parent=<null>, version=MacOSX 10.6.2]","null","null","true" -10 rows
commit 6308d13ee4d776800175ba2d07d44bb8c00aba90 Author: Joseph Marques joseph@redhat.com Date: Fri Apr 23 12:52:39 2010 -0400
remove OrderBy attribute, since alert notification order column was removed
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java index f607af3..afa5671 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertDefinition.java @@ -352,7 +352,6 @@ public class AlertDefinition implements Serializable { private Set<AlertCondition> conditions = new LinkedHashSet<AlertCondition>(1); // Most alerts will only have one condition.
@OneToMany(mappedBy = "alertDefinition", cascade = CascadeType.ALL) - @OrderBy("order asc") @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) private List<AlertNotification> alertNotifications = new ArrayList<AlertNotification>();
commit 24bb8b4dfe497ca6f8e0716e5933f8dbe55f3e8d Author: Joseph Marques joseph@redhat.com Date: Fri Apr 23 11:16:47 2010 -0400
move the upgrade procedures for postgreaming blob streaming out into its own schemaSpec
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 af19962..8a89f96 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -2665,6 +2665,27 @@ </schema-directSQL> </schemaSpec>
+ <schemaSpec version="2.81"> + <!-- fix for postgres not properly streaming blobs to JDBC clients --> + <schema-directSQL targetDBVendor="postgresql"> + <statement desc="Change bytea column to oid in postgres."> + ALTER TABLE RHQ_PACKAGE_BITS ADD COLUMN NEWOID OID + </statement> + <statement desc="Change bytea column to oid in postgres."> + UPDATE RHQ_PACKAGE_BITS t SET NEWOID = ( + SELECT oid FROM ( + SELECT oid, lowrite(lo_open(oid, 131072), t.bits) + FROM lo_create(0) o(oid)) x) + </statement> + <statement desc="Change bytea column to oid in postgres."> + ALTER TABLE RHQ_PACKAGE_BITS DROP COLUMN BITS + </statement> + <statement desc="Change bytea column to oid in postgres."> + ALTER TABLE RHQ_PACKAGE_BITS RENAME COLUMN NEWOID TO BITS + </statement> + </schema-directSQL> + </schemaSpec> + <schemaSpec version="2.82"> <schema-directSQL> <statement desc="Creating table RHQ_SAVED_SEARCH"> @@ -2711,23 +2732,6 @@ VALUES (2, 'Resource', 'Downed Servers', 'All downed servers across the entire enterprise', 'down server', 0, 1, 1) </statement> </schema-directSQL> - <schema-directSQL targetDBVendor="postgresql"> - <statement desc="Change bytea column to oid in postgres."> - ALTER TABLE RHQ_PACKAGE_BITS ADD COLUMN NEWOID OID - </statement> - <statement desc="Change bytea column to oid in postgres."> - UPDATE RHQ_PACKAGE_BITS t SET NEWOID = ( - SELECT oid FROM ( - SELECT oid, lowrite(lo_open(oid, 131072), t.bits) - FROM lo_create(0) o(oid)) x) - </statement> - <statement desc="Change bytea column to oid in postgres."> - ALTER TABLE RHQ_PACKAGE_BITS DROP COLUMN BITS - </statement> - <statement desc="Change bytea column to oid in postgres."> - ALTER TABLE RHQ_PACKAGE_BITS RENAME COLUMN NEWOID TO BITS - </statement> - </schema-directSQL> </schemaSpec>
<schemaSpec version="2.83">
commit 169dc47215afcf11a84e7d8161b2d9071d4fa4ac Author: Joseph Marques joseph@redhat.com Date: Fri Apr 23 11:11:34 2010 -0400
fix/simplified dbupgrade for RHQ_SAVED_SEARCH table
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 c3aeffe..af19962 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -2668,14 +2668,11 @@ <schemaSpec version="2.82"> <schema-directSQL> <statement desc="Creating table RHQ_SAVED_SEARCH"> - CREATE TABLE RHQ_SAVED_SEARCH ( ID INTEGER ) - </statement> - </schema-directSQL> - <schema-directSQL> - <statement desc="Creating primary key for RHQ_SAVED_SEARCH"> - ALTER TABLE RHQ_SAVED_SEARCH ADD PRIMARY KEY ( ID ) + CREATE TABLE RHQ_SAVED_SEARCH ( ID INTEGER PRIMARY KEY ) </statement> </schema-directSQL> + <schema-alterColumn table="RHQ_SAVED_SEARCH" column="ID" nullable="FALSE" /> + <schema-addColumn table="RHQ_SAVED_SEARCH" column="CONTEXT" columnType="VARCHAR2" precision="25" /> <schema-alterColumn table="RHQ_SAVED_SEARCH" column="CONTEXT" nullable="FALSE" />
commit fb8574a8eaa130bb1d2af1bb97cac5bf03d81d16 Author: Joseph Marques joseph@redhat.com Date: Fri Apr 23 11:11:15 2010 -0400
change name of primary key constraint on RHQ_SUBJECT_ROLE_LDAP_MAP to be less than 30 chars, to match dbupgrade task 2.83
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/authz-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/authz-schema.xml index 45cc880..8d9f738 100644 --- a/modules/core/dbutils/src/main/scripts/dbsetup/authz-schema.xml +++ b/modules/core/dbutils/src/main/scripts/dbsetup/authz-schema.xml @@ -84,7 +84,7 @@ <table name="RHQ_SUBJECT_ROLE_LDAP_MAP"> <column name="SUBJECT_ID" required="true" type="INTEGER" references="RHQ_SUBJECT"/> <column name="ROLE_ID" required="true" type="INTEGER" references="RHQ_ROLE"/> - <constraint name="RHQ_SUBJECT_ROLE_LDAP_MAP_KEY"> + <constraint name="RHQ_SUBJECT_ROLE_LDAP_MAP_PK"> <primaryKey> <field ref="SUBJECT_ID" /> <field ref="ROLE_ID"/>
commit a58af3b6c8c4e5aaab67c1e706d249392dcbe79e Author: Joseph Marques joseph@redhat.com Date: Fri Apr 23 11:08:22 2010 -0400
add necessary dbupgrade pieces for RHQ_SUBJECT_ROLE_LDAP_MAP table
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 047be90..c3aeffe 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -2090,7 +2090,7 @@ </schemaSpec> <schemaSpec version="2.70.2"> <!-- add structures for alert notification templates --> - <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="NOTIF_TEMPLATE_ID" columnType="INTEGER" /> + <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="TEMPLATE_ID" columnType="INTEGER" /> <schema-directSQL> <statement> ALTER TABLE RHQ_ALERT_NOTIFICATION @@ -2734,18 +2734,30 @@ </schemaSpec>
<schemaSpec version="2.83"> - <!-- The following constraint change shortens the constraint name < 30 chars for Oracle. --> - <schema-directSQL> - <statement targetDBVendor="postgresql" desc="Dropping RHQ_SUBJECT_ROLE_LDAP_MAP constraint RHQ_SUBJECT_ROLE_LDAP_MAPPING_KEY."> - ALTER TABLE RHQ_SUBJECT_ROLE_LDAP_MAP DROP CONSTRAINT RHQ_SUBJECT_ROLE_LDAP_MAPPING_KEY; + <schema-directSQL> + <statement desc="Creating table RHQ_SUBJECT_ROLE_LDAP_MAP"> + CREATE TABLE RHQ_SUBJECT_ROLE_LDAP_MAP ( SUBJECT_ID INTEGER, ROLE_ID INTEGER ) </statement> - <!-- There is no PL/SQL update for ora dbs as the problematic statement could never be created on oracle, so nothing to fix. --> - <statement targetDBVendor="postgresql" desc="Creating new RHQ_SUBJECT_ROLE_LDAP_MAP constraint RHQ_SUBJECT_ROLE_LDAP_MAP_KEY"> + <statement desc="Creating composite PK for RHQ_SUBJECT_ROLE_LDAP_MAP"> ALTER TABLE RHQ_SUBJECT_ROLE_LDAP_MAP - ADD CONSTRAINT RHQ_SUBJECT_ROLE_LDAP_MAP_KEY + ADD CONSTRAINT RHQ_SUBJECT_ROLE_LDAP_MAP_PK PRIMARY KEY ( SUBJECT_ID, ROLE_ID ) </statement> + <statement desc="Creating FK relation to RHQ_SUBJECT table for SUBJECT_ID column"> + ALTER TABLE RHQ_SUBJECT_ROLE_LDAP_MAP + ADD CONSTRAINT RHQ_SRLM_SUBJECT_ID_FK + FOREIGN KEY (SUBJECT_ID) + REFERENCES RHQ_SUBJECT (ID) + </statement> + <statement desc="Creating FK relation to RHQ_ROLE table for ROLE_ID column"> + ALTER TABLE RHQ_SUBJECT_ROLE_LDAP_MAP + ADD CONSTRAINT RHQ_SRLM_ROLE_ID_FK + FOREIGN KEY (ROLE_ID) + REFERENCES RHQ_ROLE (ID) + </statement> </schema-directSQL> + <schema-alterColumn table="RHQ_SUBJECT_ROLE_LDAP_MAP" column="SUBJECT_ID" nullable="FALSE" /> + <schema-alterColumn table="RHQ_SUBJECT_ROLE_LDAP_MAP" column="ROLE_ID" nullable="FALSE" /> </schemaSpec>
</dbupgrade>
commit 1a06c55942f3b03f78b061ec3aee6e36a8820173 Author: Joseph Marques joseph@redhat.com Date: Fri Apr 23 11:03:28 2010 -0400
fix dbupgrade logic for subject/role/email notifications
diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/CustomAlertSenderUpgradeTask.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/CustomAlertSenderUpgradeTask.java index a94f095..0fa4ee8 100644 --- a/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/CustomAlertSenderUpgradeTask.java +++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/CustomAlertSenderUpgradeTask.java @@ -147,7 +147,7 @@ public class CustomAlertSenderUpgradeTask implements DatabaseUpgradeTask { // buffer will be 0 the very first time, since definitionId is initially -1 int configId = persistConfiguration("operation-definition-id", operationDefinitionId, "selection-mode", "SELF"); - persistNotification(alertDefinitionId, configId, "Resource Operations", "Operational "); + persistNotification(alertDefinitionId, configId, "Resource Operations", "Operation Invocation"); } }
@@ -165,13 +165,18 @@ public class CustomAlertSenderUpgradeTask implements DatabaseUpgradeTask { persistNotification(definitionId, configId, sender, name); } buffer = new StringBuilder(); // reset for the next definitionId - } else { - if (buffer.length() != 0) { - // elements are already in the list - buffer.append(','); - } - buffer.append(nextData); } + + if (buffer.length() != 0) { + // elements are already in the list + buffer.append(','); + } + buffer.append(nextData); + } + + if (buffer.length() != 0) { + int configId = persistConfiguration(propertyName, buffer.toString()); + persistNotification(definitionId, configId, sender, name); } }
commit e8b7b579f801fc1c50afc7f8631dd5471d01beb1 Author: Joseph Marques joseph@redhat.com Date: Thu Apr 22 14:34:17 2010 -0400
add database upgrade support for customer alert senders
diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/ant/dbupgrade/SST_JavaTask.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/ant/dbupgrade/SST_JavaTask.java index b083510..707694f 100644 --- a/modules/core/dbutils/src/main/java/org/rhq/core/db/ant/dbupgrade/SST_JavaTask.java +++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/ant/dbupgrade/SST_JavaTask.java @@ -74,9 +74,6 @@ public class SST_JavaTask extends SchemaSpecTask { validateAttributes();
try { - DatabaseType db_type = getDatabaseType(); - Connection conn = getConnection(); - if (className.indexOf(".") == -1) { className = "org.rhq.core.db.upgrade." + className; } @@ -85,7 +82,11 @@ public class SST_JavaTask extends SchemaSpecTask {
Class<?> javaTaskClass = Class.forName(className); DatabaseUpgradeTask javaTask = (DatabaseUpgradeTask) javaTaskClass.newInstance(); - javaTask.execute(conn, db_type); + + DatabaseType db_type = getDatabaseType(); + Connection conn = getConnection(); + + javaTask.execute(db_type, conn); } catch (Exception e) { throw new BuildException(MSG.getMsg(DbAntI18NResourceKeys.JAVA_TASK_ERROR, e), e); } diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/CustomAlertSenderUpgradeTask.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/CustomAlertSenderUpgradeTask.java new file mode 100644 index 0000000..a94f095 --- /dev/null +++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/CustomAlertSenderUpgradeTask.java @@ -0,0 +1,217 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2008 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.core.db.upgrade; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.List; + +import org.rhq.core.db.DatabaseType; + +/** + * The introduction of custom alert senders brought with it the denormalization of the AlertNotification schema. + * Instead of the AlertNotification entity storing the notification-related data itself (through referential integrity) + * it has been subsumed inside of configuration objects, which are then associated back to the entity. + * + * Each custom alert sender has full control over the structure within that configuration object. This task represents + * the work necessary to translate the first-class notification data (previously stored in the rhq_alert_notification + * table itself) into appropriate configuration objects to be used by the custom senders that will be shipped with the + * product by default. + * + * In particular, this task handles the upgrade tasks for alert notifications setup against the following types of data: + * + * <ul> + * <li>RHQ Subjects</li> + * <li>RHQ Roles</li> + * <li>Direct Email Addresses</li> + * <li>SNMP Trap Receivers</li> + * <li>Resource Operations</li> + * </ul> + * + * @author Joseph Marques + */ +public class CustomAlertSenderUpgradeTask implements DatabaseUpgradeTask { + + private DatabaseType databaseType; + private Connection connection; + + private final long NOW = System.currentTimeMillis(); + + @Override + public void execute(DatabaseType databaseType, Connection connection) throws SQLException { + this.databaseType = databaseType; + this.connection = connection; + + upgradeSubjectNotifications(); + upgradeRoleNotifications(); + upgradeEmailNotifications(); + upgradeSNMPNotifications(); + upgradeOperationNotifications(); + } + + private void upgradeSubjectNotifications() throws SQLException { + String dataMapSQL = "" // + + " SELECT notif.alert_definition_id, notif.subject_id "// + + " FROM rhq_alert_notification notif "// + + " WHERE notif.notification_type = 'SUBJECT' "// + + "ORDER BY notif.alert_definition_id"; + List<Object[]> data = databaseType.executeSelectSql(connection, dataMapSQL); + + String propertyName = "subjectId"; + String senderName = "System Users"; + String name = "User Notifications"; + + persist(data, propertyName, senderName, name); + } + + private void upgradeRoleNotifications() throws SQLException { + String dataMapSQL = "" // + + " SELECT notif.alert_definition_id, notif.role_id "// + + " FROM rhq_alert_notification notif "// + + " WHERE notif.notification_type = 'ROLE' "// + + "ORDER BY notif.alert_definition_id"; + + List<Object[]> data = databaseType.executeSelectSql(connection, dataMapSQL); + + String propertyName = "roleId"; + String senderName = "System Roles"; + String name = "Role Notifications"; + + persist(data, propertyName, senderName, name); + } + + private void upgradeEmailNotifications() throws SQLException { + String dataMapSQL = "" // + + " SELECT notif.alert_definition_id, notif.email_address "// + + " FROM rhq_alert_notification notif "// + + " WHERE notif.notification_type = 'EMAIL' "// + + "ORDER BY notif.alert_definition_id"; + + List<Object[]> data = databaseType.executeSelectSql(connection, dataMapSQL); + + String propertyName = "emailAddress"; + String senderName = "Direct Emails"; + String name = "Email Notifications"; + + persist(data, propertyName, senderName, name); + } + + private void upgradeSNMPNotifications() throws SQLException { + String dataMapSQL = "" // + + " SELECT notif.alert_definition_id, notif.snmp_host, notif.snmp_port, notif.snmp_oid "// + + " FROM rhq_alert_notification notif "// + + " WHERE notif.notification_type = 'SNMP' "// + + "ORDER BY notif.alert_definition_id"; + + List<Object[]> data = databaseType.executeSelectSql(connection, dataMapSQL); + + for (Object[] next : data) { + int alertDefinitionId = ((Number) next[0]).intValue(); + String host = (String) next[1]; + String port = ((Number) next[2]).toString(); + String oid = (String) next[3]; + + // buffer will be 0 the very first time, since definitionId is initially -1 + int configId = persistConfiguration("host", host, "port", port, "oid", oid); + persistNotification(alertDefinitionId, configId, "SNMP Traps", "SNMP Notifications"); + } + } + + private void upgradeOperationNotifications() throws SQLException { + String dataMapSQL = "" // + + " SELECT def.id, def.operation_def_id" // + + " FROM rhq_alert_definition def"; + + List<Object[]> data = databaseType.executeSelectSql(connection, dataMapSQL); + + for (Object[] next : data) { + int alertDefinitionId = ((Number) next[0]).intValue(); + String operationDefinitionId = ((Number) next[1]).toString(); + + // buffer will be 0 the very first time, since definitionId is initially -1 + int configId = persistConfiguration("operation-definition-id", operationDefinitionId, "selection-mode", + "SELF"); + persistNotification(alertDefinitionId, configId, "Resource Operations", "Operational "); + } + } + + private void persist(List<Object[]> data, String propertyName, String sender, String name) throws SQLException { + int definitionId = -1; + StringBuilder buffer = new StringBuilder(); + for (Object[] next : data) { + int nextDefinitionId = ((Number) next[0]).intValue(); + String nextData = String.valueOf(next[1]); + if (nextDefinitionId != definitionId) { + definitionId = nextDefinitionId; + if (buffer.length() != 0) { + // buffer will be 0 the very first time, since definitionId is initially -1 + int configId = persistConfiguration(propertyName, buffer.toString()); + persistNotification(definitionId, configId, sender, name); + } + buffer = new StringBuilder(); // reset for the next definitionId + } else { + if (buffer.length() != 0) { + // elements are already in the list + buffer.append(','); + } + buffer.append(nextData); + } + } + } + + private int persistConfiguration(String... propertyNameValues) throws SQLException { + int configId = databaseType.getNextSequenceValue(connection, "rhq_config", "id"); + String insertConfigSQL = getInsertConfigSQL(configId); + databaseType.executeSql(connection, insertConfigSQL); + + for (int i = 0; i < propertyNameValues.length; i += 2) { + String propertyName = propertyNameValues[i]; + String propertyValue = propertyNameValues[i + 1]; + + int propertyId = databaseType.getNextSequenceValue(connection, "rhq_config_property", "id"); + String insertPropertySQL = getInsertPropertySQL(propertyId, configId, propertyName, propertyValue); + databaseType.executeSql(connection, insertPropertySQL); + } + + return configId; + } + + private void persistNotification(int definitionId, int configId, String sender, String name) throws SQLException { + int notificationId = databaseType.getNextSequenceValue(connection, "rhq_alert_notification", "id"); + String insertNotificationSQL = getInsertNotificationSQL(notificationId, definitionId, configId, sender, name); + + databaseType.executeSql(connection, insertNotificationSQL); + } + + private String getInsertConfigSQL(int id) { + return "INSERT INTO rhq_config ( id, ctime, mtime )" // + + " VALUES ( " + id + ", " + NOW + ", " + NOW + " ) "; + } + + private String getInsertPropertySQL(int id, int configId, String name, String value) { + return "INSERT INTO rhq_config_property ( id, configuration_id, name, string_value, dtype )" // + + " VALUES ( " + id + ", " + configId + ", '" + name + "', '" + value + "', 'property' ) "; + } + + private String getInsertNotificationSQL(int id, int definitionId, int configId, String sender, String name) { + return "INSERT INTO rhq_alert_notification ( id, alert_definition_id, sender_config_id, sender_name, display_name )" // + + " VALUES ( " + id + ", " + definitionId + ", " + configId + ", '" + sender + "', '" + name + "' ) "; + } + +} diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DatabaseUpgradeTask.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DatabaseUpgradeTask.java index fd438c0..4811b7d 100644 --- a/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DatabaseUpgradeTask.java +++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DatabaseUpgradeTask.java @@ -30,5 +30,5 @@ import org.rhq.core.db.ant.dbupgrade.SST_JavaTask; * @author Joseph Marques */ public interface DatabaseUpgradeTask { - public void execute(Connection connection, DatabaseType type) throws SQLException; + public void execute(DatabaseType type, Connection connection) throws SQLException; } diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml index 3098d97..9617057 100644 --- a/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml +++ b/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml @@ -79,7 +79,7 @@ <!-- required, but 0 effectively means null --> <column name="WILL_RECOVER" required="true" default="false" type="BOOLEAN"/> <column name="ACK_TIME" required="false" type="LONG"/> - <column name="ACK_BY_ID" required="false" type="INTEGER" references="RHQ_SUBJECT(ID)"/> + <column name="ACK_SUBJECT" required="false" size="100" type="VARCHAR2"/> <index name="RHQ_ALERT_IDX_TIME" unique="false"> <field ref="CTIME"/> </index> @@ -127,21 +127,17 @@ <column name="MTIME" required="true" type="LONG"/> <column name="NAME" required="true" size="100" type="VARCHAR2"/> <column name="DESCRIPTION" required="false" size="250" type="VARCHAR2"/> - </table>
<table name="RHQ_ALERT_NOTIFICATION" tablespace="@@@LARGE_TABLESPACE_FOR_DATA@@@" storage-options="freelists 5" cache="true" logging="false"> <column name="ID" default="sequence-only" initial="10001" primarykey="true" required="true" type="INTEGER"/> - <column name="NOTIFICATION_TYPE" required="true" size="20" type="VARCHAR2"/> <column name="ALERT_DEFINITION_ID" required="false" type="INTEGER" references="RHQ_ALERT_DEFINITION(ID)"/> - <column name="NOTIF_TEMPLATE_ID" required="false" type="INTEGER" references="RHQ_ALERT_NOTIF_TEMPL(ID)"/> - <column name="ALERT_CONFIG_ID" required="false" type="INTEGER" references="RHQ_CONFIG(ID)"/> - <column name="ALERT_SENDER_NAME" required="false" size="100" type="VARCHAR2" /> <!-- TODO make required = true --> - <column name="NAME" type="VARCHAR2" size="100" /> + <column name="TEMPLATE_ID" required="false" type="INTEGER" references="RHQ_ALERT_NOTIF_TEMPL(ID)"/> + <column name="SENDER_CONFIG_ID" required="false" type="INTEGER" references="RHQ_CONFIG(ID)"/> + <column name="SENDER_NAME" required="true" size="100" type="VARCHAR2" /> + <column name="DISPLAY_NAME" type="VARCHAR2" size="100" /> </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 bf9b21f..047be90 100644 --- a/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml +++ b/modules/core/dbutils/src/main/scripts/dbupgrade/db-upgrade.xml @@ -2059,28 +2059,27 @@ <schemaSpec version="2.70"> <schema-addColumn table="RHQ_ALERT" column="ACK_TIME" columnType="LONG" /> <!-- TODO: this needs to change to ack_subject_name --> - <schema-addColumn table="RHQ_ALERT" column="ACK_BY_ID" columnType="INTEGER" /> - - <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="ALERT_SENDER_NAME" columnType="VARCHAR2" precision="100"/> - <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="ALERT_CONFIG_ID" columnType="INTEGER" /> + <schema-addColumn table="RHQ_ALERT" column="ACK_SUBJECT" precision="100" columnType="VARCHAR2" /> + <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="DISPLAY_NAME" precision="100" columnType="VARCHAR2" /> + <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="SENDER_NAME" precision="100" columnType="VARCHAR2" /> + <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="SENDER_CONFIG_ID" columnType="INTEGER" /> <schema-directSQL> <statement> ALTER TABLE RHQ_ALERT_NOTIFICATION - ADD CONSTRAINT RHQ_AN_ALERT_CONFIG_ID_FK - FOREIGN KEY (ALERT_CONFIG_ID) + ADD CONSTRAINT RHQ_ALERT_NOTIFICATION_SENDER_CONFIG_ID_FK + FOREIGN KEY (SENDER_CONFIG_ID) REFERENCES RHQ_CONFIG (ID) </statement> </schema-directSQL> </schemaSpec> - <schemaSpec version="2.70.1"> <schema-createSequence name="RHQ_ALERT_NOTIF_TEMPL_ID_SEQ" initial="10001" /> <schema-directSQL> - <statement> + <statement desc="Creating table RHQ_ALERT_NOTIF_TEMPL"> CREATE TABLE RHQ_ALERT_NOTIF_TEMPL ( ID INTEGER PRIMARY KEY ) </statement> </schema-directSQL> - <schema-alterColumn table="RHQ_ALERT_NOTIF_TEMPL" column="ID" nullable="false" /> + <schema-alterColumn table="RHQ_ALERT_NOTIF_TEMPL" column="ID" nullable="false" /> <schema-addColumn table="RHQ_ALERT_NOTIF_TEMPL" column="CTIME" columnType="LONG" /> <schema-alterColumn table="RHQ_ALERT_NOTIF_TEMPL" column="CTIME" nullable="false" /> <schema-addColumn table="RHQ_ALERT_NOTIF_TEMPL" column="MTIME" columnType="LONG" /> @@ -2089,6 +2088,61 @@ <schema-alterColumn table="RHQ_ALERT_NOTIF_TEMPL" column="NAME" nullable="false" /> <schema-addColumn table="RHQ_ALERT_NOTIF_TEMPL" column="DESCRIPTION" precision="250" columnType="VARCHAR2" /> </schemaSpec> + <schemaSpec version="2.70.2"> + <!-- add structures for alert notification templates --> + <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="NOTIF_TEMPLATE_ID" columnType="INTEGER" /> + <schema-directSQL> + <statement> + ALTER TABLE RHQ_ALERT_NOTIFICATION + ADD CONSTRAINT RHQ_ALERT_NOTIFICATION_TEMPLATE_ID_FK + FOREIGN KEY (TEMPLATE_ID) + REFERENCES RHQ_ALERT_NOTIF_TEMPL (ID) + </statement> + </schema-directSQL> + </schemaSpec> + <schemaSpec version="2.70.3"> + <!-- turn first-class notification data into configuration objects for custom alert senders --> + <schema-alterColumn table="RHQ_ALERT_NOTIFICATION" column="NOTIFICATION_TYPE" nullable="TRUE" /> + <schema-javaTask className="CustomAlertSenderUpgradeTask" /> + <schema-directSQL> + <statement desc="Removing obsolete alert notifications"> + DELETE FROM RHQ_ALERT_NOTIFICATION WHERE NOTIFICATION_TYPE IS NOT NULL + </statement> + </schema-directSQL> + <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="NOTIFICATION_TYPE" /> + </schemaSpec> + <schemaSpec version="2.70.4"> + <!-- remove first-class alert notification structures from definition side of the model--> + <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="snmp_host" /> + <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="snmp_port" /> + <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="snmp_oid" /> + <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="email_address" /> + <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="role_id" /> + <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="subject_id" /> + <schema-deleteColumn table="RHQ_ALERT_DEFINITION" column="operation_def_id" /> + </schemaSpec> + <schemaSpec version="2.70.5"> + <schema-deleteColumn table="RHQ_ALERT_NOTIF_LOG" column="roles" /> + <schema-deleteColumn table="RHQ_ALERT_NOTIF_LOG" column="subjects" /> + <schema-deleteColumn table="RHQ_ALERT_NOTIF_LOG" column="emails" /> + </schemaSpec> + <schemaSpec version="2.70.6"> + <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="SENDER" columnType="VARCHAR2" precision="200" /> + <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="RESULT_STATE" columnType="VARCHAR2" precision="20" /> + <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="MESSAGE" columnType="VARCHAR2" precision="255" /> + <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="ALL_EMAILS" columnType="VARCHAR2" precision="4000" /> + <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="EMAILS_FAILED" columnType="VARCHAR2" precision="4000" /> + </schemaSpec> + <schemaSpec version="2.70.7"> + <schema-directSQL> + <statement> + DROP INDEX RHQ_ALERT_IDX_ALERT + </statement> + <statement> + CREATE INDEX RHQ_ALERT_IDX_ALERT ON RHQ_ALERT_NOTIF_LOG (alert_id) + </statement> + </schema-directSQL> + </schemaSpec>
<!-- RHQ Advisory Representation --> <schemaSpec version="2.71"> @@ -2296,47 +2350,6 @@ <schema-addColumn table="RHQ_CONFIG_PROP_DEF" column="DYNAMIC_KEY" columnType="VARCHAR2" precision="128" /> </schemaSpec>
- <schemaSpec version="2.77"> - <schema-addColumn table="RHQ_ALERT_NOTIFICATION" column="NOTIF_TEMPLATE_ID" columnType="INTEGER" /> - <schema-directSQL> - <statement> - ALTER TABLE RHQ_ALERT_NOTIFICATION - ADD CONSTRAINT RHQ_CPD_NOTIF_TEMPLATE_ID_FK - FOREIGN KEY (NOTIF_TEMPLATE_ID) - REFERENCES RHQ_ALERT_NOTIF_TEMPL(ID) - </statement> - </schema-directSQL> - </schemaSpec> - <schemaSpec version="2.77.1"> - <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="snmp_host" /> - <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="snmp_port" /> - <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="snmp_oid" /> - <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="email_address" /> - <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="role_id" /> - <schema-deleteColumn table="RHQ_ALERT_NOTIFICATION" column="subject_id" /> - </schemaSpec> - <schemaSpec version="2.77.2"> - <schema-deleteColumn table="RHQ_ALERT_NOTIF_LOG" column="roles" /> - <schema-deleteColumn table="RHQ_ALERT_NOTIF_LOG" column="subjects" /> - <schema-deleteColumn table="RHQ_ALERT_NOTIF_LOG" column="emails" /> - - <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="SENDER" columnType="VARCHAR2" precision="200" /> - <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="RESULT_STATE" columnType="VARCHAR2" precision="20" /> - <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="MESSAGE" columnType="VARCHAR2" precision="255" /> - <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="ALL_EMAILS" columnType="VARCHAR2" precision="4000" /> - <schema-addColumn table="RHQ_ALERT_NOTIF_LOG" column="EMAILS_FAILED" columnType="VARCHAR2" precision="4000" /> - </schemaSpec> - <schemaSpec version="2.77.3"> - <schema-directSQL> - <statement> - DROP INDEX RHQ_ALERT_IDX_ALERT - </statement> - <statement> - CREATE INDEX RHQ_ALERT_IDX_ALERT ON RHQ_ALERT_NOTIF_LOG (alert_id) - </statement> - </schema-directSQL> - </schemaSpec> - <schemaSpec version="2.78"> <!-- RHQ_BUNDLE_TYPE --> <schema-createSequence name="RHQ_BUNDLE_TYPE_ID_SEQ" initial="10001" /> @@ -2734,7 +2747,7 @@ </statement> </schema-directSQL> </schemaSpec> - + </dbupgrade> </target> </project> diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/Alert.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/Alert.java index 904acce..b676c05 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/Alert.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/Alert.java @@ -45,7 +45,6 @@ import javax.persistence.SequenceGenerator; import javax.persistence.Table;
import org.rhq.core.domain.alert.notification.AlertNotificationLog; -import org.rhq.core.domain.auth.Subject;
/** * @author Joseph Marques @@ -113,10 +112,10 @@ import org.rhq.core.domain.auth.Subject; + " WHERE condition.measurementDefinition.id = :measurementDefinitionId " // + " AND definition.resource.id = ( :resourceId ) " // + " AND ( a.ctime BETWEEN :startDate AND :endDate )"), - @NamedQuery(name = Alert.QUERY_GET_ALERT_COUNT_FOR_SCHEDULES, query = "SELECT sched.id, count(*) " + - " FROM Alert AS a JOIN a.alertDefinition aDef JOIN aDef.conditions condition " + - " JOIN aDef.resource res JOIN condition.measurementDefinition mDef JOIN mDef.schedules sched" + - " WHERE sched.definition = mDef.id AND sched.resource = res AND sched.id IN (:schedIds) " + @NamedQuery(name = Alert.QUERY_GET_ALERT_COUNT_FOR_SCHEDULES, query = "SELECT sched.id, count(*) " + + " FROM Alert AS a JOIN a.alertDefinition aDef JOIN aDef.conditions condition " + + " JOIN aDef.resource res JOIN condition.measurementDefinition mDef JOIN mDef.schedules sched" + + " WHERE sched.definition = mDef.id AND sched.resource = res AND sched.id IN (:schedIds) " + " AND (a.ctime BETWEEN :startDate AND :endDate)" + "GROUP BY sched.id"), @NamedQuery(name = Alert.QUERY_FIND_BY_RESOURCE_DATED, // query = "SELECT a " // @@ -258,12 +257,11 @@ public class Alert implements Serializable { @Column(name = "WILL_RECOVER", nullable = false) private boolean willRecover;
- @Column(name ="ACK_TIME") - private long ackTime = -1; + @Column(name = "ACK_TIME") + private long acknowledgeTime = -1;
- @JoinColumn(name = "ACK_BY_ID", referencedColumnName = "ID") - @ManyToOne - private Subject ackBy; + @Column(name = "ACK_SUBJECT") + private String acknowledgingSubject;
/** * Creates a new alert. (required by EJB3 spec, but not used) @@ -335,20 +333,20 @@ public class Alert implements Serializable { this.triggeredOperation = triggeredOperation; }
- public long getAckTime() { - return ackTime; + public long getAcknowledgeTime() { + return acknowledgeTime; }
- public void setAckTime(long ackTime) { - this.ackTime = ackTime; + public void setAcknowledgeTime(long acknowledgeTime) { + this.acknowledgeTime = acknowledgeTime; }
- public Subject getAckBy() { - return ackBy; + public String getAcknowledgingSubject() { + return acknowledgingSubject; }
- public void setAckBy(Subject ackBy) { - this.ackBy = ackBy; + public void setAcknowledgingSubject(String acknowledgingSubject) { + this.acknowledgingSubject = acknowledgingSubject; }
public boolean getWillRecover() { diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java index ef7b3e9..1f14aad 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotification.java @@ -26,15 +26,11 @@ import java.io.Serializable;
import javax.persistence.CascadeType; import javax.persistence.Column; -import javax.persistence.DiscriminatorColumn; -import javax.persistence.DiscriminatorType; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; -import javax.persistence.Inheritance; -import javax.persistence.InheritanceType; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; @@ -49,9 +45,7 @@ import org.jetbrains.annotations.NotNull; import org.rhq.core.domain.alert.AlertDefinition; import org.rhq.core.domain.configuration.Configuration;
-@DiscriminatorColumn(name = "NOTIFICATION_TYPE", discriminatorType = DiscriminatorType.STRING) @Entity -@Inheritance(strategy = InheritanceType.SINGLE_TABLE) @NamedQueries( { @NamedQuery(name = AlertNotification.DELETE_BY_ID, query = "DELETE FROM AlertNotification an WHERE an.id IN ( :ids )"), @NamedQuery(name = AlertNotification.QUERY_DELETE_BY_RESOURCES, query = "DELETE FROM AlertNotification an WHERE an.alertDefinition IN ( SELECT ad FROM AlertDefinition ad WHERE ad.resource.id IN ( :resourceIds ) )"), @@ -80,22 +74,19 @@ public class AlertNotification implements Serializable { @ManyToOne private AlertDefinition alertDefinition;
- @JoinColumn(name = "NOTIF_TEMPLATE_ID") + @JoinColumn(name = "TEMPLATE_ID") @ManyToOne private AlertNotificationTemplate alertNotificationTemplate;
- @JoinColumn(name = "ALERT_CONFIG_ID", referencedColumnName = "ID") + @JoinColumn(name = "SENDER_CONFIG_ID", referencedColumnName = "ID") @OneToOne(cascade = { CascadeType.ALL }, fetch = FetchType.LAZY) private Configuration configuration;
- @Column(name = "ALERT_SENDER_NAME") + @Column(name = "SENDER_NAME") private String senderName;
- @Column(name = "ALERT_ORDER") - private int order; - - @Column(name = "NAME") - private String name; + @Column(name = "DISPLAY_NAME") + private String displayName;
protected AlertNotification() { } // JPA spec @@ -127,8 +118,8 @@ public class AlertNotification implements Serializable { this.alertNotificationId = alertNotificationId; }
- public AlertNotification(String name, String sender) { - this.name = name; + public AlertNotification(String displayName, String sender) { + this.displayName = displayName; this.senderName = sender; }
@@ -155,14 +146,14 @@ public class AlertNotification implements Serializable {
public AlertNotification copyWithAlertDefintion(AlertDefinition alertDefinition, boolean cloneConfiguration) { Configuration config; - if (cloneConfiguration) + if (cloneConfiguration) { config = this.configuration.deepCopy(false); - else + } else { config = this.configuration; + } AlertNotification notification = new AlertNotification(alertDefinition, config); - notification.setName(this.name); + notification.setDisplayName(this.displayName); notification.setSenderName(this.senderName); - notification.setOrder(this.order); return notification; }
@@ -190,20 +181,12 @@ public class AlertNotification implements Serializable { this.configuration = configuration; }
- public int getOrder() { - return order; - } - - public void setOrder(int order) { - this.order = order; - } - - public String getName() { - return name; + public String getDisplayName() { + return displayName; }
- public void setName(String name) { - this.name = name; + public void setDisplayName(String displayName) { + this.displayName = displayName; }
public AlertNotificationTemplate getAlertNotificationTemplate() { @@ -231,8 +214,7 @@ public class AlertNotification implements Serializable { sb.append(", id=").append(id); sb.append(", notificationTemplate=").append(alertNotificationTemplate); sb.append(", senderName='").append(senderName).append('''); - sb.append(", order=").append(order); - sb.append(", name='").append(name).append('''); + sb.append(", displayName='").append(displayName).append('''); sb.append('}'); return sb.toString(); } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java index a97374f..c02de80 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/alert/AlertDataSource.java @@ -18,6 +18,13 @@ */ package org.rhq.enterprise.gui.coregui.client.alert;
+import java.util.ArrayList; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Set; + import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.user.client.Window; @@ -33,6 +40,7 @@ import com.smartgwt.client.data.fields.DataSourceTextField; import com.smartgwt.client.rpc.RPCResponse; import com.smartgwt.client.widgets.grid.ListGrid; import com.smartgwt.client.widgets.grid.ListGridRecord; + import org.rhq.core.domain.alert.Alert; import org.rhq.core.domain.alert.AlertCondition; import org.rhq.core.domain.alert.AlertConditionLog; @@ -46,13 +54,6 @@ import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; import org.rhq.enterprise.gui.coregui.client.util.RPCDataSource; import org.rhq.enterprise.gui.coregui.client.util.message.Message;
-import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.Set; - /** * A server-side SmartGWT DataSource for CRUD of {@link Alert}s. * @@ -107,7 +108,7 @@ public class AlertDataSource extends RPCDataSource<Alert> { DataSourceTextField ctimeField = new DataSourceTextField(AlertCriteria.SORT_FIELD_CTIME, "Creation Time"); fields.add(ctimeField);
- DataSourceBooleanField boolField = new DataSourceBooleanField("ack","Ack'd"); + DataSourceBooleanField boolField = new DataSourceBooleanField("ack", "Ack'd"); boolField.setCanSortClientOnly(true); fields.add(boolField);
@@ -127,14 +128,17 @@ public class AlertDataSource extends RPCDataSource<Alert> {
this.alertService.deleteResourceAlerts(alertIds, new AsyncCallback<Void>() { public void onSuccess(Void blah) { - CoreGUI.getMessageCenter().notify(new Message("Deleted ["+ alertIds.length + "] alerts", Message.Severity.Info)); + CoreGUI.getMessageCenter().notify( + new Message("Deleted [" + alertIds.length + "] alerts", Message.Severity.Info)); System.out.println("Deleted Alerts with id's: " + Arrays.toString(alertIds) + "."); alertsView.refresh(); }
public void onFailure(Throwable caught) { - CoreGUI.getErrorHandler().handleError("Failed to delete Alerts with id's: " + Arrays.toString(alertIds), caught); - System.err.println("Failed to delete Alerts with id's " + Arrays.toString(alertIds) + " - cause: " + caught); + CoreGUI.getErrorHandler().handleError( + "Failed to delete Alerts with id's: " + Arrays.toString(alertIds), caught); + System.err.println("Failed to delete Alerts with id's " + Arrays.toString(alertIds) + " - cause: " + + caught); } }); } @@ -189,7 +193,7 @@ public class AlertDataSource extends RPCDataSource<Alert> {
@Override public Alert copyValues(ListGridRecord from) { - return null; // TODO: Implement this method. + return null; // TODO: Implement this method. }
@Override @@ -200,8 +204,9 @@ public class AlertDataSource extends RPCDataSource<Alert> { record.setAttribute("name", from.getAlertDefinition().getName()); record.setAttribute("priority", from.getAlertDefinition().getPriority().name()); record.setAttribute("ctime", DATE_TIME_FORMAT.format(new Date(from.getCtime()))); - if (from.getAckTime() >0) - record.setAttribute("ack","true"); + if (from.getAcknowledgeTime() > 0) { + record.setAttribute("ack", "true"); + }
Set<AlertConditionLog> conditionLogs = from.getConditionLogs(); String conditionText; @@ -231,17 +236,17 @@ public class AlertDataSource extends RPCDataSource<Alert> { for (AlertConditionLog log : from.getConditionLogs()) { AlertCondition condition = log.getCondition(); DataClass dc = new DataClass(); - dc.setAttribute("text",AlertFormatUtility.formatAlertConditionForDisplay(condition)); + dc.setAttribute("text", AlertFormatUtility.formatAlertConditionForDisplay(condition)); String value = log.getValue(); if (condition.getMeasurementDefinition() != null) { value = MeasurementConverterClient.format(Double.valueOf(log.getValue()), condition .getMeasurementDefinition().getUnits(), true); } - dc.setAttribute("value",value); + dc.setAttribute("value", value); conditions[i++] = dc; } - record.setAttribute("conditionLogs",conditions); - record.setAttribute("conditionExpression",from.getAlertDefinition().getConditionExpression()); + record.setAttribute("conditionLogs", conditions); + record.setAttribute("conditionExpression", from.getAlertDefinition().getConditionExpression());
String recoveryInfo = AlertFormatUtility.getAlertRecoveryInfo(from); record.setAttribute("recoveryInfo", recoveryInfo); @@ -249,23 +254,23 @@ public class AlertDataSource extends RPCDataSource<Alert> { // Alert notification logs DataClass[] notifications = new DataClass[from.getAlertNotificationLogs().size()]; i = 0; - for(AlertNotificationLog log : from.getAlertNotificationLogs()) { + for (AlertNotificationLog log : from.getAlertNotificationLogs()) { DataClass dc = new DataClass(); - dc.setAttribute("sender",log.getSender()); - dc.setAttribute("status",log.getResultState()); - dc.setAttribute("message",log.getMessage()); - dc.setAttribute("allEmails",log.getAllEmails()); - dc.setAttribute("badEmails",log.getBadEmails()); + dc.setAttribute("sender", log.getSender()); + dc.setAttribute("status", log.getResultState()); + dc.setAttribute("message", log.getMessage()); + dc.setAttribute("allEmails", log.getAllEmails()); + dc.setAttribute("badEmails", log.getBadEmails());
notifications[i++] = dc;
} - record.setAttribute("notificationLogs",notifications); + record.setAttribute("notificationLogs", notifications); return record; }
protected void executeRemove(final DSRequest request, final DSResponse response) { - JavaScriptObject data = request.getData (); + JavaScriptObject data = request.getData(); ListGridRecord record = new ListGridRecord(data); Window.alert(String.valueOf(record.getAttributeAsInt("id"))); } @@ -283,15 +288,18 @@ public class AlertDataSource extends RPCDataSource<Alert> {
this.alertService.acknowledgeResourceAlerts(alertIds, new AsyncCallback<Void>() { public void onSuccess(Void blah) { - CoreGUI.getMessageCenter().notify(new Message("Acknowledged ["+ alertIds.length + "] alerts", Message.Severity.Info)); + CoreGUI.getMessageCenter().notify( + new Message("Acknowledged [" + alertIds.length + "] alerts", Message.Severity.Info));
System.out.println("Acknowledged Alerts with id's: " + Arrays.toString(alertIds) + "."); alertsView.refresh(); }
public void onFailure(Throwable caught) { - CoreGUI.getErrorHandler().handleError("Failed to acknowledge Alerts with id's: " + Arrays.toString(alertIds), caught); - System.err.println("Failed to acknowledge Alerts with id's " + Arrays.toString(alertIds) + " - cause: " + caught); + CoreGUI.getErrorHandler().handleError( + "Failed to acknowledge Alerts with id's: " + Arrays.toString(alertIds), caught); + System.err.println("Failed to acknowledge Alerts with id's " + Arrays.toString(alertIds) + " - cause: " + + caught); } }); } diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/AckAlertAction.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/AckAlertAction.java index 6043d19..a202c5b 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/AckAlertAction.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/AckAlertAction.java @@ -29,10 +29,7 @@ import org.apache.commons.logging.LogFactory; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; -import org.apache.struts.tiles.ComponentContext; -import org.apache.struts.tiles.actions.TilesAction;
-import org.rhq.core.domain.alert.Alert; import org.rhq.core.domain.auth.Subject; import org.rhq.enterprise.gui.legacy.action.BaseAction; import org.rhq.enterprise.gui.legacy.util.RequestUtils; @@ -49,7 +46,7 @@ public class AckAlertAction extends BaseAction { Log log = LogFactory.getLog(AckAlertAction.class);
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, - HttpServletResponse response) throws Exception { + HttpServletResponse response) throws Exception {
Subject subject = RequestUtils.getSubject(request); AlertManagerLocal alertManager = LookupUtil.getAlertManager(); @@ -58,21 +55,21 @@ public class AckAlertAction extends BaseAction { // pass-through the alertId and resource id Integer alertId = new Integer(request.getParameter("a")); request.setAttribute("a", alertId); - params.put("a",alertId); + params.put("a", alertId);
Integer resourceId = new Integer(request.getParameter("id")); - request.setAttribute("id",resourceId); - params.put("id",resourceId); + request.setAttribute("id", resourceId); + params.put("id", resourceId);
String mode = request.getParameter("mode"); - request.setAttribute("mode",mode); - params.put("mode",mode); + request.setAttribute("mode", mode); + params.put("mode", mode);
- alertManager.acknowledgeAlert(alertId,subject); + alertManager.acknowledgeAlerts(subject, new Integer[] { alertId });
log.debug("Acknowledged Alert with id " + alertId + " and user " + subject.getName());
- return returnSuccess(request,mapping,params); + return returnSuccess(request, mapping, params); }
} diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java index db62a94..2a9f4b3 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java @@ -57,6 +57,7 @@ import org.rhq.core.domain.alert.AlertDefinition; import org.rhq.core.domain.alert.AlertPriority; import org.rhq.core.domain.alert.notification.AlertNotification; import org.rhq.core.domain.alert.notification.AlertNotificationLog; +import org.rhq.core.domain.alert.notification.ResultState; import org.rhq.core.domain.alert.notification.SenderResult; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.authz.Permission; @@ -68,9 +69,9 @@ import org.rhq.core.domain.resource.Resource; import org.rhq.core.domain.util.PageControl; import org.rhq.core.domain.util.PageList; import org.rhq.core.domain.util.PageOrdering; +import org.rhq.core.domain.util.StringUtils; import org.rhq.core.server.MeasurementConverter; import org.rhq.core.server.PersistenceUtility; -import org.rhq.core.domain.util.StringUtils; import org.rhq.core.util.collection.ArrayUtils; import org.rhq.core.util.jdbc.JDBCUtil; import org.rhq.enterprise.server.RHQConstants; @@ -87,14 +88,12 @@ import org.rhq.enterprise.server.plugin.pc.MasterServerPluginContainer; import org.rhq.enterprise.server.plugin.pc.alert.AlertSender; import org.rhq.enterprise.server.plugin.pc.alert.AlertSenderPluginManager; import org.rhq.enterprise.server.plugin.pc.alert.AlertServerPluginContainer; -import org.rhq.core.domain.alert.notification.ResultState; import org.rhq.enterprise.server.resource.ResourceManagerLocal; import org.rhq.enterprise.server.system.SystemManagerLocal; import org.rhq.enterprise.server.util.CriteriaQueryGenerator; import org.rhq.enterprise.server.util.CriteriaQueryRunner; import org.rhq.enterprise.server.util.LookupUtil;
- /** * @author Joseph Marques * @author Ian Springer @@ -130,7 +129,6 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { @javax.annotation.Resource(name = "RHQ_DS") private DataSource rhqDs;
- /** * Persist a detached alert. * @@ -148,27 +146,31 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { /** * Remove the alerts with the specified id's. * @param user caller - * @param ids primary keys of the alerts to delete + * @param alertIds primary keys of the alerts to delete * @return number of alerts deleted */ - public int deleteAlerts(Subject user, Integer[] ids) { - if (!authorizationManager.hasGlobalPermission(user,Permission.MANAGE_ALERTS)) - throw new PermissionException("User [" + user.getName() + "] does not have permissions to delete alerts "); - - int i = 0; - for (Integer id : ids) { - Alert alert = entityManager.find(Alert.class, id); + public int deleteAlerts(Subject user, Integer[] alertIds) { + int count = 0; + for (Integer nextAlertId : alertIds) { + Alert alert = entityManager.find(Alert.class, nextAlertId); if (alert != null) { -// AlertNotificationLog anl = alert.getAlertNotificationLog(); TODO is that all? -// entityManager.remove(anl); + // AlertNotificationLog anl = alert.getAlertNotificationLog(); TODO is that all? + // entityManager.remove(anl); + Resource resource = alert.getAlertDefinition().getResource(); + if (!authorizationManager.hasResourcePermission(user, Permission.MANAGE_ALERTS, resource.getId())) { + throw new PermissionException("User [" + user.getName() + + "] does not have permissions to delete alerts: " + Arrays.asList(alertIds)); + } + entityManager.remove(alert); // condition logs will be removed with entity cascading } - i++; + count++; } - return i; + return count; }
- public void deleteResourceAlerts(Subject user, Integer[] alertIds) { + @SuppressWarnings("unchecked") + private void checkAlertsPermission(Subject user, Integer[] alertIds) { Query q = entityManager.createNamedQuery(Alert.QUERY_FIND_RESOURCES); q.setParameter("alertIds", Arrays.asList(alertIds)); List<Resource> resources = q.getResultList(); @@ -180,9 +182,13 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { } } if (!forbiddenResources.isEmpty()) { - throw new PermissionException("User [" + user.getName() + "] does not have permissions to delete alerts " - + "for the following Resource(s): " + forbiddenResources); + throw new PermissionException("User [" + user.getName() + "] does not have permissions to manage alerts " + + "for the following Resource(s): " + forbiddenResources); } + } + + public void deleteResourceAlerts(Subject user, Integer[] alertIds) { + checkAlertsPermission(user, alertIds);
deleteAlerts(user, alertIds); } @@ -568,48 +574,33 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { }
/** - * Mark the matching alert as acknowledged by the user - * @param alertId Id of the alert to acknowledge - * @param user user who acknowledged the alert - */ - public void acknowledgeAlert(int alertId, Subject user) { - Alert alert = entityManager.find(Alert.class,alertId); - if (alert==null) { - log.warn("Alert [ " + alertId + " ] to acknowledge was not found "); - return; - } - alert.setAckBy(user); - alert.setAckTime(System.currentTimeMillis()); - } - - /** - * Acknowledge the alerts (that got fired) so that admins know who is working - * on fixing the situation. + * Acknowledge the alerts (that got fired) so that admins know who is working on fixing the situation. + * * @param user calling user - * @param alertIds PKs of the alerts to ack + * @param alertIds PKs of the alerts to acknowledge * @return number of alerts acknowledged */ public int acknowledgeAlerts(Subject user, Integer[] alertIds) { - if (!authorizationManager.hasGlobalPermission(user, Permission.MANAGE_ALERTS)) { - throw new PermissionException("User [" + user.getName() + "] does not have permissions to acknowledge alerts "); - } - - int i=0; - if (alertIds==null || alertIds.length==0) { + if (alertIds == null || alertIds.length == 0) { log.debug("acknowledgeAlerts: no alertIds passed"); - return -1; + return 0; }
- for (int id : alertIds) { - acknowledgeAlert(id,user); - i++; - if (i % 50 == 0) { - entityManager.flush(); - entityManager.clear(); - } + checkAlertsPermission(user, alertIds);
+ int count = 0; + final long NOW = System.currentTimeMillis(); + for (int nextAlertId : alertIds) { + Alert alert = entityManager.find(Alert.class, nextAlertId); + if (alert == null) { + continue; + } else { + count++; + } + alert.setAcknowledgingSubject(user.getName()); + alert.setAcknowledgeTime(NOW); } - return i; + return count; }
public void fireAlert(int alertDefinitionId) { @@ -634,8 +625,8 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { this.createAlert(newAlert); log.debug("New alert identifier=" + newAlert.getId());
-// AlertNotificationLog alertNotifLog = new AlertNotificationLog(newAlert); TODO - is that all? -// entityManager.persist(alertNotifLog); + // AlertNotificationLog alertNotifLog = new AlertNotificationLog(newAlert); TODO - is that all? + // entityManager.persist(alertNotifLog);
List<AlertConditionLog> unmatchedConditionLogs = alertConditionLogManager .getUnmatchedLogsByAlertDefinitionId(alertDefinitionId); @@ -694,7 +685,7 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote {
// Send over the new AlertSender plugins String senderName = alertNotification.getSenderName(); - if (senderName ==null) { + if (senderName == null) { log.error("Alert notification " + alertNotification + " has no sender name defined"); continue; } @@ -707,9 +698,9 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { SenderResult result = sender.send(alert);
if (result == null) { - log.warn("- !! -- sender [" + senderName + - "] did not return a SenderResult. Please fix this -- !! - "); - alNoLo = new AlertNotificationLog(alert,senderName); + log.warn("- !! -- sender [" + senderName + + "] did not return a SenderResult. Please fix this -- !! - "); + alNoLo = new AlertNotificationLog(alert, senderName); alNoLo.setMessage("Sender did not return a SenderResult, assuming failure");
} else if (result.getState() == ResultState.DEFERRED_EMAIL) { @@ -722,20 +713,16 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { alNoLo = new AlertNotificationLog(alert, senderName, result); } log.info(result); - } - catch (Throwable t) { + } catch (Throwable t) { log.error("Sender failed: " + t.getMessage()); if (log.isDebugEnabled()) log.debug("Sender " + sender.toString() + "failed: \n", t); - alNoLo = new AlertNotificationLog(alert, senderName, - ResultState.FAILURE, - "Failed with exception: " + t.getMessage()); + alNoLo = new AlertNotificationLog(alert, senderName, ResultState.FAILURE, + "Failed with exception: " + t.getMessage()); } - } - else { - alNoLo = new AlertNotificationLog(alert, senderName, - ResultState.FAILURE, - "Failed to obtain a sender with given name"); + } else { + alNoLo = new AlertNotificationLog(alert, senderName, ResultState.FAILURE, + "Failed to obtain a sender with given name"); } entityManager.persist(alNoLo); alert.addAlertNotificatinLog(alNoLo); @@ -758,23 +745,20 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { badList.add(badOne); } } - if (anl.getResultState()==ResultState.FAILED_EMAIL) - anl.setBadEmails(StringUtils.getListAsString(badList,",")); - if (anl.getResultState()==ResultState.DEFERRED_EMAIL && badList.isEmpty()) + if (anl.getResultState() == ResultState.FAILED_EMAIL) + anl.setBadEmails(StringUtils.getListAsString(badList, ",")); + if (anl.getResultState() == ResultState.DEFERRED_EMAIL && badList.isEmpty()) anl.setResultState(ResultState.SUCCESS); } - } - else { // No bad addresses + } else { // No bad addresses // Only set the result state to success for email sending notifications // We must not set them if the notification failed. for (AlertNotificationLog anl : alert.getAlertNotificationLogs()) { - if (anl.getResultState()==ResultState.DEFERRED_EMAIL) + if (anl.getResultState() == ResultState.DEFERRED_EMAIL) anl.setResultState(ResultState.SUCCESS); } }
- - } catch (Exception e) { log.error("Failed to send all notifications for " + alert.toSimpleString(), e); } @@ -897,13 +881,11 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { format = AlertI18NResourceKeys.ALERT_EMAIL_CONDITION_LOG_FORMAT; SimpleDateFormat dateFormat; if (shortVersion) - dateFormat= new SimpleDateFormat( - "yy/MM/dd HH:mm:ss z"); + dateFormat = new SimpleDateFormat("yy/MM/dd HH:mm:ss z"); else - dateFormat= new SimpleDateFormat( - "yyyy/MM/dd HH:mm:ss z"); - builder.append(AlertI18NFactory.getMessage(format, - conditionCounter, prettyPrintAlertCondition(aLog.getCondition(), shortVersion), dateFormat.format(new Date(aLog.getCtime())), formattedValue)); + dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss z"); + builder.append(AlertI18NFactory.getMessage(format, conditionCounter, prettyPrintAlertCondition(aLog + .getCondition(), shortVersion), dateFormat.format(new Date(aLog.getCtime())), formattedValue)); conditionCounter++; }
@@ -928,7 +910,7 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { builder.append(condition.getName()).append(' '); } } else { - if (category.getName()!=null) // this is null for e.g. availability + if (category.getName() != null) // this is null for e.g. availability builder.append(condition.getName()).append(' '); }
@@ -961,7 +943,8 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { || (category == AlertConditionCategory.TRAIT)) {
if (shortVersion) - builder.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_CURRENT_LIST_VALUE_CHANGED_SHORT)); + builder.append(AlertI18NFactory + .getMessage(AlertI18NResourceKeys.ALERT_CURRENT_LIST_VALUE_CHANGED_SHORT)); else builder.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_CURRENT_LIST_VALUE_CHANGED));
@@ -973,21 +956,20 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { else propsCbEventSeverityRegexMatch = AlertI18NResourceKeys.ALERT_CONFIG_PROPS_CB_EVENT_SEVERITY_REGEX_MATCH;
- builder.append(AlertI18NFactory.getMessage( - propsCbEventSeverityRegexMatch, condition.getName(), + builder.append(AlertI18NFactory.getMessage(propsCbEventSeverityRegexMatch, condition.getName(), condition.getOption())); } else { if (shortVersion) - builder.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_CONFIG_PROPS_CB_EVENT_SEVERITY_SHORT, - condition.getName())); + builder.append(AlertI18NFactory.getMessage( + AlertI18NResourceKeys.ALERT_CONFIG_PROPS_CB_EVENT_SEVERITY_SHORT, condition.getName())); else - builder.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_CONFIG_PROPS_CB_EVENT_SEVERITY, - condition.getName())); + builder.append(AlertI18NFactory.getMessage( + AlertI18NResourceKeys.ALERT_CONFIG_PROPS_CB_EVENT_SEVERITY, condition.getName())); } } else if (category == AlertConditionCategory.AVAILABILITY) { if (shortVersion) - builder.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_CONFIG_PROPS_CB_AVAILABILITY_SHORT, - condition.getOption())); + builder.append(AlertI18NFactory.getMessage( + AlertI18NResourceKeys.ALERT_CONFIG_PROPS_CB_AVAILABILITY_SHORT, condition.getOption())); else builder.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_CONFIG_PROPS_CB_AVAILABILITY, condition.getOption())); @@ -1015,7 +997,6 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { return builder.toString(); }
- private void processRecovery(AlertDefinition firedDefinition) { Subject overlord = subjectManager.getOverlord(); Integer recoveryDefinitionId = firedDefinition.getRecoveryId(); @@ -1088,7 +1069,6 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { return false; // Default is not to disable the definition }
- @SuppressWarnings("unchecked") public PageList<Alert> findAlertsByCriteria(Subject subject, AlertCriteria criteria) { CriteriaQueryGenerator generator = new CriteriaQueryGenerator(criteria); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerLocal.java index 45deaf4..a55926a 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerLocal.java @@ -92,13 +92,6 @@ public interface AlertManagerLocal { Map<Integer, Integer> getAlertCountForSchedules(long begin, long end, List<Integer> scheduleIds);
/** - * Mark the matching alert as acknowledged by the user - * @param alertId Id of the alert to acknowledge - * @param user user who acknowledged the alert - */ - void acknowledgeAlert(int alertId, Subject user); - - /** * Return the plugin manager that is managing alert sender plugins * @return The alert sender plugin manager */ diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java index 224961f..8a4bb98 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java @@ -307,7 +307,7 @@ public class AlertNotificationManagerBean implements AlertNotificationManagerLoc entityManager.persist(configuration); AlertNotification notif = new AlertNotification(definition); notif.setSenderName(senderName); - notif.setName(alertName); + notif.setDisplayName(alertName); notif.setConfiguration(configuration); entityManager.persist(notif); definition.getAlertNotifications().add(notif); @@ -537,38 +537,4 @@ public class AlertNotificationManagerBean implements AlertNotificationManagerLoc return template; }
- /** - * Add the passed 'transient' notifications onto the alert definitions contained. The old - * notifications are removed. - * This method is mainly used when migrating alerts from an old format to the current. - * @param subject Subject of the caller - * @param notifications list of AlertNotifications that have the alert definition id encoded in a transient field - */ - public void mergeTransientAlertNotifications(Subject subject, List<AlertNotification> notifications) { - - // Clear out old notifications - for (AlertNotification n : notifications) { - AlertDefinition def = alertDefinitionManager.getAlertDefinitionById(subject, n.getAlertDefinitionId()); - if (def == null) { - LOG.error("Alert Definition with id " + n.getAlertDefinitionId() + "does not exist for notification " - + n); - continue; - } - def.getAlertNotifications().clear(); - } - - // add the new ones - for (AlertNotification n : notifications) { - AlertDefinition def = alertDefinitionManager.getAlertDefinitionById(subject, n.getAlertDefinitionId()); - if (def == null) - continue; - - AlertNotification alNo = new AlertNotification(def, n.getConfiguration()); - alNo.setSenderName(n.getSenderName()); - alNo.setName(n.getName()); - alNo.setOrder(n.getOrder()); - entityManager.persist(alNo); - def.addAlertNotification(alNo); - } - } } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerLocal.java index 80c77db..56f1c20 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerLocal.java @@ -113,15 +113,6 @@ public interface AlertNotificationManagerLocal { String getBackingBeanNameForSender(String shortName);
/** - * Add the passed 'transient' notifications onto the alert definitions contained. The old - * notifications are removed. - * This method is mainly used when migrating alerts from an old format to the current. - * @param subject Subject of the caller - * @param notifications list of AlertNotifications that have the alert definition id encoded in a transient field - */ - void mergeTransientAlertNotifications(Subject subject, List<AlertNotification> notifications); - - /** * Create a new NotificationTemplate from the passed parameters. The passed AlertNotification objects need to have the * name and sender and any configuration properties already set; alert definitions must not be set. * @param name name of this notification template. Must be unique
commit 144c8218afa68c76c5799a8efee3e8411e690989 Author: Joseph Marques joseph@redhat.com Date: Wed Apr 21 20:32:59 2010 -0400
add support for launching JavaTasks which can execute arbitrary SQL against the connection used by the DBUpgrader
diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/DatabaseType.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/DatabaseType.java index 1b48d57..bc4edb6 100644 --- a/modules/core/dbutils/src/main/java/org/rhq/core/db/DatabaseType.java +++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/DatabaseType.java @@ -25,10 +25,13 @@ import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; +import java.util.ArrayList; import java.util.List;
import mazz.i18n.Logger;
+import org.rhq.core.db.ant.dbupgrade.SST_JavaTask; + /** * A vendor-specific database with some vendor-specific method implementations in order to do things necessary for each * individual type of database. This abstract class provides some default implementations; vendor-specific subclasses @@ -356,6 +359,40 @@ public abstract class DatabaseType { }
/** + * Executes the given SQL on the given connection. Use this method if you want to return the raw results + * for further processing. This is especially useful when used in conjunction with {@link SST_JavaTask}. + * + * @param conn the connection to the database that will execute the SQL + * @param sql the actual SQL to execute + * + * @throws SQLException + */ + public List<Object[]> executeSelectSql(Connection conn, String sql) throws SQLException { + Statement ps = null; + + try { + LOG.debug(DbUtilsI18NResourceKeys.EXECUTING_SQL, sql); + ps = conn.createStatement(); + + ResultSet resultSet = ps.executeQuery(sql); + ResultSetMetaData metadata = resultSet.getMetaData(); + + int numberColumns = metadata.getColumnCount(); + List<Object[]> results = new ArrayList<Object[]>(); + while (resultSet.next()) { + Object[] nextRow = new Object[numberColumns]; + for (int i = 0; i < numberColumns; i++) { + nextRow[i] = resultSet.getObject(i + 1); + } + results.add(nextRow); + } + return results; + } finally { + closeStatement(ps); + } + } + + /** * Executes the given SQL on the given connection. Use this method if you don't care about what the results are, you * just want to execute the SQL and know if it was successful or not. * diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/ant/DbAntI18NResourceKeys.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/ant/DbAntI18NResourceKeys.java index c92d722..80061b8 100644 --- a/modules/core/dbutils/src/main/java/org/rhq/core/db/ant/DbAntI18NResourceKeys.java +++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/ant/DbAntI18NResourceKeys.java @@ -202,6 +202,16 @@ public interface DbAntI18NResourceKeys { @I18NMessage(value = "Konnte die Spalte nicht verändern. Grund: {0}", locale = "de") }) String ALTER_COLUMN_ERROR = "SchemaSpecTask.altercolumn.error";
+ @I18NMessages( { + @I18NMessage("Executing Java Task: class=[{0}]"), + @I18NMessage(value = "Führe die Java-Aufgabe: class=[{0}]", locale = "de") }) + String JAVA_TASK_EXECUTING = "SchemaSpecTask.javaTask.executing"; + + @I18NMessages( { + @I18NMessage("Java Task Error: class=[{0}]"), + @I18NMessage(value = "Fehler beim Ausführen der Aufgabe [{0}]", locale = "de") }) + String JAVA_TASK_ERROR = "SchemaSpecTask.javaTask.error"; + @I18NMessages( { @I18NMessage("No 'jdbcUrl' attribute specified."), @I18NMessage(value = "Es ist kein 'jdbcUrl' Attribut angegeben", locale = "de") }) String DBUPGRADE_NO_JDBC_URL = "DBUpgrader.no-jdbc-url"; diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/ant/dbupgrade/SST_JavaTask.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/ant/dbupgrade/SST_JavaTask.java new file mode 100644 index 0000000..b083510 --- /dev/null +++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/ant/dbupgrade/SST_JavaTask.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.core.db.ant.dbupgrade; + +import java.sql.Connection; + +import mazz.i18n.Msg; + +import org.apache.tools.ant.BuildException; + +import org.rhq.core.db.DatabaseType; +import org.rhq.core.db.ant.DbAntI18NFactory; +import org.rhq.core.db.ant.DbAntI18NResourceKeys; +import org.rhq.core.db.upgrade.DatabaseUpgradeTask; + +/** + * Task that allows more complicated upgrade logic to be externalized into a Java class. The JavaTask must implement + * the {@link DatabaseUpgradeTask} interface, which will pass the active {@link Connection} and {@link DatabaseType} + * objects used by the main upgrader to it. Authors of JavaTasks are encouraged to use the helper methods provided by + * the {@link DatabaseType} object, which will help keep the implementation vendor agnostic with respect to the set of + * databases supported by {@link DBUpgrader} at the time it was written. + * + * Ant task to invoke an external JavaTask, which can perform arbitrarily DDL and DML against the database. This task + * accepts one required attribute: + * + * <ul> + * <li>className</li> + * </ul> + * + * @author Joseph Marques + */ +public class SST_JavaTask extends SchemaSpecTask { + private static final Msg MSG = DbAntI18NFactory.getMsg(); + + private String className; + + /** + * Sets the name of the class that implements the {@link DatabaseUpgradeTask} interface. If the name is not + * package-prefixed, the default "org.rhq.core.db.upgrade" will be assumed. + * + * @param className + */ + public void setClassName(String className) { + this.className = className; + } + + /** + * Launches the {@link DatabaseUpgradeTask} defined by the className attribute, passing the {@link Connection} and + * {@link DatabaseType} from the main {@link DBUpgrader}. + * + * @see org.apache.tools.ant.Task#execute() + */ + public void execute() throws BuildException { + if (!isDBTargeted()) { + return; + } + + validateAttributes(); + + try { + DatabaseType db_type = getDatabaseType(); + Connection conn = getConnection(); + + if (className.indexOf(".") == -1) { + className = "org.rhq.core.db.upgrade." + className; + } + + log(MSG.getMsg(DbAntI18NResourceKeys.JAVA_TASK_EXECUTING, className)); + + Class<?> javaTaskClass = Class.forName(className); + DatabaseUpgradeTask javaTask = (DatabaseUpgradeTask) javaTaskClass.newInstance(); + javaTask.execute(conn, db_type); + } catch (Exception e) { + throw new BuildException(MSG.getMsg(DbAntI18NResourceKeys.JAVA_TASK_ERROR, e), e); + } + } + + private void validateAttributes() throws BuildException { + if (className == null) { + throw new BuildException(MSG.getMsg(DbAntI18NResourceKeys.SCHEMA_SPEC_TASK_MISSING_CHILD_ELEMENT, + "JavaTask", "className")); + } + } + +} \ No newline at end of file diff --git a/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DatabaseUpgradeTask.java b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DatabaseUpgradeTask.java new file mode 100644 index 0000000..fd438c0 --- /dev/null +++ b/modules/core/dbutils/src/main/java/org/rhq/core/db/upgrade/DatabaseUpgradeTask.java @@ -0,0 +1,34 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2008 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.core.db.upgrade; + +import java.sql.Connection; +import java.sql.SQLException; + +import org.rhq.core.db.DatabaseType; +import org.rhq.core.db.ant.dbupgrade.SST_JavaTask; + +/** + * Implement this interface if you wish to write database upgrade steps as {@link SST_JavaTask}s. + * + * @author Joseph Marques + */ +public interface DatabaseUpgradeTask { + public void execute(Connection connection, DatabaseType type) throws SQLException; +} diff --git a/modules/core/dbutils/src/main/resources/db-ant-tasks.properties b/modules/core/dbutils/src/main/resources/db-ant-tasks.properties index 7a135d9..c5892a9 100644 --- a/modules/core/dbutils/src/main/resources/db-ant-tasks.properties +++ b/modules/core/dbutils/src/main/resources/db-ant-tasks.properties @@ -15,5 +15,6 @@ schema-alterColumn=org.rhq.core.db.ant.dbupgrade.SST_AlterColumn schema-deleteColumn=org.rhq.core.db.ant.dbupgrade.SST_DeleteColumn schema-dropTable=org.rhq.core.db.ant.dbupgrade.SST_DropTable schema-directSQL=org.rhq.core.db.ant.dbupgrade.SST_DirectSQL +schema-javaTask=org.rhq.core.db.ant.dbupgrade.SST_JavaTask schema-createSequence=org.rhq.core.db.ant.dbupgrade.SST_CreateSequence schema-dropSequence=org.rhq.core.db.ant.dbupgrade.SST_DropSequence \ No newline at end of file
commit f7c53db7fa0085b412fcb9f462e2087726d8477c Author: Joseph Marques joseph@redhat.com Date: Wed Apr 21 16:20:59 2010 -0400
remove alert sender ordering, that feature has been removed from the release
diff --git a/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml b/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml index 8db8231..3098d97 100644 --- a/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml +++ b/modules/core/dbutils/src/main/scripts/dbsetup/alert-schema.xml @@ -139,7 +139,6 @@ <column name="NOTIF_TEMPLATE_ID" required="false" type="INTEGER" references="RHQ_ALERT_NOTIF_TEMPL(ID)"/> <column name="ALERT_CONFIG_ID" required="false" type="INTEGER" references="RHQ_CONFIG(ID)"/> <column name="ALERT_SENDER_NAME" required="false" size="100" type="VARCHAR2" /> <!-- TODO make required = true --> - <column name="ALERT_ORDER" type="INTEGER" /> <column name="NAME" type="VARCHAR2" size="100" /> </table>
rhq-commits@lists.fedorahosted.org