1 /*******************************************************************************
\r
2 * ============LICENSE_START====================================================
\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
11 * * http://www.apache.org/licenses/LICENSE-2.0
\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
20 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
\r
22 ******************************************************************************/
\r
23 package com.att.cssa.rserv;
\r
25 import java.util.ArrayList;
\r
26 import java.util.Iterator;
\r
27 import java.util.List;
\r
29 import com.att.inno.env.Trans;
\r
32 * Find Acceptable Paths and place them where TypeCode can evaluate.
\r
34 * If there are more than one, TypeCode will choose based on "q" value
\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
42 public Acceptor(List<Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>>> types) {
\r
44 acceptable = new ArrayList<Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>>>();
\r
47 private boolean eval(HttpCode<TRANS,?> code, String str, List<String> props) {
\r
48 // int plus = str.indexOf('+');
\r
51 boolean any = false;
\r
52 for(Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>> type : types) {
\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
60 acceptable.add(type);
\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
69 // nstr = first + (plus<0?str.substring(prev):str.substring(prev,plus));
\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
78 // plus=str.indexOf('+', prev);
\r
85 * Evaluate Properties
\r
91 private boolean props(Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>> type, String tag, String value) {
\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
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
108 return value.equals(prop.y);
\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
125 protected boolean parse(HttpCode<TRANS, ?> code, String cntnt) {
\r
126 byte bytes[] = cntnt.getBytes();
\r
128 int cis,cie=-1,cend;
\r
131 ArrayList<String> props = new ArrayList<String>();
\r
133 // Clear these in case more than one Semi
\r
134 props.clear(); // on loop, do not want mixed properties
\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
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
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