1 /*******************************************************************************
\r
2 * ============LICENSE_START====================================================
\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
12 * * http://www.apache.org/licenses/LICENSE-2.0
\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
21 * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
\r
23 ******************************************************************************/
\r
24 package com.att.cssa.rserv;
\r
26 import java.util.ArrayList;
\r
27 import java.util.Iterator;
\r
28 import java.util.List;
\r
30 import com.att.inno.env.Trans;
\r
33 * Find Acceptable Paths and place them where TypeCode can evaluate.
\r
35 * If there are more than one, TypeCode will choose based on "q" value
\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
43 public Acceptor(List<Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>>> types) {
\r
45 acceptable = new ArrayList<Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>>>();
\r
48 private boolean eval(HttpCode<TRANS,?> code, String str, List<String> props) {
\r
49 // int plus = str.indexOf('+');
\r
52 boolean any = false;
\r
53 for(Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>> type : types) {
\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
61 acceptable.add(type);
\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
70 // nstr = first + (plus<0?str.substring(prev):str.substring(prev,plus));
\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
79 // plus=str.indexOf('+', prev);
\r
86 * Evaluate Properties
\r
92 private boolean props(Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>> type, String tag, String value) {
\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
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
109 return value.equals(prop.y);
\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
126 protected boolean parse(HttpCode<TRANS, ?> code, String cntnt) {
\r
127 byte bytes[] = cntnt.getBytes();
\r
129 int cis,cie=-1,cend;
\r
132 ArrayList<String> props = new ArrayList<String>();
\r
134 // Clear these in case more than one Semi
\r
135 props.clear(); // on loop, do not want mixed properties
\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
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
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