ea2850aa5d7f3ee473acc49a2192357323458bec
[aaf/authz.git] / authz-core / src / main / java / com / att / cssa / rserv / Acceptor.java
1 /*******************************************************************************\r
2  * ============LICENSE_START====================================================\r
3  * * org.onap.aai\r
4  * * ===========================================================================\r
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
6  * * Copyright © 2017 Amdocs\r
7  * * ===========================================================================\r
8  * * Licensed under the Apache License, Version 2.0 (the "License");\r
9  * * you may not use this file except in compliance with the License.\r
10  * * You may obtain a copy of the License at\r
11  * * \r
12  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
13  * * \r
14  *  * Unless required by applicable law or agreed to in writing, software\r
15  * * distributed under the License is distributed on an "AS IS" BASIS,\r
16  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
17  * * See the License for the specific language governing permissions and\r
18  * * limitations under the License.\r
19  * * ============LICENSE_END====================================================\r
20  * *\r
21  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
22  * *\r
23  ******************************************************************************/\r
24 package com.att.cssa.rserv;\r
25 \r
26 import java.util.ArrayList;\r
27 import java.util.Iterator;\r
28 import java.util.List;\r
29 \r
30 import com.att.inno.env.Trans;\r
31 \r
32 /**\r
33  * Find Acceptable Paths and place them where TypeCode can evaluate.\r
34  * \r
35  * If there are more than one, TypeCode will choose based on "q" value\r
36  *\r
37  * @param <TRANS>\r
38  */\r
39 class Acceptor<TRANS extends Trans>  {\r
40         private List<Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>>> types;\r
41         List<Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>>> acceptable;\r
42         \r
43         public Acceptor(List<Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>>> types) {\r
44                 this.types = types;\r
45                 acceptable = new ArrayList<Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>>>();\r
46         }\r
47         \r
48         private boolean eval(HttpCode<TRANS,?> code, String str, List<String> props) {\r
49 //              int plus = str.indexOf('+');\r
50 //              if(plus<0) {\r
51                 boolean ok = false;\r
52                 boolean any = false;\r
53                 for(Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>> type : types) {\r
54                         ok = true;\r
55                         if(type.x.equals(str)) {\r
56                                 for(Iterator<String> iter = props.iterator();ok && iter.hasNext();) {\r
57                                         ok = props(type,iter.next(),iter.next());\r
58                                 }\r
59                                 if(ok) {\r
60                                         any = true;\r
61                                         acceptable.add(type);\r
62                                 }\r
63                         }\r
64                 }\r
65 //              } else { // Handle Accepts with "+" as in application/xaml+xml\r
66 //                      int prev = str.indexOf('/')+1;\r
67 //                      String first = str.substring(0,prev);\r
68 //                      String nstr;\r
69 //                      while(prev!=0) {\r
70 //                              nstr = first + (plus<0?str.substring(prev):str.substring(prev,plus));\r
71 //                              \r
72 //                              for(Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>> type : types) {\r
73 //                                      if(type.x.equals(nstr)) {\r
74 //                                              acceptable.add(type);\r
75 //                                              return type;\r
76 //                                      }\r
77 //                              }\r
78 //                              prev = plus+1;\r
79 //                              plus=str.indexOf('+', prev);\r
80 //                      };\r
81 //              }\r
82                 return any;\r
83         }\r
84 \r
85         /**\r
86          * Evaluate Properties\r
87          * @param type\r
88          * @param tag\r
89          * @param value\r
90          * @return\r
91          */\r
92         private boolean props(Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>> type, String tag, String value) {\r
93                 boolean rv = false;\r
94                 if(type.y!=null) {\r
95                         for(Pair<String,Object> prop : type.y.y){\r
96                                 if(tag.equals(prop.x)) {\r
97                                         if(tag.equals("charset")) {\r
98                                                 return prop.x==null?false:prop.y.equals(value.toLowerCase()); // return True if Matched\r
99                                         } else if(tag.equals("version")) {\r
100                                                 return prop.y.equals(new Version(value)); // Note: Version Class knows Minor Version encoding\r
101                                         } else if(tag.equals(Content.Q)) { // replace Q value\r
102                                                 try {\r
103                                                         type.y.y.get(0).y=Float.parseFloat(value);\r
104                                                 } catch (NumberFormatException e) {\r
105                                                         rv=false; // need to do something to make Sonar happy. But nothing to do.\r
106                                                 }\r
107                                                 return true;\r
108                                         } else {\r
109                                                 return value.equals(prop.y);\r
110                                         }\r
111                                 }\r
112                         }\r
113                 }\r
114                 return rv;\r
115         }\r
116 \r
117         /**\r
118          * parse \r
119          * \r
120          * Note: I'm processing by index to avoid lots of memory creation, which speeds things\r
121          * up for this time critical section of code. \r
122          * @param code\r
123          * @param cntnt\r
124          * @return\r
125          */\r
126         protected boolean parse(HttpCode<TRANS, ?> code, String cntnt) {\r
127                 byte bytes[] = cntnt.getBytes();\r
128                 \r
129                 int cis,cie=-1,cend;\r
130                 int sis,sie,send;\r
131                 String name;\r
132                 ArrayList<String> props = new ArrayList<String>();\r
133                 do {\r
134                         // Clear these in case more than one Semi\r
135                         props.clear(); // on loop, do not want mixed properties\r
136                         name=null;\r
137                         \r
138                         cis = cie+1; // find comma start\r
139                         while(cis<bytes.length && Character.isSpaceChar(bytes[cis]))++cis;\r
140                         cie = cntnt.indexOf(',',cis); // find comma end\r
141                         cend = cie<0?bytes.length:cie; // If no comma, set comma end to full length, else cie\r
142                         while(cend>cis && Character.isSpaceChar(bytes[cend-1]))--cend;\r
143                         // Start SEMIS\r
144                         sie=cis-1; \r
145                         do {\r
146                                 sis = sie+1;  // semi start is one after previous end\r
147                                 while(sis<bytes.length && Character.isSpaceChar(bytes[sis]))++sis;      \r
148                                 sie = cntnt.indexOf(';',sis);\r
149                                 send = sie>cend || sie<0?cend:sie;  // if the Semicolon is after the comma, or non-existent, use comma end, else keep\r
150                                 while(send>sis && Character.isSpaceChar(bytes[send-1]))--send;\r
151                                 if(name==null) { // first entry in Comma set is the name, not a property\r
152                                         name = new String(bytes,sis,send-sis);\r
153                                 } else { // We've looped past the first Semi, now process as properties\r
154                                         // If there are additional elements (more entities within Semi Colons)\r
155                                         // apply Properties\r
156                                         int eq = cntnt.indexOf('=',sis);\r
157                                         if(eq>sis && eq<send) {\r
158                                                 props.add(new String(bytes,sis,eq-sis));\r
159                                                 props.add(new String(bytes,eq+1,send-(eq+1)));\r
160                                         }\r
161                                 }\r
162                                 // End Property\r
163                         } while(sie<=cend && sie>=cis); // End SEMI processing\r
164                         // Now evaluate Comma set and return if true\r
165                         if(eval(code,name,props))return true; // else loop again to check next comma\r
166                 } while(cie>=0); // loop to next comma\r
167                 return false; // didn't get even one match\r
168         }\r
169         \r
170 }\r