modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionCategory.java | 4 modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java | 17 modules/core/domain/src/main/java/org/rhq/core/domain/operation/OperationRequestStatus.java | 4 modules/core/domain/src/main/java/org/rhq/core/domain/resource/composite/DisambiguationReport.java | 2 modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/composite/ResourceGroupComposite.java | 2 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionUIBean.java | 3 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionsUIBean.java | 71 +++ modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertMessages.java | 70 +++ modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/CustomContentUIBean.java | 9 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/converter/MetricPercentConverter.java | 9 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/description/ControlDescriber.java | 7 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/validator/AlertValidatorUtil.java | 45 ++ modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/validator/EventRegexValidator.java | 48 ++ modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/AckAlertAction.java | 78 ++++ modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/ReenableAlertDefinitionAction.java | 80 ++++ modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/group/inventory/AddGroupResourcesFormPrepareAction.java | 5 modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/subsystem/SubsystemAlertDefinitionUIBean.java | 4 modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties | 4 modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/struts-config.xml | 14 modules/enterprise/gui/portal-war/src/main/webapp/common/RSSFormat.jsp | 7 modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/ViewAlertProperties.jsp | 49 +- modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/config/AlertDefinitionActive.jsp | 10 modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/listAlertTemplates.xhtml | 31 - modules/enterprise/gui/portal-war/src/main/webapp/rhq/group/alert/listGroupAlertDefinitions.xhtml | 25 - modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/alertDefinitionProperties.xhtml | 10 modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listAlertDefinitions.xhtml | 32 - modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listConditions.xhtml | 174 +++++++-- modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/viewAlert.xhtml | 77 +++- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertManagerBean.java | 13 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/AlertNotificationManagerBean.java | 13 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/alert/CustomAlertSenderBackingBean.java | 30 + modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java | 173 +++++---- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java | 8 modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsBackingBean.java | 168 ++++++++- modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsSender.java | 81 ++++ modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/Token.java | 72 ++++ modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/TokenClass.java | 59 +++ modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/TokenReplacer.java | 178 ++++++++++ modules/enterprise/server/plugins/alert-operations/src/main/resources/operations.xhtml | 47 +- modules/enterprise/server/plugins/alert-operations/src/test/java/org/rhq/enterprise/server/plugins/alertOperations/TokenReplacementTest.java | 135 +++++++ modules/plugins/netservices/pom.xml | 18 - 41 files changed, 1600 insertions(+), 286 deletions(-)
New commits: commit d0ef49e101ef7887e834b0a9021c0c0654a7f5d5 Merge: 613b993... 8a0951a... Author: Joseph Marques joseph@redhat.com Date: Fri Feb 26 15:34:50 2010 -0500
Merge branch 'master' into search
commit 8a0951a835997a2cdc75d2cf9840a7a7fdf59c15 Author: Lukas Krejci lkrejci@redhat.com Date: Fri Feb 26 17:57:56 2010 +0100
BZ 568544 - disambiguation doesn't get confused if more than one item in the provided results corresponds to a signle resource.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/composite/DisambiguationReport.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/composite/DisambiguationReport.java index 67f3276..dd359da 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/composite/DisambiguationReport.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/composite/DisambiguationReport.java @@ -64,6 +64,6 @@ public class DisambiguationReport<T> implements Serializable { }
public String toString() { - return "DisambiguationReport(type=" + resourceTypeName + ", plugin=" + resourceTypePluginName + ", parents=" + parents + ")"; + return "DisambiguationReport(type=" + resourceTypeName + ", plugin=" + resourceTypePluginName + ", parents=" + parents + ", original=" + original + ")"; } } \ No newline at end of file diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java index 3af7a35..e5684d2 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java @@ -31,6 +31,7 @@ import java.util.LinkedList; import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.Set;
import javax.ejb.EJB; import javax.ejb.Stateless; @@ -2170,34 +2171,36 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage false); }
- //this will contain the disambiguated results - List<DisambiguationReport<T>> resolution = new ArrayList<DisambiguationReport<T>>(results.size()); boolean typeResolutionNeeded = false; boolean pluginResolutionNeeded = false; boolean parentResolutionNeeded = false;
//we can't assume the ordering of the provided results and the disambiguation query results - //will be the same, hence this map. - Map<Integer, MutableDisambiguationReport<T>> reportByResourceId = new HashMap<Integer, MutableDisambiguationReport<T>>(); + //will be the same. + + //this list contains the resulting reports in the same order as the original results + List<MutableDisambiguationReport<T>> reports = new ArrayList<MutableDisambiguationReport<T>>(results.size()); + + //this maps the reports to resourceIds. More than one report can correspond to a single + //resource id. The reports in this map are the same instances as in the reports list. + Map<Integer, List<MutableDisambiguationReport<T>>> reportsByResourceId = new HashMap<Integer, List<MutableDisambiguationReport<T>>>(); for (T r : results) { MutableDisambiguationReport<T> value = new MutableDisambiguationReport<T>(); value.original = r; int resourceId = extractor.extract(r); if (resourceId > 0) { - reportByResourceId.put(resourceId, value); + List<MutableDisambiguationReport<T>> correspondingResults = reportsByResourceId.get(resourceId); + if (correspondingResults == null) { + correspondingResults = new ArrayList<MutableDisambiguationReport<T>>(); + reportsByResourceId.put(resourceId, correspondingResults); + } + correspondingResults.add(value); } + reports.add(value); }
//check that we still have something to disambiguate - if (reportByResourceId.isEmpty()) { - //no, we don't. construct the resolution only using the results. - - for (T result : results) { - DisambiguationReport<T> report = new DisambiguationReport<T>(result, Collections - .<ResourceParentFlyweight> emptyList(), null, null); - resolution.add(report); - } - } else { + if (reportsByResourceId.size() > 0) { //first find out how many ancestors we are going to require to disambiguate the resuls String query = Resource.NATIVE_QUERY_FIND_DISAMBIGUATION_LEVEL;
@@ -2247,7 +2250,7 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage
Query parentsQuery = entityManager.createQuery(selectBuilder.append(" ").append(fromBuilder).toString());
- parentsQuery.setParameter("resourceIds", reportByResourceId.keySet()); + parentsQuery.setParameter("resourceIds", reportsByResourceId.keySet());
@SuppressWarnings("unchecked") List<Object[]> parentsResults = (List<Object[]>) parentsQuery.getResultList(); @@ -2264,28 +2267,22 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage String parentName = (String) parentsResult[2 * i + 2]; parents.add(new ResourceParentFlyweight(parentId, parentName)); } - MutableDisambiguationReport<T> report = reportByResourceId.get(resourceId); - report.typeName = typeName; - report.pluginName = pluginName; - report.parents = parents; - } - - //now we have all the information to create the result. - for (T result : results) { - int resourceId = extractor.extract(result); - if (resourceId > 0) { - //this results was disambiguated by the query above... - MutableDisambiguationReport<T> report = reportByResourceId.get(resourceId); - resolution.add(report.getReport()); - } else { - //this result doesn't correspond to any resource, need to handle it specially - DisambiguationReport<T> report = new DisambiguationReport<T>(result, Collections - .<ResourceParentFlyweight> emptyList(), null, null); - resolution.add(report); + + //update all the reports that correspond to this resourceId + for(MutableDisambiguationReport<T> report : reportsByResourceId.get(resourceId)) { + report.typeName = typeName; + report.pluginName = pluginName; + report.parents = parents; } } }
+ List<DisambiguationReport<T>> resolution = new ArrayList<DisambiguationReport<T>>(results.size()); + + for (MutableDisambiguationReport<T> report : reports) { + resolution.add(report.getReport()); + } + return new ResourceNamesDisambiguationResult<T>(resolution, typeResolutionNeeded, parentResolutionNeeded, pluginResolutionNeeded); } @@ -2297,7 +2294,8 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage public List<ResourceParentFlyweight> parents;
public DisambiguationReport<T> getReport() { - return new DisambiguationReport<T>(original, parents, typeName, pluginName); + return new DisambiguationReport<T>(original, parents == null ? Collections + .<ResourceParentFlyweight> emptyList() : parents, typeName, pluginName); } } }
commit b2f7c0e76fc8bd366bb58bda3250b75cf6f7ecca Author: Lukas Krejci lkrejci@redhat.com Date: Fri Feb 26 12:51:53 2010 +0100
BZ 565626 - fixing the URL query string for groups used in menu search.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/composite/ResourceGroupComposite.java b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/composite/ResourceGroupComposite.java index a5bd861..6a837c9 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/composite/ResourceGroupComposite.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/resource/group/composite/ResourceGroupComposite.java @@ -164,7 +164,7 @@ public class ResourceGroupComposite implements Serializable { * @return query string snippet that can appear after the "?" in group URLs. */ public String getGroupQueryString() { - return "category=" + getCategory().getName() + "&groupId=" + getResourceGroup().getId(); + return "groupId=" + getResourceGroup().getId(); }
private String getAlignedAvailabilityResults(long up, long down) {
commit f3d2b483a01c8771e106c407f4af8473bb1e61fb Author: Heiko W. Rupp hwr@redhat.com Date: Thu Feb 25 17:11:43 2010 +0100
BZ 535432 suppress 'null' is the condition has no name, which is the case for availability.
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 c21bf21..0f48f9e 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 @@ -907,7 +907,8 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { builder.append(condition.getName()).append(' '); } } else { - builder.append(condition.getName()).append(' '); + if (category.getName()!=null) // this is null for e.g. availability + builder.append(condition.getName()).append(' '); }
// next format the RHS
commit 95ab39239a9d3d2f4081a49c8edcdc51acdacbfc Merge: c8338b8... 3705350... Author: Heiko W. Rupp hwr@redhat.com Date: Thu Feb 25 14:31:21 2010 +0100
Merge branch 'master' into alertPlugin
commit 37053500c05ec42b23740e4612899f2c56a21864 Author: Heiko W. Rupp hwr@redhat.com Date: Thu Feb 25 11:27:51 2010 +0100
BZ 568275 - add commons-codec which is needed with commons-httpclient 3
diff --git a/modules/plugins/netservices/pom.xml b/modules/plugins/netservices/pom.xml index 58087fa..06ae2ae 100644 --- a/modules/plugins/netservices/pom.xml +++ b/modules/plugins/netservices/pom.xml @@ -33,6 +33,11 @@ <artifactId>commons-httpclient</artifactId> <version>3.0.1</version> </dependency> + <dependency> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + <version>1.2</version> + </dependency>
</dependencies> @@ -58,6 +63,11 @@ <artifactId>commons-httpclient</artifactId> <version>3.0.1</version> </artifactItem> + <artifactItem> + <groupId>commons-codec</groupId> + <artifactId>commons-codec</artifactId> + <version>1.2</version> + </artifactItem> </artifactItems> <outputDirectory>${project.build.outputDirectory}/lib</outputDirectory> </configuration> @@ -202,13 +212,13 @@ <id>deploy-jar-meta-inf</id> <phase>package</phase> <configuration> - <tasks> - <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" /> + <tasks> + <property name="deployment.file" location="${rhq.deploymentDir}/${project.build.finalName}.jar" /> <echo>*** Updating META-INF dir in ${deployment.file}...</echo> <unjar src="${project.build.directory}/${project.build.finalName}.jar" dest="${project.build.outputDirectory}"> <patternset><include name="META-INF/**" /></patternset> </unjar> - <jar destfile="${deployment.file}" manifest="${project.build.outputDirectory}/META-INF/MANIFEST.MF" update="true"> + <jar destfile="${deployment.file}" manifest="${project.build.outputDirectory}/META-INF/MANIFEST.MF" update="true"> </jar> </tasks> </configuration> @@ -216,7 +226,7 @@ <goal>run</goal> </goals> </execution> - + <execution> <id>undeploy</id> <phase>clean</phase>
commit b32fab5ccf90e3f6bc5c9c16e78daeb069f62675 Author: Heiko W. Rupp hwr@redhat.com Date: Thu Feb 25 10:59:56 2010 +0100
Persisting a new resource is no error ...
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java index 6755733..3af7a35 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java @@ -188,7 +188,7 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage }
entityManager.persist(resource); - log.error("********* resource persisted ************"); + log.debug("********* resource persisted ************"); // Execute sub-methods as overlord to bypass additional security checks. Subject overlord = this.subjectManager.getOverlord(); updateImplicitMembership(overlord, resource); @@ -366,7 +366,7 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage PluginConfigurationUpdate.QUERY_DELETE_BY_RESOURCES_0, PluginConfigurationUpdate.QUERY_DELETE_BY_RESOURCES_1, // first delete the config objects PluginConfigurationUpdate.QUERY_DELETE_BY_RESOURCES_2, // then the history objects wrapping those configs - AlertConditionLog.QUERY_DELETE_BY_RESOURCES, // Don't + AlertConditionLog.QUERY_DELETE_BY_RESOURCES, // Don't AlertNotificationLog.QUERY_DELETE_BY_RESOURCES, // alter Alert.QUERY_DELETE_BY_RESOURCES, // order AlertCondition.QUERY_DELETE_BY_RESOURCES, // of @@ -2134,7 +2134,7 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage parent = null; break; } - + } while (parent != null); if (resource != null) { if (!authorizationManager.canViewResource(subject, resource.getId())) { @@ -2164,7 +2164,7 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage
public <T> ResourceNamesDisambiguationResult<T> disambiguate(List<T> results, boolean alwaysIncludeParent, IntExtractor<? super T> extractor) { - + if (results.isEmpty()) { return new ResourceNamesDisambiguationResult<T>(new ArrayList<DisambiguationReport<T>>(), false, false, false);
commit c8338b898b50fbfe86e07d4c25cba30deb9c3139 Merge: a99099e... 4714eb8... Author: Justin Harris jharris@redhat.com Date: Wed Feb 24 12:24:53 2010 -0500
Merge remote branch 'origin/alertPlugin' into bugz
commit 810993311fa5e22495be1eb9cfebb154a0e3a3ef Author: John Mazzitelli mazz@redhat.com Date: Wed Feb 24 12:21:24 2010 -0500
don't bother looping/logging if debug not enabled.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java index ef27906..dd943e0 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/Criteria.java @@ -125,8 +125,11 @@ public abstract class Criteria implements Serializable { results.put(getCleansedFieldName(filterField, 6), filterFieldValue); } } - for (Map.Entry<String, Object> entries : results.entrySet()) { - LOG.debug("Filter: (" + entries.getKey() + ", " + entries.getValue() + ")"); + + if (LOG.isDebugEnabled()) { + for (Map.Entry<String, Object> entries : results.entrySet()) { + LOG.debug("Filter: (" + entries.getKey() + ", " + entries.getValue() + ")"); + } } return results; } @@ -160,8 +163,10 @@ public abstract class Criteria implements Serializable { } } } - for (String entry : results) { - LOG.debug("Fetch: (" + entry + ")"); + if (LOG.isDebugEnabled()) { + for (String entry : results) { + LOG.debug("Fetch: (" + entry + ")"); + } } return results; } @@ -283,7 +288,9 @@ public abstract class Criteria implements Serializable { } } } - LOG.debug("Page Control: " + pc); + if (LOG.isDebugEnabled()) { + LOG.debug("Page Control: " + pc); + } return pc; }
commit a99099ea48d165b4a272949d2fce9e2815a3b061 Author: Justin Harris jharris@redhat.com Date: Wed Feb 24 12:21:04 2010 -0500
Fix for BZ 561900
Adding in length and null value validation for alert definition names.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionMessages.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionMessages.java deleted file mode 100644 index 62a6fc0..0000000 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionMessages.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * RHQ Management Platform - * Copyright (C) 2005-2010 Red Hat, Inc. - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -package org.rhq.enterprise.gui.alert; - -import java.text.MessageFormat; -import java.util.Map; -import org.jboss.seam.ScopeType; -import org.jboss.seam.annotations.In; -import org.jboss.seam.annotations.Name; -import org.jboss.seam.annotations.Scope; - -@Scope(ScopeType.APPLICATION) -@Name("alertConditionMessages") -public class AlertConditionMessages { - - @In - private Map<String, String> messages; - - public String getThreshold() { - return translate("errors.double", "Threshold"); - } - - public String getPercentRange() { - return translate("errors.range", "Threshold", "0%", "1000%"); - } - - public String getDampeningCount() { - return translate("errors.integer", "Dampening Count"); - } - - public String getDampeningEvaluation() { - return translate("errors.integer", "Dampening Evaluations"); - } - - public String getTimePeriod() { - return translate("errors.integer", "Time Period"); - } - - private String translate(String key, Object... params) { - String message = messages.get(key); - - return MessageFormat.format(message, params); - } -} \ No newline at end of file diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertMessages.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertMessages.java new file mode 100644 index 0000000..79062ef --- /dev/null +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertMessages.java @@ -0,0 +1,70 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.alert; + +import java.text.MessageFormat; +import java.util.Map; +import org.jboss.seam.ScopeType; +import org.jboss.seam.annotations.In; +import org.jboss.seam.annotations.Name; +import org.jboss.seam.annotations.Scope; + +@Scope(ScopeType.APPLICATION) +@Name("alertMessages") +public class AlertMessages { + + @In + private Map<String, String> messages; + + public String getNameRequired() { + String name = translate("alerts.config.DefinitionList.ListHeader.AlertName"); + return translate("errors.required", name); + } + + public String getNameLength() { + String name = translate("alerts.config.DefinitionList.ListHeader.AlertName"); + return translate("errors.maxlength", name); + } + + public String getThreshold() { + return translate("errors.double", "Threshold"); + } + + public String getPercentRange() { + return translate("errors.range", "Threshold", "0%", "1000%"); + } + + public String getDampeningCount() { + return translate("errors.integer", "Dampening Count"); + } + + public String getDampeningEvaluation() { + return translate("errors.integer", "Dampening Evaluations"); + } + + public String getTimePeriod() { + return translate("errors.integer", "Time Period"); + } + + private String translate(String key, Object... params) { + String message = messages.get(key); + + return MessageFormat.format(message, params); + } +} \ No newline at end of file diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/alertDefinitionProperties.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/alertDefinitionProperties.xhtml index 9439c5f..fd8e260 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/alertDefinitionProperties.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/alertDefinitionProperties.xhtml @@ -17,7 +17,15 @@
<h:panelGrid columns="2" border="1" cellpadding="5" style="margin: 15px;"> <h:outputLabel for="alertNameInput" value="Name: " /> - <h:inputText id="alertNameInput" value="#{alertDefinition.name}" style="width: 300px;" /> + <h:inputText id="alertNameInput" + value="#{alertDefinition.name}" + style="width: 300px;" + maxlength="100" + required="true" + requiredMessage="#{alertMessages.nameRequired}" + validatorMessage="#{alertMessages.nameLength}"> + <f:validateLength maximum="100" /> + </h:inputText>
<h:outputLabel for="alertDescriptionInput" value="Description: " /> <h:inputTextarea id="alertDescriptionInput" value="#{alertDefinition.description}" style="width: 300px;" /> diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listConditions.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listConditions.xhtml index a5500e4..2000efd 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listConditions.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listConditions.xhtml @@ -170,9 +170,9 @@ value="#{alertDefinition.alertDampening.value}" size="4" required="true" - requiredMessage="#{alertConditionMessages.dampeningCount}" - validatorMessage="#{alertConditionMessages.dampeningCount}" - converterMessage="#{alertConditionMessages.dampeningCount}"> + requiredMessage="#{alertMessages.dampeningCount}" + validatorMessage="#{alertMessages.dampeningCount}" + converterMessage="#{alertMessages.dampeningCount}"> <f:validateDoubleRange minimum="0" /> </h:inputText> <h:outputText value=" #{messages['alert.config.props.CB.Content.DampenConsecutiveCount.2']}" /> @@ -184,9 +184,9 @@ value="#{alertDefinition.alertDampening.value}" size="4" required="true" - requiredMessage="#{alertConditionMessages.dampeningCount}" - validatorMessage="#{alertConditionMessages.dampeningCount}" - converterMessage="#{alertConditionMessages.dampeningCount}"> + requiredMessage="#{alertMessages.dampeningCount}" + validatorMessage="#{alertMessages.dampeningCount}" + converterMessage="#{alertMessages.dampeningCount}"> <f:validateLongRange minimum="0" /> </h:inputText> <h:outputText value=" #{messages['alert.config.props.CB.Content.DampenPartialCount.2']} " /> @@ -194,9 +194,9 @@ value="#{alertDefinition.alertDampening.period}" size="4" required="true" - requiredMessage="#{alertConditionMessages.dampeningEvaluation}" - validatorMessage="#{alertConditionMessages.dampeningEvaluation}" - converterMessage="#{alertConditionMessages.dampeningEvaluation}"> + requiredMessage="#{alertMessages.dampeningEvaluation}" + validatorMessage="#{alertMessages.dampeningEvaluation}" + converterMessage="#{alertMessages.dampeningEvaluation}"> <f:validateLongRange minimum="0" /> </h:inputText> <h:outputText value=" #{messages['alert.config.props.CB.Content.DampenPartialCount.3']}" /> @@ -208,9 +208,9 @@ value="#{alertDefinition.alertDampening.value}" size="4" required="true" - requiredMessage="#{alertConditionMessages.dampeningCount}" - validatorMessage="#{alertConditionMessages.dampeningCount}" - converterMessage="#{alertConditionMessages.dampeningCount}"> + requiredMessage="#{alertMessages.dampeningCount}" + validatorMessage="#{alertMessages.dampeningCount}" + converterMessage="#{alertMessages.dampeningCount}"> <f:validateLongRange minimum="0" /> </h:inputText> <h:outputText value=" #{messages['alert.config.props.CB.Content.DampenDurationCount.2']} " /> @@ -218,9 +218,9 @@ value="#{alertDefinition.alertDampening.period}" size="4" required="true" - requiredMessage="#{alertConditionMessages.timePeriod}" - validatorMessage="#{alertConditionMessages.timePeriod}" - converterMessage="#{alertConditionMessages.timePeriod}"> + requiredMessage="#{alertMessages.timePeriod}" + validatorMessage="#{alertMessages.timePeriod}" + converterMessage="#{alertMessages.timePeriod}"> <f:validateLongRange minimum="0" /> </h:inputText> <h:selectOneMenu value="#{alertDefinition.alertDampening.periodUnits}"> @@ -341,8 +341,8 @@ <h:inputText id="metricThresholdAbsolute" value="#{alertConditionsUIBean.threshold}" required="true" - requiredMessage="#{alertConditionMessages.threshold}" - validatorMessage="#{alertConditionMessages.threshold}"> + requiredMessage="#{alertMessages.threshold}" + validatorMessage="#{alertMessages.threshold}"> <f:validateDoubleRange minimum="0.0" /> </h:inputText> <h:outputLabel for="metricThresholdAbsolute" value="#{messages['alert.config.props.CB.Content.AbsoluteValue']}" /> @@ -371,8 +371,8 @@ value="#{alertConditionsUIBean.currentCondition.threshold}" converter="#{metricPercentConverter}" required="true" - requiredMessage="#{alertConditionMessages.percentRange}" - validatorMessage="#{alertConditionMessages.percentRange}"> + requiredMessage="#{alertMessages.percentRange}" + validatorMessage="#{alertMessages.percentRange}"> <f:validateDoubleRange minimum="0.0" maximum="1000.0" /> </h:inputText> <h:outputLabel for="metricBaselinePercent" value=" #{messages['alert.config.props.CB.Content.Percent']} " /> diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/viewAlert.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/viewAlert.xhtml index a987e65..dd349a1 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/viewAlert.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/viewAlert.xhtml @@ -77,8 +77,7 @@ </ui:define>
<ui:define name="body"> - <h:messages showDetail="true" - globalOnly="true" + <h:messages showSummary="true" infoClass="InfoBlock" warnClass="WarnBlock" errorClass="ErrorBlock"
commit 4714eb87aeeb6dce6a6ebcb7573bc80dafa3928d Merge: e25997a... 7f4d769... Author: Heiko W. Rupp hwr@redhat.com Date: Wed Feb 24 18:19:46 2010 +0100
Merge branch 'master' into alertPlugin
commit 7f4d76951a1e2686aa4d104477765d9b4d350dad Author: Lukas Krejci lkrejci@redhat.com Date: Wed Feb 24 18:13:05 2010 +0100
BZ 566749 - fixing the NPE when adding platforms (that don't have a parent) to a resource group.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/group/inventory/AddGroupResourcesFormPrepareAction.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/group/inventory/AddGroupResourcesFormPrepareAction.java index 698cb5a..808f331 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/group/inventory/AddGroupResourcesFormPrepareAction.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/group/inventory/AddGroupResourcesFormPrepareAction.java @@ -201,7 +201,10 @@ public class AddGroupResourcesFormPrepareAction extends Action { Resource resource = dr.getOriginal();
Resource parent = resource.getParentResource(); - parent.setName(buildLineage(dr.getParents())); + //platforms don't have parents, need to check for null here + if (parent != null) { + parent.setName(buildLineage(dr.getParents())); + }
convertedResults.add(resource); }
commit 38fb361e5cdb167bb5a947596586194d941e4221 Author: Justin Harris jharris@redhat.com Date: Wed Feb 24 10:55:35 2010 -0500
Fix for BZ 567375
Changed method of resource id lookup in control describer.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/description/ControlDescriber.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/description/ControlDescriber.java index bcf5d25..ab1bd8a 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/description/ControlDescriber.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/description/ControlDescriber.java @@ -18,9 +18,11 @@ */ package org.rhq.enterprise.gui.alert.description;
+import org.jboss.seam.Component; import org.rhq.core.domain.alert.AlertCondition; import org.rhq.core.domain.alert.AlertConditionCategory; import org.rhq.core.domain.operation.OperationDefinition; +import org.rhq.core.domain.resource.ResourceType; import org.rhq.enterprise.server.operation.OperationManagerLocal; import org.rhq.enterprise.server.util.LookupUtil;
@@ -53,12 +55,13 @@ public class ControlDescriber extends AlertConditionDescriber { private OperationDefinition getDefinition(AlertCondition condition) { OperationManagerLocal operationManager = LookupUtil.getOperationManager();
- Integer resourceTypeId = condition.getAlertDefinition().getResource().getResourceType().getId(); + // this is not a seam component, so look it up in the component contexts + ResourceType resourceType = (ResourceType)Component.getInstance("resourceType"); String operationName = condition.getName();
try { return operationManager.getOperationDefinitionByResourceTypeAndName( - resourceTypeId, operationName, false); + resourceType.getId(), operationName, false); } catch (Exception e) { return null; }
commit e25997a61a0e49e38768d20461afffb9d19a554e Merge: 33e3625... 1e8ab54... Author: Heiko W. Rupp hwr@redhat.com Date: Wed Feb 24 16:53:45 2010 +0100
Merge branch 'master' into alertPlugin
commit 33e3625f6e4383d2bf44e832452347fc08241b97 Author: Heiko W. Rupp hwr@redhat.com Date: Wed Feb 24 16:33:43 2010 +0100
Linking fixes for BZ 566896
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/group/alert/listGroupAlertDefinitions.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/group/alert/listGroupAlertDefinitions.xhtml index 2e5a565..5768c23 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/group/alert/listGroupAlertDefinitions.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/group/alert/listGroupAlertDefinitions.xhtml @@ -18,10 +18,10 @@ <ui:param name="pageTitle" value="List Alert Definitions for Group '#{ResourceGroupUIBean.name}'"/> <ui:param name="selectedTabName" value="Alert.Definitions"/> <ui:define name="content"> - + <h:form id="alertDefinitionsListForm"> <input type="hidden" name="groupId" value="${param.groupId}"/> - + <rich:panel styleClass="BlockContent"> <f:facet name="header"> <h:outputText value="Alert Definitions"/> @@ -48,12 +48,12 @@ <f:facet name="PageControlView"> <onc:paginationControl id="GroupAlertDefinitionsList" /> </f:facet> - + rich:column <f:facet name="header"> <onc:allSelect target="selectedAlertDefinitions" /> </f:facet> - + <onc:select name="selectedAlertDefinitions" value="#{item.id}" /> </rich:column>
@@ -63,25 +63,24 @@ <h:outputText styleClass="headerText" value="Name" /> </onc:sortableColumnHeader> </f:facet> - - <h:outputLink value="/alerts/Config.do"> - <f:param name="mode" value="viewRoles"/> + + <h:outputLink value="/rhq/resource/alert/viewAlert.xhtml"> <f:param name="groupId" value="#{param.groupId}"/> <f:param name="ad" value="#{item.id}"/> <h:outputText value="#{item.name}" /> </h:outputLink> </rich:column> - + rich:column <f:facet name="header"> <onc:sortableColumnHeader sort="a.description"> <h:outputText styleClass="headerText" value="Description" /> </onc:sortableColumnHeader> </f:facet> - + <h:outputText value="#{item.description}"/> </rich:column> - + rich:column <f:facet name="header"> <onc:sortableColumnHeader sort="a.ctime"> @@ -93,14 +92,14 @@ <f:converter converterId="UserDateTimeConverter" /> </h:outputText> </rich:column> - + rich:column <f:facet name="header"> <onc:sortableColumnHeader sort="a.enabled"> <h:outputText styleClass="headerText" value="Active" /> </onc:sortableColumnHeader> </f:facet> - + <h:outputText value="#{item.enabled}"/> </rich:column>
@@ -134,7 +133,7 @@ </rich:dataTable>
</h:panelGrid> - + </rich:panel> </h:form>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listAlertDefinitions.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listAlertDefinitions.xhtml index 708f559..ef13121 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listAlertDefinitions.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listAlertDefinitions.xhtml @@ -18,10 +18,10 @@ <ui:param name="pageTitle" value="List Alert Definitions for Resource '#{ResourceUIBean.name}'"/> <ui:param name="selectedTabName" value="Alert.Definitions"/> <ui:define name="content"> - + <h:form id="alertDefinitionsListForm"> <input type="hidden" name="id" value="${param.id}"/> - + <rich:panel styleClass="BlockContent"> <f:facet name="header"> <h:outputText value="Alert Definitions"/> @@ -48,12 +48,12 @@ <f:facet name="PageControlView"> <onc:paginationControl id="AlertDefinitionsList" /> </f:facet> - + rich:column <f:facet name="header"> <onc:allSelect target="selectedAlertDefinitions" /> </f:facet> - + <onc:select name="selectedAlertDefinitions" value="#{item.id}" /> </rich:column>
@@ -63,24 +63,24 @@ <h:outputText styleClass="headerText" value="Name" /> </onc:sortableColumnHeader> </f:facet> - + <h:outputLink value="/rhq/resource/alert/viewAlert.xhtml"> <f:param name="id" value="#{Resource.id}"/> <f:param name="ad" value="#{item.id}"/> <h:outputText value="#{item.name}" /> </h:outputLink> </rich:column> - + rich:column <f:facet name="header"> <onc:sortableColumnHeader sort="a.description"> <h:outputText styleClass="headerText" value="Description" /> </onc:sortableColumnHeader> </f:facet> - + <h:outputText value="#{item.description}"/> </rich:column> - + rich:column <f:facet name="header"> <onc:sortableColumnHeader sort="a.ctime"> @@ -92,14 +92,14 @@ <f:converter converterId="UserDateTimeConverter" /> </h:outputText> </rich:column> - + rich:column <f:facet name="header"> <onc:sortableColumnHeader sort="a.enabled"> <h:outputText styleClass="headerText" value="Active" /> </onc:sortableColumnHeader> </f:facet> - + <h:outputText value="#{item.enabled}"/> </rich:column>
@@ -107,15 +107,13 @@ <f:facet name="header"> <h:outputText styleClass="headerText" value="Parent" /> </f:facet> - - <h:outputLink value="/alerts/Config.do" rendered="#{item.parentId ne 0}"> - <f:param name="mode" value="viewRoles"/> + + <h:outputLink value="http://localhost:7080/rhq/resource/alert/viewAlert.xhtml" rendered="#{item.parentId ne 0}"> <f:param name="type" value="#{item.resource.resourceType.id}"/> - <f:param name="from" value="#{item.id}"/> <f:param name="ad" value="#{item.parentId}"/> <h:outputText value="View Template" /> </h:outputLink> - + <h:outputLink value="/alerts/Config.do" rendered="#{not empty item.groupAlertDefinition}"> <f:param name="mode" value="viewRoles"/> <f:param name="groupId" value="#{item.groupAlertDefinition.resourceGroup.id}"/> @@ -129,7 +127,7 @@ <f:facet name="header"> <h:outputText styleClass="headerText" value="Read Only" /> </f:facet> - + <h:outputText value="N/A" rendered="#{item.parentId eq 0 and empty item.groupAlertDefinition}"/> <h:outputText value="#{item.readOnly}" rendered="#{item.parentId ne 0 or not empty item.groupAlertDefinition}"/> </rich:column> @@ -167,7 +165,7 @@ </rich:dataTable>
</h:panelGrid> - + </rich:panel> </h:form>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/viewAlert.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/viewAlert.xhtml index a987e65..75a1d50 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/viewAlert.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/viewAlert.xhtml @@ -19,6 +19,9 @@ <c:when test="#{not empty param.type}"> <c:set var="title" value="Definition for '#{alertDefinition.name}' on resource type '#{ResourceTypeUIBean.name}'"/> </c:when> + <c:when test="#{not empty param.groupId}"> + <c:set var="title" value="Definition for '#{alertDefinition.name}' on group '#{ResourceGroupUIBean.name}'"/> + </c:when> <c:otherwise> <c:set var="title" value="Definition for '#{alertDefinition.name}' on resource '#{alertDefinition.resource.name}'"/> </c:otherwise> @@ -55,18 +58,25 @@ <h:outputText>Alert Definitions</h:outputText> </h:outputLink> <h:outputText> > </h:outputText> - <h:outputLink value="viewAlert.xhtml"> - <f:param name="ad" value="#{alertDefinition.id}" /> - <h:outputText value=" Definition for '#{alertDefinition.name}' "/> - </h:outputLink> <c:choose> <c:when test="#{not empty param.type}"> - <h:outputText> on resource type </h:outputText> + <h:outputText value=" Definition for alert template '#{alertDefinition.name}' "/> + <h:outputText> on Resource Type </h:outputText> <h:outputLink value="/rhq/admin/listAlertTemplates.xhtml?type=${param.type}"> <h:outputText value=" #{ResourceTypeUIBean.name}"/> </h:outputLink> </c:when> + <c:when test="#{not empty param.groupId}"> + <h:outputText> on resource group </h:outputText> + <h:outputLink value="/rhq/group/alert/listGroupAlertDefinitions.xhtml?groupId=${param.groupId}"> + <h:outputText value=" #{ResourceGroupUIBean.name}"/> + </h:outputLink> + </c:when> <c:otherwise> + <h:outputLink value="viewAlert.xhtml"> + <f:param name="ad" value="#{alertDefinition.id}" /> + <h:outputText value=" Definition for '#{alertDefinition.name}' "/> + </h:outputLink> <h:outputText> on resource </h:outputText> <h:outputLink value="/rhq/resource/summary/overview.xhtml"> <f:param name="id" value="#{alertDefinition.resource.id}" /> @@ -196,6 +206,11 @@ <h:outputText value="Back to Alert Definitions for Resource Type '#{ResourceTypeUIBean.name}'"/> </h:outputLink> </c:when> + <c:when test="#{not empty param.groupId}"> + <h:outputLink value="/rhq/group/alert/listGroupAlertDefinitions.xhtml?groupId=${param.groupId}"> + <h:outputText value="Back to Alert Definitions for Resource Group '#{ResourceGroupUIBean.name}'"/> + </h:outputLink> + </c:when> <c:otherwise> <h:outputLink value="/rhq/resource/alert/listAlertDefinitions.xhtml"> <f:param name="id" value="#{alertDefinition.resource.id}"/>
commit 1e8ab544201de380a8911b2fa88701c4b9b1a206 Author: Lukas Krejci lkrejci@redhat.com Date: Wed Feb 24 15:33:18 2010 +0100
BZ 567925 - Restructured the ResourceManagerBean.disambiguate() method to handle (hopefully) all the corner cases resulting from the fact that not all of the provided results have to be mappable to a resource.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java index b0db81c..6755733 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java @@ -2162,45 +2162,23 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage return (findChildResources(subject, parentResource, pageControl)); }
- public <T> ResourceNamesDisambiguationResult<T> disambiguate(List<T> results, boolean alwaysIncludeParent, IntExtractor<? super T> extractor) { - if (results.isEmpty()) { - return new ResourceNamesDisambiguationResult<T>(new ArrayList<DisambiguationReport<T>>(), false, false, false); - } + public <T> ResourceNamesDisambiguationResult<T> disambiguate(List<T> results, boolean alwaysIncludeParent, + IntExtractor<? super T> extractor) {
- String query = Resource.NATIVE_QUERY_FIND_DISAMBIGUATION_LEVEL; - - query = JDBCUtil.transformQueryForMultipleInParameters(query, "@@RESOURCE_IDS@@", results.size()); - Query disambiguateQuery = entityManager.createNativeQuery(query); - int i = 1; - for (T r : results) { - disambiguateQuery.setParameter(i++, extractor.extract(r)); - } - - Object[] rs = (Object[]) disambiguateQuery.getSingleResult(); - - int disambiguationLevel = Resource.MAX_SUPPORTED_RESOURCE_HIERARCHY_DEPTH; //the max we support - - int targetCnt = ((BigInteger) rs[0]).intValue(); - int typeCnt = ((BigInteger) rs[1]).intValue(); - int typeAndPluginCnt = ((BigInteger) rs[2]).intValue(); - for (i = 1; i <= Resource.MAX_SUPPORTED_RESOURCE_HIERARCHY_DEPTH; ++i) { - int levelCnt = ((BigInteger) rs[2 + i]).intValue(); - if (levelCnt == targetCnt) { - disambiguationLevel = i - 1; - break; - } - } - - if (alwaysIncludeParent && disambiguationLevel == 0) { - disambiguationLevel = 1; + if (results.isEmpty()) { + return new ResourceNamesDisambiguationResult<T>(new ArrayList<DisambiguationReport<T>>(), false, false, + false); }
- boolean typeResolutionNeeded = typeAndPluginCnt > 1; - boolean pluginResolutionNeeded = typeAndPluginCnt > typeCnt; - boolean parentResolutionNeeded = disambiguationLevel > 0; + //this will contain the disambiguated results + List<DisambiguationReport<T>> resolution = new ArrayList<DisambiguationReport<T>>(results.size()); + boolean typeResolutionNeeded = false; + boolean pluginResolutionNeeded = false; + boolean parentResolutionNeeded = false;
- //we can't assume any ordering in the results, hence this map - Map<Integer, MutableDisambiguationReport<T>> reportByResourceId = new LinkedHashMap<Integer, MutableDisambiguationReport<T>>(); + //we can't assume the ordering of the provided results and the disambiguation query results + //will be the same, hence this map. + Map<Integer, MutableDisambiguationReport<T>> reportByResourceId = new HashMap<Integer, MutableDisambiguationReport<T>>(); for (T r : results) { MutableDisambiguationReport<T> value = new MutableDisambiguationReport<T>(); value.original = r; @@ -2210,57 +2188,101 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage } }
- //k, now let's construct the JPQL query to get the parents and type infos... - StringBuilder selectBuilder = new StringBuilder("SELECT r0.id, r0.resourceType.name, r0.resourceType.plugin"); - StringBuilder fromBuilder = new StringBuilder("FROM Resource r0"); + //check that we still have something to disambiguate + if (reportByResourceId.isEmpty()) { + //no, we don't. construct the resolution only using the results.
- for (i = 1; i <= disambiguationLevel; ++i) { - int pi = i - 1; - selectBuilder.append(", r").append(i).append(".id"); - selectBuilder.append(", r").append(i).append(".name"); - fromBuilder.append(" left join r").append(pi).append(".parentResource r").append(i); - } + for (T result : results) { + DisambiguationReport<T> report = new DisambiguationReport<T>(result, Collections + .<ResourceParentFlyweight> emptyList(), null, null); + resolution.add(report); + } + } else { + //first find out how many ancestors we are going to require to disambiguate the resuls + String query = Resource.NATIVE_QUERY_FIND_DISAMBIGUATION_LEVEL; + + query = JDBCUtil.transformQueryForMultipleInParameters(query, "@@RESOURCE_IDS@@", results.size()); + Query disambiguateQuery = entityManager.createNativeQuery(query); + int i = 1; + for (T r : results) { + disambiguateQuery.setParameter(i++, extractor.extract(r)); + }
- fromBuilder.append(" WHERE r0.id IN (:resourceIds)"); + Object[] rs = (Object[]) disambiguateQuery.getSingleResult();
- Query parentsQuery = entityManager.createQuery(selectBuilder.append(" ").append(fromBuilder).toString()); + int disambiguationLevel = Resource.MAX_SUPPORTED_RESOURCE_HIERARCHY_DEPTH; //the max we support
- parentsQuery.setParameter("resourceIds", reportByResourceId.keySet()); + int targetCnt = ((BigInteger) rs[0]).intValue(); + int typeCnt = ((BigInteger) rs[1]).intValue(); + int typeAndPluginCnt = ((BigInteger) rs[2]).intValue(); + for (i = 1; i <= Resource.MAX_SUPPORTED_RESOURCE_HIERARCHY_DEPTH; ++i) { + int levelCnt = ((BigInteger) rs[2 + i]).intValue(); + if (levelCnt == targetCnt) { + disambiguationLevel = i - 1; + break; + } + } + + if (alwaysIncludeParent && disambiguationLevel == 0) { + disambiguationLevel = 1; + }
- @SuppressWarnings("unchecked") - List<Object[]> parentsResults = (List<Object[]>) parentsQuery.getResultList(); - for (Object[] parentsResult : parentsResults) { - List<ResourceParentFlyweight> parents = new ArrayList<ResourceParentFlyweight>(disambiguationLevel); - Integer resourceId = (Integer) parentsResult[0]; - String typeName = (String) parentsResult[1]; - String pluginName = (String) parentsResult[2]; + typeResolutionNeeded = typeAndPluginCnt > 1; + pluginResolutionNeeded = typeAndPluginCnt > typeCnt; + parentResolutionNeeded = disambiguationLevel > 0; + + //k, now let's construct the JPQL query to get the parents and type infos... + StringBuilder selectBuilder = new StringBuilder( + "SELECT r0.id, r0.resourceType.name, r0.resourceType.plugin"); + StringBuilder fromBuilder = new StringBuilder("FROM Resource r0");
for (i = 1; i <= disambiguationLevel; ++i) { - Integer parentId = (Integer) parentsResult[2 * i + 1]; - if (parentId == null) - break; - String parentName = (String) parentsResult[2 * i + 2]; - parents.add(new ResourceParentFlyweight(parentId, parentName)); + int pi = i - 1; + selectBuilder.append(", r").append(i).append(".id"); + selectBuilder.append(", r").append(i).append(".name"); + fromBuilder.append(" left join r").append(pi).append(".parentResource r").append(i); } - MutableDisambiguationReport<T> report = reportByResourceId.get(resourceId); - report.typeName = typeName; - report.pluginName = pluginName; - report.parents = parents; - }
- //now we have all the information to create the result. - //first create the immutable reports. - List<DisambiguationReport<T>> resolution = new ArrayList<DisambiguationReport<T>>(results.size()); + fromBuilder.append(" WHERE r0.id IN (:resourceIds)");
- for(T result : results) { - int resourceId = extractor.extract(result); - if (resourceId > 0) { + Query parentsQuery = entityManager.createQuery(selectBuilder.append(" ").append(fromBuilder).toString()); + + parentsQuery.setParameter("resourceIds", reportByResourceId.keySet()); + + @SuppressWarnings("unchecked") + List<Object[]> parentsResults = (List<Object[]>) parentsQuery.getResultList(); + for (Object[] parentsResult : parentsResults) { + List<ResourceParentFlyweight> parents = new ArrayList<ResourceParentFlyweight>(disambiguationLevel); + Integer resourceId = (Integer) parentsResult[0]; + String typeName = (String) parentsResult[1]; + String pluginName = (String) parentsResult[2]; + + for (i = 1; i <= disambiguationLevel; ++i) { + Integer parentId = (Integer) parentsResult[2 * i + 1]; + if (parentId == null) + break; + String parentName = (String) parentsResult[2 * i + 2]; + parents.add(new ResourceParentFlyweight(parentId, parentName)); + } MutableDisambiguationReport<T> report = reportByResourceId.get(resourceId); - resolution.add(report.getReport()); - } else { - //this result doesn't correspond to any resource, need to handle it specially - DisambiguationReport<T> report = new DisambiguationReport<T>(result, Collections.<ResourceParentFlyweight>emptyList(), null, null); - resolution.add(report); + report.typeName = typeName; + report.pluginName = pluginName; + report.parents = parents; + } + + //now we have all the information to create the result. + for (T result : results) { + int resourceId = extractor.extract(result); + if (resourceId > 0) { + //this results was disambiguated by the query above... + MutableDisambiguationReport<T> report = reportByResourceId.get(resourceId); + resolution.add(report.getReport()); + } else { + //this result doesn't correspond to any resource, need to handle it specially + DisambiguationReport<T> report = new DisambiguationReport<T>(result, Collections + .<ResourceParentFlyweight> emptyList(), null, null); + resolution.add(report); + } } }
commit 2b28eb953aad5656ce7c7ecf6eaf029e767b27a9 Merge: 40bfa51... 7b5ccc1... Author: Heiko W. Rupp hwr@redhat.com Date: Wed Feb 24 13:48:36 2010 +0100
Merge branch 'master' into alertPlugin
commit 40bfa515fa1c5dcc785e80597505f43866dd399c Author: Heiko W. Rupp hwr@redhat.com Date: Wed Feb 24 13:46:00 2010 +0100
Provide an internal cleanup method that is called when the notification is deleted. This way, the backing bean can do some housekeeping if needed.
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 dfa59f3..0896c6e 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 @@ -41,7 +41,6 @@ import org.rhq.core.domain.alert.notification.AlertNotification; import org.rhq.core.domain.alert.notification.NotificationTemplate; 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.configuration.Configuration; import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; import org.rhq.core.domain.plugin.PluginKey; @@ -154,6 +153,18 @@ public class AlertNotificationManagerBean implements AlertNotificationManagerLoc } }
+ // Before we delete the notification, check if has a custom backing bean + // and give it the possibility to clean up + for (AlertNotification notification : toBeRemoved) { + CustomAlertSenderBackingBean bb = getBackingBeanForSender(notification.getSenderName(),notification.getId()); + try { + bb.internalCleanup(); + } + catch (Throwable t ) { + LOG.error("removeNotifications, calling backingBean.internalCleanup() resulted in " + t.getMessage()); + } + } + alertDefinition.getAlertNotifications().removeAll(toBeRemoved);
postProcessAlertDefinition(alertDefinition); 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 5b39eae..e4b2d20 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 @@ -44,7 +44,7 @@ public class CustomAlertSenderBackingBean { * This method is called when the alert notification that uses this backing bean * is removed, so that the backing bean can do some cleanup work */ - protected void cleanup() {} + public void internalCleanup() {}
/** * Persist the passed configuration object. This can be a new object or one 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 2a3b635..98fa0e9 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.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -71,6 +72,17 @@ public class OperationsBackingBean extends CustomAlertSenderBackingBean { log.info("init"); }
+ @Override + public void internalCleanup() { + PropertySimple parameterConfigProp = alertParameters.getSimple(OperationsSender.PARAMETERS_CONFIG); + if (parameterConfigProp!=null) { + Integer paramId = parameterConfigProp.getIntegerValue(); + if (paramId!=null) { + ConfigurationManagerLocal cmgr = LookupUtil.getConfigurationManager(); + cmgr.deleteConfigurations(Arrays.asList(paramId)); + } + } + }
public String selectResource() {
commit 780776f1eaf8067d86fa2ca45354fc5686f9d9c5 Author: Heiko W. Rupp hwr@redhat.com Date: Wed Feb 24 13:33:37 2010 +0100
Add a link to re-enable the definition on the detail page. Alternate solution to BZ 535889
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/ReenableAlertDefinitionAction.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/ReenableAlertDefinitionAction.java new file mode 100644 index 0000000..265db09 --- /dev/null +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/ReenableAlertDefinitionAction.java @@ -0,0 +1,80 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.legacy.action.resource.common.monitor.alerts; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +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.rhq.core.domain.auth.Subject; +import org.rhq.enterprise.gui.legacy.action.BaseAction; +import org.rhq.enterprise.gui.legacy.util.RequestUtils; +import org.rhq.enterprise.server.alert.AlertDefinitionManagerLocal; +import org.rhq.enterprise.server.alert.AlertManagerLocal; +import org.rhq.enterprise.server.util.LookupUtil; + +/** + * Struts action to re-enable an alert definition from the + * AlertdefinitionActive.jsp tile, that gets included from + * ViewAlertProperties.jsp + * @author Heiko W. Rupp + */ +public class ReenableAlertDefinitionAction extends BaseAction { + + private final Log log = LogFactory.getLog(ReenableAlertDefinitionAction.class); + + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + Subject subject = RequestUtils.getSubject(request); + AlertDefinitionManagerLocal alertDefinitionManager = LookupUtil.getAlertDefinitionManager(); + + Map<String,Object> params = new HashMap<String,Object>(4); + // pass-through the alertId and resource id + Integer alertId = new Integer(request.getParameter("a")); + request.setAttribute("a", alertId); + params.put("a",alertId); + + Integer alertDefId = new Integer(request.getParameter("ad")); + request.setAttribute("ad", alertDefId); + params.put("ad",alertDefId); + + Integer resourceId = new Integer(request.getParameter("id")); + request.setAttribute("id",resourceId); + params.put("id",resourceId); + + String mode = request.getParameter("mode"); + request.setAttribute("mode",mode); + params.put("mode",mode); + + alertDefinitionManager.enableAlertDefinitions(subject, new Integer[]{alertDefId}); + + log.debug("Reenabled Alert definition with id " + alertId + " and user " + subject.getName()); + + return returnSuccess(request,mapping,params); + } +} diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/struts-config.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/struts-config.xml index a4c1b31..76321ce 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/struts-config.xml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/struts-config.xml @@ -2563,9 +2563,13 @@ scope="request" type="org.rhq.enterprise.gui.legacy.action.resource.common.monitor.alerts.AckAlertAction"> <set-property property="title" value="View+Alert"/> - <exception key="exception.AlertNotFoundException" - type="org.rhq.enterprise.server.legacy.events.AlertNotFoundException" - path="/common/GenericError.jsp"/> + <forward name="success" path="/alerts/Alerts.do" redirect="true" /> + </action> + + <action path="/alerts/RenableAlertDefinition" + scope="request" + type="org.rhq.enterprise.gui.legacy.action.resource.common.monitor.alerts.ReenableAlertDefinitionAction"> + <set-property property="title" value="View+Alert"/> <forward name="success" path="/alerts/Alerts.do" redirect="true" /> </action>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/config/AlertDefinitionActive.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/config/AlertDefinitionActive.jsp index 6affcc2..ed6b4fa 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/config/AlertDefinitionActive.jsp +++ b/modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/config/AlertDefinitionActive.jsp @@ -14,10 +14,14 @@ <fmt:message key="alert.config.props.PB.ActiveYes"/> </td> </c:when> - <c:otherwise> + <c:otherwise> <td width="30%" class="BlockContent"> - <html:img page="/images/icon_available_red.gif" width="12" height="12" border="0"/> - <fmt:message key="alert.config.props.PB.ActiveNo"/> + <html:img page="/images/icon_available_red.gif" width="12" height="12" border="0"/> + <fmt:message key="alert.config.props.PB.ActiveNo"/> + + <c:if test="${not alertDef.deleted}"> + <a href="/alerts/RenableAlertDefinition.do?id=${Resource.id}&a=${alert.id}&mode=${param.mode}&ad=${alertDef.id}">click to re-enable</a> + </c:if> </td> </c:otherwise> </c:choose>
commit 7b5ccc130607114a539bae8a97e7b097e7edc1ba Author: Lukas Krejci lkrejci@redhat.com Date: Wed Feb 24 13:27:56 2010 +0100
BZ 567925 - a follow up to my previous commit should finally fix the issue.
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java index 54cebf6..b0db81c 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerBean.java @@ -2204,7 +2204,10 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage for (T r : results) { MutableDisambiguationReport<T> value = new MutableDisambiguationReport<T>(); value.original = r; - reportByResourceId.put(extractor.extract(r), value); + int resourceId = extractor.extract(r); + if (resourceId > 0) { + reportByResourceId.put(resourceId, value); + } }
//k, now let's construct the JPQL query to get the parents and type infos... @@ -2247,10 +2250,18 @@ public class ResourceManagerBean implements ResourceManagerLocal, ResourceManage
//now we have all the information to create the result. //first create the immutable reports. - List<DisambiguationReport<T>> resolution = new ArrayList<DisambiguationReport<T>>(reportByResourceId.size()); + List<DisambiguationReport<T>> resolution = new ArrayList<DisambiguationReport<T>>(results.size());
- for (Map.Entry<Integer, MutableDisambiguationReport<T>> entry : reportByResourceId.entrySet()) { - resolution.add(entry.getValue().getReport()); + for(T result : results) { + int resourceId = extractor.extract(result); + if (resourceId > 0) { + MutableDisambiguationReport<T> report = reportByResourceId.get(resourceId); + resolution.add(report.getReport()); + } else { + //this result doesn't correspond to any resource, need to handle it specially + DisambiguationReport<T> report = new DisambiguationReport<T>(result, Collections.<ResourceParentFlyweight>emptyList(), null, null); + resolution.add(report); + } }
return new ResourceNamesDisambiguationResult<T>(resolution, typeResolutionNeeded, parentResolutionNeeded, diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java index 2c99c9d..6db6155 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/resource/ResourceManagerLocal.java @@ -36,6 +36,7 @@ import org.rhq.core.domain.resource.ResourceCategory; import org.rhq.core.domain.resource.ResourceError; import org.rhq.core.domain.resource.ResourceErrorType; import org.rhq.core.domain.resource.ResourceType; +import org.rhq.core.domain.resource.composite.DisambiguationReport; import org.rhq.core.domain.resource.composite.RecentlyAddedResourceComposite; import org.rhq.core.domain.resource.composite.ResourceAvailabilitySummary; import org.rhq.core.domain.resource.composite.ResourceComposite; @@ -449,7 +450,12 @@ public interface ResourceManagerLocal { * The disambiguation result contains information on what types of information are needed to make the resources * in the original result unambiguous and contains the decorated original data in the same order as the * supplied result list. - * + * <p> + * The objects in results do not necessarily need to correspond to a resource. In case of such objects, + * the resourceIdExtractor should return 0. In the resulting report such objects will still be wrapped + * in a {@link DisambiguationReport} but the parent list will be empty and resource type and plugin name will + * be null. + * * @see ResourceNamesDisambiguationResult * * @param <T> the type of the result elements
commit ee6254859736c4b3447259517988e6ffe57e4cc8 Author: Lukas Krejci lkrejci@redhat.com Date: Wed Feb 24 12:33:52 2010 +0100
Fixing an NPE on alert definitions subsystem page caused by alert defs without an attached resource.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/subsystem/SubsystemAlertDefinitionUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/subsystem/SubsystemAlertDefinitionUIBean.java index 4d656b5..5831f3e 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/subsystem/SubsystemAlertDefinitionUIBean.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/subsystem/SubsystemAlertDefinitionUIBean.java @@ -34,6 +34,7 @@ import org.rhq.core.domain.alert.AlertCondition; import org.rhq.core.domain.alert.AlertConditionCategory; import org.rhq.core.domain.alert.composite.AlertDefinitionComposite; import org.rhq.core.domain.auth.Subject; +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.gui.util.FacesContextUtility; @@ -74,7 +75,8 @@ public class SubsystemAlertDefinitionUIBean extends SubsystemView { private IntExtractor<AlertDefinitionComposite> RESOURCE_ID_EXTRACTOR = new IntExtractor<AlertDefinitionComposite>() {
public int extract(AlertDefinitionComposite object) { - return object.getAlertDefinition().getResource().getId(); + Resource resource = object.getAlertDefinition().getResource(); + return resource == null ? 0 : resource.getId(); } };
commit dbbfa75ddfa4ce4443f2f72df49b483970ea4e8c Author: Justin Harris jharris@redhat.com Date: Tue Feb 23 16:54:51 2010 -0500
Adding in validation rules and messaging for the alert conditions page.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionCategory.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionCategory.java index b304f29..531857b 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionCategory.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/AlertConditionCategory.java @@ -60,6 +60,10 @@ public enum AlertConditionCategory { return name(); }
+ public String getDisplayName() { + return displayName; + } + @Override public String toString() { return this.displayName; diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/OperationRequestStatus.java b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/OperationRequestStatus.java index cd0dcdb..bf816e8 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/operation/OperationRequestStatus.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/operation/OperationRequestStatus.java @@ -38,6 +38,10 @@ public enum OperationRequestStatus { this.displayName = displayName; }
+ public String getDisplayName() { + return displayName; + } + public String toString() { return displayName; } diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionMessages.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionMessages.java new file mode 100644 index 0000000..62a6fc0 --- /dev/null +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionMessages.java @@ -0,0 +1,60 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.alert; + +import java.text.MessageFormat; +import java.util.Map; +import org.jboss.seam.ScopeType; +import org.jboss.seam.annotations.In; +import org.jboss.seam.annotations.Name; +import org.jboss.seam.annotations.Scope; + +@Scope(ScopeType.APPLICATION) +@Name("alertConditionMessages") +public class AlertConditionMessages { + + @In + private Map<String, String> messages; + + public String getThreshold() { + return translate("errors.double", "Threshold"); + } + + public String getPercentRange() { + return translate("errors.range", "Threshold", "0%", "1000%"); + } + + public String getDampeningCount() { + return translate("errors.integer", "Dampening Count"); + } + + public String getDampeningEvaluation() { + return translate("errors.integer", "Dampening Evaluations"); + } + + public String getTimePeriod() { + return translate("errors.integer", "Time Period"); + } + + private String translate(String key, Object... params) { + String message = messages.get(key); + + return MessageFormat.format(message, params); + } +} \ No newline at end of file diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionUIBean.java index 1d5fe02..f15e5de 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionUIBean.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionUIBean.java @@ -18,6 +18,7 @@ */ package org.rhq.enterprise.gui.alert;
+import java.util.Arrays; import java.util.EnumSet; import java.util.HashMap; import java.util.List; @@ -74,9 +75,9 @@ public class AlertConditionUIBean { private Map<String, String> conditionExpressions; private Map<String, String> availabilities; private Map<String, String> severities; - private Map<String, String> operationStatuses; private Map<String, String> comparators; private Map<String, String> baselines; + private Map<String, String> operationStatuses;
private Map<String, Integer> measurements; private Map<String, Integer> traits; diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionsUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionsUIBean.java index f3365f0..c32965d 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionsUIBean.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/AlertConditionsUIBean.java @@ -19,6 +19,7 @@ package org.rhq.enterprise.gui.alert;
import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -36,6 +37,7 @@ import org.jboss.seam.international.StatusMessage.Severity; import org.jboss.seam.log.Log; import org.rhq.core.domain.alert.AlertCondition; import org.rhq.core.domain.alert.AlertConditionCategory; +import org.rhq.core.domain.alert.AlertDampening; import org.rhq.core.domain.alert.AlertDefinition; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.measurement.MeasurementDefinition; @@ -70,7 +72,7 @@ public class AlertConditionsUIBean { @In private AlertDescriber alertDescriber; private MetricAbsoluteConverter metricAbsoluteConverter = new MetricAbsoluteConverter(); - private Map<AlertConditionCategory, String> categories; + private Map<String, String> categories; private List<ConditionDescription> conditionDescriptions; private AlertCondition currentCondition;
@@ -86,11 +88,19 @@ public class AlertConditionsUIBean { }
public String getMeasurementDefinitionId() { - return measurementDefinitionId.toString(); + if (this.measurementDefinitionId != null) { + return measurementDefinitionId.toString(); + } + + return null; }
public void setMeasurementDefinitionId(String measurementDefinitionId) { - this.measurementDefinitionId = Integer.parseInt(measurementDefinitionId); + try { + this.measurementDefinitionId = Integer.parseInt(measurementDefinitionId); + } catch (NumberFormatException e) { + this.measurementDefinitionId = null; + } }
public String getThreshold() { @@ -109,7 +119,7 @@ public class AlertConditionsUIBean { return conditionDescriptions; }
- public Map<AlertConditionCategory, String> getCategories() { + public Map<String, String> getCategories() { return categories; }
@@ -136,7 +146,10 @@ public class AlertConditionsUIBean { @Create public void init() { this.conditionDescriptions = createDescriptions(); - this.categories = createCategoryMap(); + this.categories = createCategories(); + + // start out with an empty condition + createCondition(); }
private List<ConditionDescription> createDescriptions() { @@ -183,6 +196,10 @@ public class AlertConditionsUIBean { }
public String saveAlertDefinition() { + if (!validateDefinition()) { + return null; + } + alertDefinition.setConditions(findConditions());
try { @@ -198,12 +215,16 @@ public class AlertConditionsUIBean { }
public String newAlertDefinition() { + if (!validateDefinition()) { + return null; + } + alertDefinition.setConditions(findConditions());
try { alertDefinitionManager.createAlertDefinition(subject, alertDefinition, resourceId); } catch(Exception e) { - this.facesMessages.add(Severity.ERROR, "There was an error creating the alert definitino."); + this.facesMessages.add(Severity.ERROR, "There was an error creating the alert definition."); this.log.error("Error persisting AlertDefinition: " + alertDefinition.getName(), e);
return null; @@ -212,6 +233,28 @@ public class AlertConditionsUIBean { return SUCCESS_OUTCOME; }
+ private boolean validateDefinition() { + Set<AlertCondition> conditions = findConditions(); + + if (conditions.isEmpty()) { + this.facesMessages.add(Severity.ERROR, "Please add at least one condition."); + + return false; + } + + AlertDampening dampening = alertDefinition.getAlertDampening(); + + if (dampening.getCategory() == AlertDampening.Category.PARTIAL_COUNT) { + if (dampening.getValue() > dampening.getPeriod()) { + this.facesMessages.addFromResourceBundle(Severity.ERROR, "alert.config.error.PartialCountRangeTooSmall"); + + return false; + } + } + + return true; + } + private boolean shouldSetMeasurementDefinition() { if (currentCondition != null) { AlertConditionCategory category = currentCondition.getCategory(); @@ -245,17 +288,17 @@ public class AlertConditionsUIBean { return conditionSet; }
- private Map<AlertConditionCategory, String> createCategoryMap() { - Map<AlertConditionCategory, String> categoryMap = new HashMap<AlertConditionCategory, String>(); + private Map<String, String> createCategories() { + Map<String, String> categoryMap = new HashMap<String, String>(); + List<AlertConditionCategory> categoryList = new ArrayList(Arrays.asList(AlertConditionCategory.values())); + categoryList.remove(AlertConditionCategory.ALERT);
- for (AlertConditionCategory category : AlertConditionCategory.values()) { - categoryMap.put(category, category.getName()); + if (configurationManager.getResourceConfigurationDefinitionForResourceType(subject, resourceType.getId()) == null) { + categoryList.remove(AlertConditionCategory.RESOURCE_CONFIG); }
- categoryMap.remove(AlertConditionCategory.ALERT); - - if (configurationManager.getResourceConfigurationDefinitionForResourceType(subject, resourceType.getId()) == null) { - categoryMap.remove(AlertConditionCategory.RESOURCE_CONFIG); + for (AlertConditionCategory category : categoryList) { + categoryMap.put(category.toString(), category.getName()); }
return categoryMap; diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/converter/MetricPercentConverter.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/converter/MetricPercentConverter.java index eec5333..19dae93 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/converter/MetricPercentConverter.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/converter/MetricPercentConverter.java @@ -30,6 +30,7 @@ import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.faces.Converter; import org.rhq.core.domain.measurement.MeasurementUnits; import org.rhq.core.domain.measurement.composite.MeasurementNumericValueAndUnits; +import org.rhq.core.domain.measurement.util.MeasurementConversionException; import org.rhq.core.domain.measurement.util.MeasurementConverter;
@Converter @@ -38,9 +39,13 @@ import org.rhq.core.domain.measurement.util.MeasurementConverter; public class MetricPercentConverter implements javax.faces.convert.Converter {
public Object getAsObject(FacesContext context, UIComponent component, String value) { - MeasurementNumericValueAndUnits percentage = MeasurementConverter.parse(value, MeasurementUnits.PERCENTAGE); + try { + MeasurementNumericValueAndUnits percentage = MeasurementConverter.parse(value, MeasurementUnits.PERCENTAGE);
- return percentage.getValue(); + return percentage.getValue(); + } catch (MeasurementConversionException e) { + return null; + } }
public String getAsString(FacesContext context, UIComponent component, Object value) { diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/validator/AlertValidatorUtil.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/validator/AlertValidatorUtil.java new file mode 100644 index 0000000..d8f142c --- /dev/null +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/validator/AlertValidatorUtil.java @@ -0,0 +1,45 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.alert.validator; + +import javax.faces.application.FacesMessage; +import javax.faces.validator.ValidatorException; +import org.jboss.seam.ScopeType; +import org.jboss.seam.annotations.AutoCreate; +import org.jboss.seam.annotations.Name; +import org.jboss.seam.annotations.Scope; +import org.jboss.seam.faces.FacesMessages; + +@AutoCreate +@Scope(ScopeType.APPLICATION) +@Name("validatorUtil") +public class AlertValidatorUtil { + + public void error(String message) throws ValidatorException { + FacesMessage facesMessage = FacesMessages.createFacesMessage(FacesMessage.SEVERITY_ERROR , message); + + throw new ValidatorException(facesMessage); + } + + public void templateError(String key, Object... params) throws ValidatorException { + FacesMessage facesMessage = FacesMessages.createFacesMessage(FacesMessage.SEVERITY_ERROR , key, key, params); + + throw new ValidatorException(facesMessage); + } +} \ No newline at end of file diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/validator/EventRegexValidator.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/validator/EventRegexValidator.java new file mode 100644 index 0000000..e4831d4 --- /dev/null +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/validator/EventRegexValidator.java @@ -0,0 +1,48 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.alert.validator; + +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; +import javax.faces.component.UIComponent; +import javax.faces.context.FacesContext; +import javax.faces.validator.ValidatorException; +import org.jboss.seam.annotations.In; +import org.jboss.seam.annotations.Name; +import org.jboss.seam.annotations.faces.Validator; + +@Name("eventRegexValidator") +@Validator +public class EventRegexValidator implements javax.faces.validator.Validator { + + @In + private AlertValidatorUtil validatorUtil; + + public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException { + String stringValue = (String)value; + + if (stringValue != null && stringValue.length() > 0) { + try { + Pattern.compile(stringValue); + } catch (PatternSyntaxException e) { + validatorUtil.templateError("alert.config.error.InvalidEventDetails"); + } + } + } +} \ No newline at end of file diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listConditions.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listConditions.xhtml index 24a0bdf..a5500e4 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listConditions.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/listConditions.xhtml @@ -35,7 +35,16 @@ </ui:define>
<ui:define name="body"> - <a4j:form id="alertConditionsForm"> + + <rich:messages showSummary="true" + infoClass="InfoBlock" + warnClass="WarnBlock" + errorClass="ErrorBlock" + fatalClass="FatalBlock" + layout="table" + width="100%" /> + + <h:form id="alertConditionsForm"> <ui:insert name="formTop" />
<rich:panel id="conditionsPanel"> @@ -44,11 +53,11 @@ </f:facet>
<rich:panel id="conditionExpression"> - <h:outputText value="#{messages['alert.config.props.CB.ExpressionDetails.1']} " /> - <h:selectOneMenu value="#{alertDefinition.conditionExpression}"> - <f:selectItems value="#{alertConditionUIBean.conditionExpressions}" /> - </h:selectOneMenu> - <h:outputText value=" #{messages['alert.config.props.CB.ExpressionDetails.2']}" /> + <h:outputText value="#{messages['alert.config.props.CB.ExpressionDetails.1']} " /> + <h:selectOneMenu value="#{alertDefinition.conditionExpression}"> + <f:selectItems value="#{alertConditionUIBean.conditionExpressions}" /> + </h:selectOneMenu> + <h:outputText value=" #{messages['alert.config.props.CB.ExpressionDetails.2']}" /> </rich:panel>
<rich:panel id="conditionSet"> @@ -56,8 +65,6 @@ <h:outputText value="Condition Set"/> </f:facet>
- <h:messages /> - <rich:dataTable id="categoryTable" value="#{alertConditionsUIBean.conditionDescriptions}" var="conditionDescription"> rich:column <h:outputText value="#{conditionDescription.description}" /> @@ -71,6 +78,7 @@
<f:setPropertyActionListener value="#{conditionDescription.condition}" target="#{alertConditionsUIBean.currentCondition}" /> <rich:componentControl for="categoryModalPanel" attachTo="editButton" operation="show" event="onclick" /> + <a4j:support event="onclick" reRender="categoryOptionOkButton" /> </a4j:commandButton> </rich:column>
@@ -93,7 +101,7 @@ action="#{alertConditionsUIBean.createCondition}" styleClass="buttonmed"> <rich:componentControl for="categoryModalPanel" attachTo="addConditionButton" operation="show" event="onclick" /> - <a4j:support event="onclick" reRender="categoryOptionsPanel" /> + <a4j:support event="onclick" reRender="categoryOptionsPanel,categoryOptionOkButton" /> </a4j:commandButton>
</rich:panel> @@ -107,13 +115,20 @@ <h:outputText value="#{messages['alert.config.props.CB.Recovery']} " /> <h:outputText value="#{messages['alert.config.props.CB.RecoveryFor']}" />
- <h:selectOneMenu value="#{alertDefinition.recoveryId}"> + <h:selectOneMenu id="recoveryForAlertSelectBox" + value="#{alertDefinition.recoveryId}" + disabled="#{alertDefinition.willRecover}"> <f:selectItem itemLabel="#{messages['alert.dropdown.SelectOption']}" itemValue="0" /> <f:selectItems value="#{alertConditionUIBean.existingAlerts}" /> + <a4j:support event="onchange" reRender="willRecoverCheckbox" /> </h:selectOneMenu> <br />
- <h:selectBooleanCheckbox id="willRecoverCheckbox" value="#{alertDefinition.willRecover}" /> + <h:selectBooleanCheckbox id="willRecoverCheckbox" + value="#{alertDefinition.willRecover}" + disabled="#{alertDefinition.recoveryId != 0}"> + <a4j:support event="onchange" reRender="recoveryForAlertSelectBox" /> + </h:selectBooleanCheckbox> <h:outputLabel for="willRecoverCheckbox" value="#{messages['alert.config.props.CB.Content.UntilRecovered']}" />
<br /> @@ -151,28 +166,63 @@
<ui:fragment rendered="#{alertDefinition.alertDampening.category == 'CONSECUTIVE_COUNT'}"> <h:outputText value="#{messages['alert.config.props.CB.Content.DampenConsecutiveCount.1']} " /> - <h:inputText value="#{alertDefinition.alertDampening.value}" - required="true" - maxlength="5"/> + <h:inputText id="consecutiveCount" + value="#{alertDefinition.alertDampening.value}" + size="4" + required="true" + requiredMessage="#{alertConditionMessages.dampeningCount}" + validatorMessage="#{alertConditionMessages.dampeningCount}" + converterMessage="#{alertConditionMessages.dampeningCount}"> + <f:validateDoubleRange minimum="0" /> + </h:inputText> <h:outputText value=" #{messages['alert.config.props.CB.Content.DampenConsecutiveCount.2']}" /> </ui:fragment>
<ui:fragment rendered="#{alertDefinition.alertDampening.category == 'PARTIAL_COUNT'}"> <h:outputText value="#{messages['alert.config.props.CB.Content.DampenPartialCount.1']} " /> - <h:inputText value="#{alertDefinition.alertDampening.value}" - required="true" - maxlength="5"/> + <h:inputText id="partialCount" + value="#{alertDefinition.alertDampening.value}" + size="4" + required="true" + requiredMessage="#{alertConditionMessages.dampeningCount}" + validatorMessage="#{alertConditionMessages.dampeningCount}" + converterMessage="#{alertConditionMessages.dampeningCount}"> + <f:validateLongRange minimum="0" /> + </h:inputText> <h:outputText value=" #{messages['alert.config.props.CB.Content.DampenPartialCount.2']} " /> - <h:inputText value="#{alertDefinition.alertDampening.period}" /> + <h:inputText id="partialCountPeriod" + value="#{alertDefinition.alertDampening.period}" + size="4" + required="true" + requiredMessage="#{alertConditionMessages.dampeningEvaluation}" + validatorMessage="#{alertConditionMessages.dampeningEvaluation}" + converterMessage="#{alertConditionMessages.dampeningEvaluation}"> + <f:validateLongRange minimum="0" /> + </h:inputText> <h:outputText value=" #{messages['alert.config.props.CB.Content.DampenPartialCount.3']}" /> </ui:fragment>
<ui:fragment rendered="#{alertDefinition.alertDampening.category == 'DURATION_COUNT'}"> <h:outputText value="#{messages['alert.config.props.CB.Content.DampenDurationCount.1']} " /> - <h:inputText value="#{alertDefinition.alertDampening.value}" /> + <h:inputText id="durationCount" + value="#{alertDefinition.alertDampening.value}" + size="4" + required="true" + requiredMessage="#{alertConditionMessages.dampeningCount}" + validatorMessage="#{alertConditionMessages.dampeningCount}" + converterMessage="#{alertConditionMessages.dampeningCount}"> + <f:validateLongRange minimum="0" /> + </h:inputText> <h:outputText value=" #{messages['alert.config.props.CB.Content.DampenDurationCount.2']} " /> - <h:inputText value="#{alertDefinition.alertDampening.period}" /> - + <h:inputText id="durationCountPeriod" + value="#{alertDefinition.alertDampening.period}" + size="4" + required="true" + requiredMessage="#{alertConditionMessages.timePeriod}" + validatorMessage="#{alertConditionMessages.timePeriod}" + converterMessage="#{alertConditionMessages.timePeriod}"> + <f:validateLongRange minimum="0" /> + </h:inputText> <h:selectOneMenu value="#{alertDefinition.alertDampening.periodUnits}"> <f:selectItems value="#{alertConditionUIBean.timeUnits}" /> </h:selectOneMenu> @@ -190,7 +240,7 @@ styleClass="buttonmed" style="margin: 10px;" /> </ui:insert> - </a4j:form> + </h:form>
<rich:modalPanel id="categoryModalPanel" moveable="false" autosized="true" width="400">
@@ -199,8 +249,8 @@ <h:form id="categoryForm"> <h:selectOneMenu value="#{alertConditionsUIBean.currentCondition.category}"> <f:selectItem itemLabel="#{messages['alert.dropdown.SelectOption']}" /> - <s:selectItems value="#{alertConditionsUIBean.categories}" /> - <a4j:support event="onchange" reRender="categoryOptions" status="categoryLoadStatus" /> + <f:selectItems value="#{alertConditionsUIBean.categories}" /> + <a4j:support event="onchange" reRender="EditConditionForm" status="categoryLoadStatus" /> </h:selectOneMenu> </h:form>
@@ -221,14 +271,20 @@ <ui:fragment rendered="#{alertConditionsUIBean.currentCondition.category == 'CONTROL'}"> <h:outputLabel for="operationSelection" value="#{messages['alert.config.props.CB.Content.ControlAction']} " />
- <h:selectOneMenu id="operationSelection" value="#{alertConditionsUIBean.currentCondition.name}"> + <h:selectOneMenu id="operationSelection" + value="#{alertConditionsUIBean.currentCondition.name}" + required="true" + requiredMessage="#{messages['alert.config.error.NoControlActionSelected']}"> <f:selectItem itemLabel="#{messages['alert.dropdown.SelectOption']}" /> <f:selectItems value="#{alertConditionUIBean.operations}" /> </h:selectOneMenu>
<h:outputText value=" #{messages['alert.config.props.CB.Content.Comparator.=']} " />
- <h:selectOneMenu id="operationStatusSelection" value="#{alertConditionsUIBean.currentCondition.option}"> + <h:selectOneMenu id="operationStatusSelection" + value="#{alertConditionsUIBean.currentCondition.option}" + required="true" + requiredMessage="#{messages['alert.config.error.NoControlActionStatusSelected']}"> <f:selectItem itemLabel="#{messages['alert.dropdown.SelectOption']}" /> <f:selectItems value="#{alertConditionUIBean.operationStatuses}" /> </h:selectOneMenu> @@ -238,7 +294,10 @@ <ui:fragment rendered="#{alertConditionsUIBean.currentCondition.category == 'AVAILABILITY'}"> <h:outputLabel for="availabilitySelection" value="#{messages['alert.config.props.CB.Content.Availability']} " />
- <h:selectOneMenu id="availabilitySelection" value="#{alertConditionsUIBean.currentCondition.option}"> + <h:selectOneMenu id="availabilitySelection" + value="#{alertConditionsUIBean.currentCondition.option}" + required="true" + requiredMessage="#{messages['alert.config.error.NoAvailabilityStatusSelected']}"> <f:selectItem itemLabel="#{messages['alert.dropdown.SelectOption']}" /> <f:selectItems value="#{alertConditionUIBean.availabilities}" /> </h:selectOneMenu> @@ -248,7 +307,10 @@ <ui:fragment rendered="#{alertConditionsUIBean.currentCondition.category == 'CHANGE'}"> <h:outputLabel for="metricChangeSelection" value="#{messages['alert.config.props.CB.Content.Metric']} " />
- <h:selectOneMenu id="metricChangeSelection" value="#{alertConditionsUIBean.measurementDefinitionId}"> + <h:selectOneMenu id="metricChangeSelection" + value="#{alertConditionsUIBean.measurementDefinitionId}" + required="true" + requiredMessage="#{messages['alert.config.error.NoMetricSelected']}"> <f:selectItem itemLabel="#{messages['alert.dropdown.SelectOption']}" /> <f:selectItems value="#{alertConditionUIBean.measurements}" /> </h:selectOneMenu> @@ -260,7 +322,10 @@ <ui:fragment rendered="#{alertConditionsUIBean.currentCondition.category == 'THRESHOLD'}"> <h:outputLabel for="metricThresholdSelection" value="#{messages['alert.config.props.CB.Content.Metric']}" />
- <h:selectOneMenu id="metricThresholdSelection" value="#{alertConditionsUIBean.measurementDefinitionId}"> + <h:selectOneMenu id="metricThresholdSelection" + value="#{alertConditionsUIBean.measurementDefinitionId}" + required="true" + requiredMessage="#{messages['alert.config.error.NoMetricSelected']}"> <f:selectItem itemLabel="#{messages['alert.dropdown.SelectOption']}" /> <f:selectItems value="#{alertConditionUIBean.measurements}" /> </h:selectOneMenu> @@ -273,14 +338,23 @@ <br /> <br />
- <h:inputText id="metricThresholdAbsolute" value="#{alertConditionsUIBean.threshold}" /> + <h:inputText id="metricThresholdAbsolute" + value="#{alertConditionsUIBean.threshold}" + required="true" + requiredMessage="#{alertConditionMessages.threshold}" + validatorMessage="#{alertConditionMessages.threshold}"> + <f:validateDoubleRange minimum="0.0" /> + </h:inputText> <h:outputLabel for="metricThresholdAbsolute" value="#{messages['alert.config.props.CB.Content.AbsoluteValue']}" /> </ui:fragment>
<ui:fragment rendered="#{alertConditionsUIBean.currentCondition.category == 'BASELINE'}"> <h:outputLabel for="metricBaselineSelection" value="#{messages['alert.config.props.CB.Content.Metric']} " />
- <h:selectOneMenu id="metricBaselineSelection" value="#{alertConditionsUIBean.measurementDefinitionId}"> + <h:selectOneMenu id="metricBaselineSelection" + value="#{alertConditionsUIBean.measurementDefinitionId}" + required="true" + requiredMessage="#{messages['alert.config.error.NoMetricSelected']}"> <f:selectItem itemLabel="#{messages['alert.dropdown.SelectOption']}" /> <f:selectItems value="#{alertConditionUIBean.measurements}" /> </h:selectOneMenu> @@ -293,10 +367,20 @@ <br /> <br />
- <h:inputText id="metricBaselinePercent" value="#{alertConditionsUIBean.currentCondition.threshold}" converter="#{metricPercentConverter}" /> + <h:inputText id="metricBaselinePercent" + value="#{alertConditionsUIBean.currentCondition.threshold}" + converter="#{metricPercentConverter}" + required="true" + requiredMessage="#{alertConditionMessages.percentRange}" + validatorMessage="#{alertConditionMessages.percentRange}"> + <f:validateDoubleRange minimum="0.0" maximum="1000.0" /> + </h:inputText> <h:outputLabel for="metricBaselinePercent" value=" #{messages['alert.config.props.CB.Content.Percent']} " />
- <h:selectOneMenu id="metricBaselineBaselineSelection" value="#{alertConditionsUIBean.currentCondition.option}"> + <h:selectOneMenu id="metricBaselineBaselineSelection" + value="#{alertConditionsUIBean.currentCondition.option}" + required="true" + requiredMessage="#{messages['alert.config.error.NoBaselineOptionSelected']}"> <f:selectItems value="#{alertConditionUIBean.baselines}" /> </h:selectOneMenu> </ui:fragment> @@ -305,20 +389,29 @@ <ui:fragment rendered="#{alertConditionsUIBean.currentCondition.category == 'EVENT'}"> <h:outputLabel for="eventSelection" value="#{messages['alert.config.props.CB.Content.EventSeverity']} " />
- <h:selectOneMenu id="eventSelection" value="#{alertConditionsUIBean.currentCondition.name}"> + <h:selectOneMenu id="eventSelection" + value="#{alertConditionsUIBean.currentCondition.name}" + required="true" + requiredMessage="#{messages['alert.config.error.NoEventSeveritySelected']}"> <f:selectItem itemLabel="#{messages['alert.dropdown.SelectOption']}" /> <f:selectItems value="#{alertConditionUIBean.severities}" /> </h:selectOneMenu>
<h:outputText value=" #{messages['alert.config.props.CB.Content.Match']}" /> - <h:inputText id="eventExpression" value="#{alertConditionsUIBean.currentCondition.option}" /> + <h:inputText id="eventExpression" + value="#{alertConditionsUIBean.currentCondition.option}"> + <f:validator validatorId="eventRegexValidator" /> + </h:inputText> </ui:fragment>
<ui:fragment rendered="#{alertConditionsUIBean.currentCondition.category == 'TRAIT'}"> <h:outputLabel for="traitSelection" value="#{messages['alert.config.props.CB.Content.Trait']} " />
- <h:selectOneMenu id="traitSelection" value="#{alertConditionsUIBean.measurementDefinitionId}"> + <h:selectOneMenu id="traitSelection" + value="#{alertConditionsUIBean.measurementDefinitionId}" + required="true" + requiredMessage="#{messages['alert.config.error.NoTraitSelected']}"> <f:selectItem itemLabel="#{messages['alert.dropdown.SelectOption']}" /> <f:selectItems value="#{alertConditionUIBean.traits}" /> </h:selectOneMenu> @@ -335,10 +428,11 @@ </rich:panel>
<h:commandButton id="categoryOptionOkButton" - value="OK" - action="#{alertConditionsUIBean.updateCondition}" - styleClass="buttonmed" - style="margin: 5px;"> + value="OK" + rendered="#{not empty alertConditionsUIBean.currentCondition.category}" + action="#{alertConditionsUIBean.updateCondition}" + styleClass="buttonmed" + style="margin: 5px;"> <rich:componentControl for="categoryModalPanel" attachTo="categoryOptionOkButton" operation="hide" event="onclick" /> <a4j:support event="onclick" reRender="categoryTable" /> </h:commandButton>
commit e956b6f8b2608bc9d2941daba6e732caf4ad5715 Author: Heiko W. Rupp hwr@redhat.com Date: Tue Feb 23 22:25:45 2010 +0100
Introduce the possibility to ack an alert on the detail page. BZ 567383
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 new file mode 100644 index 0000000..6043d19 --- /dev/null +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/legacy/action/resource/common/monitor/alerts/AckAlertAction.java @@ -0,0 +1,78 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.gui.legacy.action.resource.common.monitor.alerts; + +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +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; +import org.rhq.enterprise.server.alert.AlertManagerLocal; +import org.rhq.enterprise.server.util.LookupUtil; + +/** + * Struts action to acknowledge one single alert from the + * ViewAlertProperties.jsp page + * @author Heiko W. Rupp + */ +public class AckAlertAction extends BaseAction { + + Log log = LogFactory.getLog(AckAlertAction.class); + + public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, + HttpServletResponse response) throws Exception { + + Subject subject = RequestUtils.getSubject(request); + AlertManagerLocal alertManager = LookupUtil.getAlertManager(); + + Map params = new HashMap(3); + // pass-through the alertId and resource id + Integer alertId = new Integer(request.getParameter("a")); + request.setAttribute("a", alertId); + params.put("a",alertId); + + Integer resourceId = new Integer(request.getParameter("id")); + request.setAttribute("id",resourceId); + params.put("id",resourceId); + + String mode = request.getParameter("mode"); + request.setAttribute("mode",mode); + params.put("mode",mode); + + alertManager.acknowledgeAlert(alertId,subject); + + log.debug("Acknowledged Alert with id " + alertId + " and user " + subject.getName()); + + return returnSuccess(request,mapping,params); + } + +} diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/struts-config.xml b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/struts-config.xml index 41da1ee..a4c1b31 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/struts-config.xml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/WEB-INF/struts-config.xml @@ -2559,6 +2559,16 @@ path="/common/GenericError.jsp"/> </action>
+ <action path="/alerts/AckAlert" + scope="request" + type="org.rhq.enterprise.gui.legacy.action.resource.common.monitor.alerts.AckAlertAction"> + <set-property property="title" value="View+Alert"/> + <exception key="exception.AlertNotFoundException" + type="org.rhq.enterprise.server.legacy.events.AlertNotFoundException" + path="/common/GenericError.jsp"/> + <forward name="success" path="/alerts/Alerts.do" redirect="true" /> + </action> + <action path="/alerts/ViewDefinition" scope="request" type="org.rhq.enterprise.gui.legacy.action.resource.common.monitor.alerts.config.ViewDefinitionAction"> diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/ViewAlertProperties.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/ViewAlertProperties.jsp index 1b1c04b..0b49ecb 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/ViewAlertProperties.jsp +++ b/modules/enterprise/gui/portal-war/src/main/webapp/resource/common/monitor/alerts/ViewAlertProperties.jsp @@ -39,26 +39,37 @@ <td class="BlockLabel"><fmt:message key="alert.current.detail.props.AlertDate"/></td> <td class="BlockContent" colspan="2"><hq:dateFormatter time="false" value="${alert.ctime}"/></td> </tr> - <tr valign="top"> - <td class="BlockLabel">Acknowledged by:</td> - <td class="BlockContent"> - <c:if test="${not empty alert.ackBy}"> - <c:out value="${alert.ackBy.firstName}"/> - <c:out value=" "/> - <c:out value="${alert.ackBy.lastName}"/> - <c:out value=" ("/> - <c:out value="${alert.ackBy.name}"/> - <c:out value=")"/> - </c:if> - </td> - <td class="BlockLabel">Acknowledged at:</td> - <td class="BlockContent"> - <c:if test="${alert.ackTime > 0}"> - <hq:dateFormatter time="false" value="${alert.ackTime}"/> - </c:if> + <c:choose> + <c:when test="${not empty alert.ackBy}"> + <tr valign="top"> + <td class="BlockLabel">Acknowledged by:</td> + <td class="BlockContent"> + <c:out value="${alert.ackBy.firstName}"/> + <c:out value=" "/> + <c:out value="${alert.ackBy.lastName}"/> + <c:out value=" ("/> + <c:out value="${alert.ackBy.name}"/> + <c:out value=")"/> + </td> + <td class="BlockLabel">Acknowledged at:</td> + <td class="BlockContent"> + <hq:dateFormatter time="false" value="${alert.ackTime}"/> + </td> + </tr> + </c:when> + <c:otherwise> + <tr valign="top"> + <td class="BlockLabel">Acknowledge Alert</td> + <td class="BlockContent"> + <a href="/alerts/AckAlert.do?id=${Resource.id}&a=${alert.id}&mode=${param.mode}">click here</a> + </td> + <td class="BlockContent"> </td> + <td class="BlockContent"> </td> + </tr>
- </td> - </tr> + </c:otherwise> + + </c:choose> <tr> <td colspan="5" class="BlockContent"><html:img page="/images/spacer.gif" width="1" height="1" border="0"/></td> </tr>
commit b22dc41c2c2251ee2c29387eabbdfbf9a616a41d Author: Heiko W. Rupp hwr@redhat.com Date: Tue Feb 23 16:20:56 2010 +0100
Add a new cleanup() method and some JavaDoc
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 72f6ec8..5b39eae 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 @@ -40,9 +40,24 @@ public class CustomAlertSenderBackingBean { public void setAlertParameters(Configuration alertParameters) { this.alertParameters = alertParameters; } + /** + * This method is called when the alert notification that uses this backing bean + * is removed, so that the backing bean can do some cleanup work + */ + protected void cleanup() {}
+ /** + * Persist the passed configuration object. This can be a new object or one + * that already exists in the database. If the input is null, not persistence + * happens and null is returned. + * @param config configuration to persist or update + * @return a merged copy of the configuration or null + */ protected Configuration persistConfiguration(Configuration config) {
+ if (config==null) + return null; + ConfigurationManagerLocal mgr = LookupUtil.getConfigurationManager(); config = mgr.mergeConfiguration(config);
@@ -50,6 +65,14 @@ public class CustomAlertSenderBackingBean {
}
+ /** + * Persist a single property of a given configuration. If the property does not yet exist, + * it is created otherwise overwritten with the new value. + * @param config configuration the property is on + * @param propertyName name of the property to persist + * @param value (new) value of the property to persist + * @return the updated configuration + */ protected Configuration persistProperty(Configuration config, String propertyName, Object value) {
PropertySimple prop = config.getSimple(propertyName); @@ -65,6 +88,12 @@ public class CustomAlertSenderBackingBean { return ret; }
+ /** + * Remove one property from the passed configuration. Returns the updated configuration + * @param config configuration the property is on + * @param propertyName name of the property to remove + * @return the updated configuration + */ protected Configuration cleanProperty(Configuration config, String propertyName) {
Configuration ret = config; @@ -76,4 +105,5 @@ public class CustomAlertSenderBackingBean {
return ret; } + }
commit 6c0f0ebe7f448eb3aec0acdf04f581146938f45a Merge: 354dd60... 59776e2... Author: Heiko W. Rupp hwr@redhat.com Date: Tue Feb 23 15:29:43 2010 +0100
Merge branch 'master' into alertPlugin
commit 354dd6076c8e6c700086c6472963924f35b8deb1 Author: Heiko W. Rupp hwr@redhat.com Date: Tue Feb 23 15:28:34 2010 +0100
Cleanup of variable names and obtain the right operation name.
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 deabeae..2a3b635 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 @@ -28,7 +28,6 @@ import org.apache.commons.logging.LogFactory; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.Create; import org.jboss.seam.annotations.Scope; -import org.jboss.seam.annotations.web.RequestParameter;
import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.configuration.Configuration; @@ -54,8 +53,8 @@ public class OperationsBackingBean extends CustomAlertSenderBackingBean { private String resMode; private String tokenMode; Integer resId; - private Integer operationName; - private Map<String, Integer> operationNames = new HashMap<String, Integer>(); + private Integer operationId; + private Map<String, Integer> operationIds = new HashMap<String, Integer>(); private String resourceName;
@@ -79,12 +78,12 @@ public class OperationsBackingBean extends CustomAlertSenderBackingBean {
if (resId != null) { persistProperty(alertParameters, OperationsSender.RESOURCE_ID,resId); - cleanProperty(alertParameters,OperationsSender.OPERATION_NAME); + cleanProperty(alertParameters,OperationsSender.OPERATION_ID); cleanProperty(alertParameters,OperationsSender.USABLE);
}
- obtainOperationNames(); + obtainOperationIds();
return ALERT_NOTIFICATIONS; } @@ -92,10 +91,10 @@ public class OperationsBackingBean extends CustomAlertSenderBackingBean {
public String selectOperation() { - log.info("In selectOperation, resId is " + resId + " opName is " + operationName); + log.info("In selectOperation, resId is " + resId + " opName is " + operationId);
- if (operationName != null ) { - persistProperty(alertParameters, OperationsSender.OPERATION_NAME,operationName); + if (operationId != null ) { + persistProperty(alertParameters, OperationsSender.OPERATION_ID, operationId); lookupConfiguration(); }
@@ -112,10 +111,10 @@ public class OperationsBackingBean extends CustomAlertSenderBackingBean {
// int operationId = Integer.valueOf(FacesContextUtility.getRequiredRequestParameter("opId")); OperationManagerLocal opMan = LookupUtil.getOperationManager(); - obtainOperationNames(); + obtainOperationIds();
- OperationDefinition operationDefinition = opMan.getOperationDefinition(subject, operationName); + OperationDefinition operationDefinition = opMan.getOperationDefinition(subject, operationId); configurationDefinition = operationDefinition.getParametersConfigurationDefinition();
@@ -140,7 +139,7 @@ log.info("gConfig: " + configuration + ", " + configuration.hashCode() + ", " + return ALERT_NOTIFICATIONS; }
- private void obtainOperationNames() { + private void obtainOperationIds() {
PropertySimple prop = alertParameters.getSimple(OperationsSender.RESOURCE_ID); if (prop!=null) @@ -152,7 +151,7 @@ log.info("gConfig: " + configuration + ", " + configuration.hashCode() + ", " + Subject subject = LookupUtil.getSubjectManager().getOverlord(); // TODO replace with real subject List<OperationDefinition> opDefs = opMan.findSupportedResourceOperations(subject, resId, false); for (OperationDefinition def : opDefs) { - operationNames.put(def.getDisplayName(),def.getId()); // TODO add more distinctive stuff in display + operationIds.put(def.getDisplayName(),def.getId()); // TODO add more distinctive stuff in display } } } @@ -205,30 +204,30 @@ log.info("gConfig: " + configuration + ", " + configuration.hashCode() + ", " + this.resourceName = resourceName; }
- public Integer getOperationName() { + public Integer getOperationId() {
- if (operationName==null) { - PropertySimple prop = alertParameters.getSimple(OperationsSender.OPERATION_NAME); + if (operationId ==null) { + PropertySimple prop = alertParameters.getSimple(OperationsSender.OPERATION_ID); if (prop!=null) - operationName = prop.getIntegerValue(); + operationId = prop.getIntegerValue(); }
- return operationName; + return operationId; }
- public void setOperationName(Integer operationName) { - this.operationName = operationName; + public void setOperationId(Integer operationId) { + this.operationId = operationId; }
- public Map<String, Integer> getOperationNames() { + public Map<String, Integer> getOperationIds() {
- obtainOperationNames(); + obtainOperationIds();
- return operationNames; + return operationIds; }
- public void setOperationNames(Map<String, Integer> operationNames) { - this.operationNames = operationNames; + public void setOperationIds(Map<String, Integer> operationIds) { + this.operationIds = operationIds; }
public ConfigurationDefinition getConfigurationDefinition() { @@ -239,15 +238,11 @@ log.info("gConfig: " + configuration + ", " + configuration.hashCode() + ", " + }
public void setConfigurationDefinition(ConfigurationDefinition configurationDefinition) { - log.info("set CD: " + configurationDefinition); this.configurationDefinition = configurationDefinition; }
public Configuration getConfiguration() { - return configuration; - - }
public void setConfiguration(Configuration configuration) { @@ -255,7 +250,7 @@ log.info("gConfig: " + configuration + ", " + configuration.hashCode() + ", " + log.info("setC: " + configuration); }
- public String getNullConfigurationDefinitionMessage() { + public String getNullConfigurationDefinitionMessage() { return "This operation does not take any parameters."; }
@@ -280,5 +275,4 @@ log.info("gConfig: " + configuration + ", " + configuration.hashCode() + ", " + persistProperty(alertParameters, OperationsSender.TOKEN_MODE,tokenMode); }
- } diff --git a/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsSender.java b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsSender.java index 4359ad4..4f6c88e 100644 --- a/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsSender.java +++ b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsSender.java @@ -18,9 +18,8 @@ */ package org.rhq.enterprise.server.plugins.alertOperations;
+import java.util.List; import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern;
import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -34,7 +33,7 @@ import org.rhq.core.domain.alert.notification.SenderResult; import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.PropertySimple; -import org.rhq.core.domain.resource.Resource; +import org.rhq.core.domain.operation.OperationDefinition; import org.rhq.enterprise.server.configuration.ConfigurationManagerLocal; import org.rhq.enterprise.server.exception.ScheduleException; import org.rhq.enterprise.server.operation.OperationManagerLocal; @@ -51,7 +50,7 @@ public class OperationsSender extends AlertSender {
private final Log log = LogFactory.getLog(OperationsSender.class); static final String RESOURCE_ID = "resourceId"; - static final String OPERATION_NAME = "operationName"; + static final String OPERATION_ID = "operationName"; static final String USABLE = "usable"; protected static final String TOKEN_MODE = "tokenMode"; private static final String LITERAL = "literal"; @@ -62,8 +61,8 @@ public class OperationsSender extends AlertSender { public SenderResult send(Alert alert) {
PropertySimple resProp = alertParameters.getSimple(RESOURCE_ID); - PropertySimple opNameProp = alertParameters.getSimple(OPERATION_NAME); - if (resProp==null || resProp.getIntegerValue() == null || opNameProp == null || opNameProp.getStringValue() == null) + PropertySimple opIdProp = alertParameters.getSimple(OPERATION_ID); + if (resProp==null || resProp.getIntegerValue() == null || opIdProp == null || opIdProp.getStringValue() == null) return new SenderResult(ResultState.FAILURE, "Not enough parameters given");
PropertySimple usableProp = alertParameters.getSimple(USABLE); @@ -71,11 +70,26 @@ public class OperationsSender extends AlertSender { return new SenderResult(ResultState.FAILURE,"Not yet configured");
Integer resourceId = resProp.getIntegerValue(); - String opName = opNameProp.getStringValue(); + Integer opId = opIdProp.getIntegerValue(); + + String opName = null;
OperationManagerLocal opMgr = LookupUtil.getOperationManager(); Subject subject = LookupUtil.getSubjectManager().getOverlord(); // TODO get real subject
+ List<OperationDefinition> opdefs = opMgr.findSupportedResourceOperations(subject,resourceId,false); + for (OperationDefinition opdef : opdefs ) { + if (opdef.getId() == opId) { + opName = opdef.getName(); + break; + } + } + + if (opName==null) { + return new SenderResult(ResultState.FAILURE, "No operation found "); + } + + PropertySimple parameterConfigProp = alertParameters.getSimple(PARAMETERS_CONFIG); Configuration parameters = null ; if (parameterConfigProp!=null) { diff --git a/modules/enterprise/server/plugins/alert-operations/src/main/resources/operations.xhtml b/modules/enterprise/server/plugins/alert-operations/src/main/resources/operations.xhtml index 4a6c0e6..98dcada 100644 --- a/modules/enterprise/server/plugins/alert-operations/src/main/resources/operations.xhtml +++ b/modules/enterprise/server/plugins/alert-operations/src/main/resources/operations.xhtml @@ -36,13 +36,13 @@ </h:panelGroup>
<h:panelGroup style="width:60%; vertical-align:top;" > - <rich:panel rendered="#{not empty operationsBean.operationNames}"> + <rich:panel rendered="#{not empty operationsBean.operationIds}">
Operations for: <h:outputText value=" #{operationsBean.resourceName}"/> <br/>
- <h:selectOneMenu id="selectOperationMenu" value="#{operationsBean.operationName}"> - <f:selectItems value="#{operationsBean.operationNames}"/> + <h:selectOneMenu id="selectOperationMenu" value="#{operationsBean.operationId}"> + <f:selectItems value="#{operationsBean.operationIds}"/> </h:selectOneMenu> <p/> <h:commandButton id="opNameSubmit" @@ -57,9 +57,9 @@ <p/> <h:panelGroup style="width:100%"> <h:messages /> - <rich:panel rendered="#{not empty operationsBean.operationName}"> + <rich:panel rendered="#{not empty operationsBean.operationId}"> <br/> - Parameters for <h:outputText value=" #{operationsBean.operationName}"/> + Parameters for <h:outputText value=" #{operationsBean.operationId}"/> <p/> <h:selectOneMenu id="tokenModeMenu" value="#{operationsBean.tokenMode}"> <f:selectItem itemValue="literal" itemLabel="Literal"/>
commit 59776e2009c2e2b17ca45d5c88e6373def9da879 Author: Ian P. Springer <ips@jetengine.(none)> Date: Tue Feb 23 09:23:23 2010 -0500
fix a couple invalid docs URLs
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties b/modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties index 571cf22..8132311 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties +++ b/modules/enterprise/gui/portal-war/src/main/webapp-filtered/WEB-INF/classes/ApplicationResources.properties @@ -88,7 +88,7 @@ common.field.value=Value
common.marketing.FeatureDisabled=This feature is unavailable, please contact sales to upgrade
-common.url.help=https://network.jboss.com/confluence/display/DOC/Users+Guide +common.url.help=http://www.rhq-project.org/display/JOPR2
common.error.invalid.oid=OID specified is invalid, please enter OID in form of 1.2.3.4
@@ -2916,7 +2916,7 @@ software.common.InstallPreview.PatchTitle=Title software.common.InstallPreview.StepDescription=Step Description software.common.InstallPreview.ShortDescription=Short Description software.common.InstallPreview.LongDescription=Detailed Description -software.common.InstallPreview.TopMessage=Clicking the [Install] button will begin the execution of the steps listed below. Review each step carefully before proceeding with the update installation.<br/><ul><li>Prior to installing this update, if you have applied any one-off fixes to this instance, please check the update description to see that they are included in the fixes that make up this update. If they are not included then this update may overwrite the one-off fix and leave your instance in an unstable state.</li><li>When updating a JBoss instance that shares a common server configuration, follow the instructions documented in the wiki: <a href="https://network.jboss.com/confluence/display/DOC/Installing+a+Patch" target="_new">Installing a Patch</a>. Please contact support for more information.</li></ul> +software.common.InstallPreview.TopMessage=Clicking the [Install] button will begin the execution of the steps listed below. Review each step carefully before proceeding with the update installation.<br/><ul><li>Prior to installing this update, if you have applied any one-off fixes to this instance, please check the update description to see that they are included in the fixes that make up this update. If they are not included then this update may overwrite the one-off fix and leave your instance in an unstable state.</li><li>When updating a JBoss instance that shares a common server configuration, follow the instructions documented in the wiki: <a href="http://www.rhq-project.org/display/JOPR2/Demos#Demos-ContentSubsystem" target="_new">Installing a Patch</a>. Please contact support for more information.</li></ul> software.common.InstallPreview.NotAllowedToInstall=This user doesn't have the appropriate rights to install an update. Only users that can control a resource may install an update.
software.common.ManualUninstall.TableTitle=Manual Update Uninstallation
commit b3c691dfd0f407658ba9004bbcbdda0c235404ef Author: Ian P. Springer <ips@jetengine.(none)> Date: Tue Feb 23 09:22:03 2010 -0500
fix regression in RSS feed template (https://bugzilla.redhat.com/show_bug.cgi?id=567636)
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/common/RSSFormat.jsp b/modules/enterprise/gui/portal-war/src/main/webapp/common/RSSFormat.jsp index 59bb5d1..3831ebb 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/common/RSSFormat.jsp +++ b/modules/enterprise/gui/portal-war/src/main/webapp/common/RSSFormat.jsp @@ -1,10 +1,10 @@ -<?xml version="1.0" encoding="utf-8" ?> +<?xml version="1.0" encoding="UTF-8"?> <%@ page language="java" contentType="text/xml" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%@ taglib uri="http://jakarta.apache.org/struts/tags-html-el" prefix="html" %> <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"> - <repo> + <channel> <title><c:out value="${rssFeed.title}"/></title> <link><c:out value="${rssFeed.baseUrl}"/></link> <description><fmt:message key="dashboard.template.title"/> <c:out value="${rssFeed.title}"/></description> @@ -25,5 +25,6 @@ <guid><![CDATA[<c:out value="${item.guid}"/>]]></guid> </item> </c:forEach> - </repo> + </channel> </rss> +
commit 7bdec1c039fbda0b202c078fe0c7be1507d95612 Author: Heiko W. Rupp hwr@redhat.com Date: Tue Feb 23 10:57:34 2010 +0100
Display, persist and use operation parameters.
diff --git a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/CustomContentUIBean.java b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/CustomContentUIBean.java index 8b7c8d8..683057b 100644 --- a/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/CustomContentUIBean.java +++ b/modules/enterprise/gui/portal-war/src/main/java/org/rhq/enterprise/gui/alert/CustomContentUIBean.java @@ -73,7 +73,12 @@ public class CustomContentUIBean { * name of bean, but this class is not an "official" seam component. */ private void outjectBean(String name, CustomAlertSenderBackingBean bean) { - Context pageContext = Contexts.getPageContext(); - pageContext.set(name, bean); + + Context context = Contexts.getSessionContext(); + + CustomAlertSenderBackingBean csb = (CustomAlertSenderBackingBean) context.get(name); + if (csb ==null) + context.set(name,bean); + } } 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 32e9f16..deabeae 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 @@ -25,38 +25,64 @@ import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
+import org.jboss.seam.ScopeType; +import org.jboss.seam.annotations.Create; +import org.jboss.seam.annotations.Scope; +import org.jboss.seam.annotations.web.RequestParameter; + import org.rhq.core.domain.auth.Subject; import org.rhq.core.domain.configuration.Configuration; import org.rhq.core.domain.configuration.PropertySimple; import org.rhq.core.domain.configuration.definition.ConfigurationDefinition; import org.rhq.core.domain.operation.OperationDefinition; +import org.rhq.core.domain.resource.Resource; +import org.rhq.enterprise.server.configuration.ConfigurationManagerLocal; import org.rhq.enterprise.server.operation.OperationManagerLocal; import org.rhq.enterprise.server.plugin.pc.alert.CustomAlertSenderBackingBean; +import org.rhq.enterprise.server.resource.ResourceManagerLocal; import org.rhq.enterprise.server.util.LookupUtil;
/** * Backing bean for the operations alert sender * @author Heiko W. Rupp */ - +@Scope(ScopeType.PAGE) public class OperationsBackingBean extends CustomAlertSenderBackingBean {
private final Log log = LogFactory.getLog(OperationsBackingBean.class);
private String resMode; + private String tokenMode; Integer resId; - private String operationName; - private Map<String,String> operationNames = new HashMap<String,String>(); + private Integer operationName; + private Map<String, Integer> operationNames = new HashMap<String, Integer>(); + private String resourceName; + + private ConfigurationDefinition configurationDefinition; private Configuration configuration; private static final String ALERT_NOTIFICATIONS = "ALERT_NOTIFICATIONS";
+ public OperationsBackingBean() { + log.info("new " + hashCode()); + } + + @Create + public void init() { + log.info("init"); + } + + public String selectResource() {
log.info("In select Resource, resId is " + resId + " resMode is " + resMode);
- if (resId != null) + if (resId != null) { persistProperty(alertParameters, OperationsSender.RESOURCE_ID,resId); + cleanProperty(alertParameters,OperationsSender.OPERATION_NAME); + cleanProperty(alertParameters,OperationsSender.USABLE); + + }
obtainOperationNames();
@@ -68,15 +94,47 @@ public class OperationsBackingBean extends CustomAlertSenderBackingBean { public String selectOperation() { log.info("In selectOperation, resId is " + resId + " opName is " + operationName);
- if (operationName != null ) + if (operationName != null ) { persistProperty(alertParameters, OperationsSender.OPERATION_NAME,operationName); + lookupConfiguration(); + }
return ALERT_NOTIFICATIONS; }
+ private void lookupConfiguration() { + + +// log.info("getCD: " + configurationDefinition); + try { +// Subject subject = EnterpriseFacesContextUtility.getSubject(); + Subject subject = LookupUtil.getSubjectManager().getOverlord(); // TODO replace with real subject + +// int operationId = Integer.valueOf(FacesContextUtility.getRequiredRequestParameter("opId")); + OperationManagerLocal opMan = LookupUtil.getOperationManager(); + obtainOperationNames(); + + + OperationDefinition operationDefinition = opMan.getOperationDefinition(subject, operationName); + configurationDefinition = operationDefinition.getParametersConfigurationDefinition(); + + + // call a SLSB method to get around lazy initialization of configDefs and configTemplates + ConfigurationManagerLocal configurationManager = LookupUtil.getConfigurationManager(); + configuration = configurationManager.getConfigurationFromDefaultTemplate(configurationDefinition); +// Configuration newConfiguration = configuration.deepCopy(false); +log.info("gConfig: " + configuration + ", " + configuration.hashCode() + ", " + configuration.getSimpleValue("detailedDiscovery","-unset-")); + } catch (Exception e) { + e.printStackTrace(); + } + } + public String useConfiguration() { - log.info("In useConfiguration"); + log.info("In useConfiguration, Configuration is " + configuration );
+ // COnfiguration should be valid here ... + super.persistConfiguration(configuration); + persistProperty(alertParameters,OperationsSender.PARAMETERS_CONFIG,configuration.getId()); persistProperty(alertParameters, OperationsSender.USABLE,true);
return ALERT_NOTIFICATIONS; @@ -94,7 +152,7 @@ public class OperationsBackingBean extends CustomAlertSenderBackingBean { Subject subject = LookupUtil.getSubjectManager().getOverlord(); // TODO replace with real subject List<OperationDefinition> opDefs = opMan.findSupportedResourceOperations(subject, resId, false); for (OperationDefinition def : opDefs) { - operationNames.put(def.getDisplayName(),def.getName()); // TODO add more distinctive stuff in display + operationNames.put(def.getDisplayName(),def.getId()); // TODO add more distinctive stuff in display } } } @@ -107,6 +165,7 @@ public class OperationsBackingBean extends CustomAlertSenderBackingBean {
public void setResMode(String resMode) { this.resMode = resMode; + log.info("setResMode: " + resMode); }
public Integer getResId() { @@ -122,47 +181,104 @@ public class OperationsBackingBean extends CustomAlertSenderBackingBean {
public void setResId(Integer resId) { this.resId = resId; + log.info("Set resid " + resId); + if (resId!=null) { + persistProperty(alertParameters,OperationsSender.RESOURCE_ID,resId); + } }
- public String getOperationName() { + public String getResourceName() { + if (resId==null) + getResId(); + + if (resId!=null) { + ResourceManagerLocal resMgr = LookupUtil.getResourceManager(); + Subject subject = LookupUtil.getSubjectManager().getOverlord(); // TODO replace with real subject + Resource res = resMgr.getResource(subject,resId); + + resourceName = res.getName() + " (" + res.getResourceType().getName() + ")"; + } + return resourceName; + } + + public void setResourceName(String resourceName) { + this.resourceName = resourceName; + } + + public Integer getOperationName() {
if (operationName==null) { PropertySimple prop = alertParameters.getSimple(OperationsSender.OPERATION_NAME); if (prop!=null) - operationName = prop.getStringValue(); + operationName = prop.getIntegerValue(); }
return operationName; }
- public void setOperationName(String operationName) { + public void setOperationName(Integer operationName) { this.operationName = operationName; }
- public Map<String,String> getOperationNames() { + public Map<String, Integer> getOperationNames() {
obtainOperationNames();
return operationNames; }
- public void setOperationNames(Map<String,String> operationNames) { + public void setOperationNames(Map<String, Integer> operationNames) { this.operationNames = operationNames; }
public ConfigurationDefinition getConfigurationDefinition() { return configurationDefinition; + + + }
public void setConfigurationDefinition(ConfigurationDefinition configurationDefinition) { + log.info("set CD: " + configurationDefinition); this.configurationDefinition = configurationDefinition; }
public Configuration getConfiguration() { + return configuration; + + }
public void setConfiguration(Configuration configuration) { this.configuration = configuration; + log.info("setC: " + configuration); } + + public String getNullConfigurationDefinitionMessage() { + return "This operation does not take any parameters."; + } + + public String getNullConfigurationMessage() { + return "This operation parameters definition has not been initialized."; + } + + public String getTokenMode() { + if (tokenMode==null) { + PropertySimple prop = alertParameters.getSimple(OperationsSender.TOKEN_MODE); + if (prop!=null) + tokenMode = prop.getStringValue(); + } + + return tokenMode; + } + + public void setTokenMode(String tokenMode) { + this.tokenMode = tokenMode; + log.info("token mode" + tokenMode); + + persistProperty(alertParameters, OperationsSender.TOKEN_MODE,tokenMode); + } + + } diff --git a/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsSender.java b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsSender.java index 4fa9bba..4359ad4 100644 --- a/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsSender.java +++ b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/OperationsSender.java @@ -18,14 +18,24 @@ */ package org.rhq.enterprise.server.plugins.alertOperations;
+import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory;
+import org.jboss.seam.ScopeType; +import org.jboss.seam.annotations.Scope; + import org.rhq.core.domain.alert.Alert; 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.configuration.Configuration; import org.rhq.core.domain.configuration.PropertySimple; +import org.rhq.core.domain.resource.Resource; +import org.rhq.enterprise.server.configuration.ConfigurationManagerLocal; import org.rhq.enterprise.server.exception.ScheduleException; import org.rhq.enterprise.server.operation.OperationManagerLocal; import org.rhq.enterprise.server.operation.ResourceOperationSchedule; @@ -36,12 +46,17 @@ import org.rhq.enterprise.server.util.LookupUtil; * Alert sender that triggers an operation on the resource * @author Heiko W. Rupp */ +@Scope(value = ScopeType.PAGE) public class OperationsSender extends AlertSender {
private final Log log = LogFactory.getLog(OperationsSender.class); static final String RESOURCE_ID = "resourceId"; static final String OPERATION_NAME = "operationName"; static final String USABLE = "usable"; + protected static final String TOKEN_MODE = "tokenMode"; + private static final String LITERAL = "literal"; + private static final String INTERPRETED = "interpreted"; + public static final String PARAMETERS_CONFIG = "parametersConfig";
@Override public SenderResult send(Alert alert) { @@ -52,7 +67,7 @@ public class OperationsSender extends AlertSender { return new SenderResult(ResultState.FAILURE, "Not enough parameters given");
PropertySimple usableProp = alertParameters.getSimple(USABLE); - if (usableProp==null || usableProp.getBooleanValue()== null || usableProp.getBooleanValue() == false) + if (usableProp==null || usableProp.getBooleanValue()== null || !usableProp.getBooleanValue()) return new SenderResult(ResultState.FAILURE,"Not yet configured");
Integer resourceId = resProp.getIntegerValue(); @@ -61,17 +76,53 @@ public class OperationsSender extends AlertSender { OperationManagerLocal opMgr = LookupUtil.getOperationManager(); Subject subject = LookupUtil.getSubjectManager().getOverlord(); // TODO get real subject
+ PropertySimple parameterConfigProp = alertParameters.getSimple(PARAMETERS_CONFIG); + Configuration parameters = null ; + if (parameterConfigProp!=null) { + Integer paramId = parameterConfigProp.getIntegerValue(); + if (paramId!=null) { + ConfigurationManagerLocal cmgr = LookupUtil.getConfigurationManager(); + parameters = cmgr.getConfiguration(subject,paramId); + } + } + + + String tokenMode = alertParameters.getSimpleValue(TOKEN_MODE, LITERAL); + + /* + * If we have parameters and the user wants tokens to be interpreted, then loop + * over the parameters and do token replacement. + */ + if (parameters!=null && tokenMode.equals(INTERPRETED)) { + Map<String,PropertySimple> propsMap = parameters.getSimpleProperties(); + if (!propsMap.isEmpty()) { + TokenReplacer tr = new TokenReplacer(alert); + for (PropertySimple prop : propsMap.values()) { + String tmp = prop.getStringValue(); + tmp = tr.replaceTokens(tmp); + prop.setStringValue(tmp); + } + } + } + + + + /* + * Now fire off the operation with no delay and no repetition. + */ ResourceOperationSchedule sched; try { - sched = opMgr.scheduleResourceOperation(subject, resourceId, opName, 0, 0, 0, 0, null, + sched = opMgr.scheduleResourceOperation(subject, resourceId, opName, 0, 0, 0, 0, parameters, "Alert operation for " + alert.getAlertDefinition().getName()); } catch (ScheduleException e) { return new SenderResult(ResultState.FAILURE, "Scheduling of operation " + opName + " on resource " + resourceId + " failed: " + e.getMessage()); }
- // TODO evaluate retuen of schedule() call and defer, so we can leter check - // If op sending was successfull + // If op sending was successful return new SenderResult(ResultState.SUCCESS, "Scheduled operation " + opName + " on resource " + resourceId + " with jobId " + sched.getJobId() );
} + + + } diff --git a/modules/enterprise/server/plugins/alert-operations/src/main/resources/operations.xhtml b/modules/enterprise/server/plugins/alert-operations/src/main/resources/operations.xhtml index 1fd74ad..4a6c0e6 100644 --- a/modules/enterprise/server/plugins/alert-operations/src/main/resources/operations.xhtml +++ b/modules/enterprise/server/plugins/alert-operations/src/main/resources/operations.xhtml @@ -29,12 +29,18 @@ <h:commandButton id="resourceIdSubmit" value="Select" type="submit" - action="#{operationsBean.selectResource}" /> + action="#{operationsBean.selectResource}" + styleClass="buttonmed" + /> </rich:panel> </h:panelGroup>
- <h:panelGroup style="width:60%"> + <h:panelGroup style="width:60%; vertical-align:top;" > <rich:panel rendered="#{not empty operationsBean.operationNames}"> + + Operations for: <h:outputText value=" #{operationsBean.resourceName}"/> + <br/> + <h:selectOneMenu id="selectOperationMenu" value="#{operationsBean.operationName}"> <f:selectItems value="#{operationsBean.operationNames}"/> </h:selectOneMenu> @@ -42,31 +48,40 @@ <h:commandButton id="opNameSubmit" value="Select" type="submit" - action="#{operationsBean.selectOperation}" /> + action="#{operationsBean.selectOperation}" + styleClass="buttonmed" + /> </rich:panel> </h:panelGroup> </h:panelGrid> <p/> <h:panelGroup style="width:100%"> - <h:outputText value="3rd panel : "/> - <h:outputText value="#{operationsBean.operationName}"/> - <br/> + <h:messages /> <rich:panel rendered="#{not empty operationsBean.operationName}"> + <br/> + Parameters for <h:outputText value=" #{operationsBean.operationName}"/> + <p/> + <h:selectOneMenu id="tokenModeMenu" value="#{operationsBean.tokenMode}"> + <f:selectItem itemValue="literal" itemLabel="Literal"/> + <f:selectItem itemValue="interpreted" itemLabel="Interpreted"/> + </h:selectOneMenu> + <p/> <onc:config configurationDefinition="#{operationsBean.configurationDefinition}" configuration="#{operationsBean.configuration}" - nullConfigurationDefinitionMessage="NUll configuration definition" - nullConfigurationMessage="null configuration" + nullConfigurationDefinitionMessage="#{operationsBean.nullConfigurationDefinitionMessage}" + nullConfigurationMessage="#{nullConfigurationMessage}" nullConfigurationStyle="InfoBlock" - - id="opParamConfiguration" + readOnly="false" /> <p/> <h:commandButton id="opParamSubmit" value="Set" type="submit" - action="#{operationsBean.useConfiguration}" /> + action="#{operationsBean.useConfiguration}" + styleClass="buttonmed" + /> </rich:panel> </h:panelGroup>
</body> -</html> \ No newline at end of file +</html>
commit b196e883688008615778ad6eb73fb94caff12015 Author: Heiko W. Rupp hwr@redhat.com Date: Tue Feb 23 10:56:59 2010 +0100
Implement code for token replacement
diff --git a/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/Token.java b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/Token.java new file mode 100644 index 0000000..bcd7570 --- /dev/null +++ b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/Token.java @@ -0,0 +1,72 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.server.plugins.alertOperations; + +import java.util.EnumSet; + +/** + * Tokens that can be replaced in + * @author Heiko W. Rupp + */ +public enum Token { + + // Alert related tokens + ALERT_ID(TokenClass.ALERT, "id"), + ALERT_URL(TokenClass.ALERT, "url"), + + // resource that triggered the alert related tokens + RESOURCE_ID(TokenClass.RESOURCE, "id"), + RESOURCE_NAME(TokenClass.RESOURCE, "name"), + + + // resource the operation is run on related tokens + TRESOURCE_ID(TokenClass.TARGET_RESOURCE, "id"), + TRESOURCE_NAME(TokenClass.TARGET_RESOURCE, "name"), + + + // only for testing + TEST_ECHO(TokenClass.TEST,"echo"), + TEST_FIX(TokenClass.TEST,"fix") + + ; + + + private String text; + + private Token(TokenClass tc, String text) { + + this.text = tc.getText() + "." + text; + } + + /** + * Return the token that matches the input text or null if not found. + * The token delimiters need to be already stripped from the input + * @param input a token text like <i>alert.id</i>, which would return the + * <i>ALERT_ID</i> token. + * @return The matching token or null if not found + */ + public static Token getByText(String input) { + EnumSet<Token> es = EnumSet.allOf(Token.class); + for (Token t : es) { + if (t.text.equals(input)) + return t; + } + return null; + } +} diff --git a/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/TokenClass.java b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/TokenClass.java new file mode 100644 index 0000000..5125a72 --- /dev/null +++ b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/TokenClass.java @@ -0,0 +1,59 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.server.plugins.alertOperations; + +import java.util.EnumSet; + +/** + * Class a @See{Token} can be in. + * @author Heiko W. Rupp + */ +public enum TokenClass { + + ALERT("alert"), + RESOURCE("resource"), + TARGET_RESOURCE("targetResource"), + TEST("test"); + + private String text; + + private TokenClass(String text) { + this.text = text; + } + + public String getText() { + return text; + } + + /** + * Return the tokenclass that matches the input text or null if not found. + * The token delimiters need to be already stripped from the input + * @param input a token text like <i>alert</i>, which would return the + * <i>ALERT</i> token class. + * @return The matching token class or null if not found + */ + public static TokenClass getByText(String input) { + EnumSet<TokenClass> es = EnumSet.allOf(TokenClass.class); + for (TokenClass t : es) { + if (t.text.equals(input)) + return t; + } + return null; + } +} diff --git a/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/TokenReplacer.java b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/TokenReplacer.java new file mode 100644 index 0000000..0b230b4 --- /dev/null +++ b/modules/enterprise/server/plugins/alert-operations/src/main/java/org/rhq/enterprise/server/plugins/alertOperations/TokenReplacer.java @@ -0,0 +1,178 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.server.plugins.alertOperations; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.rhq.core.domain.alert.Alert; +import org.rhq.core.domain.resource.Resource; + +/** + * Helper to replace tokens by their values + * @author Heiko W. Rupp + */ +public class TokenReplacer { + + private final Log log = LogFactory.getLog(TokenReplacer.class); + private static final String NOT_YET_IMPLEMENTED = " - not yet implemented -"; + protected static final String THE_QUICK_BROWN_FOX_JUMPS_OVER_THE_LAZY_DOG = "TheQuickBrownFoxJumpsOverTheLazyDOg"; + private Alert alert; + private Pattern pattern; + + public TokenReplacer(Alert alert) { + this.alert = alert; + pattern = Pattern.compile("<%\s*([a-z]+\.[a-z0-9]+)\s*%>"); + } + + /** + * Replace all tokens on the input line. If no tokens are found the input is returned. + * Tokens have the form '<i><% class.sub %></i>' + * @param input a line of text + * @return input with tokens replaced. + * @see org.rhq.enterprise.server.plugins.alertOperations.Token + * @see org.rhq.enterprise.server.plugins.alertOperations.TokenClass + */ + public String replaceTokens(String input) { + + String work = input; + Matcher matcher = pattern.matcher(work); + if (!matcher.find()) { + log.warn("No tokens found in " + input); + return input; + } + matcher.reset(); + + do { +// System.out.println(input); + matcher = pattern.matcher(work); + if (!matcher.find()) { + break; + } +// System.out.println(matcher.regionStart() + ":" + matcher.regionEnd() + input.substring(matcher.regionStart(),matcher.regionEnd())); +// System.out.println(matcher.group(1)); + String replacement = replaceToken(matcher.group(1) ); + String s = matcher.replaceFirst(replacement); +// System.out.println(s); + work = s; + +// System.out.println("----"); + } while (true); + + return work; + } + + + + /** + * Replace the token string passed (without the token delimiters ) with the actual value + * @param tokenString Input like alert.id + * @return replacement string or the input if the token was not valid. + */ + public String replaceToken(String tokenString) { + + // Ok, we have at least one token. Now split the tokenString and loop over the tokens + + if (!tokenString.contains(".")) + return tokenString; + + String tmp = tokenString.substring(0, tokenString.indexOf(".")); + TokenClass tc = TokenClass.getByText(tmp); + if (tc==null) { + log.warn("Unknown token class in [" + tokenString + "], not replacing tokens"); + return tokenString; + } + + Token token = Token.getByText(tokenString); + if (token == null) { + log.warn("No known token found in [" + tokenString + "], not replacing token"); + return tokenString; + } + String ret = null; + switch (tc) { + case ALERT: + ret = replaceAlertToken(token,alert); + break; + case RESOURCE: + ret = replaceResourceToken(token,alert.getAlertDefinition().getResource()); + break; + case TARGET_RESOURCE: + Resource resource = null; // TODO + ret = replaceTargetResourceToken(token, resource); + break; + case TEST: + switch (token) { + case TEST_ECHO: + ret = tokenString; + break; + case TEST_FIX: + ret = THE_QUICK_BROWN_FOX_JUMPS_OVER_THE_LAZY_DOG; + break; + default: + ret = NOT_YET_IMPLEMENTED; + } + break; + } + return ret; + } + + private String replaceAlertToken(Token token, Alert alert) { + + switch (token) { + case ALERT_ID: + return String.valueOf(alert.getId()); + case ALERT_URL: + return NOT_YET_IMPLEMENTED; + + default: + return NOT_YET_IMPLEMENTED; + } + + } + + private String replaceResourceToken(Token token, Resource resource) { + + switch (token) { + case RESOURCE_ID: + return String.valueOf(resource.getId()); + case RESOURCE_NAME: + return resource.getName(); + + default: + return NOT_YET_IMPLEMENTED; + } + } + + private String replaceTargetResourceToken(Token token, Resource resource) { + + switch (token) { + case TRESOURCE_ID: + return String.valueOf(resource.getId()); + case TRESOURCE_NAME: + return resource.getName(); + + default: + return NOT_YET_IMPLEMENTED; + } + } + +} diff --git a/modules/enterprise/server/plugins/alert-operations/src/test/java/org/rhq/enterprise/server/plugins/alertOperations/TokenReplacementTest.java b/modules/enterprise/server/plugins/alert-operations/src/test/java/org/rhq/enterprise/server/plugins/alertOperations/TokenReplacementTest.java new file mode 100644 index 0000000..f41fc85 --- /dev/null +++ b/modules/enterprise/server/plugins/alert-operations/src/test/java/org/rhq/enterprise/server/plugins/alertOperations/TokenReplacementTest.java @@ -0,0 +1,135 @@ +/* + * RHQ Management Platform + * Copyright (C) 2005-2010 Red Hat, Inc. + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +package org.rhq.enterprise.server.plugins.alertOperations; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.testng.annotations.Test; + +import org.rhq.core.domain.alert.Alert; +import org.rhq.core.domain.alert.AlertDefinition; +import org.rhq.core.domain.resource.Resource; + +/** + * // TODO: Document this + * @author Heiko W. Rupp + */ +@Test +public class TokenReplacementTest { + + private final Log log = LogFactory.getLog(TokenReplacementTest.class); + private static final String TEST_ECHO = "test.echo"; + private static final String FOO_BAR = "fooBar"; + private static final String FOO_DOT_BAR = "foo.bar"; + private static final String ALERT_BAR = "alert.bar"; + + public void testSimpleReplacement() throws Exception { + + Alert al = new Alert(); + TokenReplacer tr = new TokenReplacer(al); + + + String res = tr.replaceToken("test.fix"); + assert res != null; + assert res.equals(TokenReplacer.THE_QUICK_BROWN_FOX_JUMPS_OVER_THE_LAZY_DOG); + + res = tr.replaceToken(TEST_ECHO); + assert res != null; + assert res.equals(TEST_ECHO); + + res = tr.replaceToken("alert.id"); + assert res != null; + assert res.equals("0"); + + Resource r = new Resource(1234); + r.setName("A resource"); + AlertDefinition def = new AlertDefinition(); + def.setResource(r); + al = new Alert(def, System.currentTimeMillis()); + tr = new TokenReplacer(al); + + res = tr.replaceToken("resource.id"); + assert "1234".equals(res); + res = tr.replaceToken("resource.name"); + assert "A resource".equals(res); + } + + public void testInvalidTokenString() { + + Alert al = new Alert(); + TokenReplacer tr = new TokenReplacer(al); + + + String res = tr.replaceToken(FOO_BAR); + assert res != null; + assert res.equals(FOO_BAR); + + res = tr.replaceToken(FOO_DOT_BAR); + assert res != null; + assert res.equals(FOO_DOT_BAR); + + res = tr.replaceToken(ALERT_BAR); + assert res != null; + assert res.equals(ALERT_BAR); + + } + + public void testFullTokenSimple() { + + Alert al = new Alert(); + TokenReplacer tr = new TokenReplacer(al); + + + String res = tr.replaceTokens("<%test.fix%>"); + assert res != null; + assert !res.equals("<%test.fix%>") : "Res was " + res; + assert res.equals(TokenReplacer.THE_QUICK_BROWN_FOX_JUMPS_OVER_THE_LAZY_DOG); + + String TF2 = "<% test.fix %>"; + res = tr.replaceTokens(TF2); + assert res != null; + assert !res.equals(TF2) : "Res was " + res; + + String TF3 = "<% test.fix %>"; + res = tr.replaceTokens(TF3); + assert res != null; + assert !res.equals(TF3) : "Res was " + res; + + String TF4 = "<% test.fix%> xXx <% test.echo%>"; + res = tr.replaceTokens(TF4); + assert res != null; + assert !res.equals(TF4) : "Res was " + res; + + res = tr.replaceTokens(FOO_BAR); + assert res != null; + assert res.equals(FOO_BAR) : "Res was " + res; + + Resource r = new Resource(1234); + r.setName("A resource"); + AlertDefinition def = new AlertDefinition(); + def.setResource(r); + al = new Alert(def, System.currentTimeMillis()); + + tr = new TokenReplacer(al); + res = tr.replaceTokens("<% test.fix%><%resource.id%>"); + assert res!=null; + assert res.equals(TokenReplacer.THE_QUICK_BROWN_FOX_JUMPS_OVER_THE_LAZY_DOG+"1234"); + } + +}
commit e60d5bc39ad9c103e072eaa1e8fca7a0aedb9191 Author: Heiko W. Rupp hwr@redhat.com Date: Mon Feb 22 21:35:49 2010 +0100
If no emails failed, we can set the state to success
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 ff4025f..c21bf21 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 @@ -739,6 +739,16 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { } 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 + // 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) + anl.setResultState(ResultState.SUCCESS); } }
commit a57abc5879531e4f58cc16f6fcd6655fdb035b77 Author: Heiko W. Rupp hwr@redhat.com Date: Mon Feb 22 12:14:53 2010 +0100
Fix link from alert templates list to the view alert page. BZ 566896
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/listAlertTemplates.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/listAlertTemplates.xhtml index b7131e8..2f30a9c 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/listAlertTemplates.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/admin/listAlertTemplates.xhtml @@ -28,7 +28,7 @@ </ui:define>
<ui:define name="body"> - + <br/> <h:messages showSummary="true" showDetail="true" @@ -39,10 +39,10 @@ globalOnly="true" layout="table" width="100%"/> - + <h:form id="alertTemplatesListForm"> <input type="hidden" name="type" value="${param.type}"/> - + rich:panel <f:facet name="header"> <h:outputText value="#{ResourceTypeUIBean.name} Alert Templates"/> @@ -66,50 +66,49 @@ <f:facet name="PageControlView"> <onc:paginationControl id="AlertTemplatesList" /> </f:facet> - + rich:column <f:facet name="header"> <onc:allSelect target="selectedAlertTemplates" /> </f:facet> - + <onc:select name="selectedAlertTemplates" value="#{item.id}" /> </rich:column> - + <rich:column rendered="#{param.debug}"> <f:facet name="header"> <onc:sortableColumnHeader sort="a.id"> <h:outputText styleClass="headerText" value="ID" /> </onc:sortableColumnHeader> </f:facet> - + <h:outputText value="#{item.id}"/> </rich:column> - + rich:column <f:facet name="header"> <onc:sortableColumnHeader sort="a.name"> <h:outputText styleClass="headerText" value="Name" /> </onc:sortableColumnHeader> </f:facet> - - <h:outputLink value="/alerts/Config.do"> - <f:param name="mode" value="viewRoles"/> + + <h:outputLink value="/rhq/resource/alert/viewAlert.xhtml"> <f:param name="type" value="#{param.type}"/> <f:param name="ad" value="#{item.id}"/> <h:outputText value="#{item.name}" /> </h:outputLink> </rich:column> - + rich:column <f:facet name="header"> <onc:sortableColumnHeader sort="a.description"> <h:outputText styleClass="headerText" value="Description" /> </onc:sortableColumnHeader> </f:facet> - + <h:outputText value="#{item.description}"/> </rich:column> - + rich:column <f:facet name="header"> <onc:sortableColumnHeader sort="a.ctime"> @@ -121,14 +120,14 @@ <f:converter converterId="UserDateTimeConverter" /> </h:outputText> </rich:column> - + rich:column <f:facet name="header"> <onc:sortableColumnHeader sort="a.enabled"> <h:outputText styleClass="headerText" value="Active" /> </onc:sortableColumnHeader> </f:facet> - + <h:outputText value="#{item.enabled}"/> </rich:column>
diff --git a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/viewAlert.xhtml b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/viewAlert.xhtml index dcfff68..a987e65 100644 --- a/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/viewAlert.xhtml +++ b/modules/enterprise/gui/portal-war/src/main/webapp/rhq/resource/alert/viewAlert.xhtml @@ -15,8 +15,18 @@ xmlns:a4j="https://ajax4jsf.dev.java.net/ajax" xmlns:rich="http://richfaces.ajax4jsf.org/rich%22%3E
+ <c:choose> + <c:when test="#{not empty param.type}"> + <c:set var="title" value="Definition for '#{alertDefinition.name}' on resource type '#{ResourceTypeUIBean.name}'"/> + </c:when> + <c:otherwise> + <c:set var="title" value="Definition for '#{alertDefinition.name}' on resource '#{alertDefinition.resource.name}'"/> + </c:otherwise> + </c:choose> + <ui:composition template="/rhq/layout/main.xhtml"> - <ui:param name="pageTitle" value="Definition for '#{alertDefinition.name}' on resource '#{alertDefinition.resource.name}'"/> + <ui:param name="pageTitle" value="#{title}"/> +
<ui:define name="metaHeaders"> <style> @@ -49,11 +59,21 @@ <f:param name="ad" value="#{alertDefinition.id}" /> <h:outputText value=" Definition for '#{alertDefinition.name}' "/> </h:outputLink> - <h:outputText> on resource </h:outputText> - <h:outputLink value="/rhq/resource/summary/overview.xhtml"> - <f:param name="id" value="#{alertDefinition.resource.id}" /> - <h:outputText value=" '#{alertDefinition.resource.name}'" /> - </h:outputLink> + <c:choose> + <c:when test="#{not empty param.type}"> + <h:outputText> on resource type </h:outputText> + <h:outputLink value="/rhq/admin/listAlertTemplates.xhtml?type=${param.type}"> + <h:outputText value=" #{ResourceTypeUIBean.name}"/> + </h:outputLink> + </c:when> + <c:otherwise> + <h:outputText> on resource </h:outputText> + <h:outputLink value="/rhq/resource/summary/overview.xhtml"> + <f:param name="id" value="#{alertDefinition.resource.id}" /> + <h:outputText value=" '#{alertDefinition.resource.name}'" /> + </h:outputLink> + </c:otherwise> + </c:choose> </ui:define>
<ui:define name="body"> @@ -170,10 +190,19 @@
<br /> <br /> - <h:outputLink value="/rhq/resource/alert/listAlertDefinitions.xhtml"> - <f:param name="id" value="#{alertDefinition.resource.id}"/> - <h:outputText value="Back to Alert Definitions for Resource '#{alertDefinition.resource.name}'"/> - </h:outputLink> + <c:choose> + <c:when test="#{not empty param.type}"> + <h:outputLink value="/rhq/admin/listAlertTemplates.xhtml?type=${param.type}"> + <h:outputText value="Back to Alert Definitions for Resource Type '#{ResourceTypeUIBean.name}'"/> + </h:outputLink> + </c:when> + <c:otherwise> + <h:outputLink value="/rhq/resource/alert/listAlertDefinitions.xhtml"> + <f:param name="id" value="#{alertDefinition.resource.id}"/> + <h:outputText value="Back to Alert Definitions for Resource '#{alertDefinition.resource.name}'"/> + </h:outputLink> + </c:otherwise> + </c:choose>
<rich:modalPanel id="addAlertFromTemplatePanel" moveable="false" autosized="true"> <f:facet name="header"> @@ -230,4 +259,4 @@
</ui:define> </ui:composition> -</html> \ No newline at end of file +</html>
commit 3602414a6baff7fb52d637d2006574610212b46f Author: Heiko W. Rupp pilhuhn@fedorapeople.org Date: Sat Feb 20 10:49:01 2010 +0100
Fix potential NPE
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationLog.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationLog.java index 5ed6d4f..b90def3 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationLog.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationLog.java @@ -113,8 +113,8 @@ public class AlertNotificationLog implements Serializable { @PrePersist @PreUpdate public void trimMessage() { - if (message.length()>255) - message = message.substring(0,254); + if (message!=null && message.length()>255) + message = message.substring(0,255); }
protected AlertNotificationLog() {
commit 1c26e0f7c827ae7a250b4de583d6ce623ca3ff50 Merge: 32b3daf... e1c7603... Author: Heiko W. Rupp pilhuhn@fedorapeople.org Date: Sat Feb 20 09:52:53 2010 +0100
Merge branch 'master' into alertPlugin
commit 32b3daf0e818830cabf9797197666b8059472ba5 Author: Heiko W. Rupp pilhuhn@fedorapeople.org Date: Sat Feb 20 09:47:10 2010 +0100
Truncate the message at 140 chars, as identi.ca bails out on longer messages; seems to improve stability with Twitter too. Introduce abbreviated versions of the messages as space on Microblog etc is scarce. BZ 555091
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationLog.java b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationLog.java index ba75940..5ed6d4f 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationLog.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/alert/notification/AlertNotificationLog.java @@ -38,6 +38,8 @@ import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.NamedQueries; import javax.persistence.NamedQuery; +import javax.persistence.PrePersist; +import javax.persistence.PreUpdate; import javax.persistence.SequenceGenerator; import javax.persistence.Table; import javax.persistence.Transient; @@ -108,6 +110,13 @@ public class AlertNotificationLog implements Serializable { @Transient transient List<String> transientEmails = new ArrayList<String>();
+ @PrePersist + @PreUpdate + public void trimMessage() { + if (message.length()>255) + message = message.substring(0,254); + } + protected AlertNotificationLog() { } // JPA
@@ -130,7 +139,6 @@ public class AlertNotificationLog implements Serializable {
public AlertNotificationLog(Alert alert, String senderName, ResultState state, String message) { this.alert = alert; - this.sender = sender; this.resultState = state; this.message = message;
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 454b9a9..ff4025f 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 @@ -780,7 +780,7 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { Map<String, String> alertMessage = emailManager.getAlertEmailMessage( prettyPrintResourceHierarchy(alertDefinition.getResource()), alertDefinition.getResource().getName(), alertDefinition.getName(), alertDefinition.getPriority().toString(), new Date(alert.getCtime()).toString(), - prettyPrintAlertConditions(alert.getConditionLogs()), prettyPrintAlertURL(alert)); + prettyPrintAlertConditions(alert.getConditionLogs(), false), prettyPrintAlertURL(alert)); String messageSubject = alertMessage.keySet().iterator().next(); String messageBody = alertMessage.values().iterator().next();
@@ -834,13 +834,14 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { /** * Create a human readable description of the conditions that led to this alert. * @param alert Alert to create human readable condition description + * @param shortVersion if true the messages printed are abbreviated to save space * @return human readable condition log */ - public String prettyPrintAlertConditions(Alert alert) { - return prettyPrintAlertConditions(alert.getConditionLogs()); + public String prettyPrintAlertConditions(Alert alert, boolean shortVersion) { + return prettyPrintAlertConditions(alert.getConditionLogs(), shortVersion); }
- private String prettyPrintAlertConditions(Set<AlertConditionLog> conditionLogs) { + private String prettyPrintAlertConditions(Set<AlertConditionLog> conditionLogs, boolean shortVersion) { StringBuilder builder = new StringBuilder();
int conditionCounter = 1; @@ -858,16 +859,27 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote {
builder.append(NEW_LINE);
- builder.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_EMAIL_CONDITION_LOG_FORMAT, - conditionCounter, prettyPrintAlertCondition(aLog.getCondition()), new SimpleDateFormat( - "yyyy/MM/dd HH:mm:ss z").format(new Date(aLog.getCtime())), formattedValue)); + String format; + if (shortVersion) + format = AlertI18NResourceKeys.ALERT_EMAIL_CONDITION_LOG_FORMAT_SHORT; + else + format = AlertI18NResourceKeys.ALERT_EMAIL_CONDITION_LOG_FORMAT; + SimpleDateFormat dateFormat; + if (shortVersion) + 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)); conditionCounter++; }
return builder.toString(); }
- private String prettyPrintAlertCondition(AlertCondition condition) { + private String prettyPrintAlertCondition(AlertCondition condition, boolean shortVersion) { StringBuilder builder = new StringBuilder();
AlertConditionCategory category = condition.getCategory(); @@ -915,19 +927,38 @@ public class AlertManagerBean implements AlertManagerLocal, AlertManagerRemote { } } else if ((category == AlertConditionCategory.RESOURCE_CONFIG) || (category == AlertConditionCategory.CHANGE) || (category == AlertConditionCategory.TRAIT)) { - builder.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_CURRENT_LIST_VALUE_CHANGED)); + + if (shortVersion) + builder.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_CURRENT_LIST_VALUE_CHANGED_SHORT)); + else + builder.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_CURRENT_LIST_VALUE_CHANGED)); + } else if (category == AlertConditionCategory.EVENT) { if ((condition.getOption() != null) && (condition.getOption().length() > 0)) { + String propsCbEventSeverityRegexMatch; + if (shortVersion) + propsCbEventSeverityRegexMatch = AlertI18NResourceKeys.ALERT_CONFIG_PROPS_CB_EVENT_SEVERITY_REGEX_MATCH_SHORT; + else + propsCbEventSeverityRegexMatch = AlertI18NResourceKeys.ALERT_CONFIG_PROPS_CB_EVENT_SEVERITY_REGEX_MATCH; + builder.append(AlertI18NFactory.getMessage( - AlertI18NResourceKeys.ALERT_CONFIG_PROPS_CB_EVENT_SEVERITY_REGEX_MATCH, condition.getName(), + propsCbEventSeverityRegexMatch, condition.getName(), condition.getOption())); } else { - builder.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_CONFIG_PROPS_CB_EVENT_SEVERITY, - condition.getName())); + if (shortVersion) + 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())); } } else if (category == AlertConditionCategory.AVAILABILITY) { - builder.append(AlertI18NFactory.getMessage(AlertI18NResourceKeys.ALERT_CONFIG_PROPS_CB_AVAILABILITY, - condition.getOption())); + if (shortVersion) + 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())); } else { // do nothing } 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 996f245..e482ffa 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 @@ -96,9 +96,10 @@ public interface AlertManagerLocal { /** * Create a human readable description of the conditions that led to this alert. * @param alert Alert to create human readable condition description + * @param shortVersion if true the messages printed are abbreviated to save space * @return human readable condition log */ - String prettyPrintAlertConditions(Alert alert); + String prettyPrintAlertConditions(Alert alert, boolean shortVersion);
/** * Tells us if the definition of the passed alert will be disabled after this alert was fired diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java index 8734771..1de3d85 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/alert/i18n/AlertI18NResourceKeys.java @@ -32,20 +32,41 @@ public interface AlertI18NResourceKeys { @I18NMessage(locale = "de", value = "Verfgbarkeit wird {0}") }) String ALERT_CONFIG_PROPS_CB_AVAILABILITY = "alert.config.props.CB.Availability";
+ @I18NMessages( { @I18NMessage("Avail goes {0}"), + @I18NMessage(locale = "de", value = "Verf. wird {0}") }) + String ALERT_CONFIG_PROPS_CB_AVAILABILITY_SHORT = "alert.config.props.CB.Availability.short"; + @I18NMessages( { @I18NMessage("Event Severity: {0}"), @I18NMessage(locale = "de", value = "Schwere des Ereignesses: {0}") }) String ALERT_CONFIG_PROPS_CB_EVENT_SEVERITY = "alert.config.props.CB.EventSeverity";
+ @I18NMessages( { @I18NMessage("Sev: {0}"), + @I18NMessage(locale = "de", value = "Schwere: {0}") }) + String ALERT_CONFIG_PROPS_CB_EVENT_SEVERITY_SHORT = "alert.config.props.CB.EventSeverity.short"; + @I18NMessages( { @I18NMessage("Event Severity: {0} and matching expression "{1}""), @I18NMessage(locale = "de", value = "Schwere des Ereignesses: {0} und zugehriger Ausdruck "{1}"") }) String ALERT_CONFIG_PROPS_CB_EVENT_SEVERITY_REGEX_MATCH = "alert.config.props.CB.EventSeverity.RegexMatch";
+ @I18NMessages( { @I18NMessage("Sev: {0} & exp "{1}""), + @I18NMessage(locale = "de", value = "Schwere: {0} & Ausdruck "{1}"") }) + String ALERT_CONFIG_PROPS_CB_EVENT_SEVERITY_REGEX_MATCH_SHORT = "alert.config.props.CB.EventSeverity.RegexMatch.short"; + @I18NMessages( { @I18NMessage("value changed"), @I18NMessage(locale = "de", value = "Der Wert hat sich gendert") }) String ALERT_CURRENT_LIST_VALUE_CHANGED = "alert.current.list.ValueChanged";
+ @I18NMessages( { @I18NMessage("val chg"), @I18NMessage(locale = "de", value = "Wertnd.") }) + String ALERT_CURRENT_LIST_VALUE_CHANGED_SHORT = "alert.current.list.ValueChanged.short"; + @I18NMessages( { @I18NMessage("\ - Condition {0}: {1}\n\\n" + "\ - Date/Time: {2}\n\\n" + "\ - Details: {3}\n\\n"), @I18NMessage(locale = "de", value = " - Bedingung {0}: {1}\n\\n - Datum/Uhrzeit: {2}\n\\n" + "\ - Details: {3}\n\\n") }) String ALERT_EMAIL_CONDITION_LOG_FORMAT = "alert.email.condition.log.format"; + + @I18NMessages( { + @I18NMessage("\ - Cond {0}: {1}\n\\n" + "\ - Time: {2}\n\\n" + "\ - Det: {3}\n\\n"), + @I18NMessage(locale = "de", value = " - Bed {0}: {1}\n\\n - Zeit: {2}\n\\n" + + "\ - Det: {3}\n\\n") }) + String ALERT_EMAIL_CONDITION_LOG_FORMAT_SHORT = "alert.email.condition.log.format.short"; } \ No newline at end of file diff --git a/modules/enterprise/server/plugins/alert-irc/src/main/java/org/rhq/enterprise/server/plugins/alertIrc/IrcSender.java b/modules/enterprise/server/plugins/alert-irc/src/main/java/org/rhq/enterprise/server/plugins/alertIrc/IrcSender.java index 93eecc6..95abdb9 100644 --- a/modules/enterprise/server/plugins/alert-irc/src/main/java/org/rhq/enterprise/server/plugins/alertIrc/IrcSender.java +++ b/modules/enterprise/server/plugins/alert-irc/src/main/java/org/rhq/enterprise/server/plugins/alertIrc/IrcSender.java @@ -65,7 +65,7 @@ public class IrcSender extends AlertSender<IrcAlertComponent> { b.append("): "); b.append(alertManager.prettyPrintAlertURL(alert)); b.append("\n"); - b.append(alertManager.prettyPrintAlertConditions(alert)); + b.append(alertManager.prettyPrintAlertConditions(alert, false));
return b.toString(); } diff --git a/modules/enterprise/server/plugins/alert-microblog/src/main/java/org/rhq/enterprise/server/plugins/alertMicroblog/MicroblogSender.java b/modules/enterprise/server/plugins/alert-microblog/src/main/java/org/rhq/enterprise/server/plugins/alertMicroblog/MicroblogSender.java index 257b315..b13763e 100644 --- a/modules/enterprise/server/plugins/alert-microblog/src/main/java/org/rhq/enterprise/server/plugins/alertMicroblog/MicroblogSender.java +++ b/modules/enterprise/server/plugins/alert-microblog/src/main/java/org/rhq/enterprise/server/plugins/alertMicroblog/MicroblogSender.java @@ -57,14 +57,19 @@ public class MicroblogSender extends AlertSender { b.append("' ("); b.append(alert.getAlertDefinition().getResource().getId()); b.append("): "); - b.append(alertManager.prettyPrintAlertConditions(alert)); + b.append(alertManager.prettyPrintAlertConditions(alert, true)); b.append("-by @JBossJopr"); // TODO not for production :-) // TODO use some alert url shortening service
SenderResult result ; String txt = "user@baseUrl [" + user + "@" + baseUrl + "]:"; try { - Status status = twitter.updateStatus(b.toString()); + String msg = b.toString(); + if (msg.length()>140) + msg = msg.substring(0,140); + + Status status = twitter.updateStatus(msg); + result = new SenderResult(ResultState.SUCCESS,"Send notification to " + txt + ", msg-id: " + status.getId()); } catch (TwitterException e) {
diff --git a/modules/enterprise/server/plugins/alert-mobicents/src/main/java/org/rhq/enterprise/server/plugins/alertMobicents/MobicentsSender.java b/modules/enterprise/server/plugins/alert-mobicents/src/main/java/org/rhq/enterprise/server/plugins/alertMobicents/MobicentsSender.java index 649d6ed..b14c85d 100644 --- a/modules/enterprise/server/plugins/alert-mobicents/src/main/java/org/rhq/enterprise/server/plugins/alertMobicents/MobicentsSender.java +++ b/modules/enterprise/server/plugins/alert-mobicents/src/main/java/org/rhq/enterprise/server/plugins/alertMobicents/MobicentsSender.java @@ -74,7 +74,7 @@ public class MobicentsSender extends AlertSender { // Switch locale to english, as the voice synthesizer expects this for now Locale currentLocale = Locale.getDefault(); Locale.setDefault(Locale.ENGLISH); - b.append(alertManager.prettyPrintAlertConditions(alert)); + b.append(alertManager.prettyPrintAlertConditions(alert, false)); Locale.setDefault(currentLocale);
boolean willBeDisabled = alertManager.willDefinitionBeDisabled(alert); diff --git a/modules/enterprise/server/plugins/alert-scriptlang/src/main/java/org.rhq.enterprise.server.plugins.alertScriptlang/ScriptLangSender.java b/modules/enterprise/server/plugins/alert-scriptlang/src/main/java/org.rhq.enterprise.server.plugins.alertScriptlang/ScriptLangSender.java index 985d890..bac51fb 100644 --- a/modules/enterprise/server/plugins/alert-scriptlang/src/main/java/org.rhq.enterprise.server.plugins.alertScriptlang/ScriptLangSender.java +++ b/modules/enterprise/server/plugins/alert-scriptlang/src/main/java/org.rhq.enterprise.server.plugins.alertScriptlang/ScriptLangSender.java @@ -93,7 +93,7 @@ public class ScriptLangSender extends AlertSender<ScriptLangComponent> { Object[] args = new Object[3]; args[0] = alert; args[1] = alertManager.prettyPrintAlertURL(alert); - args[2] = alertManager.prettyPrintAlertConditions(alert); + args[2] = alertManager.prettyPrintAlertConditions(alert, false); result = ((Invocable) engine).invokeFunction("sendAlert", args);
if (result == null) { diff --git a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java index 3fd5d79..045c3bb 100644 --- a/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java +++ b/modules/enterprise/server/plugins/alert-snmp/src/main/java/org/rhq/enterprise/server/plugins/alertSnmp/SnmpSender.java @@ -68,7 +68,7 @@ public class SnmpSender extends AlertSender { String result; List<Resource> lineage = resourceManager.getResourceLineage(alert.getAlertDefinition().getResource().getId()); String platformName = lineage.get(0).getName(); - String conditions = alertManager.prettyPrintAlertConditions(alert); + String conditions = alertManager.prettyPrintAlertConditions(alert, false); String alertUrl = alertManager.prettyPrintAlertURL(alert);
SenderResult res ;
commit e1c760378fe3f3fdcbee42beef05f9930eb3fd65 Author: John Mazzitelli mazz@redhat.com Date: Fri Feb 19 17:51:53 2010 -0500
i think this should report an error always on lock acq failure. we'll leave the flag alone - don't set it to true - let the next call take care of whether or not the init callback should be invoked or not
diff --git a/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/command/client/JBossRemotingRemoteCommunicator.java b/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/command/client/JBossRemotingRemoteCommunicator.java index 8c37b50..cd3b479 100644 --- a/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/command/client/JBossRemotingRemoteCommunicator.java +++ b/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/command/client/JBossRemotingRemoteCommunicator.java @@ -588,11 +588,9 @@ public class JBossRemotingRemoteCommunicator implements RemoteCommunicator { writeLock.unlock(); } } else { - if (m_needToCallInitializeCallback) { - Throwable t = new Throwable("Initialize callback lock could not be acquired"); - LOG.error(CommI18NResourceKeys.INITIALIZE_CALLBACK_FAILED, t.getMessage()); - return new GenericCommandResponse(command, false, null, t); - } + Throwable t = new Throwable("Initialize callback lock could not be acquired"); + LOG.error(CommI18NResourceKeys.INITIALIZE_CALLBACK_FAILED, t.getMessage()); + return new GenericCommandResponse(command, false, null, t); } } return null;
commit 1740b73d4ec9dddf1222fcf99b69a8164c090bbb Author: John Mazzitelli mazz@redhat.com Date: Fri Feb 19 17:44:11 2010 -0500
should not worry about the lock failure if the init callback doesn't need to be invoked anyway
diff --git a/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/command/client/JBossRemotingRemoteCommunicator.java b/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/command/client/JBossRemotingRemoteCommunicator.java index 762b9b4..8c37b50 100644 --- a/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/command/client/JBossRemotingRemoteCommunicator.java +++ b/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/command/client/JBossRemotingRemoteCommunicator.java @@ -588,10 +588,11 @@ public class JBossRemotingRemoteCommunicator implements RemoteCommunicator { writeLock.unlock(); } } else { - m_needToCallInitializeCallback = true; // can't invoke callback, we'll want to still call it later - Throwable t = new Throwable("Initialize callback lock could not be acquired"); - LOG.error(CommI18NResourceKeys.INITIALIZE_CALLBACK_FAILED, t.getMessage()); - return new GenericCommandResponse(command, false, null, t); + if (m_needToCallInitializeCallback) { + Throwable t = new Throwable("Initialize callback lock could not be acquired"); + LOG.error(CommI18NResourceKeys.INITIALIZE_CALLBACK_FAILED, t.getMessage()); + return new GenericCommandResponse(command, false, null, t); + } } } return null;
commit 60fa4314138911d607d6e95110987feb5a7b8fb7 Author: John Mazzitelli mazz@redhat.com Date: Fri Feb 19 17:38:16 2010 -0500
BZ 537396 - to not block indefinitely if a lock cannot be acquired before attempting to invoke the initialize callback
diff --git a/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/command/client/JBossRemotingRemoteCommunicator.java b/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/command/client/JBossRemotingRemoteCommunicator.java index 3775212..762b9b4 100644 --- a/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/command/client/JBossRemotingRemoteCommunicator.java +++ b/modules/enterprise/comm/src/main/java/org/rhq/enterprise/communications/command/client/JBossRemotingRemoteCommunicator.java @@ -21,6 +21,9 @@ package org.rhq.enterprise.communications.command.client; import java.net.MalformedURLException; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import mazz.i18n.Logger;
@@ -95,10 +98,22 @@ public class JBossRemotingRemoteCommunicator implements RemoteCommunicator { private InitializeCallback m_initializeCallback;
/** - * When the first element is <code>true</code>, the initialize callback will need to be called prior - * to sending any commands. This is an array because the array itself is used for its lock. + * When <code>true</code>, the initialize callback will need to be called prior + * to sending any commands. Used in conjunection with its associated RW lock. */ - private final boolean[] m_needToCallInitializeCallback; + private boolean m_needToCallInitializeCallback; + + /** + * RW lock when needing to access its associated atomic boolean flag. + */ + private final ReentrantReadWriteLock m_needToCallInitializeCallbackLock; + + /** + * Number of minutes to wait while attempting to aquire a lock before attempting + * to invoke the initialize callback. If this amount of minutes expires before the lock + * is acquired, an error will occur and the initialize callback will have to be attempted later. + */ + private final long m_initializeCallbackLockAcquisitionTimeoutMins;
/** * Constructor for {@link JBossRemotingRemoteCommunicator} that initializes the client with no invoker locator @@ -200,7 +215,17 @@ public class JBossRemotingRemoteCommunicator implements RemoteCommunicator { m_clientConfiguration.putAll(client_config); }
- m_needToCallInitializeCallback = new boolean[] { false }; + m_needToCallInitializeCallback = false; + m_needToCallInitializeCallbackLock = new ReentrantReadWriteLock(); + + long mins; + try { + String minsStr = System.getProperty("rhq.communications.initial-callback-lock-wait-mins", "60"); + mins = Long.parseLong(minsStr); + } catch (Throwable t) { + mins = 60L; + } + m_initializeCallbackLockAcquisitionTimeoutMins = mins;
return; } @@ -319,7 +344,7 @@ public class JBossRemotingRemoteCommunicator implements RemoteCommunicator { if (m_remotingClient != null) { m_remotingClient.disconnect(); m_remotingClient = null; - m_needToCallInitializeCallback[0] = (getInitializeCallback() != null); // specifically do not synchronize, just set it + m_needToCallInitializeCallback = (getInitializeCallback() != null); // specifically do not synchrononize by using lock, just set it }
LOG.info(CommI18NResourceKeys.COMMUNICATOR_CHANGING_ENDPOINT, m_invokerLocator, locator); @@ -377,7 +402,7 @@ public class JBossRemotingRemoteCommunicator implements RemoteCommunicator {
public void setInitializeCallback(InitializeCallback callback) { m_initializeCallback = callback; - m_needToCallInitializeCallback[0] = (callback != null); // specifically do not synchronize, just set it + m_needToCallInitializeCallback = (callback != null); // specifically do not synchrononize by using lock, just set it }
public String getRemoteEndpoint() { @@ -403,7 +428,7 @@ public class JBossRemotingRemoteCommunicator implements RemoteCommunicator { public void connect() throws Exception { if ((m_remotingClient != null) && !m_remotingClient.isConnected()) { m_remotingClient.connect(); - m_needToCallInitializeCallback[0] = (getInitializeCallback() != null); // specifically do not synchronize, just set it + m_needToCallInitializeCallback = (getInitializeCallback() != null); // specifically do not synchrononize by using lock, just set it }
return; @@ -412,7 +437,7 @@ public class JBossRemotingRemoteCommunicator implements RemoteCommunicator { public void disconnect() { if (m_remotingClient != null) { m_remotingClient.disconnect(); - m_needToCallInitializeCallback[0] = (getInitializeCallback() != null); // specifically do not synchronize, just set it + m_needToCallInitializeCallback = (getInitializeCallback() != null); // specifically do not synchrononize by using lock, just set it }
return; @@ -535,18 +560,38 @@ public class JBossRemotingRemoteCommunicator implements RemoteCommunicator { private CommandResponse invokeInitializeCallbackIfNeeded(Command command) { InitializeCallback callback = getInitializeCallback(); if (callback != null) { - // block here - in effect, this will stop all commands from going out until the callback is done - synchronized (m_needToCallInitializeCallback) { - if (m_needToCallInitializeCallback[0]) { - try { - m_needToCallInitializeCallback[0] = !callback.sendingInitialCommand(this, command); - LOG.debug(CommI18NResourceKeys.INITIALIZE_CALLBACK_DONE, m_needToCallInitializeCallback[0]); - } catch (Throwable t) { - m_needToCallInitializeCallback[0] = true; // callback failed, we'll want to call it again - LOG.error(t, CommI18NResourceKeys.INITIALIZE_CALLBACK_FAILED, ThrowableUtil.getAllMessages(t)); - return new GenericCommandResponse(command, false, null, t); + // block here - in effect, this will stop all commands from going out until the callback is done + // to avoid infinite blocking, we'll only wait for a set time (though long). + + WriteLock writeLock = m_needToCallInitializeCallbackLock.writeLock(); + boolean locked; + try { + locked = writeLock.tryLock(m_initializeCallbackLockAcquisitionTimeoutMins, TimeUnit.MINUTES); + } catch (InterruptedException ie) { + locked = false; + } + + if (locked) { + try { + if (m_needToCallInitializeCallback) { + try { + m_needToCallInitializeCallback = (!callback.sendingInitialCommand(this, command)); + LOG.debug(CommI18NResourceKeys.INITIALIZE_CALLBACK_DONE, m_needToCallInitializeCallback); + } catch (Throwable t) { + m_needToCallInitializeCallback = true; // callback failed, we'll want to call it again + LOG.error(t, CommI18NResourceKeys.INITIALIZE_CALLBACK_FAILED, ThrowableUtil + .getAllMessages(t)); + return new GenericCommandResponse(command, false, null, t); + } } + } finally { + writeLock.unlock(); } + } else { + m_needToCallInitializeCallback = true; // can't invoke callback, we'll want to still call it later + Throwable t = new Throwable("Initialize callback lock could not be acquired"); + LOG.error(CommI18NResourceKeys.INITIALIZE_CALLBACK_FAILED, t.getMessage()); + return new GenericCommandResponse(command, false, null, t); } } return null;
commit 474b186034125b179eb03e1ff069036a3299f730 Author: John Mazzitelli mazz@redhat.com Date: Fri Feb 19 11:10:53 2010 -0500
BZ 566724 - if classloader fails to be created, master PC will skip the plugin
diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java index f46eaf5..bd4feac 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/MasterServerPluginContainer.java @@ -136,16 +136,23 @@ public class MasterServerPluginContainer { String pluginName = descriptor.getName(); ServerPluginType pluginType = new ServerPluginType(descriptor); PluginKey pluginKey = PluginKey.createServerPluginKey(pluginType.stringify(), pluginName); - ClassLoader classLoader = this.classLoaderManager.obtainServerPluginClassLoader(pluginKey); - log.debug("Pre-loading server plugin [" + pluginKey + "] from [" + pluginUrl - + "] into its plugin container"); try { - ServerPluginEnvironment env = new ServerPluginEnvironment(pluginUrl, classLoader, descriptor); - boolean enabled = !allDisabledPlugins.contains(pluginKey); - pc.loadPlugin(env, enabled); - log.info("Preloaded server plugin [" + pluginKey.getPluginName() + "]"); + ClassLoader classLoader = this.classLoaderManager.obtainServerPluginClassLoader(pluginKey); + log.debug("Pre-loading server plugin [" + pluginKey + "] from [" + pluginUrl + + "] into its plugin container"); + try { + ServerPluginEnvironment env = new ServerPluginEnvironment(pluginUrl, classLoader, + descriptor); + boolean enabled = !allDisabledPlugins.contains(pluginKey); + pc.loadPlugin(env, enabled); + log.info("Preloaded server plugin [" + pluginName + "]"); + } catch (Exception e) { + log.warn("Failed to preload server plugin [" + pluginName + "] from URL [" + pluginUrl + + "]", e); + } } catch (Exception e) { - log.warn("Failed to preload server plugin [" + pluginUrl + "]", e); + log.warn("Failed to preload server plugin [" + pluginName + + "]; cannot get its classloader from URL [ " + pluginUrl + "]", e); } } else { log.warn("There is no server plugin container to support plugin: " + pluginUrl); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginClassLoader.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginClassLoader.java index 9f27ce9..fa26970 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginClassLoader.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/plugin/pc/ServerPluginClassLoader.java @@ -64,7 +64,7 @@ public class ServerPluginClassLoader extends URLClassLoader { try { unpackedDirectory = unpackEmbeddedJars(pluginJarName, pluginUrl, classpathUrlList, tmpDirectory); } catch (Exception e) { - throw new Exception("Failed to unpack embedded JARs within: " + pluginUrl); + throw new Exception("Failed to unpack embedded JARs within: " + pluginUrl, e); } } }
commit b5e46e4c6e802cdf883307c46e5a275a94514457 Author: Heiko W. Rupp pilhuhn@fedorapeople.org Date: Fri Feb 19 13:37:36 2010 +0100
Fix link to definitions BZ 566004
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 b6e386c..fd09f82 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 @@ -148,8 +148,7 @@ </onc:sortableColumnHeader> </f:facet>
- <h:outputLink value="/alerts/Config.do"> - <f:param name="mode" value="viewRoles"/> + <h:outputLink value="/rhq/resource/alert/viewAlert.xhtml"> <f:param name="id" value="#{Resource.id}"/> <f:param name="ad" value="#{item.alert.alertDefinition.id}"/> <h:outputText value="#{item.alert.alertDefinition.name}" />