source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/OAIResumptionToken.java@ 28874

Last change on this file since 28874 was 28874, checked in by kjdon, 10 years ago

in reset token file, only try to create a new file if one doesn't exist. otherwise we just write over the top.

File size: 10.7 KB
Line 
1/*
2 * OAIResumptionToken.java
3 * Copyright (C) 2014 New Zealand Digital Library, http://www.nzdl.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20package org.greenstone.gsdl3.util;
21
22import org.greenstone.util.GlobalProperties;
23
24import org.w3c.dom.*;
25
26import java.io.File;
27import java.net.URL;
28import java.util.HashMap;
29import java.util.Iterator;
30import java.util.Map;
31import java.util.Set;
32
33
34// import file Logger.java
35import org.apache.log4j.*;
36
37/** */
38public class OAIResumptionToken {
39
40
41
42 // Other fields we save
43 public static final String CURRENT_SET = "current_set";
44 public static final String CURRENT_CURSOR = "current_cursor";
45
46 // for token XML
47 public static final String TOKEN = "token";
48 public static final String TOKEN_LIST = "tokenList";
49 public static final String NAME = "name";
50 public static final String EXPIRATION = "expiration";
51 //public static final String FROM
52 public static final String FILE_SEPARATOR = File.separator;
53 static Logger logger = Logger.getLogger(org.greenstone.gsdl3.util.GSXML.class.getName());
54
55 public static XMLConverter converter = new XMLConverter();
56 public static Element resumption_token_elem = null;
57 //used when saving the token file
58 public static File resumption_token_file = null;
59
60 private static HashMap<String, HashMap<String,String>> stored_tokens = new HashMap<String, HashMap<String,String>>();
61
62 private static HashMap<String, Long> expiration_data = new HashMap<String, Long>();
63
64 /** initialize stored resumption tokens and clear any expired ones*/
65 public static void init() {
66 if (!findOrCreateTokenFile()) {
67 // can't read in old tokens
68 logger.error("Can't find token file, so we can't initialise tokens");
69 return;
70 }
71
72 Document token_doc = converter.getDOM(resumption_token_file, "utf-8");
73 Element token_elem = null;
74 if (token_doc != null) {
75 token_elem = token_doc.getDocumentElement();
76 } else {
77 logger.error("Failed to parse oai resumption token file OAIResumptionToken.xml.");
78 resetTokenFile();
79 return;
80 }
81
82 // read in stored tokens
83 NodeList tokens = token_elem.getElementsByTagName(TOKEN);
84 for(int i=0; i<tokens.getLength(); i++) {
85 Element token = (Element)tokens.item(i);
86 String set = token.getAttribute(OAIXML.SET);
87 if (set.isEmpty()) {
88 set = null;
89 }
90 String meta_prefix = token.getAttribute(OAIXML.METADATA_PREFIX);
91 if (meta_prefix.isEmpty()) {
92 meta_prefix = null;
93 }
94 String from = token.getAttribute(OAIXML.FROM);
95 if (from.isEmpty()) {
96 from = null;
97 }
98 String until = token.getAttribute(OAIXML.UNTIL);
99 if (until.isEmpty()) {
100 until = null;
101 }
102 storeToken(token.getAttribute(NAME), set, meta_prefix, from, until, token.getAttribute(EXPIRATION));
103
104 }
105 }
106 // store the token read in from saved tokens file
107 protected static void storeToken(String name, String set, String metadata_prefix, String from, String until, String expiration) {
108 HashMap<String, String> data = new HashMap<String, String>();
109 data.put(OAIXML.FROM, from);
110 data.put(OAIXML.UNTIL, until);
111 data.put(OAIXML.SET, set);
112 data.put(OAIXML.METADATA_PREFIX, metadata_prefix);
113 stored_tokens.put(name, data);
114 expiration_data.put(name, new Long(expiration));
115 }
116
117 /** generate the token, and store all the data for it */
118 public static String createAndStoreResumptionToken(String set, String metadata_prefix, String from, String until, String cursor, String current_set, String current_cursor) {
119 HashMap<String, String> data = new HashMap<String, String>();
120 long expiration_date = System.currentTimeMillis();
121 String base_token_name = ""+expiration_date;
122 stored_tokens.put(base_token_name, data);
123 expiration_date += (OAIXML.getTokenExpiration());
124 expiration_data.put(base_token_name, new Long(expiration_date));
125 String token_name = base_token_name+":" + cursor + ":" + current_set +":"+ current_cursor;
126 data.put(OAIXML.FROM, from);
127 data.put(OAIXML.UNTIL, until);
128 data.put(OAIXML.SET, set);
129 data.put(OAIXML.METADATA_PREFIX, metadata_prefix);
130 return token_name;
131
132 }
133
134 public static long getExpirationDate(String token) {
135 if (token.indexOf(":") != -1) {
136 token = token.substring(0, token.indexOf(":"));
137 }
138 return expiration_data.get(token).longValue();
139 }
140
141 public static String updateToken(String token, String cursor, String current_set, String current_cursor) {
142 if (token.indexOf(":") != -1) {
143 token = token.substring(0, token.indexOf(":"));
144 }
145
146 // when we are generating a new token, we update the expiration date to allow the new token to have the full length of time
147 long exp_date = System.currentTimeMillis();
148 exp_date += (OAIXML.getTokenExpiration());
149 expiration_data.put(token, exp_date);
150
151 token = token + ":" + cursor + ":" + current_set + ":" + current_cursor;
152 return token;
153 }
154
155 /** check that this token is currently valid */
156 public static boolean isValidToken(String token) {
157 // we clear expired tokens each time we check one.
158 clearExpiredTokens();
159 // take off the set/cursor parts to check for the main key
160 if (token.indexOf(":") != -1) {
161 token = token.substring(0, token.indexOf(":"));
162 logger.error("looking up "+token);
163 }
164 if (stored_tokens.containsKey(token)) {
165 return true;
166 }
167 return false;
168 }
169
170 public static HashMap<String, String> getTokenData(String token) {
171 // find the base name
172 String base_name = token;
173 if (token.indexOf(":") != -1) {
174 base_name = token.substring(0, token.indexOf(":"));
175 logger.error("getting data for "+base_name);
176 }
177 HashMap<String, String> data = new HashMap<String, String>(stored_tokens.get(base_name));
178 if (data == null) {
179 logger.error("data was null!!");
180 return null;
181 }
182 // add in cursor, etc from the token name
183 if (base_name != token) {
184 String[] parts = token.split(":");
185 if (parts.length != 4) {
186 // something wrong!!
187 }
188 data.put(OAIXML.CURSOR, parts[1]);
189 data.put(CURRENT_SET, parts[2]);
190 data.put(CURRENT_CURSOR, parts[3]);
191 }
192 return data;
193
194 }
195
196 // read through all stored expiry dates, and delete any tokens that are too
197 // old
198 public static void clearExpiredTokens() {
199
200 Set<Map.Entry<String,Long>> token_set = expiration_data.entrySet();
201 Iterator<Map.Entry<String,Long>> i = token_set.iterator();
202 int size = expiration_data.size();
203 logger.error("start tokens "+size);
204 Long time_now = System.currentTimeMillis();
205 while (i.hasNext()==true) {
206 Map.Entry<String,Long> entry = i.next();
207 String key = entry.getKey();
208 Long exp = entry.getValue();
209 if (exp < time_now) {
210 logger.error("token "+key+" is expired, "+ OAIXML.getTime(exp));
211 i.remove();
212 // also remove the token from the stored tokens
213 stored_tokens.remove(key);
214 }
215 }
216 size = expiration_data.size();
217 logger.error("end tokens "+size);
218 }
219
220 protected static boolean findOrCreateTokenFile() {
221
222 try {
223 URL token_file_url = Class.forName("org.greenstone.gsdl3.OAIServer").getClassLoader().getResource("OAIResumptionToken.xml");
224 if (token_file_url != null) {
225 resumption_token_file = new File(token_file_url.toURI());
226 if (resumption_token_file != null && resumption_token_file.exists()) {
227 return true;
228 }
229 else {
230 logger.error("Resumption token file found, "+ token_file_url.toURI()+" but couldn't create a file from it.");
231 }
232 }
233 } catch (Exception e) {
234 logger.error("couldn't find or ResumptionToken.xml "+e.getMessage());
235 }
236 // if we have got here, have't managed to load file via class loader -
237 // it may not exist yet.
238 // try and create a new empty one
239 if (resetTokenFile()) {
240 return true;
241 }
242 return false;
243 }
244
245 // If there was no file, or something went wrong with the file, use this to
246 // create a new one.
247 public static boolean resetTokenFile() {
248 resumption_token_file = new File(GlobalProperties.getGSDL3Home() +
249 FILE_SEPARATOR + "WEB-INF" +
250 FILE_SEPARATOR + "classes" +
251 FILE_SEPARATOR + "OAIResumptionToken.xml");
252 try {
253 if (!resumption_token_file.exists()) {
254
255 if (!resumption_token_file.createNewFile()) {
256 logger.error("Couldn't create a new resumption token file "+ resumption_token_file.getPath());
257 resumption_token_file = null;
258 return false;
259 }
260 }
261 } catch (Exception e) {
262 logger.error("Couldn't create a new resumption token file "+ resumption_token_file.getPath()+", "+e.getMessage());
263 resumption_token_file = null;
264 return false;
265 }
266 Document doc = converter.newDOM();
267 Element elem = doc.createElement(TOKEN_LIST);
268 if (converter.writeDOM(elem, resumption_token_file)) {
269 return true;
270 }
271 resumption_token_file = null;
272 return false;
273 }
274
275
276 public static boolean saveTokensToFile() {
277 clearExpiredTokens();
278 if (resumption_token_file == null) {
279 logger.error("no available resumption token file, not storing tokens");
280 return false;
281 }
282
283 // Create an XML representation of the stored tokens
284 Document doc = converter.newDOM();
285 Element token_list = doc.createElement(TOKEN_LIST);
286
287 if (stored_tokens.size() == 0) {
288 // nothing to store, store an empty file
289 converter.writeDOM(token_list, resumption_token_file);
290 return true;
291 }
292 Set<String> keys = stored_tokens.keySet();
293 Iterator<String> i = keys.iterator();
294 while(i.hasNext()) {
295 String token = i.next();
296 HashMap<String, String> data = stored_tokens.get(token);
297 Element token_elem = doc.createElement(TOKEN);
298 token_elem.setAttribute(NAME, token);
299 token_elem.setAttribute(OAIXML.FROM, data.get(OAIXML.FROM));
300 token_elem.setAttribute(OAIXML.UNTIL, data.get(OAIXML.UNTIL));
301 token_elem.setAttribute(OAIXML.SET, data.get(OAIXML.SET));
302 token_elem.setAttribute(OAIXML.METADATA_PREFIX, data.get(OAIXML.METADATA_PREFIX));
303 token_elem.setAttribute(EXPIRATION, ""+expiration_data.get(token));
304 token_list.appendChild(token_elem);
305 }
306 converter.writeDOM(token_list, resumption_token_file);
307 return true;
308 }
309
310}
Note: See TracBrowser for help on using the repository browser.