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