Merge "Adding simple, missing junit"
[policy/engine.git] / PolicyEngineUtils / src / main / java / org / onap / policy / utils / PolicyUtils.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * PolicyEngineUtils
4  * ================================================================================
5  * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.utils;
22
23 import java.io.IOException;
24 import java.io.StringReader;
25 import java.io.UnsupportedEncodingException;
26 import java.util.Arrays;
27 import java.util.Base64;
28 import java.util.List;
29 import java.util.Scanner;
30 import java.util.StringTokenizer;
31 import java.util.regex.Matcher;
32 import java.util.regex.Pattern;
33
34 import javax.xml.XMLConstants;
35 import javax.xml.parsers.SAXParser;
36 import javax.xml.parsers.SAXParserFactory;
37
38 import org.drools.core.io.impl.ReaderResource;
39 import org.drools.verifier.Verifier;
40 import org.drools.verifier.VerifierError;
41 import org.drools.verifier.builder.VerifierBuilder;
42 import org.drools.verifier.builder.VerifierBuilderFactory;
43 import org.kie.api.io.ResourceType;
44 import org.onap.policy.common.logging.flexlogger.FlexLogger;
45 import org.onap.policy.common.logging.flexlogger.Logger;
46 import org.xml.sax.InputSource;
47 import org.xml.sax.XMLReader;
48
49 import com.fasterxml.jackson.core.JsonProcessingException;
50 import com.fasterxml.jackson.databind.ObjectMapper;
51 import com.google.common.base.CharMatcher;
52 import com.google.gson.JsonParser;
53 import com.google.gson.JsonSyntaxException;
54
55 public class PolicyUtils {
56     private static final Logger LOGGER = FlexLogger.getLogger(PolicyUtils.class);
57     public static final String CATCH_EXCEPTION = "PE500: An exception was caught.";  
58     public static final String EMAIL_PATTERN =
59             "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
60             + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";
61     private static final String PACKAGE_ERROR = "mismatched input '{' expecting one of the following tokens: '[package";
62     public static final String SUCCESS = "success";
63     
64     private PolicyUtils(){
65         // Private Constructor
66     }
67     
68     /**
69      * Converts an Object to JSON String 
70      * 
71      * @param o Object 
72      * @return String format of Object JSON. 
73      * @throws JsonProcessingException
74      */
75     public static String objectToJsonString(Object o) throws JsonProcessingException{
76         ObjectMapper mapper = new ObjectMapper();
77         return mapper.writeValueAsString(o);
78     }
79     
80     /**
81      * Converts JSON string into Object
82      * 
83      * @param jsonString 
84      * @param className equivalent Class of the given JSON string 
85      * @return T instance of the class given. 
86      * @throws IOException
87      */
88     public static <T> T jsonStringToObject(String jsonString, Class<T> className) throws IOException{
89         ObjectMapper mapper = new ObjectMapper();
90         return mapper.readValue(jsonString, className);
91     }
92     
93     /**
94      * Decode a base64 string 
95      * 
96      * @param encodedString
97      * @return String
98      * @throws UnsupportedEncodingException
99      */
100     public static String decode(String encodedString) throws UnsupportedEncodingException { 
101         if(encodedString!=null && !encodedString.isEmpty()){ 
102             return new String(Base64.getDecoder().decode(encodedString) ,"UTF-8"); 
103         }else{ 
104             return null; 
105         } 
106     }
107     
108     /**
109      * Decodes Basic Authentication 
110      * 
111      * @param encodedValue
112      * @return
113      * @throws UnsupportedEncodingException
114      */
115     public static String[] decodeBasicEncoding(String encodedValue) throws UnsupportedEncodingException {
116         if(encodedValue!=null && encodedValue.contains("Basic ")){
117             String encodedUserPassword = encodedValue.replaceFirst("Basic"  + " ", "");
118             String usernameAndPassword;
119             byte[] decodedBytes = Base64.getDecoder().decode(encodedUserPassword);
120             usernameAndPassword = new String(decodedBytes, "UTF-8");
121             StringTokenizer tokenizer = new StringTokenizer(usernameAndPassword, ":");
122             String username = tokenizer.nextToken();
123             String password = tokenizer.nextToken();
124             return new String[]{username, password};
125         }else{
126             return new String[]{};
127         }
128     }
129     
130     /**
131      * Validate a field if contains space or unacceptable policy input and return "success" if good. 
132      * 
133      * @param field
134      * @return
135      */
136     public static String  policySpecialCharValidator(String field){
137         String error;
138         if ("".equals(field) || field.contains(" ") || !field.matches("^[a-zA-Z0-9_]*$")) {
139             error = "The Value in Required Field will allow only '{0-9}, {a-z}, {A-Z}, _' following set of Combinations";
140             return error; 
141         }
142         return SUCCESS;   
143     } 
144     
145     /**
146      * Validate a field (accepts space) if it contains unacceptable policy input and return "success" if good. 
147      * 
148      * @param field
149      * @return
150      */
151     public static String  policySpecialCharWithSpaceValidator(String field){
152         String error;
153         if ("".equals(field) || !field.matches("^[a-zA-Z0-9_ ]*$")) {
154             error = "The Value in Required Field will allow only '{0-9}, {a-z}, {A-Z}, _' following set of Combinations";
155             return error;
156         }
157         return SUCCESS;   
158     } 
159     
160     /**
161      * Validate a field (accepts Dash) if it contains unacceptable policy input and return "success" if good. 
162      * 
163      * @param field
164      * @return
165      */
166     public static String  policySpecialCharWithDashValidator(String field){
167         String error;
168         if ("".equals(field) || !field.matches("^[a-zA-Z0-9_-]*$")) {
169             error = "The Value in Required Field will allow only '{0-9}, {a-z}, {A-Z}, _, -' following set of Combinations";
170             return error;
171         }
172         return SUCCESS;   
173     } 
174     
175     /**
176      * Validate the XACML description tag and return "success" if good. 
177      * 
178      * @param field
179      * @return
180      */
181     public static String descriptionValidator(String field) {
182         String error;
183         if (field.contains("@CreatedBy:") || field.contains("@ModifiedBy:")) {
184              error = "The value in the description shouldn't contain @CreatedBy: or @ModifiedBy:";
185              return error;
186         } else {
187             error = SUCCESS;
188         }
189         return error;   
190     }
191     
192     /**
193      * Validate if string contains non ASCII characters 
194      * 
195      * @param value
196      * @return
197      */
198     public static boolean containsNonAsciiEmptyChars(String value) {
199         return (value == null || value.contains(" ") || "".equals(value.trim()) || !CharMatcher.ascii().matchesAllOf((CharSequence) value)) ? true : false;
200     }
201     
202     /**
203      * Validate if given string is an integer. 
204      * 
205      * @param number
206      * @return
207      */
208     public static Boolean isInteger(String number){
209         if(number==null) {
210             return false;
211         }
212         for (char c : number.toCharArray()){
213             if (!Character.isDigit(c)) {
214                 return false;
215             }
216         }
217         return true;
218     }
219     
220     /**
221      * Validate Email Address and return "success" if good. 
222      * 
223      * @param emailAddressValue
224      * @return
225      */
226     public static String validateEmailAddress(String emailAddressValue) {
227         String error = SUCCESS;
228         List<String> emailList = Arrays.asList(emailAddressValue.split(","));
229         for(int i =0 ; i < emailList.size() ; i++){
230             Pattern pattern = Pattern.compile(EMAIL_PATTERN);
231             Matcher matcher = pattern.matcher(emailList.get(i).trim());
232             if(!matcher.matches()){
233                 error = "Please check the Following Email Address is not Valid ....   " +emailList.get(i);
234                 return error;
235             }else{
236                 error = SUCCESS;
237             }
238         }
239         return error;       
240     }
241     
242     /**
243      * Validates BRMS rule as per Policy Platform and return string contains "[ERR" if there are any errors.
244      * 
245      * @param rule
246      * @return String error message
247      */
248     public static String brmsRawValidate(String rule){
249         VerifierBuilder vBuilder = VerifierBuilderFactory.newVerifierBuilder();
250         Verifier verifier = vBuilder.newVerifier();
251         verifier.addResourcesToVerify(new ReaderResource(new StringReader(rule)), ResourceType.DRL);
252         // Check if there are any Errors in Verification. 
253         if(!verifier.getErrors().isEmpty()){
254             boolean ignore = false;
255             StringBuilder message = new StringBuilder("Not a Valid DRL rule"); 
256             for(VerifierError error: verifier.getErrors()){
257                 // Ignore annotations Error Messages
258                 if(!error.getMessage().contains("'@'") && !error.getMessage().contains(PACKAGE_ERROR)){
259                     ignore= true;
260                     message.append("\n" + error.getMessage());
261                 }
262             }
263             // Ignore new package names with '{'
264             // More checks for message to check if its a package error.
265             if(ignore && !message.toString().contains("Parser returned a null Package")){
266                 message.append("[ERR 107]");
267             }
268             return message.toString();
269         }
270         return "";
271     }
272     
273     /**
274      * Validates if the given string is proper JSON format. 
275      * 
276      * @param data
277      * @return
278      */
279     public static boolean isJSONValid(String data) {
280         try{
281             JsonParser parser = new JsonParser();
282             parser.parse(data);
283         }catch(JsonSyntaxException e){
284             LOGGER.error("Exception Occurred While Validating"+e);
285             return false;
286         }
287         return true;
288     }
289
290     /**
291      * Validates if the given string is proper XML format. 
292      * 
293      * @param data
294      * @return
295      */
296     public static boolean isXMLValid(String data) {
297         if(data == null || data.isEmpty()){
298                 return false;
299         }
300         SAXParserFactory factory = SAXParserFactory.newInstance();
301         factory.setValidating(false);
302         factory.setNamespaceAware(true);
303         
304         try {    
305                         factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);               
306             SAXParser parser = factory.newSAXParser();
307             XMLReader reader = parser.getXMLReader();
308             reader.setErrorHandler(new XMLErrorHandler());
309             reader.parse(new InputSource(new StringReader(data)));
310         } catch (Exception e) {
311             LOGGER.error("Exception Occured While Validating"+e);
312             return false;
313         }
314         return true;
315     }
316
317     /**
318      * Validates if given string is valid Properties format. 
319      * 
320      * @param prop
321      * @return
322      */
323     public static boolean isPropValid(String prop) {
324         Scanner scanner = new Scanner(prop);
325         while (scanner.hasNextLine()) {
326             String line = scanner.nextLine();
327             line = line.replaceAll("\\s+", "");
328             if (line.startsWith("#")) {
329                 continue;
330             } else {
331                 if (line.contains("=")) {
332                     String[] parts = line.split("=");
333                     if (parts.length < 2) {
334                         scanner.close();
335                         return false;
336                     }
337                 } else if(!line.trim().isEmpty()){
338                     scanner.close();
339                     return false;
340                 }
341             }
342         }
343         scanner.close();
344         return true;
345     }
346     
347     /**
348      * Given a version string consisting of integers with dots between them, convert it into an array of integers.
349      * 
350      * @param version
351      * @return 
352      * @throws NumberFormatException
353      */
354     public static int[] versionStringToArray(String version){
355         if (version == null || version.length() == 0) {
356             return new int[0];
357         }
358         String[] stringArray = version.split("\\.");
359         int[] resultArray = new int[stringArray.length];
360         for (int i = 0; i < stringArray.length; i++) {
361             resultArray[i] = Integer.parseInt(stringArray[i].trim());
362         }
363         return resultArray;
364     }
365 }