Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * fb-contrib - Auxiliary detectors for Java programs
   * Copyright (C) 2005-2013 Dave Brosius
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 package com.mebigfatguy.fbcontrib.detect;
 
 import java.io.File;
 import java.net.URL;
 import java.util.Map;
 import java.util.Set;
 
 import  org.apache.bcel.Constants;
 import  org.apache.bcel.Repository;
 import  org.apache.bcel.classfile.ClassParser;
 import  org.apache.bcel.classfile.JavaClass;
 import  org.apache.bcel.classfile.Method;
 
 import  edu.umd.cs.findbugs.BugInstance;
 import  edu.umd.cs.findbugs.BugReporter;
 import  edu.umd.cs.findbugs.BytecodeScanningDetector;
 import  edu.umd.cs.findbugs.ba.ClassContext;
 
 public class SuspiciousJDKVersionUse extends BytecodeScanningDetector
 {
 	private static final Map<IntegerStringverRegEx = new HashMap<IntegerString>();
 	static {
 		.put(Integer.valueOf(Constants.MAJOR_1_1), "(jdk|j2?re)1.1");
 		.put(Integer.valueOf(Constants.MAJOR_1_2), "(jdk|j2?re)1.2");
 		.put(Integer.valueOf(Constants.MAJOR_1_3), "(jdk|j2?re)1.3");
 		.put(Integer.valueOf(Constants.MAJOR_1_4), "(jdk|j2?re)1.4");
 		.put(Integer.valueOf(Constants.MAJOR_1_5), "(jdk|j2?re)1.5");
 		.put(Integer.valueOf(50), "(jdk|j2?re)1.6");
 	}
 	private static final Map<IntegerStringversionStrings = new HashMap<IntegerString>();
 	static {
 		.put(Integer.valueOf(Constants.MAJOR_1_1), "JDK 1.1");
 		.put(Integer.valueOf(Constants.MAJOR_1_2), "JDK 1.2");
 		.put(Integer.valueOf(Constants.MAJOR_1_3), "JDK 1.3");
 		.put(Integer.valueOf(Constants.MAJOR_1_4), "JDK 1.4");
 		.put(Integer.valueOf(Constants.MAJOR_1_5), "JDK 1.5");
 		.put(Integer.valueOf(50), "JDK 1.6");
 	}
 	private static final Pattern jarPattern = Pattern.compile("jar:file:/*([^!]*)");
 	private static final String SJVU_JDKHOME = "fb-contrib.sjvu.jdkhome";
 
 	private final Map<StringFileversionPaths;
 	private final Map<IntegerMap<StringSet<String>>> validMethodsByVersion;
 	private final Map<StringStringsuperNames;
 	private File jdksRoot = null;
 	private ZipFile jdkZip;
 	private final BugReporter bugReporter;
 
 	public SuspiciousJDKVersionUse(BugReporter bugReporter) {
 		this. = bugReporter;
 		 = new HashMap<StringFile>();
 		 = new HashMap<StringString>();
 	}
 
 	public void visitClassContext(ClassContext classContext) {
 		try {
 			 = Integer.valueOf(classContext.getJavaClass().getMajor());
 			File rtJar = getRTJarFile();
 			if (rtJar == null)
 				rtJar = getRTJarFromProperty();
 
 			if (rtJar != null) {
 				 = new ZipFile(rtJar);
 				super.visitClassContext(classContext);
 			} else {
				if (version != null)
					cnfe = new ClassNotFoundException("The " + version + " rt.jar was not found. This file is needed for finding invalid methods with the SuspiciousJDKVersionUse detector. The system property 'fb-contrib.sjvu.jdkhome' can be used to specify the location of the appropriate JDK.");
				else
					cnfe = new ClassNotFoundException("The JDK's rt.jar for classes with class version " +  + " was not found. This file is needed for finding invalid methods with the SuspiciousJDKVersionUse detector. The system property 'fb-contrib.sjvu.jdkhome' can be used to specify the location of the appropriate JDK.");
				.reportMissingClass(cnfe);
			}
catch (IOException ioe) {
			//Hmm What to do
finally {
			try {
				if ( != null)
catch (IOException ioe) {
			}
			 = null;
		}
	}
	public void sawOpcode(int seen) {
		String clsName;
		try {
			if ((seen == INVOKEVIRTUAL) //Interfaces are more difficult, ignore for now
			||  (seen == INVOKESTATIC)
			||  (seen == INVOKESPECIAL)) {
				if ((clsName.startsWith("java/"))
				||  (clsName.startsWith("javax/"))) {
					Method m = findCalledMethod();
					if (m == null)
						return;
					if (validMethods == null) {
						validMethods = new HashMap<StringSet<String>>();
					}
					if (!isValid(validMethodsclsName)) {
						.reportBug(new BugInstance(this"SJVU_SUSPICIOUS_JDK_VERSION_USE", HIGH_PRIORITY)
								   .addClass(this)
								   .addMethod(this)
								   .addSourceLine(this)
								   .addCalledMethod(this));
					}
				}
			}
catch (ClassNotFoundException cnfe) {
			.reportMissingClass(cnfe);
catch (IOException ioe) {
			//Hmm what do do.
		}
	}
	private Method findCalledMethod() {
		try {
			JavaClass clss = Repository.lookupClass(getClassConstantOperand());
			Method[] methods = clss.getMethods();
			String calledMethod = getNameConstantOperand();
			String calledSignature = getSigConstantOperand();
			for (Method m : methods) {
				if (m.getName().equals(calledMethod) && m.getSignature().equals(calledSignature)) {
					return m;
				}
			}
			return null;
catch (ClassNotFoundException cnfe) {
			.reportMissingClass(cnfe);
			return null;
		}
	}
	private boolean isValid(Map<StringSet<String>> validMethodsString clsNamethrows IOExceptionClassNotFoundException {
		InputStream is = null;
		try {
			Set<StringmethodInfos = validMethods.get(clsName);
			if (methodInfos == null) {
				ZipEntry ze = .getEntry(clsName + ".class");
				if (ze != null) {
					ClassParser parser = new ClassParser(isclsName);
					JavaClass calledClass = parser.parse();
					.put(clsNamecalledClass.getSuperclassName().replace('.''/'));
					Method[] methods = calledClass.getMethods();
					methodInfos = new HashSet<String>();
					validMethods.put(clsNamemethodInfos);
					for (Method m : methods) {
						methodInfos.add(m.getName() + m.getSignature());
					}
else if (clsName.startsWith("java/")) {
					.reportBug(new BugInstance(this"SJVU_SUSPICIOUS_JDK_VERSION_USE", HIGH_PRIORITY)
							   .addClass(this)
							   .addMethod(this)
							   .addSourceLine(this)
							   .addClass(clsName));
				}
			}
			if (methodInfos != null) {
				if (methodInfos.contains(wantedMethod))
					return true;
				else if ("java/lang/Object".equals(clsName))
					return false;
				else
					return isValid(validMethods.get(clsName));
			}
			return true;
		}
		finally {
			if (is != null) {
				try {
					is.close();
catch (IOException ioe) {
				}
			}
		}
	}
	private File getRTJarFile(){
		if (versionStr == null)
			return null;
		File rtPath = .get(versionStr);
		if (rtPath != null)
			return rtPath;
		if ( == null) {
			URL jdkUrl = SuspiciousJDKVersionUse.class.getResource("/java/lang/Object.class");
			if (jdkUrl != null) {
				if (m.find()) {
					String path = m.group(1);
					 = new File(path);
					Pattern verPat = Pattern.compile(versionStr);
					m = verPat.matcher(.getName());
					while ((.getParentFile() != null) && !m.find()) {
						m = verPat.matcher(.getName());
					}
					if (.getParentFile() == null)
						return null;
					try {
						String encoding = System.getProperty("file.encoding");
						 = new File(URLDecoder.decode(.getParentFile().getPath(), encoding));
catch (UnsupportedEncodingException uee) {
						return null;
					}
				}
			}
		}
		if ( != null) {
			File[] possibleJdks = .listFiles();
			for (File possibleJdk : possibleJdks) {
				Pattern verPat = Pattern.compile(versionStr);
				Matcher m = verPat.matcher(possibleJdk.getName());
				if (m.find()) {
					File wantedRtJar = new File(possibleJdk"lib/rt.jar");
					if (!wantedRtJar.exists()) {
						wantedRtJar = new File(possibleJdk"jre/lib/rt.jar");
						if (!wantedRtJar.exists())
							return null;
					}
					.put(versionStrwantedRtJar);
					return wantedRtJar;
				}
			}
		}
		return null;
	}
		String jdkHome = System.getProperty();
		if (jdkHome == null)
			return null;
		File rtJar = new File(jdkHome"lib/rt.jar");
		if (rtJar.exists())
			return rtJar;
		rtJar = new File(jdkHome"jre/lib/rt.jar");
		if (rtJar.exists())
			return rtJar;
		return null;
	}
New to GrepCode? Check out our FAQ X