AT&T 2.0.19 Code drop, stage 3
[aaf/authz.git] / auth / auth-core / src / main / java / org / onap / aaf / auth / local / AbsData.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.local;
23
24 import java.io.File;
25 import java.io.FileNotFoundException;
26 import java.io.IOException;
27 import java.io.RandomAccessFile;
28 import java.util.Iterator;
29
30 import org.onap.aaf.auth.env.AuthzTrans;
31 import org.onap.aaf.auth.local.DataFile.Token;
32 import org.onap.aaf.auth.local.DataFile.Token.Field;
33 import org.onap.aaf.misc.env.Env;
34 import org.onap.aaf.misc.env.TimeTaken;
35
36 public abstract class AbsData implements Iterable<String> {
37         protected DataFile data;
38         protected TextIndex ti;
39         private File dataf,idxf,lockf;
40         private String name;
41         private char delim;
42         private int maxLineSize;
43         private int fieldOffset;
44         private int skipLines;
45
46         public AbsData(File dataf,char sepChar, int maxLineSize, int fieldOffset) {
47                 File dir = dataf.getParentFile();
48                 int dot = dataf.getName().lastIndexOf('.');
49                 name = dataf.getName().substring(0,dot);
50
51                 this.dataf=dataf;
52                 this.delim = sepChar;
53                 this.maxLineSize = maxLineSize;
54                 this.fieldOffset = fieldOffset;
55                 idxf = new File(dir,name.concat(".idx"));
56                 lockf = new File(dir,name.concat(".lock"));
57                 
58                 
59                 data = new DataFile(dataf,"r");
60                 ti = new TextIndex(idxf);
61                 skipLines=0;
62         }
63         
64         public void skipLines(int lines) {
65                 skipLines=lines;
66         }
67         
68         public String name() {
69                 return name;
70         }
71         
72         public void open(AuthzTrans trans, long timeout) throws IOException {
73                 TimeTaken tt = trans.start("Open Data File", Env.SUB);
74                 boolean opened = false, first = true;
75                 try {
76                                 if(!dataf.exists()) {
77                                         throw new FileNotFoundException("Data File Missing:" + dataf.getCanonicalPath());
78                                 }
79                                 long begin = System.currentTimeMillis();
80                                 long end = begin+timeout;
81                                 boolean exists;
82                                 while((exists=lockf.exists()) && begin<end) {
83                                         if(first) {
84                                                 trans.warn().log("Waiting for",lockf.getCanonicalPath(),"to close");
85                                                 first = false;
86                                         } 
87                                         try {
88                                                 Thread.sleep(200);
89                                         } catch (InterruptedException e) {
90                                                 break;
91                                         }
92                                         begin = System.currentTimeMillis();
93                                 }
94                                 if(exists) {
95                                         throw new IOException(lockf.getCanonicalPath() + "exists.  May not open Datafile");
96                                 }
97                                 data.open();
98                                 try {
99                                         ensureIdxGood(trans);
100                                 } catch (IOException e) {
101                                         data.close();
102                                         throw e;
103                                 }
104                                 ti.open();
105                                 opened = true;
106                         
107                 } finally {
108                         tt.done();
109                 }
110                 if(!opened) {
111                         throw new IOException("DataFile pair for " + name + " was not able to be opened in " + timeout + "ms");
112                 }
113         }
114         
115         private synchronized void ensureIdxGood(AuthzTrans trans) throws IOException {
116                 if(!idxf.exists() || idxf.length()==0 || dataf.lastModified()>idxf.lastModified()) {
117                         trans.warn().log(idxf.getAbsolutePath(),"is missing, empty or out of date, creating");
118                         RandomAccessFile raf = new RandomAccessFile(lockf, "rw");
119                         try {
120                                 ti.create(trans, data, maxLineSize, delim, fieldOffset, skipLines);
121                                 if(!idxf.exists() || (idxf.length()==0 && dataf.length()!=0)) {
122                                         throw new IOException("Data Index File did not create correctly");
123                                 }
124                         } finally {
125                                 raf.close();
126                                 lockf.delete();
127                         }
128                 }
129         }
130
131         public void close(AuthzTrans trans) throws IOException {
132                 ti.close();
133                 data.close();
134         }
135         
136         public class Reuse {
137                 public Token tokenData;
138                 private Field fieldData;
139
140                 private Reuse(int size,char delim) {
141                         tokenData = data.new Token(size);
142                         fieldData = tokenData.new Field(delim);
143                 }
144                 
145                 public void reset() {
146                         getFieldData().reset();
147                 }
148
149                 public void pos(int rec) {
150                         getFieldData().reset();
151                         tokenData.pos(rec);
152                 }
153
154                 public String next() {
155                         return getFieldData().next();
156                 }
157                 
158                 public String at(int field) {
159                         return getFieldData().at(field);
160                 }
161
162                 public String atToEnd(int field) {
163                         return getFieldData().atToEnd(field);
164                 }
165
166                 public Field getFieldData() {
167                         return fieldData;
168                 }
169         }
170         
171         public Reuse reuse() {
172                 return new Reuse(maxLineSize,delim);
173         }
174
175         public Iter iterator() {
176                 return new Iter();
177         }
178         
179         public class Iter implements Iterator<String> {
180                 private Reuse reuse;
181                 private org.onap.aaf.auth.local.TextIndex.Iter tii;
182
183                 public Iter() {
184                         reuse = reuse();
185                         tii = ti.new Iter();
186                 }
187
188                 @Override
189                 public boolean hasNext() {
190                         return tii.hasNext();
191                 }
192
193                 @Override
194                 public String next() {
195                         reuse.reset();
196                         int rec = tii.next();
197                         reuse.pos(rec);
198                         return reuse.at(0);
199                 }
200
201                 @Override
202                 public void remove() {
203                         // read only
204                 }
205         }
206 }