View Javadoc

1   package org.apache.helix.alerts;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.HashMap;
23  import java.util.Map;
24  
25  import org.apache.helix.HelixException;
26  import org.apache.helix.manager.zk.DefaultParticipantErrorMessageHandlerFactory.ActionOnError;
27  import org.apache.log4j.Logger;
28  
29  
30  public class AlertParser {
31  	private static Logger logger = Logger.getLogger(AlertParser.class);
32  	
33  	public static final String EXPRESSION_NAME = "EXP";
34  	public static final String COMPARATOR_NAME = "CMP";
35  	public static final String CONSTANT_NAME = "CON";
36  	public static final String ACTION_NAME = "ACTION";
37  	
38  	static Map<String, AlertComparator> comparatorMap = new HashMap<String, AlertComparator>();
39  	
40  	static
41  	  {
42  		  
43  		  addComparatorEntry("GREATER", new GreaterAlertComparator());
44  	  }
45  	
46  	 private static void addComparatorEntry(String label, AlertComparator comp)
47  	  {
48  		  if (!comparatorMap.containsKey(label))
49  		    {
50  		      comparatorMap.put(label, comp);
51  		    }
52  		    logger.info("Adding comparator: "+comp);
53  	  }
54  	
55  	public static AlertComparator getComparator(String compName)
56  	{
57  		compName = compName.replaceAll("\\s+", ""); //remove white space
58  		if (!comparatorMap.containsKey(compName)) {
59  			throw new HelixException("Comparator type <"+compName+"> unknown");
60  		}
61  		return comparatorMap.get(compName);
62  	}
63  	 
64  	public static String getComponent(String component, String alert) throws HelixException
65  	{
66  		//find EXP and keep going until paren are closed
67  		int expStartPos = alert.indexOf(component);
68  		if (expStartPos < 0) {
69  			throw new HelixException(alert+" does not contain component "+component);
70  		}
71  		expStartPos += (component.length()+1); //advance length of string and one for open paren
72  		int expEndPos = expStartPos;
73  		int openParenCount = 1;
74  		while (openParenCount > 0) {
75  			if (alert.charAt(expEndPos) == '(') {
76  				openParenCount++;
77  			}
78  			else if (alert.charAt(expEndPos) == ')') {
79  				openParenCount--;
80  			}
81  			expEndPos++;
82  		}
83  		if (openParenCount != 0) {
84  			throw new HelixException(alert+" does not contain valid "+component+" component, " +
85  					"parentheses do not close");
86  		}
87  		//return what is in between paren
88  		return alert.substring(expStartPos, expEndPos-1);
89  	}
90  	
91  	public static boolean validateAlert(String alert) throws HelixException
92  	{
93  		//TODO: decide if toUpperCase is going to cause problems with stuff like db name
94  		alert = alert.replaceAll("\\s+", ""); //remove white space
95  		String exp = getComponent(EXPRESSION_NAME, alert);
96  		String cmp = getComponent(COMPARATOR_NAME, alert);
97  		String val = getComponent(CONSTANT_NAME, alert);
98  		logger.debug("exp: "+exp);
99  		logger.debug("cmp: "+cmp);
100 		logger.debug("val: "+val);
101 		
102 		//separately validate each portion
103 		ExpressionParser.validateExpression(exp);
104 		
105 		//validate comparator
106 		if (!comparatorMap.containsKey(cmp.toUpperCase())) {
107 			throw new HelixException("Unknown comparator type "+cmp);
108 		}
109 		String actionValue = null;
110     try
111     {
112       actionValue = AlertParser.getComponent(AlertParser.ACTION_NAME, alert);
113     }
114     catch(Exception e)
115     {
116       logger.info("No action specified in " + alert);
117     }
118 
119     if(actionValue != null)
120     {
121       validateActionValue(actionValue);
122     }
123 		//ValParser.  Probably don't need this.  Just make sure it's a valid tuple.  But would also be good
124 		//to validate that the tuple is same length as exp's output...maybe leave that as future todo
125 		//not sure we can really do much here though...anything can be in a tuple.
126 		
127 		//TODO: try to compare tuple width of CON against tuple width of agg type!  Not a good idea, what if
128 		//is not at full width yet, like with window  
129 		
130 		//if all of this passes, then we can safely record the alert in zk.  still need to implement zk location
131 		
132 		return false;
133 	}
134 	
135   public static void validateActionValue(String actionValue)
136   {
137     try
138     {
139       ActionOnError actionVal = ActionOnError.valueOf(actionValue);
140     }
141     catch(Exception e)
142     {
143       String validActions = "";
144       for (ActionOnError action : ActionOnError.values())
145       {
146         validActions = validActions + action + " ";
147       }
148       throw new HelixException("Unknown cmd type " + actionValue + ", valid types : " + validActions);
149     }
150   }
151 }