1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.apache.commons.net.ftp.parser;
  17. import java.util.HashMap;
  18. import java.util.List;
  19. import java.util.ListIterator;
  20. import org.apache.oro.text.regex.MalformedPatternException;
  21. import org.apache.oro.text.regex.MatchResult;
  22. import org.apache.oro.text.regex.Pattern;
  23. import org.apache.oro.text.regex.Perl5Compiler;
  24. import org.apache.oro.text.regex.Perl5Matcher;
  25. /**
  26. * Special implementation VMSFTPEntryParser with versioning turned on.
  27. * This parser removes all duplicates and only leaves the version with the highest
  28. * version number for each filename.
  29. *
  30. * This is a sample of VMS LIST output
  31. *
  32. * "1-JUN.LIS;1 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
  33. * "1-JUN.LIS;2 9/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
  34. * "DATA.DIR;1 1/9 2-JUN-1998 07:32:04 [GROUP,OWNER] (RWED,RWED,RWED,RE)",
  35. * <P>
  36. *
  37. * @author <a href="Winston.Ojeda@qg.com">Winston Ojeda</a>
  38. * @author <a href="mailto:scohen@apache.org">Steve Cohen</a>
  39. * @author <a href="sestegra@free.fr">Stephane ESTE-GRACIAS</a>
  40. * @version $Id: VMSVersioningFTPEntryParser.java,v 1.8 2004/04/22 00:48:07 scohen Exp $
  41. *
  42. * @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
  43. */
  44. public class VMSVersioningFTPEntryParser extends VMSFTPEntryParser
  45. {
  46. private Perl5Matcher _preparse_matcher_;
  47. private Pattern _preparse_pattern_;
  48. private static final String PRE_PARSE_REGEX =
  49. "(.*);([0-9]+)\\s*.*";
  50. /**
  51. * Constructor for a VMSFTPEntryParser object. Sets the versioning member
  52. * to the supplied value.
  53. *
  54. * @exception IllegalArgumentException
  55. * Thrown if the regular expression is unparseable. Should not be seen
  56. * under normal conditions. It it is seen, this is a sign that
  57. * <code>REGEX</code> is not a valid regular expression.
  58. */
  59. public VMSVersioningFTPEntryParser()
  60. {
  61. super();
  62. try
  63. {
  64. _preparse_matcher_ = new Perl5Matcher();
  65. _preparse_pattern_ = new Perl5Compiler().compile(PRE_PARSE_REGEX);
  66. }
  67. catch (MalformedPatternException e)
  68. {
  69. throw new IllegalArgumentException (
  70. "Unparseable regex supplied: " + PRE_PARSE_REGEX);
  71. }
  72. }
  73. private class NameVersion {
  74. String name;
  75. int versionNumber;
  76. NameVersion(String name, String vers) {
  77. this.name = name;
  78. this.versionNumber = Integer.parseInt(vers);
  79. }
  80. }
  81. /**
  82. * Implement hook provided for those implementers (such as
  83. * VMSVersioningFTPEntryParser, and possibly others) which return
  84. * multiple files with the same name to remove the duplicates ..
  85. *
  86. * @param original Original list
  87. *
  88. * @return Original list purged of duplicates
  89. */
  90. public List preParse(List original) {
  91. original = super.preParse(original);
  92. HashMap existingEntries = new HashMap();
  93. ListIterator iter = original.listIterator();
  94. while (iter.hasNext()) {
  95. String entry = ((String)iter.next()).trim();
  96. MatchResult result = null;
  97. if (_preparse_matcher_.matches(entry, _preparse_pattern_)) {
  98. result = _preparse_matcher_.getMatch();
  99. String name = result.group(1);
  100. String version = result.group(2);
  101. NameVersion nv = new NameVersion(name, version);
  102. NameVersion existing = (NameVersion) existingEntries.get(name);
  103. if (null != existing) {
  104. if (nv.versionNumber < existing.versionNumber) {
  105. iter.remove(); // removal removes from original list.
  106. continue;
  107. }
  108. }
  109. existingEntries.put(name, nv);
  110. }
  111. }
  112. // we've now removed all entries less than with less than the largest
  113. // version number for each name that were listed after the largest.
  114. // we now must remove those with smaller than the largest version number
  115. // for each name that were found before the largest
  116. while (iter.hasPrevious()) {
  117. String entry = ((String)iter.previous()).trim();
  118. MatchResult result = null;
  119. if (_preparse_matcher_.matches(entry, _preparse_pattern_)) {
  120. result = _preparse_matcher_.getMatch();
  121. String name = result.group(1);
  122. String version = result.group(2);
  123. NameVersion nv = new NameVersion(name, version);
  124. NameVersion existing = (NameVersion) existingEntries.get(name);
  125. if (null != existing) {
  126. if (nv.versionNumber < existing.versionNumber) {
  127. iter.remove(); // removal removes from original list.
  128. }
  129. }
  130. }
  131. }
  132. return original;
  133. }
  134. protected boolean isVersioning() {
  135. return true;
  136. }
  137. }
  138. /* Emacs configuration
  139. * Local variables: **
  140. * mode: java **
  141. * c-basic-offset: 4 **
  142. * indent-tabs-mode: nil **
  143. * End: **
  144. */