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