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