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