Mercurial > hg > Members > kono > jpf-core
view src/main/gov/nasa/jpf/util/Source.java @ 6:3a19eedcc13d
added a UniqueRandomPermGenerator that makes sure we don't return duplicates. It also checks the (unlikely and pointless) case that we request more permutations than N! and caps the number of samples accordingly
author | Peter Mehlitz <Peter.C.Mehlitz@nasa.gov> |
---|---|
date | Fri, 06 Feb 2015 10:12:12 -0800 |
parents | 61d41facf527 |
children |
line wrap: on
line source
/* * Copyright (C) 2014, United States Government, as represented by the * Administrator of the National Aeronautics and Space Administration. * All rights reserved. * * The Java Pathfinder core (jpf-core) platform is licensed 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. */ package gov.nasa.jpf.util; import gov.nasa.jpf.Config; import gov.nasa.jpf.JPF; 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.util.ArrayList; import java.util.Hashtable; import java.util.LinkedList; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.logging.Logger; /** * utility class to access arbitrary source files by line number * sources can be files inside of root directories, or * can be entries in jars */ public class Source { static Logger logger = JPF.getLogger("gov.nasa.jpf.util.Source"); static List<SourceRoot> sourceRoots; static Hashtable<String,Source> sources = new Hashtable<String,Source>(); static Source noSource = new Source(null, null); static abstract class SourceRoot { // common base abstract InputStream getInputStream (String fname); } static class DirRoot extends SourceRoot { String path; DirRoot (String path){ this.path = path; } @Override InputStream getInputStream (String fname) { if (File.separatorChar != '/'){ fname = fname.replace('/', File.separatorChar); } File f = new File(path, fname); if (f.exists()) { try { return new FileInputStream(f); } catch (FileNotFoundException fnfx) { return null; } } else { return null; } } @Override public boolean equals (Object other){ return (other != null) && (other instanceof DirRoot) && path.equals(((DirRoot)other).path); } @Override public String toString() { return path; } } static class JarRoot extends SourceRoot { JarFile jar; String entryPrefix; JarRoot (String path, String ep) throws IOException { jar = new JarFile(path); if (ep == null) { entryPrefix = null; } else { entryPrefix = ep; if (ep.charAt(ep.length()-1) != '/') { entryPrefix += '/'; } } } @Override InputStream getInputStream (String fname) { String en = (entryPrefix != null) ? entryPrefix + fname : fname; JarEntry entry = jar.getJarEntry(en); if (entry != null) { try { return jar.getInputStream(entry); } catch (IOException e) { return null; } } else { return null; } } @Override public boolean equals (Object other){ if ( (other != null) && (other instanceof JarRoot)){ // just how hard can it be to check if two JarFiles instances refer to // the same file? JarRoot o = (JarRoot)other; File f = new File(jar.getName()); File fOther = new File(o.jar.getName()); if (f.getAbsolutePath().equals(fOther.getAbsolutePath())){ if (entryPrefix == null){ return o.entryPrefix == null; } else { entryPrefix.equals(o.entryPrefix); } } } return false; } @Override public String toString() { return jar.getName(); } } static void addSourceRoot (Config config, List<SourceRoot> roots, String spec){ SourceRoot sr = null; try { int i = spec.indexOf(".jar"); if (i >= 0) { // jar String pn = FileUtils.asPlatformPath(spec.substring(0, i + 4)); File jar = new File(pn); if (jar.exists()) { int i0 = i + 5; // scrub the leading path separator // JarFile assumes Unix for archive-internal paths (also on Windows) String ep = (spec.length() > i0) ? FileUtils.asCanonicalUnixPath(spec.substring(i0)) : null; // we should probably check here if there is such a dir in the Jar sr = new JarRoot(pn, ep); } } else { // directory String pn = FileUtils.asPlatformPath(spec); File dir = new File(pn); if (dir.exists()) { sr = new DirRoot(pn); } } } catch (IOException iox) { // we report this below } if (sr != null) { if (!roots.contains(sr)){ roots.add(sr); } } else { logger.info("not a valid source root: " + spec); } } static String findSrcRoot (String cpEntry){ if (cpEntry.endsWith(".jar")){ // check if there is a 'src' dir in the jar try { JarFile jf = new JarFile(cpEntry); JarEntry srcEntry = jf.getJarEntry("src"); if (srcEntry != null && srcEntry.isDirectory()) { return jf.getName() + "/src"; // jar internal paths use '/' separators } } catch (IOException iox){ return null; } } else { // is it a dir? File cpe = new File(cpEntry); if (cpe.isDirectory()){ // go up until you hit a dir that has a 'src' subdir // remember the traversed path elements LinkedList<String> dirStack = new LinkedList<String>(); dirStack.addFirst(cpe.getName()); for (File pd = cpe.getParentFile(); pd != null; pd = pd.getParentFile()){ File sd = new File(pd,"src"); if (sd.isDirectory()){ String srcRoot = sd.getPath(); for (String e : dirStack) { srcRoot = srcRoot + File.separatorChar + e; } sd = new File(srcRoot); if (sd.isDirectory()){ return srcRoot; } } else { dirStack.addFirst(pd.getName()); } } } } return null; } public static void init (Config config) { ArrayList<SourceRoot> roots = new ArrayList<SourceRoot>(); String[] srcPaths = config.getCompactStringArray("sourcepath"); if (srcPaths != null){ for (String e : srcPaths){ addSourceRoot(config, roots, e); } } sourceRoots = roots; sources.clear(); //printRoots(); } // for debugging purposes static void printRoots() { System.out.println("source roots:"); for (SourceRoot sr : sourceRoots){ System.out.println(" " + sr); } } public static Source getSource (String relPathName) { if (relPathName == null){ return null; } Source s = sources.get(relPathName); if (s == noSource) { return null; } if (s == null) { for (SourceRoot root : sourceRoots) { InputStream is = root.getInputStream(relPathName); if (is != null) { try { s = new Source(root,relPathName); s.loadLines(is); is.close(); sources.put(relPathName, s); return s; } catch (IOException iox) { logger.warning("error reading " + relPathName + " from" + root); return null; } } } } else { return s; } sources.put(relPathName, noSource); return null; } //--- the Source instance data itself protected SourceRoot root; protected String fname; protected String[] lines; protected Source (SourceRoot root, String fname) { this.root = root; this.fname = fname; } protected void loadLines (InputStream is) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(is)); ArrayList<String> l = new ArrayList<String>(); for (String line = in.readLine(); line != null; line = in.readLine()) { l.add(line); } in.close(); if (l.size() > 0) { lines = l.toArray(new String[l.size()]); } } /** * this is our sole purpose in life - answer line strings * line index is 1-based */ public String getLine (int i) { if ((lines == null) || (i <= 0) || (i > lines.length)) { return null; } else { return lines[i-1]; } } public int getLineCount() { return(lines.length); } public String getPath() { return root.toString() + File.separatorChar + fname; } }