Package gov.nasa.jpf.conformanceChecker.providers

Source Code of gov.nasa.jpf.conformanceChecker.providers.NativePeerProvider

//
// Copyright (C) 2012 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA).  All Rights Reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3.  The NOSA has been approved by the Open Source
// Initiative.  See the file NOSA-1.3-JPF at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
package gov.nasa.jpf.conformanceChecker.providers;

import gov.nasa.jpf.Config;
import gov.nasa.jpf.JPF;
import gov.nasa.jpf.classfile.ClassFile;
import gov.nasa.jpf.classfile.ClassFileException;
import gov.nasa.jpf.jvm.ClassInfo;
import gov.nasa.jpf.jvm.JVM;
import gov.nasa.jpf.jvm.NativePeer;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Logger;

/**
* This class serves as as provider for native peers. It is based on the
* {@link NativePeer} class.
*
* This class, given a ClassInfo object (or its name) returns the
* ClassInfo object that represents its native peer.
*
* @author Matteo Ceccarello <matteo.ceccarello AT gmail.com>
*
*/
public class NativePeerProvider {
 
  static {
    // FIXME the hack used to avoid null pointers
    if(JVM.getVM() == null)
      new JVM(null, new Config(new String[0]));
  }
 
  private static Logger logger = JPF.getLogger(NativePeerProvider.class.getName());
 
  private static final String PEER_PREFIX = "gov/nasa/jpf/jvm/JPF_";
 
  private static final String MODEL_PACKAGE = "<model>";
  private static final String DEFAULT_PACKAGE = "<default>";
 
  private Config config;
 
  private Map<String, ClassInfo> cache;
  private String[] peerPackages;
 
  /** This is the array that stores the jar files in which we want to look into
   * to load classes */
  private JarFile[] nativeJarFiles;
 
  public NativePeerProvider() {
    this(JPF.createConfig(new String[0]));
  }

  public NativePeerProvider(Config config) {
    this.cache = new HashMap<String, ClassInfo>();
    this.config = config;
    this.peerPackages = getPeerPackages(this.config);
    this.nativeJarFiles = loadNativeJarFiles(this.config);
  }

  static JarFile[] loadNativeJarFiles(Config config) {
    List<JarFile> configJars = new LinkedList<JarFile>();
    for (Object k : config.keySet()) {
      if(((String) k).endsWith("native_classpath")) {
        String[] pathElements = config.getStringArray((String) k);
        for (String p : pathElements) {
          try {
            configJars.add(new JarFile(new File(p)));
          } catch (IOException e) {
            logger.warning("Failed to load jar file from path "
                + p + "\n\t" + e);
          }
        }
      }
    }
    return configJars.toArray(new JarFile[0]);
  }

  static String[] getPeerPackages(Config config) {
    String[] defPeerPackages = { MODEL_PACKAGE, "gov.nasa.jpf.jvm", DEFAULT_PACKAGE };
    String[] packages = config.getStringArray("peer_packages", defPeerPackages);

    // internalize
    for (int i=0; i<packages.length; i++) {
      if (packages[i].equals(MODEL_PACKAGE)) {
        packages[i] = MODEL_PACKAGE;
      } else if (packages[i].equals(DEFAULT_PACKAGE)) {
        packages[i] = DEFAULT_PACKAGE;
      }
    }
    return packages;
  }
 
  /**
   * Tries to get a ClassInfo object associated with the given
   * class. Returns null if it does not find anything.
   */
  public ClassInfo loadNativePeerClass(ClassInfo cls) {
    return loadNativePeerClass(cls.getName());
  }
 
  /**
   * Tries to get a ClassInfo object associated with the given
   * class name. Returns null if it does not find anything.
   */
  public ClassInfo loadNativePeerClass(String name) {
    ClassInfo peer = cache.get(name);
    if(peer == null) {
      peer = loadClassInfo(name);
      cache.put(name, peer);
    }   
    return peer;
  }
 
  /**
   * Loads all the native peer classes.
   */
  public Iterable<ClassInfo> loadNativePeerClasses() {
    LinkedList<ClassInfo> peers = new LinkedList<ClassInfo>();
    for (JarFile jar : nativeJarFiles) {
      peers.addAll(loadFromJar(jar));
    }
    return peers;
  }

 
  Collection<ClassInfo> loadFromJar(JarFile jar) {
    LinkedList<ClassInfo> peers = new LinkedList<ClassInfo>();
    Enumeration<JarEntry> entries = jar.entries();
    while (entries.hasMoreElements()) {
      JarEntry entry = entries.nextElement();
      String name = entry.getName();
      if (name.endsWith(".class") && name.startsWith(PEER_PREFIX)) {
        // FIXME see separator char in windows inside jar files
        String peerName = name.replace('/', '.');
        System.out.println(peerName);
       
        try {
          byte[] classBytes = Util.getClassBytes(jar.getInputStream(entry));
          ClassFile cf = new ClassFile(peerName, classBytes);
          peers.add(new UnregisteredClassInfo(cf));
        } catch (IOException e) {
          logger.warning("error while loading class from " +
              jar.getName() + "\n" + e.getMessage());
        } catch (ClassFileException e) {
          logger.warning("error while loading class from " +
              jar.getName() + "\n" + e.getMessage());
        }
       
      }
    }
    return peers;
  }

  ClassInfo loadClassInfo(String name) {
    String peerName = "JPF_" + name.replace('.', '_');
   
    for (int i=0; i<peerPackages.length; i++) {
      String peerClassName;
      String pkg = peerPackages[i];

      if (pkg == MODEL_PACKAGE) {
        int j = name.lastIndexOf('.');
        peerClassName = name.substring(0, j+1) + peerName;
      } else if (pkg == DEFAULT_PACKAGE) {
        peerClassName = peerName;
      } else {
        peerClassName = pkg + '.' + peerName;
      }     
     
      for (JarFile jar : nativeJarFiles) {
        ClassInfo ci = loadFromJar(jar, peerClassName);
        if(ci != null &&
            Modifier.isPublic(ci.getModifiers())) { // to avoid IllegalAccessExceptions
          return ci;
        }
      }
    }

    return null; // nothing found
  }
 
  /**
   * Loads from the given jar the requested class.
   * Returns null if the class is not found
   */
  static ClassInfo loadFromJar(JarFile jar, String className) {
    // FIXME: check if on Windows the file separator inside jar files
    // is / or \
    String fileName = className.replace('.', '/') + ".class";
    try {
      JarEntry entry = jar.getJarEntry(fileName);
      if (entry != null) {
        byte[] classBytes = Util.getClassBytes(jar.getInputStream(entry));
        ClassFile cf = new ClassFile(className, classBytes);
        return new UnregisteredClassInfo(cf);
      }
    } catch (IOException e) {
      logger.warning("error while loading class " + className +
          " from jar file " + jar.getName() + "\n" + e.getMessage());
      return null;
    } catch (ClassFileException e) {
      logger.warning("error while loading class " + className +
          " from jar file " + jar.getName() + "\n" + e.getMessage());
      return null;
    }
    return null;
  }
 
}
TOP

Related Classes of gov.nasa.jpf.conformanceChecker.providers.NativePeerProvider

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.