1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.waarp.openr66.dao.xml;
22
23 import org.w3c.dom.Document;
24 import org.w3c.dom.Element;
25 import org.w3c.dom.Node;
26 import org.w3c.dom.NodeList;
27 import org.waarp.common.file.FileUtils;
28 import org.waarp.common.guid.LongUuid;
29 import org.waarp.common.logging.WaarpLogger;
30 import org.waarp.common.logging.WaarpLoggerFactory;
31 import org.waarp.common.lru.SynchronizedLruCache;
32 import org.waarp.openr66.context.ErrorCode;
33 import org.waarp.openr66.dao.Filter;
34 import org.waarp.openr66.dao.TransferDAO;
35 import org.waarp.openr66.dao.exception.DAOConnectionException;
36 import org.waarp.openr66.dao.exception.DAONoDataException;
37 import org.waarp.openr66.database.DbConstantR66;
38 import org.waarp.openr66.pojo.Transfer;
39 import org.waarp.openr66.protocol.configuration.Configuration;
40 import org.xml.sax.SAXException;
41
42 import javax.xml.namespace.QName;
43 import javax.xml.parsers.DocumentBuilderFactory;
44 import javax.xml.parsers.ParserConfigurationException;
45 import javax.xml.xpath.XPath;
46 import javax.xml.xpath.XPathConstants;
47 import javax.xml.xpath.XPathExpression;
48 import javax.xml.xpath.XPathExpressionException;
49 import javax.xml.xpath.XPathFactory;
50 import java.io.File;
51 import java.io.FilenameFilter;
52 import java.io.IOException;
53 import java.sql.Timestamp;
54 import java.util.ArrayList;
55 import java.util.List;
56
57 import static org.waarp.openr66.dao.DAOFactory.*;
58 import static org.waarp.openr66.dao.database.DBTransferDAO.*;
59
60 public class XMLTransferDAO implements TransferDAO {
61
62 private static final WaarpLogger logger =
63 WaarpLoggerFactory.getLogger(XMLTransferDAO.class);
64
65 public static final String ROOT_LIST = "taskrunners";
66 public static final String ROOT_ELEMENT = "runner";
67
68
69 private static final String XML_SELECT =
70 "//runner[" + ID_FIELD + "='$" + ID_FIELD + "' and " + REQUESTER_FIELD +
71 "='$" + REQUESTER_FIELD + "' and " + REQUESTED_FIELD + "='$" +
72 REQUESTED_FIELD + "' and " + OWNER_REQUEST_FIELD + "='$" +
73 OWNER_REQUEST_FIELD + "']";
74 private static final String XML_GET_ALL = "runner";
75
76
77
78
79
80 private static SynchronizedLruCache<Long, Transfer> dbR66TaskHashMap;
81
82 private static boolean noFile = false;
83
84
85
86
87
88 public static void setNoFile(final boolean newNoFile) {
89 noFile = newNoFile;
90 }
91
92
93
94
95
96
97
98 public static void createLruCache(final int limit, final long ttl) {
99 dbR66TaskHashMap = new SynchronizedLruCache<Long, Transfer>(limit, ttl);
100 }
101
102 public static String hashStatus() {
103 return "DbTaskRunner: [dbR66TaskHashMap: " + dbR66TaskHashMap.size() + "] ";
104 }
105
106
107
108
109
110
111 public static int clearCache() {
112 return dbR66TaskHashMap.forceClearOldest();
113 }
114
115
116
117
118
119
120 public static void updateLruCacheTimeout(final long ttl) {
121 dbR66TaskHashMap.setNewTtl(ttl);
122 }
123
124
125
126
127
128
129 public static void removeNoDbSpecialId(final long specialId) {
130 dbR66TaskHashMap.remove(specialId);
131 }
132
133
134
135
136
137
138 public static void updateUsed(final long specialId) {
139 dbR66TaskHashMap.updateTtl(specialId);
140 }
141
142 public XMLTransferDAO() {
143
144 }
145
146 @Override
147 public void close() {
148
149 }
150
151 public static final String XMLEXTENSION = "_singlerunner.xml";
152
153 private File getFile(final String requester, final String requested,
154 final long id) {
155 return new File(Configuration.configuration.getBaseDirectory() +
156 Configuration.configuration.getArchivePath() + '/' +
157 requester + '_' + requested + '_' + id + XMLEXTENSION);
158 }
159
160 @Override
161 public void delete(final Transfer transfer) {
162 removeNoDbSpecialId(transfer.getId());
163 }
164
165
166
167
168 @Override
169 public void deleteAll() {
170 dbR66TaskHashMap.clear();
171 final File arch = new File(Configuration.configuration.getBaseDirectory() +
172 Configuration.configuration.getArchivePath());
173 if (arch.isDirectory()) {
174 FileUtils.forceDeleteRecursiveDir(arch);
175 }
176 }
177
178 @Override
179 public List<Transfer> getAll() throws DAOConnectionException {
180 if (noFile) {
181 return new ArrayList<Transfer>(dbR66TaskHashMap.values());
182 }
183 final File arch = new File(Configuration.configuration.getArchivePath());
184 final File[] runnerFiles = arch.listFiles(new FilenameFilter() {
185 @Override
186 public boolean accept(final File file, final String s) {
187 return s.endsWith(XMLEXTENSION);
188 }
189 });
190 final List<Transfer> res = new ArrayList<Transfer>();
191 if (runnerFiles != null) {
192 for (final File fileNew : runnerFiles) {
193 try {
194 final DocumentBuilderFactory dbf = getDocumentBuilderFactory();
195 final Document document = dbf.newDocumentBuilder().parse(fileNew);
196
197 final XPath xPath = XPathFactory.newInstance().newXPath();
198 final XPathExpression xpe = xPath.compile(XML_GET_ALL);
199 final NodeList listNode =
200 (NodeList) xpe.evaluate(document, XPathConstants.NODESET);
201
202 for (int i = 0; i < listNode.getLength(); i++) {
203 final Node node = listNode.item(i);
204 final Transfer transfer = getFromNode(node);
205 res.add(transfer);
206 dbR66TaskHashMap.put(transfer.getId(), transfer);
207 }
208 } catch (final SAXException e) {
209 throw new DAOConnectionException(e);
210 } catch (final XPathExpressionException e) {
211 throw new DAOConnectionException(e);
212 } catch (final ParserConfigurationException e) {
213 throw new DAOConnectionException(e);
214 } catch (final IOException e) {
215 throw new DAOConnectionException(e);
216 }
217 }
218 }
219 synchronized (dbR66TaskHashMap) {
220 for (final Transfer transfer : dbR66TaskHashMap.values()) {
221 if (transfer != null && !res.contains(transfer)) {
222 res.add(transfer);
223 }
224 }
225 }
226 return res;
227 }
228
229 @Override
230 public boolean exist(final long id, final String requester,
231 final String requested, final String owner) {
232 if (dbR66TaskHashMap.contains(id)) {
233 return true;
234 }
235 final File file = getFile(requester, requested, id);
236 return file.exists();
237 }
238
239
240
241
242
243
244 @Override
245 public List<Transfer> find(final List<Filter> fitlers)
246 throws DAOConnectionException {
247 throw new DAOConnectionException("Operation not supported on XML DAO");
248 }
249
250
251
252
253
254
255 @Override
256 public long count(final List<Filter> fitlers) throws DAOConnectionException {
257 if (fitlers == null || fitlers.isEmpty()) {
258 return dbR66TaskHashMap.size();
259 }
260 throw new DAOConnectionException("Operation not supported on XML DAO");
261 }
262
263
264
265
266
267
268 @Override
269 public Transfer select(final String id) {
270 throw new UnsupportedOperationException();
271 }
272
273
274
275
276
277
278 @Override
279 public boolean exist(final String id) {
280 throw new UnsupportedOperationException();
281 }
282
283
284
285
286
287
288 @Override
289 public List<Transfer> find(final List<Filter> filters, final int limit)
290 throws DAOConnectionException {
291 throw new DAOConnectionException("Operation not supported on XML DAO");
292 }
293
294
295
296
297
298
299 @Override
300 public List<Transfer> find(final List<Filter> filters, final int limit,
301 final int offset) throws DAOConnectionException {
302 throw new DAOConnectionException("Operation not supported on XML DAO");
303 }
304
305
306
307
308
309
310 @Override
311 public List<Transfer> find(final List<Filter> filters, final String column,
312 final boolean ascend)
313 throws DAOConnectionException {
314 throw new DAOConnectionException("Operation not supported on XML DAO");
315 }
316
317
318
319
320
321
322 @Override
323 public List<Transfer> find(final List<Filter> filters, final String column,
324 final boolean ascend, final int limit)
325 throws DAOConnectionException {
326 throw new DAOConnectionException("Operation not supported on XML DAO");
327 }
328
329
330
331
332
333
334 @Override
335 public List<Transfer> find(final List<Filter> filters, final String column,
336 final boolean ascend, final int limit,
337 final int offset) throws DAOConnectionException {
338 throw new DAOConnectionException("Operation not supported on XML DAO");
339 }
340
341 @Override
342 public void update(final List<Filter> filters, final String toSet)
343 throws DAOConnectionException {
344 throw new DAOConnectionException("Operation not supported on XML DAO");
345 }
346
347 @Override
348 public void insert(final Transfer transfer) throws DAOConnectionException {
349
350 if (transfer.getId() == DbConstantR66.ILLEGALVALUE) {
351 transfer.setId(LongUuid.getLongUuid());
352 }
353 dbR66TaskHashMap.put(transfer.getId(), transfer);
354 if (noFile) {
355 return;
356 }
357 final File file = getFile(transfer.getRequester(), transfer.getRequested(),
358 transfer.getId());
359 if (file.exists()) {
360 throw new DAOConnectionException(
361 "File already exist: " + file.getAbsolutePath());
362 }
363 try {
364 final DocumentBuilderFactory dbf = getDocumentBuilderFactory();
365 final Document document = dbf.newDocumentBuilder().newDocument();
366 final Element root = document.createElement(ROOT_LIST);
367 document.appendChild(root);
368 root.appendChild(getNode(document, transfer));
369
370 XMLUtils.writeToFile(file, document);
371 } catch (final ParserConfigurationException e) {
372 throw new DAOConnectionException(e);
373 }
374 }
375
376 @Override
377 public Transfer select(final long id, final String requester,
378 final String requested, final String owner)
379 throws DAOConnectionException, DAONoDataException {
380 if (dbR66TaskHashMap.contains(id)) {
381 final Transfer value = dbR66TaskHashMap.get(id);
382 if (value != null) {
383 dbR66TaskHashMap.updateTtl(id);
384 }
385 return value;
386 }
387 if (noFile) {
388 throw new DAONoDataException("Transfer cannot be found");
389 }
390 final File file = getFile(requester, requested, id);
391 if (!file.exists()) {
392 throw new DAONoDataException("Transfer cannot be found");
393 }
394 try {
395 final DocumentBuilderFactory dbf = getDocumentBuilderFactory();
396 final Document document = dbf.newDocumentBuilder().parse(file);
397
398 final SimpleVariableResolver resolver = new SimpleVariableResolver();
399 resolver.addVariable(new QName(null, ID_FIELD), id);
400 resolver.addVariable(new QName(null, REQUESTER_FIELD), requester);
401 resolver.addVariable(new QName(null, REQUESTED_FIELD), requested);
402 resolver.addVariable(new QName(null, "owner"), owner);
403
404 final XPath xPath = XPathFactory.newInstance().newXPath();
405 xPath.setXPathVariableResolver(resolver);
406 final XPathExpression xpe = xPath.compile(XML_SELECT);
407
408 final Node node = (Node) xpe.evaluate(document, XPathConstants.NODE);
409 if (node != null) {
410 return getFromNode(node);
411 }
412 throw new DAONoDataException("Transfer cannot be found");
413 } catch (final SAXException e) {
414 throw new DAOConnectionException(e);
415 } catch (final XPathExpressionException e) {
416 throw new DAOConnectionException(e);
417 } catch (final ParserConfigurationException e) {
418 throw new DAOConnectionException(e);
419 } catch (final IOException e) {
420 throw new DAOConnectionException(e);
421 }
422 }
423
424 @Override
425 public void update(final Transfer transfer) throws DAOConnectionException {
426 dbR66TaskHashMap.put(transfer.getId(), transfer);
427 if (noFile) {
428 return;
429 }
430 final File file = getFile(transfer.getRequester(), transfer.getRequested(),
431 transfer.getId());
432 if (!file.exists()) {
433 throw new DAOConnectionException("File doesn't exist");
434 }
435 try {
436 final DocumentBuilderFactory dbf = getDocumentBuilderFactory();
437 final Document document = dbf.newDocumentBuilder().parse(file);
438 final Element root = document.getDocumentElement();
439 Node node = null;
440 if (root.hasChildNodes()) {
441 final NodeList nodeList = root.getChildNodes();
442 final int nb = nodeList.getLength();
443 for (int i = 0; i < nb; i++) {
444 int found = -4;
445 node = nodeList.item(0);
446 if (node.hasChildNodes()) {
447 final NodeList nodeChildList = node.getChildNodes();
448 final int nbChild = nodeChildList.getLength();
449 for (int j = 0; j < nbChild; j++) {
450 final Node child = nodeChildList.item(j);
451 if (child.getNodeName().equals(ID_FIELD) && child.getTextContent()
452 .equals(
453 Long.toString(
454 transfer.getId()))) {
455 found++;
456 } else if (child.getNodeName().equals(OWNER_REQUEST_FIELD) &&
457 child.getTextContent()
458 .equals(transfer.getOwnerRequest())) {
459 found++;
460 } else if (child.getNodeName().equals(REQUESTER_FIELD) &&
461 child.getTextContent()
462 .equals(transfer.getRequester())) {
463 found++;
464 } else if (child.getNodeName().equals(REQUESTED_FIELD) &&
465 child.getTextContent()
466 .equals(transfer.getRequested())) {
467 found++;
468 }
469 if (found == 0) {
470 break;
471 }
472 }
473 if (found == 0) {
474 break;
475 }
476 }
477 }
478 }
479 if (node == null) {
480 logger.warn("Entry not found cannot update for {} {} {} {}",
481 transfer.getId(), transfer.getRequester(),
482 transfer.getRequested(), transfer.getOwnerRequest());
483 return;
484 }
485 node.getParentNode().removeChild(node);
486
487 root.appendChild(getNode(document, transfer));
488
489 XMLUtils.writeToFile(file, document);
490 } catch (final SAXException e) {
491 throw new DAOConnectionException(e);
492 } catch (final ParserConfigurationException e) {
493 throw new DAOConnectionException(e);
494 } catch (final IOException e) {
495 throw new DAOConnectionException(e);
496 }
497 }
498
499 private Transfer getFromNode(final Node parent) {
500 final Transfer res = new Transfer();
501 final NodeList children = parent.getChildNodes();
502 for (int j = 0; j < children.getLength(); j++) {
503 final Node node = children.item(j);
504 if (node.getNodeName().equals(ID_FIELD)) {
505 res.setId(Long.parseLong(node.getTextContent()));
506 } else if (node.getNodeName().equals(OWNER_REQUEST_FIELD)) {
507 res.setOwnerRequest(node.getTextContent());
508 } else if (node.getNodeName().equals(REQUESTER_FIELD)) {
509 res.setRequester(node.getTextContent());
510 } else if (node.getNodeName().equals(REQUESTED_FIELD)) {
511 res.setRequested(node.getTextContent());
512 } else if (node.getNodeName().equals(ID_RULE_FIELD)) {
513 res.setRule(node.getTextContent());
514 } else if (node.getNodeName().equals(RETRIEVE_MODE_FIELD)) {
515 res.setRetrieveMode(Boolean.parseBoolean(node.getTextContent()));
516 } else if (node.getNodeName().equals(TRANSFER_MODE_FIELD)) {
517 res.setTransferMode(Integer.parseInt(node.getTextContent()));
518 } else if (node.getNodeName().equals(FILENAME_FIELD)) {
519 res.setFilename(node.getTextContent());
520 } else if (node.getNodeName().equals(ORIGINAL_NAME_FIELD)) {
521 res.setOriginalName(node.getTextContent());
522 } else if (node.getNodeName().equals(FILE_INFO_FIELD)) {
523 res.setFileInfo(node.getTextContent());
524 } else if (node.getNodeName().equals(TRANSFER_INFO_FIELD)) {
525 res.setTransferInfo(node.getTextContent());
526 } else if (node.getNodeName().equals(IS_MOVED_FIELD)) {
527 res.setIsMoved(Boolean.parseBoolean(node.getTextContent()));
528 } else if (node.getNodeName().equals(BLOCK_SIZE_FIELD)) {
529 res.setBlockSize(Integer.parseInt(node.getTextContent()));
530 } else if (node.getNodeName().equals(GLOBAL_STEP_FIELD)) {
531 res.setGlobalStep(
532 Transfer.TASKSTEP.valueOf(Integer.parseInt(node.getTextContent())));
533 } else if (node.getNodeName().equals(GLOBAL_LAST_STEP_FIELD)) {
534 res.setLastGlobalStep(
535 Transfer.TASKSTEP.valueOf(Integer.parseInt(node.getTextContent())));
536 } else if (node.getNodeName().equals(STEP_FIELD)) {
537 res.setStep(Integer.parseInt(node.getTextContent()));
538 } else if (node.getNodeName().equals(RANK_FIELD)) {
539 res.setRank(Integer.parseInt(node.getTextContent()));
540 } else if (node.getNodeName().equals(STEP_STATUS_FIELD)) {
541 res.setStepStatus(ErrorCode.getFromCode(node.getTextContent()));
542 } else if (node.getNodeName().equals(INFO_STATUS_FIELD)) {
543 res.setInfoStatus(ErrorCode.getFromCode(node.getTextContent()));
544 } else if (node.getNodeName().equals(TRANSFER_START_FIELD)) {
545 res.setStart(Timestamp.valueOf(node.getTextContent()));
546 } else if (node.getNodeName().equals(TRANSFER_STOP_FIELD)) {
547 res.setStop(Timestamp.valueOf(node.getTextContent()));
548 }
549 }
550 return res;
551 }
552
553 private Node getNode(final Document doc, final Transfer transfer) {
554 final Node res = doc.createElement(ROOT_ELEMENT);
555 res.appendChild(
556 XMLUtils.createNode(doc, ID_FIELD, Long.toString(transfer.getId())));
557 res.appendChild(XMLUtils.createNode(doc, OWNER_REQUEST_FIELD,
558 transfer.getOwnerRequest()));
559 res.appendChild(
560 XMLUtils.createNode(doc, REQUESTER_FIELD, transfer.getRequester()));
561 res.appendChild(
562 XMLUtils.createNode(doc, REQUESTED_FIELD, transfer.getRequested()));
563 res.appendChild(
564 XMLUtils.createNode(doc, ID_RULE_FIELD, transfer.getRule()));
565 res.appendChild(XMLUtils.createNode(doc, RETRIEVE_MODE_FIELD,
566 Boolean.toString(
567 transfer.getRetrieveMode())));
568 res.appendChild(XMLUtils.createNode(doc, TRANSFER_MODE_FIELD,
569 Integer.toString(
570 transfer.getTransferMode())));
571 res.appendChild(
572 XMLUtils.createNode(doc, FILENAME_FIELD, transfer.getRequested()));
573 res.appendChild(
574 XMLUtils.createNode(doc, ORIGINAL_NAME_FIELD, transfer.getFilename()));
575 res.appendChild(
576 XMLUtils.createNode(doc, REQUESTED_FIELD, transfer.getOriginalName()));
577 res.appendChild(
578 XMLUtils.createNode(doc, FILE_INFO_FIELD, transfer.getFileInfo()));
579 res.appendChild(XMLUtils.createNode(doc, TRANSFER_INFO_FIELD,
580 transfer.getTransferInfo()));
581 res.appendChild(XMLUtils.createNode(doc, IS_MOVED_FIELD, Boolean.toString(
582 transfer.getIsMoved())));
583 res.appendChild(XMLUtils.createNode(doc, BLOCK_SIZE_FIELD, Integer.toString(
584 transfer.getBlockSize())));
585 res.appendChild(XMLUtils.createNode(doc, GLOBAL_STEP_FIELD,
586 Integer.toString(
587 transfer.getGlobalStep()
588 .ordinal())));
589 res.appendChild(XMLUtils.createNode(doc, GLOBAL_LAST_STEP_FIELD,
590 Integer.toString(
591 transfer.getLastGlobalStep()
592 .ordinal())));
593 res.appendChild(XMLUtils.createNode(doc, STEP_FIELD,
594 Integer.toString(transfer.getStep())));
595 res.appendChild(XMLUtils.createNode(doc, RANK_FIELD,
596 Integer.toString(transfer.getRank())));
597 res.appendChild(XMLUtils.createNode(doc, STEP_STATUS_FIELD,
598 transfer.getStepStatus().getCode()));
599 res.appendChild(XMLUtils.createNode(doc, INFO_STATUS_FIELD,
600 transfer.getInfoStatus().getCode()));
601 res.appendChild(XMLUtils.createNode(doc, TRANSFER_START_FIELD,
602 transfer.getStart().toString()));
603 res.appendChild(XMLUtils.createNode(doc, TRANSFER_STOP_FIELD,
604 transfer.getStop().toString()));
605 return res;
606 }
607 }