Index: lucene/build.xml
===================================================================
--- lucene/build.xml (revision 1528672)
+++ lucene/build.xml (working copy)
@@ -151,7 +151,8 @@
-
+
Index: lucene/common-build.xml
===================================================================
--- lucene/common-build.xml (revision 1528672)
+++ lucene/common-build.xml (working copy)
@@ -2262,4 +2262,8 @@
+
+
+
Index: lucene/ivy-versions.properties
===================================================================
--- lucene/ivy-versions.properties (revision 1528672)
+++ lucene/ivy-versions.properties (working copy)
@@ -48,9 +48,7 @@
/org.apache.hadoop/hadoop-auth = ${hadoop.version}
/org.apache.hadoop/hadoop-common = ${hadoop.version}
/org.apache.hadoop/hadoop-hdfs = ${hadoop.version}
-/org.apache.httpcomponents/httpclient = 4.2.3
/org.apache.httpcomponents/httpclient = 4.2.6
-/org.apache.httpcomponents/httpcore = 4.2.2
/org.apache.httpcomponents/httpcore = 4.2.5
/org.apache.httpcomponents/httpmime = 4.2.6
/org.apache.james/apache-mime4j-core = 0.7.2
@@ -119,4 +117,3 @@
/org.tukaani/xz = 1.0
/rome/rome = 0.9
/xerces/xercesImpl = 2.9.1
-
Index: lucene/tools/custom-tasks.xml
===================================================================
--- lucene/tools/custom-tasks.xml (revision 1528672)
+++ lucene/tools/custom-tasks.xml (working copy)
@@ -84,4 +84,29 @@
+
+
+
+
+
+
+ Lib versions check under: @{dir}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Index: lucene/tools/src/java/lucene-solr.antlib.xml
===================================================================
--- lucene/tools/src/java/lucene-solr.antlib.xml (revision 1528672)
+++ lucene/tools/src/java/lucene-solr.antlib.xml (working copy)
@@ -18,4 +18,7 @@
+
Index: lucene/tools/src/java/org/apache/lucene/validation/LibVersionsCheckTask.java
===================================================================
--- lucene/tools/src/java/org/apache/lucene/validation/LibVersionsCheckTask.java (revision 0)
+++ lucene/tools/src/java/org/apache/lucene/validation/LibVersionsCheckTask.java (working copy)
@@ -0,0 +1,365 @@
+package org.apache.lucene.validation;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.ResourceCollection;
+import org.apache.tools.ant.types.resources.FileResource;
+import org.apache.tools.ant.types.resources.Resources;
+import org.apache.tools.ant.util.FileNameMapper;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CodingErrorAction;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * An Ant task that verifies if Ivy dependencies across all Lucene/Solr
+ * modules refer to the centralized version file: lucene/ivy-versions.properties;
+ * this task also verifies that the centralized version file is sorted
+ * alphabetically.
+ */
+public class LibVersionsCheckTask extends Task {
+
+ private static final String IVY_XML_FILENAME = "ivy.xml";
+ private static final Pattern COORDINATE_KEY_PATTERN = Pattern.compile("(/[^/ \t\f]+/[^=:/ \t\f]+).*");
+ private static final Pattern BLANK_OR_COMMENT_LINE_PATTERN = Pattern.compile("[ \t\f]*(?:[#!].*)?");
+ private static final Pattern TRAILING_BACKSLASH_PATTERN = Pattern.compile("[^\\\\]*(\\\\+)$");
+ private static final Pattern LEADING_WHITESPACE_PATTERN = Pattern.compile("[ \t\f]+(.*)");
+ private static final Pattern WHITESPACE_GOODSTUFF_WHITESPACE_BACKSLASH_PATTERN
+ = Pattern.compile("[ \t\f]*(.*?)(?:(? iter = (Iterator)ivyXmlResources.iterator();
+ while (iter.hasNext()) {
+ final Resource resource = iter.next();
+ if ( ! resource.isExists()) {
+ throw new BuildException("Resource does not exist: " + resource.getName());
+ }
+ if ( ! (resource instanceof FileResource)) {
+ throw new BuildException("Only filesystem resources are supported: "
+ + resource.getName() + ", was: " + resource.getClass().getName());
+ }
+
+ File ivyXmlFile = ((FileResource)resource).getFile();
+ try {
+ if ( ! checkIvyXmlFile(ivyXmlFile) ) {
+ failures = true;
+ errors++;
+ }
+ } catch (Exception e) {
+ throw new BuildException("Exception reading file " + ivyXmlFile.getPath(), e);
+ }
+ checked++;
+ }
+
+ log(String.format(Locale.ROOT, "Checked %s for alpha sort, and scanned %d %s"
+ + " file(s) for rev=\"${/org/name}\" format (in %.2fs.), %d error(s).",
+ centralizedVersionsFile.getPath(), checked, IVY_XML_FILENAME,
+ (System.currentTimeMillis() - start) / 1000.0, errors),
+ errors > 0 ? Project.MSG_ERR : Project.MSG_INFO);
+
+ if (failures) {
+ throw new BuildException("Lib versions check failed. Check the logs.");
+ }
+ }
+
+ /**
+ * Returns true if the "/org/name = rev" properties lines in the
+ * centralized versions properties file are alphabetically sorted, ignoring
+ * any leading whitespace.
+ * @return
+ */
+ private boolean verifySortedCentralizedVersionsFile() {
+ log("Scanning: " + centralizedVersionsFile, verboseLevel);
+ final InputStream stream;
+ try {
+ stream = new FileInputStream(centralizedVersionsFile);
+ } catch (FileNotFoundException e) {
+ throw new BuildException("Centralized versions file does not exist: "
+ + centralizedVersionsFile.getPath());
+ }
+ // Properties files are encoded as Latin-1
+ final Reader reader = new InputStreamReader(stream, Charset.forName("ISO-8859-1"));
+ final BufferedReader bufferedReader = new BufferedReader(reader);
+
+ String line = null;
+ String currentKey = null;
+ String previousKey = null;
+ try {
+ while (null != (line = readLogicalPropertiesLine(bufferedReader))) {
+ final Matcher keyMatcher = COORDINATE_KEY_PATTERN.matcher(line);
+ if ( ! keyMatcher.matches()) {
+ continue;
+ }
+ currentKey = keyMatcher.group(1);
+ if (null == previousKey) {
+ previousKey = currentKey;
+ continue;
+ }
+ int comparison = currentKey.compareTo(previousKey);
+ if (0 == comparison) {
+ log("DUPLICATE property key found: '" + currentKey + "'", Project.MSG_ERR);
+ failures = true;
+ break;
+ } else if (comparison < 0) {
+ log("OUT-OF-ORDER property key found: '" + currentKey + "'", Project.MSG_ERR);
+ failures = true;
+ break;
+ }
+ previousKey = currentKey;
+ }
+ } catch (IOException e) {
+ throw new BuildException("Exception reading centralized versions file: "
+ + centralizedVersionsFile.getPath(), e);
+ } finally {
+ try { reader.close(); } catch (IOException e) { }
+ }
+ return ! failures;
+ }
+
+ /**
+ * Builds up logical {@link java.util.Properties} lines, composed of one non-blank,
+ * non-comment initial line, either:
+ *
+ * 1. without a non-escaped trailing slash; or
+ * 2. with a non-escaped trailing slash, followed by
+ * zero or more lines with a non-escaped trailing slash, followed by
+ * one or more lines without a non-escaped trailing slash
+ *
+ * All leading whitespace and trailing whitespace + non-escaped slash are
+ * trimmed from each line before concatenating.
+ *
+ * After composing the logical line, leading whitespace is trimmed, then
+ * escaped characters are un-escaped.
+ *
+ * null is returned if there are no lines left to read.
+ */
+ private String readLogicalPropertiesLine(BufferedReader reader) throws IOException {
+ final StringBuilder logicalLine = new StringBuilder();
+ String line;
+ do {
+ line = reader.readLine();
+ if (null == line) {
+ return null;
+ }
+ } while (BLANK_OR_COMMENT_LINE_PATTERN.matcher(line).matches());
+
+ Matcher backslashMatcher = TRAILING_BACKSLASH_PATTERN.matcher(line);
+ // Check for a non-escaped backslash
+ if (backslashMatcher.find() && 1 == (backslashMatcher.group(1).length() % 2)) {
+ final Matcher firstLineMatcher = TRAILING_WHITESPACE_BACKSLASH_PATTERN.matcher(line);
+ if (firstLineMatcher.matches()) {
+ logicalLine.append(firstLineMatcher.group(1)); // trim trailing backslash and any preceding whitespace
+ }
+ line = reader.readLine();
+ while (null != line
+ && (backslashMatcher = TRAILING_BACKSLASH_PATTERN.matcher(line)).find()
+ && 1 == (backslashMatcher.group(1).length() % 2)) {
+ // Trim leading whitespace, the trailing backslash and any preceding whitespace
+ final Matcher goodStuffMatcher = WHITESPACE_GOODSTUFF_WHITESPACE_BACKSLASH_PATTERN.matcher(line);
+ if (goodStuffMatcher.matches()) {
+ logicalLine.append(goodStuffMatcher.group(1));
+ }
+ line = reader.readLine();
+ }
+ if (null != line) {
+ // line can't have a non-escaped trailing backslash
+ final Matcher leadingWhitespaceMatcher = LEADING_WHITESPACE_PATTERN.matcher(line);
+ if (leadingWhitespaceMatcher.matches()) {
+ line = leadingWhitespaceMatcher.group(1); // trim leading whitespace
+ }
+ logicalLine.append(line);
+ }
+ } else {
+ logicalLine.append(line);
+ }
+ // trim non-escaped leading whitespace
+ final Matcher leadingWhitespaceMatcher = LEADING_WHITESPACE_PATTERN.matcher(logicalLine);
+ final CharSequence leadingWhitespaceStripped = leadingWhitespaceMatcher.matches()
+ ? leadingWhitespaceMatcher.group(1)
+ : logicalLine;
+
+ // unescape all chars in the logical line
+ StringBuilder output = new StringBuilder();
+ final int numChars = leadingWhitespaceStripped.length();
+ for (int pos = 0 ; pos < numChars - 1 ; ++pos) {
+ char ch = leadingWhitespaceStripped.charAt(pos);
+ if (ch == '\\') {
+ ch = leadingWhitespaceStripped.charAt(++pos);
+ }
+ output.append(ch);
+ }
+ if (numChars > 0) {
+ output.append(leadingWhitespaceStripped.charAt(numChars - 1));
+ }
+
+ return output.toString();
+ }
+
+ /**
+ * Check a single ivy.xml file. Returns true if it has no problems, false otherwise.
+ */
+ private boolean checkIvyXmlFile(File ivyXmlFile)
+ throws ParserConfigurationException, SAXException, IOException {
+ log("Scanning: " + ivyXmlFile.getPath(), verboseLevel);
+ XMLReader xmlReader = XMLReaderFactory.createXMLReader();
+ DependencyRevChecker revChecker = new DependencyRevChecker(ivyXmlFile);
+ xmlReader.setContentHandler(revChecker);
+ xmlReader.setErrorHandler(revChecker);
+ // To work around a bug in XERCES (XERCESJ-1257), we assume the XML is always UTF8, so we simply provide reader.
+ CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder()
+ .onMalformedInput(CodingErrorAction.REPORT)
+ .onUnmappableCharacter(CodingErrorAction.REPORT);
+ InputStream stream = new FileInputStream(ivyXmlFile);
+ xmlReader.parse(new InputSource(new BufferedReader(new InputStreamReader(stream, decoder))));
+ return ! revChecker.fail;
+ }
+
+ private class DependencyRevChecker extends DefaultHandler {
+ private final File ivyXmlFile;
+ private final Stack tags = new Stack();
+
+ public boolean fail = false;
+
+ public DependencyRevChecker(File ivyXmlFile) {
+ this.ivyXmlFile = ivyXmlFile;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ if (localName.equals("dependency") && insideDependenciesTag()) {
+ String org = attributes.getValue("org");
+ boolean foundAllAttributes = true;
+ if (null == org) {
+ log("MISSING 'org' attribute on in " + ivyXmlFile.getPath(), Project.MSG_ERR);
+ fail = true;
+ foundAllAttributes = false;
+ }
+ String name = attributes.getValue("name");
+ if (null == name) {
+ log("MISSING 'name' attribute on in " + ivyXmlFile.getPath(), Project.MSG_ERR);
+ fail = true;
+ foundAllAttributes = false;
+ }
+ String rev = attributes.getValue("rev");
+ if (null == rev) {
+ log("MISSING 'rev' attribute on in " + ivyXmlFile.getPath(), Project.MSG_ERR);
+ fail = true;
+ foundAllAttributes = false;
+ }
+ if (foundAllAttributes) {
+ String expectedRev = "${/" + org + '/' + name + '}';
+ if ( ! rev.equals(expectedRev)) {
+ log("BAD 'rev' attribute value '" + rev + "' - expected '" + expectedRev + "'"
+ + " in " + ivyXmlFile.getPath(), Project.MSG_ERR);
+ fail = true;
+ }
+ }
+ }
+ tags.push(localName);
+ }
+
+ @Override
+ public void endElement (String uri, String localName, String qName) throws SAXException {
+ tags.pop();
+ }
+
+ private boolean insideDependenciesTag() {
+ return tags.size() == 2 && tags.get(0).equals("ivy-module") && tags.get(1).equals("dependencies");
+ }
+ }
+}
Property changes on: lucene/tools/src/java/org/apache/lucene/validation/LibVersionsCheckTask.java
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Index: solr/build.xml
===================================================================
--- solr/build.xml (revision 1528672)
+++ solr/build.xml (working copy)
@@ -234,7 +234,8 @@
-
+