2 * Copyright (C) 2014, United States Government, as represented by the
3 * Administrator of the National Aeronautics and Space Administration.
6 * The Java Pathfinder core (jpf-core) platform is licensed under the
7 * Apache License, Version 2.0 (the "License"); you may not use this file except
8 * in compliance with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0.
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 package gov.nasa.jpf.tool;
20 import gov.nasa.jpf.Config;
21 import gov.nasa.jpf.JPFShell;
22 import gov.nasa.jpf.util.JPFSiteUtils;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.lang.reflect.InvocationTargetException;
29 import java.util.Properties;
32 * This class is a wrapper for loading JPF or a JPFShell through a classloader
33 * that got initialized from a Config object (i.e. 'native_classpath').
35 * This is the main-class entry in the executable RunJPF.jar, which does not
36 * require any JPF specific classpath settings, provided the site.properties
37 * is configured correctly
39 * NOTE this class is not allowed to use any types that would require
40 * loading JPF classes during class resolution - this would result in
41 * NoClassDefFoundErrors if the respective class is not in RunJPF.jar
43 public class RunJPF extends Run {
45 public static final int HELP = 0x1;
46 public static final int SHOW = 0x2;
47 public static final int LOG = 0x4;
48 public static final int BUILD_INFO = 0x8;
49 public static final int ADD_PROJECT = 0x10;
50 public static final int VERSION = 0x20;
51 public static final int DELAY_START = 0x40;
52 public static final int DELAY_EXIT = 0x80;
54 static final String JPF_CLASSNAME = "gov.nasa.jpf.JPF";
56 static void delay (String msg) {
57 System.out.println(msg);
60 } catch (IOException iox) {
65 public static void main (String[] args) {
67 int options = getOptions(args);
69 if (args.length == 0 || isOptionEnabled(HELP, options)) {
74 if (isOptionEnabled(ADD_PROJECT, options)){
79 if (isOptionEnabled(DELAY_START, options)) {
80 delay("press any key to start");
83 if (isOptionEnabled(LOG, options)) {
84 Config.enableLogging(true);
87 Config conf = new Config(args);
89 if (isOptionEnabled(SHOW, options)) {
93 ClassLoader cl = conf.initClassLoader(RunJPF.class.getClassLoader());
95 if (isOptionEnabled(VERSION, options)) {
99 if (isOptionEnabled(BUILD_INFO, options)) {
103 // using JPFShell is Ok since it is just a simple non-derived interface
104 // note this uses a <init>(Config) ctor in the shell class if there is one, i.e. there is no need for a separate
105 // start(Config,..) or re-loading the config itself
106 JPFShell shell = conf.getInstance("shell", JPFShell.class);
108 shell.start( removeConfigArgs(args)); // responsible for exception handling itself
111 // we have to load JPF explicitly through the URLClassLoader, and
112 // call its start() via reflection - interfaces would only work if
113 // we instantiate a JPF object here, which would force us to duplicate all
114 // the logging and event handling that preceedes JPF instantiation
115 Class<?> jpfCls = cl.loadClass(JPF_CLASSNAME);
116 if (!call( jpfCls, "start", new Object[] {conf,args})){
117 error("cannot find 'public static start(Config,String[])' in " + JPF_CLASSNAME);
121 if (isOptionEnabled(DELAY_EXIT, options)) {
122 delay("press any key to exit");
126 } catch (NoClassDefFoundError ncfx){
127 ncfx.printStackTrace();
128 } catch (ClassNotFoundException cnfx){
129 error("cannot find " + JPF_CLASSNAME);
130 } catch (InvocationTargetException ix){
131 // should already be handled by JPF
132 ix.getCause().printStackTrace();
137 public static int getOptions (String[] args){
142 for (int i = 0; i < args.length; i++) {
144 if ("-help".equals(a)){
148 } else if ("-show".equals(a)) {
152 } else if ("-log".equals(a)){
156 } else if ("-buildinfo".equals(a)){
160 } else if ("-addproject".equals(a)){
164 } else if ("-delay-start".equals(a)) {
168 } else if ("-delay-exit".equals(a)) {
172 } else if ("-version".equals(a)){
182 public static boolean isOptionEnabled (int option, int mask){
183 return ((mask & option) != 0);
186 public static void showUsage() {
187 System.out.println("Usage: \"java [<vm-option>..] -jar ...RunJPF.jar [<jpf-option>..] [<app> [<app-arg>..]]");
188 System.out.println(" <jpf-option> : -help : print usage information and exit");
189 System.out.println(" | -version : print JPF version information");
190 System.out.println(" | -buildinfo : print build and runtime information");
191 System.out.println(" | -addproject [init] [<pathname>] : add project to site properties and exit");
192 System.out.println(" | -log : print configuration initialization steps");
193 System.out.println(" | -show : print configuration dictionary contents");
194 System.out.println(" | +<key>=<value> : add or override key/value pair to config dictionary");
195 System.out.println(" <app> : *.jpf application properties file pathname | fully qualified application class name");
196 System.out.println(" <app-arg> : arguments passed into main() method of application class");
199 public static void addProject(String[] args){
200 boolean init = false;
202 String sitePathName = null;
204 // check if the first non-null arg is 'init', which means this project
205 // should be added to the 'extensions' list
206 for(; i<args.length; i++){
207 if (args[i] != null){
208 if ("init".equals(args[i])){
212 sitePathName = args[i];
218 File siteProps = (sitePathName == null) ? JPFSiteUtils.getStandardSiteProperties() : new File(sitePathName);
219 if (siteProps == null) {
220 siteProps = new File(JPFSiteUtils.getGlobalSitePropertiesPath());
223 File curDir = new File( System.getProperty("user.dir"));
224 String pid = JPFSiteUtils.getCurrentProjectId();
226 error("current dir not a valid JPF project: " + curDir);
229 if ("jpf-core".equals(pid)){ // jpf-core always needs to be in the extensions list
233 if (JPFSiteUtils.addProject( siteProps, pid, curDir, init)){
234 System.out.println("added project '" + pid + "' to site properties at: " + siteProps);
236 error("failed to add project: '" + pid + "' to site properties at: " + siteProps);
240 public static void showVersion (ClassLoader cl){
242 InputStream is = cl.getResourceAsStream("gov/nasa/jpf/.version");
244 System.out.print("JPF version: ");
246 int len = is.available();
247 byte[] data = new byte[len];
250 String version = new String(data);
251 System.out.println(version);
254 System.out.println("no JPF version information available");
258 } catch (Throwable t){
259 System.err.println("error reading version information: " + t.getMessage());
263 // print out the build.properties settings
264 public static void showBuild(ClassLoader cl) {
266 InputStream is = cl.getResourceAsStream("gov/nasa/jpf/build.properties");
268 System.out.println("JPF build information:");
270 Properties buildProperties = new Properties();
271 buildProperties.load(is);
273 for (Map.Entry<Object, Object> e : buildProperties.entrySet()) {
274 System.out.print('\t');
275 System.out.print(e.getKey());
276 System.out.print(" = ");
277 System.out.println(e.getValue());
283 System.out.println("no JPF build information available");
286 } catch (Throwable t){
287 System.err.println("error reading build information: " + t.getMessage());