e9c8adb0c50f3fd4956c93be8521308ea0b6f212
[aaf/authz.git] / auth / auth-core / src / main / java / org / onap / aaf / auth / rserv / Content.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.List;
25
26 import org.onap.aaf.misc.env.Trans;
27
28
29
30 /**
31  * A Class to hold Service "ContentTypes", and to match incoming "Accept" types from HTTP.
32  *
33  * This is a multi-use class built to use the same Parser for ContentTypes and Accept.
34  *
35  * Thus, you would create and use "Content.Type" within your service, and use it to match
36  * Accept Strings.  What is returned is an Integer (for faster processing), which can be
37  * used in a switch statement to act on match different Actions.  The server should
38  * know which behaviors match.
39  *
40  * "bestMatch" returns an integer for the best match, or -1 if no matches.
41  *
42  * @author Jonathan
43  *
44  */
45 public abstract class Content<TRANS extends Trans> {
46     public static final String Q = "q";
47     protected abstract Pair<String,Pair<HttpCode<TRANS,?>,List<Pair<String,Object>>>> types(HttpCode<TRANS,?> code, String str);
48     protected abstract boolean props(Pair<String, Pair<HttpCode<TRANS,?>,List<Pair<String,Object>>>> type, String tag, String value);
49
50     /**
51      * Parse a Content-Type/Accept.  As found, call "types" and "props", which do different
52      * things depending on if it's a Content-Type or Accepts.
53      *
54      * For Content-Type, it builds a tree suitable for Comparison
55      * For Accepts, it compares against the tree, and builds an acceptable type list
56      *
57      * Since this parse code is used for every incoming HTTP transaction, I have removed the implementation
58      * that uses String.split, and replaced with integers evaluating the Byte array.  This results
59      * in only the necessary strings created, resulting in 1/3 better speed, and less
60      * Garbage collection.
61      *
62      * @param trans
63      * @param code
64      * @param cntnt
65      * @return
66      */
67     protected boolean parse(HttpCode<TRANS,?> code, String cntnt) {
68         byte bytes[] = cntnt.getBytes();
69         boolean contType=false,contProp=true;
70         int cis,cie=-1,cend;
71         int sis,sie,send;
72         do {
73             cis = cie+1;
74             cie = cntnt.indexOf(',',cis);
75             cend = cie<0?bytes.length:cie;
76             // Start SEMIS
77             sie=cis-1;
78             Pair<String, Pair<HttpCode<TRANS,?>, List<Pair<String, Object>>>> me = null;
79             do {
80                 sis = sie+1;
81                 sie = cntnt.indexOf(';',sis);
82                 send = sie>cend || sie<0?cend:sie;
83                 if (me==null) {
84                     String semi = new String(bytes,sis,send-sis);
85                     // trans.checkpoint(semi);
86                     // Look at first entity within comma group
87                     // Is this an acceptable Type?
88                     me=types(code, semi);
89                     if (me==null) {
90                         sie=-1; // skip the rest of the processing... not a type
91                     } else {
92                         contType=true;
93                     }
94                 } else { // We've looped past the first Semi, now process as properties
95                     // If there are additional elements (more entities within Semi Colons)
96                     // apply Propertys
97                     int eq = cntnt.indexOf('=',sis);
98                     if (eq>sis && eq<send) {
99                         String tag = new String(bytes,sis,eq-sis);
100                         String value = new String(bytes,eq+1,send-(eq+1));
101                         // trans.checkpoint("    Prop " + tag + "=" + value);
102                         boolean bool =  props(me,tag,value);
103                         if (!bool) {
104                             contProp=false;
105                         }
106                     }
107                 }
108                 // End Property
109             } while (sie<=cend && sie>=cis);
110             // End SEMIS
111         } while (cie>=0);
112         return contType && contProp; // for use in finds, True if a type found AND all props matched
113     }
114
115 }