2 * ============LICENSE_START=======================================================
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 package org.openecomp.policy.pdp.rest;
24 import java.text.DateFormat;
25 import java.text.ParseException;
26 import java.text.SimpleDateFormat;
27 import java.util.Arrays;
28 import java.util.Date;
29 import java.util.NoSuchElementException;
30 import java.util.Properties;
32 import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
33 import org.openecomp.policy.common.logging.flexlogger.Logger;
34 import org.openecomp.policy.rest.XACMLRestProperties;
36 import com.att.research.xacml.util.XACMLProperties;
38 public class PapUrlResolver {
39 private static final Logger LOGGER = FlexLogger.getLogger(PapUrlResolver.class);
40 //how long to keep a pap failed before making it un-failed, in milli-seconds
41 private static final long FAIL_TIMEOUT = 18000000;
44 public static final Object propertyLock = new Object();
46 //keeping this here for backward compatibility
47 public static String extractIdFromUrl(String url){
48 return extractQuery(url);
50 public static String extractQuery(String url){
52 return URI.create(url).getQuery();
54 LOGGER.error("Exception occured while extracting query. So, empty string is returned"+e);
58 public static String modifyUrl(String idUrl, String serverUrl){
59 URI one = URI.create(idUrl);
60 String host = one.getPath()+one.getQuery();
61 URI two = URI.create(serverUrl);
63 return two.toString();
66 //get an instance of a new PapUrlResolver, using XACMLProperties to get the url lists
67 public static PapUrlResolver getInstance(){
68 return new PapUrlResolver(null,null,null,true);
71 //get an instance of a new PapUrlResolver, using the provides strings for the url lists
72 public static PapUrlResolver getInstance(String urlList, String failedList, String succeededList){
73 return new PapUrlResolver(urlList, failedList, succeededList,false);
76 //keeps track of our current location in the list of urls, allows for iterating
79 //should the XACML property lists be updated after anything changes or should we wait for the update
80 //method to be called.
81 private boolean autoUpdateProperties;
83 //this list keeps the sorted, priority of PAP URLs
84 private PapUrlNode[] sortedUrlNodes;
85 //this list keeps the original list of nodes so that they can be entered into the property list correctly
86 private PapUrlNode[] originalUrlNodes;
88 //private constructor to make an instance of a PapUrlResolver, called by static method getInstance.
89 //If the list property strings are not defined, we get the values from XACMLProperties.
90 //The instance acts as an iterator, with hasNext and next methods, but does not implement Iterable,
91 //because it is used for a difference purpose.
92 private PapUrlResolver(String urlList, String failedList, String succeededList, boolean autoUpdateProperties){
93 this.autoUpdateProperties = autoUpdateProperties;
94 String papUrlLists = urlList;
95 String papUrlFailedList = failedList;
96 String papUrlSuccessList = succeededList;
97 if(papUrlLists == null){
98 papUrlLists = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URLS);
99 if(papUrlLists == null){
100 papUrlLists = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL);
102 papUrlFailedList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS);
103 papUrlSuccessList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS);
106 String[] urls = papUrlLists.split(",");
107 if(urls.length == 0){
110 String[] failed = emptyOrSplit(papUrlFailedList,urls.length);
111 String[] succeeded = emptyOrSplit(papUrlSuccessList,urls.length);
113 sortedUrlNodes = new PapUrlNode[urls.length];
114 for(int i=0;i<urls.length;i++){
116 String userId = null;
118 userId = XACMLProperties.getProperty(urls[i]+"."+XACMLRestProperties.PROP_PAP_USERID);
119 pass = XACMLProperties.getProperty(urls[i]+"."+XACMLRestProperties.PROP_PAP_PASS);
120 if(userId == null || pass == null){
121 userId = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID);
122 pass = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS);
124 if(userId == null || pass == null){
128 PapUrlNode newNode = new PapUrlNode(urls[i],userId,pass);
129 newNode.setFailedTime(failed[i]);
130 newNode.setSucceededTime(succeeded[i]);
131 if(sortedUrlNodes[i] == null){
132 sortedUrlNodes[i] = newNode;
135 originalUrlNodes = sortedUrlNodes.clone();
136 sort(sortedUrlNodes);
141 //either split a list by commas, or fill an array to the expected length, if the property list is not long enough
142 private String[] emptyOrSplit(String list,int expectedLength){
145 ret = new String[expectedLength];
146 for(int i=0;i<expectedLength;i++){
150 ret = list.split(",");
151 if(ret.length != expectedLength){
152 ret = emptyOrSplit(null,expectedLength);
158 private void sort(PapUrlNode[] array){
160 //O(n^2) double-loop most likely the best in this case, since number of records will be VERY small
161 for(int i=0;i<array.length;i++){
162 for(int j=i;j<array.length;j++){
163 if(array[j].compareTo(array[i])<0){
164 PapUrlNode temp = array[i];
172 //returns whether this PapUrlResolver object has more PAP urls that can be tried
173 public boolean hasMoreUrls(){
174 return pointer < sortedUrlNodes.length;
177 //sets the current PAP url as being failed
178 //this will set the failed time to now and remove any succeeded time
179 public void failed(){
180 LOGGER.error("PAP Server FAILED: "+sortedUrlNodes[pointer].getUrl());
182 sortedUrlNodes[pointer].setFailedTime(new Date());
183 sortedUrlNodes[pointer].setSucceededTime(null);
187 //sets the current PAP url as being working
188 //this will set the succeeded time to now and remove any failed time
189 //Also, this will cause hasMoreUrls to return false, since a working one has been found
191 public void succeeded(){
193 pointer = sortedUrlNodes.length;
195 public void registered(){
196 sortedUrlNodes[pointer].setFailedTime(null);
197 sortedUrlNodes[pointer].setSucceededTime(new Date());
198 LOGGER.info("PAP server SUCCEEDED "+sortedUrlNodes[pointer].getUrl());
202 //returns a properties object with the properties that pertain to PAP urls
203 public Properties getProperties(){
204 String failedPropertyString = "";
205 String succeededPropertyString = "";
206 String urlPropertyString = "";
207 for(int i=0;i<originalUrlNodes.length;i++){
208 failedPropertyString = failedPropertyString.concat(",").concat(originalUrlNodes[i].getFailedTime());
209 succeededPropertyString = succeededPropertyString.concat(",").concat(originalUrlNodes[i].getSucceededTime());
210 urlPropertyString = urlPropertyString.concat(",").concat(originalUrlNodes[i].getUrl());
212 Properties prop = new Properties();
213 failedPropertyString = failedPropertyString.substring(1);
214 succeededPropertyString = succeededPropertyString.substring(1);
215 urlPropertyString = urlPropertyString.substring(1);
216 prop.setProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS,failedPropertyString);
217 prop.setProperty(XACMLRestProperties.PROP_PAP_URLS,urlPropertyString);
218 prop.setProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS,succeededPropertyString);
222 //saves the updates urls to the correct properties
223 private void propertiesUpdated(){
224 if(!autoUpdateProperties){
227 Properties prop = getProperties();
229 LOGGER.debug("Failed PAP Url List: "+prop.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS));
230 LOGGER.debug("Succeeded PAP Url List: "+prop.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS));
231 XACMLProperties.setProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS,prop.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS));
232 XACMLProperties.setProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS,prop.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS));
235 //iterates to the next available PAP url, according to the priority order
236 public void getNext(){
240 //returns the url of the current PAP server that we are iterating over
241 //will append the provided policy id to the url
242 public String getUrl(String query){
243 if(sortedUrlNodes[pointer]== null){
244 throw new NoSuchElementException();
246 return sortedUrlNodes[pointer].getUrl().concat("?").concat(query);
250 //returns the url of the current PAP server that we are iterating over
251 //Just returns the url, with no id appended to it
252 public String getUrl(){
253 if(sortedUrlNodes[pointer]== null){
254 throw new NoSuchElementException();
257 return sortedUrlNodes[pointer].getUrl();
260 public String getUserId(){
261 if(sortedUrlNodes[pointer]== null){
262 throw new NoSuchElementException();
265 return sortedUrlNodes[pointer].getUserId();
268 public String getPass(){
269 if(sortedUrlNodes[pointer]== null){
270 throw new NoSuchElementException();
273 return sortedUrlNodes[pointer].getPass();
278 //This is the class to hold the details of a single PAP URL
279 //including: the url itself, the last time it failed, and the last time it succeeded
280 //It also includes the custom comparer which can compare based on failed and succeeded times, and takes into account
281 //the timeout on failures.
282 private class PapUrlNode implements Comparable<PapUrlNode> {
283 private String papUrl;
284 private Date failedTime;
285 private Date succeededTime;
286 private String userId;
289 public PapUrlNode(String url,String userId,String pass){
292 this.succeededTime = null;
293 this.userId = userId;
297 public String getUserId(){
300 public String getPass(){
304 public void setFailedTime(Object time){
305 Date failedTimeAsDate = setHandler(time);
306 if(failedTimeAsDate == null){
307 this.failedTime = null;
309 long timeDifference = new Date().getTime() - failedTimeAsDate.getTime();
310 if(timeDifference < FAIL_TIMEOUT){
311 this.failedTime = failedTimeAsDate;
313 this.failedTime = null;
318 //set the time that this url succeeded at
319 public void setSucceededTime(Object time){
320 this.succeededTime = setHandler(time);
323 //parses string into a date or a null date, if the url never failed/succeeded (since -1 will be in the property)
324 private Date setHandler(Object time){
325 if(time instanceof String){
326 if("-1".equals((String)time)){
330 DateFormat df = new SimpleDateFormat();
331 return df.parse((String)time);
332 } catch (ParseException e) {
336 if(time instanceof Date){
343 public String getFailedTime(){
344 return formatTime(this.failedTime);
347 public String getSucceededTime(){
348 return formatTime(this.succeededTime);
351 //formats a Date into a string or a -1 if there is not date (-1 is used in properties for no date)
352 private String formatTime(Date d){
356 DateFormat df = new SimpleDateFormat();
360 public String getUrl(){
365 public int compareTo(PapUrlNode other){
366 if(this.failedTime == null && other.failedTime != null){
369 if(this.failedTime != null && other.failedTime == null){
372 if(this.failedTime != null){
373 return this.failedTime.compareTo(other.failedTime);