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.Date;
28 import java.util.NoSuchElementException;
29 import java.util.Properties;
31 import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
32 import org.openecomp.policy.common.logging.flexlogger.Logger;
33 import org.openecomp.policy.rest.XACMLRestProperties;
35 import com.att.research.xacml.util.XACMLProperties;
37 public class PapUrlResolver {
38 private static final Logger LOGGER = FlexLogger.getLogger(PapUrlResolver.class);
39 //how long to keep a pap failed before making it un-failed, in milli-seconds
40 private static final long FAIL_TIMEOUT = 18000000;
43 public static final Object propertyLock = new Object();
45 //keeping this here for backward compatibility
46 public static String extractIdFromUrl(String url){
47 return extractQuery(url);
49 public static String extractQuery(String url){
51 return URI.create(url).getQuery();
53 LOGGER.error("Exception occured while extracting query. So, empty string is returned"+e);
57 public static String modifyUrl(String idUrl, String serverUrl){
58 URI one = URI.create(idUrl);
59 String host = one.getPath()+one.getQuery();
60 URI two = URI.create(serverUrl);
62 return two.toString();
65 //get an instance of a new PapUrlResolver, using XACMLProperties to get the url lists
66 public static PapUrlResolver getInstance(){
67 return new PapUrlResolver(null,null,null,true);
70 //get an instance of a new PapUrlResolver, using the provides strings for the url lists
71 public static PapUrlResolver getInstance(String urlList, String failedList, String succeededList){
72 return new PapUrlResolver(urlList, failedList, succeededList,false);
75 //keeps track of our current location in the list of urls, allows for iterating
78 //should the XACML property lists be updated after anything changes or should we wait for the update
79 //method to be called.
80 private boolean autoUpdateProperties;
82 //this list keeps the sorted, priority of PAP URLs
83 private PapUrlNode[] sortedUrlNodes;
84 //this list keeps the original list of nodes so that they can be entered into the property list correctly
85 private PapUrlNode[] originalUrlNodes;
87 //private constructor to make an instance of a PapUrlResolver, called by static method getInstance.
88 //If the list property strings are not defined, we get the values from XACMLProperties.
89 //The instance acts as an iterator, with hasNext and next methods, but does not implement Iterable,
90 //because it is used for a difference purpose.
91 private PapUrlResolver(String urlList, String failedList, String succeededList, boolean autoUpdateProperties){
92 this.autoUpdateProperties = autoUpdateProperties;
93 String papUrlLists = urlList;
94 String papUrlFailedList = failedList;
95 String papUrlSuccessList = succeededList;
96 if(papUrlLists == null){
97 papUrlLists = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URLS);
98 if(papUrlLists == null){
99 papUrlLists = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL);
101 papUrlFailedList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS);
102 papUrlSuccessList = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS);
105 String[] urls = papUrlLists.split(",");
106 if(urls.length == 0){
109 String[] failed = emptyOrSplit(papUrlFailedList,urls.length);
110 String[] succeeded = emptyOrSplit(papUrlSuccessList,urls.length);
112 sortedUrlNodes = new PapUrlNode[urls.length];
113 for(int i=0;i<urls.length;i++){
115 String userId = null;
117 userId = XACMLProperties.getProperty(urls[i]+"."+XACMLRestProperties.PROP_PAP_USERID);
118 pass = XACMLProperties.getProperty(urls[i]+"."+XACMLRestProperties.PROP_PAP_PASS);
119 if(userId == null || pass == null){
120 userId = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID);
121 pass = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS);
123 if(userId == null || pass == null){
127 PapUrlNode newNode = new PapUrlNode(urls[i],userId,pass);
128 newNode.setFailedTime(failed[i]);
129 newNode.setSucceededTime(succeeded[i]);
130 if(sortedUrlNodes[i] == null){
131 sortedUrlNodes[i] = newNode;
134 originalUrlNodes = sortedUrlNodes.clone();
135 sort(sortedUrlNodes);
140 //either split a list by commas, or fill an array to the expected length, if the property list is not long enough
141 private String[] emptyOrSplit(String list,int expectedLength){
144 ret = new String[expectedLength];
145 for(int i=0;i<expectedLength;i++){
149 ret = list.split(",");
150 if(ret.length != expectedLength){
151 ret = emptyOrSplit(null,expectedLength);
157 private void sort(PapUrlNode[] array){
159 //O(n^2) double-loop most likely the best in this case, since number of records will be VERY small
160 for(int i=0;i<array.length;i++){
161 for(int j=i;j<array.length;j++){
162 if(array[j].compareTo(array[i])<0){
163 PapUrlNode temp = array[i];
171 //returns whether this PapUrlResolver object has more PAP urls that can be tried
172 public boolean hasMoreUrls(){
173 return pointer < sortedUrlNodes.length;
176 //sets the current PAP url as being failed
177 //this will set the failed time to now and remove any succeeded time
178 public void failed(){
179 LOGGER.error("PAP Server FAILED: "+sortedUrlNodes[pointer].getUrl());
181 sortedUrlNodes[pointer].setFailedTime(new Date());
182 sortedUrlNodes[pointer].setSucceededTime(null);
186 //sets the current PAP url as being working
187 //this will set the succeeded time to now and remove any failed time
188 //Also, this will cause hasMoreUrls to return false, since a working one has been found
190 public void succeeded(){
192 pointer = sortedUrlNodes.length;
194 public void registered(){
195 sortedUrlNodes[pointer].setFailedTime(null);
196 sortedUrlNodes[pointer].setSucceededTime(new Date());
197 LOGGER.info("PAP server SUCCEEDED "+sortedUrlNodes[pointer].getUrl());
201 //returns a properties object with the properties that pertain to PAP urls
202 public Properties getProperties(){
203 String failedPropertyString = "";
204 String succeededPropertyString = "";
205 String urlPropertyString = "";
206 for(int i=0;i<originalUrlNodes.length;i++){
207 failedPropertyString = failedPropertyString.concat(",").concat(originalUrlNodes[i].getFailedTime());
208 succeededPropertyString = succeededPropertyString.concat(",").concat(originalUrlNodes[i].getSucceededTime());
209 urlPropertyString = urlPropertyString.concat(",").concat(originalUrlNodes[i].getUrl());
211 Properties prop = new Properties();
212 failedPropertyString = failedPropertyString.substring(1);
213 succeededPropertyString = succeededPropertyString.substring(1);
214 urlPropertyString = urlPropertyString.substring(1);
215 prop.setProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS,failedPropertyString);
216 prop.setProperty(XACMLRestProperties.PROP_PAP_URLS,urlPropertyString);
217 prop.setProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS,succeededPropertyString);
221 //saves the updates urls to the correct properties
222 private void propertiesUpdated(){
223 if(!autoUpdateProperties){
226 Properties prop = getProperties();
228 LOGGER.debug("Failed PAP Url List: "+prop.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS));
229 LOGGER.debug("Succeeded PAP Url List: "+prop.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS));
230 XACMLProperties.setProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS,prop.getProperty(XACMLRestProperties.PROP_PAP_FAILED_URLS));
231 XACMLProperties.setProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS,prop.getProperty(XACMLRestProperties.PROP_PAP_SUCCEEDED_URLS));
234 //iterates to the next available PAP url, according to the priority order
235 public void getNext(){
239 //returns the url of the current PAP server that we are iterating over
240 //will append the provided policy id to the url
241 public String getUrl(String query){
242 if(sortedUrlNodes[pointer]== null){
243 throw new NoSuchElementException();
245 return sortedUrlNodes[pointer].getUrl().concat("?").concat(query);
249 //returns the url of the current PAP server that we are iterating over
250 //Just returns the url, with no id appended to it
251 public String getUrl(){
252 if(sortedUrlNodes[pointer]== null){
253 throw new NoSuchElementException();
256 return sortedUrlNodes[pointer].getUrl();
259 public String getUserId(){
260 if(sortedUrlNodes[pointer]== null){
261 throw new NoSuchElementException();
264 return sortedUrlNodes[pointer].getUserId();
267 public String getPass(){
268 if(sortedUrlNodes[pointer]== null){
269 throw new NoSuchElementException();
272 return sortedUrlNodes[pointer].getPass();
277 //This is the class to hold the details of a single PAP URL
278 //including: the url itself, the last time it failed, and the last time it succeeded
279 //It also includes the custom comparer which can compare based on failed and succeeded times, and takes into account
280 //the timeout on failures.
281 private class PapUrlNode implements Comparable<PapUrlNode> {
282 private String papUrl;
283 private Date failedTime;
284 private Date succeededTime;
285 private String userId;
288 public PapUrlNode(String url,String userId,String pass){
291 this.succeededTime = null;
292 this.userId = userId;
296 public String getUserId(){
299 public String getPass(){
303 public void setFailedTime(Object time){
304 Date failedTimeAsDate = setHandler(time);
305 if(failedTimeAsDate == null){
306 this.failedTime = null;
308 long timeDifference = new Date().getTime() - failedTimeAsDate.getTime();
309 if(timeDifference < FAIL_TIMEOUT){
310 this.failedTime = failedTimeAsDate;
312 this.failedTime = null;
317 //set the time that this url succeeded at
318 public void setSucceededTime(Object time){
319 this.succeededTime = setHandler(time);
322 //parses string into a date or a null date, if the url never failed/succeeded (since -1 will be in the property)
323 private Date setHandler(Object time){
324 if(time instanceof String){
325 if("-1".equals((String)time)){
329 DateFormat df = new SimpleDateFormat();
330 return df.parse((String)time);
331 } catch (ParseException e) {
335 if(time instanceof Date){
342 public String getFailedTime(){
343 return formatTime(this.failedTime);
346 public String getSucceededTime(){
347 return formatTime(this.succeededTime);
350 //formats a Date into a string or a -1 if there is not date (-1 is used in properties for no date)
351 private String formatTime(Date d){
355 DateFormat df = new SimpleDateFormat();
359 public String getUrl(){
364 public int compareTo(PapUrlNode other){
365 if(this.failedTime == null && other.failedTime != null){
368 if(this.failedTime != null && other.failedTime == null){
371 if(this.failedTime != null){
372 return this.failedTime.compareTo(other.failedTime);