Index: lucene/build.xml =================================================================== --- lucene/build.xml (revision 1358133) +++ lucene/build.xml (working copy) @@ -174,6 +174,11 @@ + + + + + Index: lucene/tools/build.xml =================================================================== --- lucene/tools/build.xml (revision 1358133) +++ lucene/tools/build.xml (working copy) @@ -24,7 +24,11 @@ - + + + + + - + + + Index: lucene/tools/custom-tasks.xml =================================================================== --- lucene/tools/custom-tasks.xml (revision 1358133) +++ lucene/tools/custom-tasks.xml (working copy) @@ -55,4 +55,24 @@ + + + + + + + + + + + + + + + + + + + + Index: lucene/tools/ivy.xml =================================================================== --- lucene/tools/ivy.xml (revision 1358133) +++ lucene/tools/ivy.xml (working copy) @@ -18,4 +18,8 @@ --> + + + + Index: lucene/tools/lib =================================================================== --- lucene/tools/lib (revision 0) +++ lucene/tools/lib (working copy) Property changes on: lucene/tools/lib ___________________________________________________________________ Added: svn:ignore ## -0,0 +1 ## +*.jar Index: lucene/tools/src/java/lucene-solr.antlib.xml =================================================================== --- lucene/tools/src/java/lucene-solr.antlib.xml (revision 1358133) +++ lucene/tools/src/java/lucene-solr.antlib.xml (working copy) @@ -18,4 +18,7 @@ + Index: lucene/tools/src/java/org/apache/lucene/validation/ForbiddenMethodCallCheckTask.java =================================================================== --- lucene/tools/src/java/org/apache/lucene/validation/ForbiddenMethodCallCheckTask.java (revision 0) +++ lucene/tools/src/java/org/apache/lucene/validation/ForbiddenMethodCallCheckTask.java (working copy) @@ -0,0 +1,157 @@ +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.objectweb.asm.*; +import org.objectweb.asm.commons.EmptyVisitor; + +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 java.io.*; +import java.util.Iterator; +import java.util.Locale; +import java.util.Set; +import java.util.HashSet; + +/** + * todo + */ +public class ForbiddenMethodCallCheckTask extends Task { + + private Resources classFiles = new Resources(); + + /** + * Adds a set of JAR resources to check. + */ + public void add(ResourceCollection rc) { + classFiles.add(rc); + } + + static final Set forbiddenMethods = new HashSet(); + static { + addConstructor(String.class, byte[].class); + addConstructor(String.class, byte[].class, int.class); + addConstructor(String.class, byte[].class, int.class, int.class); + addConstructor(String.class, byte[].class, int.class, int.class, int.class); + addMethod(String.class, "getBytes"); + addMethod(String.class, "toLowerCase"); + addMethod(String.class, "toUpperCase"); + } + + private static void addMethod(Class clazz, String name, Class... parameterTypes) { + try { + forbiddenMethods.add( + Type.getInternalName(clazz) + '#' + name + + Type.getMethodDescriptor(clazz.getDeclaredMethod(name, parameterTypes)) + ); + } catch (Exception e) { + throw new RuntimeException("Reflection problem: ", e); + } + } + + private static void addConstructor(Class clazz, Class... parameterTypes) { + try { + forbiddenMethods.add( + Type.getInternalName(clazz) + "#" + + Type.getConstructorDescriptor(clazz.getConstructor(parameterTypes)) + ); + } catch (Exception e) { + throw new RuntimeException("Reflection problem: ", e); + } + } + + @Override + public void execute() throws BuildException { + classFiles.setProject(getProject()); + + long start = System.currentTimeMillis(); + + @SuppressWarnings("unchecked") + Iterator iter = (Iterator) classFiles.iterator(); + + int checked = 0; + int errors = 0; + while (iter.hasNext()) { + final Resource r = iter.next(); + if (!r.isExists()) { + throw new BuildException("JAR resource does not exist: " + r.getName()); + } + if (!(r instanceof FileResource)) { + throw new BuildException("Only filesystem resource are supported: " + r.getName() + + ", was: " + r.getClass().getName()); + } + + final File f = ((FileResource) r).getFile(); + try { + errors += checkClass(f); + } catch (IOException ioe) { + throw new BuildException("IO problem while reading class file " + f, ioe); + } + checked++; + } + + log(String.format(Locale.ENGLISH, + "Scanned %d class file(s) for forbidden method invocations (in %.2fs.), %d error(s).", + checked, (System.currentTimeMillis() - start) / 1000.0, errors), + errors > 0 ? Project.MSG_ERR : Project.MSG_INFO); + + if (errors > 0) { + throw new BuildException("Check for forbidden method calls failed, see log."); + } + } + + private final int checkClass(final File file) throws IOException { + InputStream stream = new BufferedInputStream(new FileInputStream(file)); + try { + final int[] violations = new int[1]; + new ClassReader(stream).accept(new EmptyVisitor() { + @Override + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + return new EmptyVisitor() { + private int lineNo; + + @Override + public void visitMethodInsn(int opcode, String owner, String name, String desc) { + final String key = owner + '#' + name + desc; + if (forbiddenMethods.contains(key)) { + violations[0]++; + log(String.format(Locale.ENGLISH, "Forbidden method invocation: %s\n in %s, source line %d", + key, file.toString(), lineNo), Project.MSG_ERR); + } + } + + @Override + public void visitLineNumber(int lineNo, Label start) { + this.lineNo = lineNo; + } + }; + } + }, 0); + return violations[0]; + } finally { + stream.close(); + } + } + +} Index: lucene/tools/src/java/org/apache/lucene/validation/ForbiddenMethodCallCheckTask.java =================================================================== --- lucene/tools/src/java/org/apache/lucene/validation/ForbiddenMethodCallCheckTask.java (revision 0) +++ lucene/tools/src/java/org/apache/lucene/validation/ForbiddenMethodCallCheckTask.java (working copy) Property changes on: lucene/tools/src/java/org/apache/lucene/validation/ForbiddenMethodCallCheckTask.java ___________________________________________________________________ Added: svn:keywords ## -0,0 +1 ## +Date Author Id Revision HeadURL \ No newline at end of property Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property