AT&T 2.0.19 Code drop, stage 3
[aaf/authz.git] / auth / auth-cass / src / main / java / org / onap / aaf / auth / dao / cass / ArtiDAO.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.dao.cass;
23
24 import java.io.ByteArrayOutputStream;
25 import java.io.DataInputStream;
26 import java.io.DataOutputStream;
27 import java.io.IOException;
28 import java.nio.ByteBuffer;
29 import java.util.Date;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Set;
33
34 import org.onap.aaf.auth.dao.Bytification;
35 import org.onap.aaf.auth.dao.CassDAOImpl;
36 import org.onap.aaf.auth.dao.Loader;
37 import org.onap.aaf.auth.dao.Streamer;
38 import org.onap.aaf.auth.env.AuthzTrans;
39 import org.onap.aaf.auth.layer.Result;
40 import org.onap.aaf.misc.env.util.Chrono;
41
42 import com.datastax.driver.core.Cluster;
43 import com.datastax.driver.core.Row;
44
45 /**
46  * CredDAO manages credentials. 
47  * @author Jonathan
48  * Date: 7/19/13
49  */
50 public class ArtiDAO extends CassDAOImpl<AuthzTrans,ArtiDAO.Data> {
51     public static final String TABLE = "artifact";
52     
53     private HistoryDAO historyDAO;
54     private PSInfo psByMechID,psByMachine, psByNs;
55         
56     public ArtiDAO(AuthzTrans trans, Cluster cluster, String keyspace) {
57         super(trans, ArtiDAO.class.getSimpleName(),cluster, keyspace, Data.class,TABLE, readConsistency(trans,TABLE), writeConsistency(trans,TABLE));
58         init(trans);
59     }
60
61     public ArtiDAO(AuthzTrans trans, HistoryDAO hDao, CacheInfoDAO ciDao) {
62         super(trans, ArtiDAO.class.getSimpleName(),hDao, Data.class,TABLE, readConsistency(trans,TABLE), writeConsistency(trans,TABLE));
63         historyDAO = hDao;
64         init(trans);
65     }
66
67     public static final int KEYLIMIT = 2;
68         public static class Data implements Bytification {
69                 public String                           mechid;
70                 public String                           machine;
71         private Set<String>                     type;
72         public String                                   sponsor;
73         public String                                   ca;
74         public String                                   dir;
75         public String                                   ns;
76         public String                                   os_user;
77         public String                                   notify;
78         public Date                                     expires;
79         public int                                              renewDays;
80         public Set<String>                              sans;
81         
82 //      // Getters
83                 public Set<String> type(boolean mutable) {
84                         if (type == null) {
85                                 type = new HashSet<String>();
86                         } else if (mutable && !(type instanceof HashSet)) {
87                                 type = new HashSet<String>(type);
88                         }
89                         return type;
90                 }
91
92                 public Set<String> sans(boolean mutable) {
93                         if (sans == null) {
94                                 sans = new HashSet<String>();
95                         } else if (mutable && !(sans instanceof HashSet)) {
96                                 sans = new HashSet<String>(sans);
97                         }
98                         return sans;
99                 }
100
101                 @Override
102                 public ByteBuffer bytify() throws IOException {
103                         ByteArrayOutputStream baos = new ByteArrayOutputStream();
104                         ArtifactLoader.deflt.marshal(this,new DataOutputStream(baos));
105                         return ByteBuffer.wrap(baos.toByteArray());
106                 }
107                 
108                 @Override
109                 public void reconstitute(ByteBuffer bb) throws IOException {
110                         ArtifactLoader.deflt.unmarshal(this, toDIS(bb));
111                 }
112
113                 public String toString() {
114                         return mechid + ' ' + machine + ' ' + Chrono.dateTime(expires);
115                 }
116     }
117
118     private static class ArtifactLoader extends Loader<Data> implements Streamer<Data>{
119                 public static final int MAGIC=95829343;
120         public static final int VERSION=1;
121         public static final int BUFF_SIZE=48; // Note: 
122
123         public static final ArtifactLoader deflt = new ArtifactLoader(KEYLIMIT);
124         public ArtifactLoader(int keylimit) {
125             super(keylimit);
126         }
127
128         @Override
129         public Data load(Data data, Row row) {
130             data.mechid = row.getString(0);
131             data.machine = row.getString(1);
132             data.type = row.getSet(2, String.class);
133             data.sponsor = row.getString(3);
134             data.ca = row.getString(4);
135             data.dir = row.getString(5);
136             data.ns = row.getString(6);
137             data.os_user = row.getString(7);
138             data.notify = row.getString(8);
139             data.expires = row.getTimestamp(9);
140             data.renewDays = row.getInt(10);
141             data.sans = row.getSet(11, String.class);
142             return data;
143         }
144
145         @Override
146         protected void key(final Data data, final int idx, Object[] obj) {
147                 int i;
148             obj[i=idx] = data.mechid;
149             obj[++i] = data.machine;
150         }
151
152         @Override
153         protected void body(final Data data, final int idx, Object[] obj) {
154             int i;
155             obj[i=idx] = data.type;
156             obj[++i] = data.sponsor;
157             obj[++i] = data.ca;
158             obj[++i] = data.dir;
159             obj[++i] = data.ns;
160             obj[++i] = data.os_user;
161             obj[++i] = data.notify;
162             obj[++i] = data.expires;
163             obj[++i] = data.renewDays;
164             obj[++i] = data.sans;
165         }
166
167                 @Override
168                 public void marshal(Data data, DataOutputStream os) throws IOException {
169                         writeHeader(os,MAGIC,VERSION);
170                         writeString(os, data.mechid);
171                         writeString(os, data.machine);
172                         os.writeInt(data.type.size());
173                         for(String s : data.type) {
174                                 writeString(os, s);
175                         }
176                         writeString(os, data.sponsor);
177                         writeString(os, data.ca);
178                         writeString(os, data.dir);
179                         writeString(os, data.ns);
180                         writeString(os, data.os_user);
181                         writeString(os, data.notify);
182                         os.writeLong(data.expires==null?-1:data.expires.getTime());
183                         os.writeInt(data.renewDays);
184                         if(data.sans!=null) {
185                                 os.writeInt(data.sans.size());
186                                 for(String s : data.sans) {
187                                         writeString(os, s);
188                                 }
189                         } else {
190                                 os.writeInt(0);
191                         }
192                 }
193
194                 @Override
195                 public void unmarshal(Data data, DataInputStream is) throws IOException {
196                         /*int version = */readHeader(is,MAGIC,VERSION);
197                         // If Version Changes between Production runs, you'll need to do a switch Statement, and adequately read in fields
198                         byte[] buff = new byte[BUFF_SIZE];
199                         data.mechid = readString(is,buff);
200                         data.machine = readString(is,buff);
201                         int size = is.readInt();
202                         data.type = new HashSet<String>(size);
203                         for(int i=0;i<size;++i) {
204                                 data.type.add(readString(is,buff));
205                         }
206                         data.sponsor = readString(is,buff);
207                         data.ca = readString(is,buff);
208                         data.dir = readString(is,buff);
209                         data.ns = readString(is,buff);
210                         data.os_user = readString(is,buff);
211                         data.notify = readString(is,buff);
212                         long l = is.readLong();
213                         data.expires = l<0?null:new Date(l);
214                         data.renewDays = is.readInt();
215                         size = is.readInt();
216                         data.sans = new HashSet<String>(size);
217                         for(int i=0;i<size;++i) {
218                                 data.sans.add(readString(is,buff));
219                         }
220                 }
221     }
222
223     private void init(AuthzTrans trans) {
224         // Set up sub-DAOs
225         if(historyDAO==null) {
226                 historyDAO = new HistoryDAO(trans,this);
227         }
228         
229         String[] helpers = setCRUD(trans, TABLE, Data.class, ArtifactLoader.deflt);
230
231                 psByMechID = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + " FROM " + TABLE + 
232                                 " WHERE mechid = ?", new ArtifactLoader(1) {
233                         @Override
234                         protected void key(Data data, int idx, Object[] obj) {
235                                 obj[idx]=data.type;
236                         }
237                 },readConsistency);
238
239                 psByMachine = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + " FROM " + TABLE + 
240                                 " WHERE machine = ?", new ArtifactLoader(1) {
241                         @Override
242                         protected void key(Data data, int idx, Object[] obj) {
243                                 obj[idx]=data.type;
244                         }
245                 },readConsistency);
246
247                 psByNs = new PSInfo(trans, SELECT_SP + helpers[FIELD_COMMAS] + " FROM " + TABLE + 
248                                 " WHERE ns = ?", new ArtifactLoader(1) {
249                         @Override
250                         protected void key(Data data, int idx, Object[] obj) {
251                                 obj[idx]=data.type;
252                         }
253                 },readConsistency);
254
255 }
256     
257         
258     public Result<List<Data>> readByMechID(AuthzTrans trans, String mechid) {
259                 return psByMechID.read(trans, R_TEXT, new Object[]{mechid});
260         }
261
262         public Result<List<ArtiDAO.Data>> readByMachine(AuthzTrans trans, String machine) {
263                 return psByMachine.read(trans, R_TEXT, new Object[]{machine});
264         }
265
266         public Result<List<org.onap.aaf.auth.dao.cass.ArtiDAO.Data>> readByNs(AuthzTrans trans, String ns) {
267                 return psByNs.read(trans, R_TEXT, new Object[]{ns});
268         }
269
270         /**
271      * Log Modification statements to History
272      *
273      * @param modified        which CRUD action was done
274      * @param data            entity data that needs a log entry
275      * @param overrideMessage if this is specified, we use it rather than crafting a history message based on data
276      */
277     @Override
278     protected void wasModified(AuthzTrans trans, CRUD modified, Data data, String ... override) {
279         boolean memo = override.length>0 && override[0]!=null;
280         boolean subject = override.length>1 && override[1]!=null;
281
282         HistoryDAO.Data hd = HistoryDAO.newInitedData();
283         hd.user = trans.user();
284         hd.action = modified.name();
285         hd.target = TABLE;
286         hd.subject = subject?override[1]: data.mechid;
287         hd.memo = memo
288                 ? String.format("%s by %s", override[0], hd.user)
289                 : String.format("%sd %s for %s",modified.name(),data.mechid,data.machine);
290         // Detail?
291                 if(modified==CRUD.delete) {
292                                 try {
293                                         hd.reconstruct = data.bytify();
294                                 } catch (IOException e) {
295                                         trans.error().log(e,"Could not serialize CredDAO.Data");
296                                 }
297                         }
298
299         if(historyDAO.create(trans, hd).status!=Status.OK) {
300                 trans.error().log("Cannot log to History");
301         }
302     }
303 }