GitHub PullRequestReviewCommentEvent at 2014-07-03 16:39:08
Repository: javamop
Actor: owolabileg
Payload: {"action":"created","comment":{"url":"https://api.github.com/repos/runtimeverification/javamop/pulls/comments/14524079","id":14524079,"diff_hunk":"@@ -0,0 +1,278 @@\n+package javamop;\n+\n+import java.io.File;\n+import java.io.FileInputStream;\n+import java.io.FileOutputStream;\n+import java.io.IOException;\n+import java.io.PrintWriter;\n+\n+import java.net.URL;\n+import java.net.URLClassLoader;\n+\n+import java.nio.channels.FileChannel;\n+\n+import java.nio.file.Files;\n+import java.nio.file.FileVisitResult;\n+import java.nio.file.Path;\n+import java.nio.file.SimpleFileVisitor;\n+\n+import java.nio.file.attribute.BasicFileAttributes;\n+\n+import java.util.Arrays;\n+\n+/**\n+ * Handles generating a complete Java agent after .mop files have been processed into .rvm files\n+ * and .rvm files have been processed into .java files. Based on Owolabi's build-agent.sh.\n+ * @author A. Cody Schuffelen\n+ */\n+public class GenerateAgent {\n+    \n+    private static final String manifest = \"MANIFEST.MF\";\n+    \n+    /**\n+     * Generate a JavaMOP agent.\n+     * @param outputDir The place to put all the intermediate generated files in.\n+     * @param aspectname Generates {@code aspectname}.jar.\n+     * @throws IOException If something goes wrong in the many filesystem operations.\n+     */\n+    public static void generate(final File outputDir, final String aspectname) throws IOException {\n+        final String ajOutDir = outputDir.getAbsolutePath();\n+        \n+        final String baseClasspath = System.getProperty(\"java.class.path\") + File.pathSeparator + \".\";\n+        \n+        // Step 10: Compile the generated Java File (allRuntimeMonitor.java)\n+        final int javacReturn = runCommandDir(outputDir, \"javac\", \"-d\", \".\",\n+            \"-cp\", baseClasspath, aspectname + \"RuntimeMonitor.java\");\n+        if(javacReturn != 0) {\n+            System.err.println(\"(javac) Failed to compile agent.\");\n+            return;\n+        }\n+        \n+        final File baseAspect = new File(outputDir, \"BaseAspect.aj\");\n+        if(baseAspect.exists()) {}\n+        else {\n+            final boolean success = baseAspect.createNewFile();\n+            if(success) {\n+                writeBaseAspect(baseAspect);\n+            } else {\n+                System.err.println(\"Unable to write BaseAspect.aj.\");\n+            }\n+        }\n+        \n+        // Step 11: Compile the generated AJC File (allMonitorAspect.aj)\n+        final int ajcReturn = runCommandDir(outputDir, \"java\", \"-cp\", baseClasspath,\n+            \"org.aspectj.tools.ajc.Main\", \"-1.6\", \"-d\", ajOutDir, \"-outxml\", \"BaseAspect.aj\", \n+            aspectname + \"MonitorAspect.aj\");\n+        /*\n+        if(ajcReturn != 0) {\n+            System.err.println(\"(ajc) Failed to compile agent.\");\n+            System.exit(ajcReturn);\n+        }*/\n+        final File aopAjc = new File(ajOutDir + File.separator + \"META-INF\" + File.separator +\n+            \"aop-ajc.xml\");\n+        if(aopAjc.exists()) {}\n+        else {\n+            System.err.println(\"(ajc) Failed to produce aop-ajc.xml\");\n+            return;\n+        }\n+        // Step 13: Prepare the directory from which the agent will be built\n+        final File agentDir = Files.createTempDirectory(outputDir.toPath(), \"agent-jar\").toFile();\n+        agentDir.deleteOnExit();\n+        try {\n+            // Copy in the postprocessed xml file\n+            final File metaInf = new File(agentDir, \"META-INF\");\n+            final boolean mkdirMetaInfReturn = (metaInf.exists() && metaInf.isDirectory()) ||\n+                metaInf.mkdir();\n+            if(mkdirMetaInfReturn) {}\n+            else {\n+                System.err.println(\"(mkdir) Failed to create META-INF\");\n+                return;\n+            }\n+            copyFile(aopAjc, new File(metaInf, \"aop-ajc.xml\"));\n+            \n+            // directory to hold compiled library files\n+            // Copy in all the .class files for all the monitor libraries\n+            new File(outputDir, \"mop\").renameTo(new File(agentDir, \"mop\"));\n+            \n+            // # Step 14: copy in the correct MANIFEST FILE\n+            final File jarManifest = new File(metaInf, manifest);\n+            writeAgentManifest(jarManifest);\n+            \n+            // # Step 15: Stepmake the java agent jar\n+            final int jarReturn = runCommandDir(new File(\".\"), \"jar\", \"cmf\", jarManifest.toString(), \n+                aspectname + \".jar\", \"-C\", agentDir.toString(), \".\");\n+            if(jarReturn != 0) {\n+                System.err.println(\"(jar) Failed to produce final jar\");\n+                return;\n+            }\n+            \n+            System.out.println(aspectname + \".jar is generated.\");\n+        } finally {\n+            deleteDirectory(agentDir.toPath());\n+        }\n+    }\n+    \n+    /**\n+     * Run a command in a directory. Passes the output of the run commands through if the program\n+     * is in verbose mode.\n+     */\n+    private static int runCommandDir(final File dir, final String... args) throws IOException {\n+        try {\n+            if(MOPProcessor.verbose) { // -v\n+                System.out.println(dir.toString() + \": \" + Arrays.asList(args).toString());\n+            }\n+            final ProcessBuilder builder = new ProcessBuilder();\n+            builder.command(args).directory(dir);\n+            if(MOPProcessor.verbose) { // -v\n+                builder.inheritIO();\n+            }\n+            final Process proc = builder.start();\n+            return proc.waitFor();\n+        } catch(InterruptedException ie) {\n+            ie.printStackTrace();\n+            return -1;\n+        }\n+    }\n+    \n+    /**\n+     * Copy the contents of one file to another.\n+     * @param sourceFile The file to take the contents from.\n+     * @param destFile The file to output to. Created if it does not already exist.\n+     * @throws IOException If something goes wrong copying the file.\n+     */\n+    private static void copyFile(final File sourceFile, final File destFile) throws IOException {\n+        // http://www.javalobby.org/java/forums/t17036.html\n+        if(!destFile.exists()) {\n+            destFile.createNewFile();\n+        }\n+        \n+        FileChannel source = null;\n+        FileChannel destination = null;\n+        try {\n+            source = new FileInputStream(sourceFile).getChannel();\n+            destination = new FileOutputStream(destFile).getChannel();\n+            destination.transferFrom(source, 0, source.size());\n+        }\n+        finally {\n+            \n+            if(source != null) {\n+                source.close();\n+            }\n+            if(destination != null) {\n+                destination.close();\n+            }\n+        }\n+    }\n+    \n+    /**\n+     * Delete a directory and all its contents. Every file has to be individually deleted, since\n+     * there is no built-in java function to delete an entire directory and its contents\n+     * recursively.\n+     * @param path The path of the directory to delete.\n+     * @throws IOException If it cannot traverse the directories or the files cannot be deleted.\n+     */\n+    public static void deleteDirectory(final Path path) throws IOException {\n+        // http://stackoverflow.com/a/8685959\n+        Files.walkFileTree(path, new SimpleFileVisitor<Path>() {\n+            @Override\n+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)\n+                    throws IOException {\n+                Files.delete(file);\n+                return FileVisitResult.CONTINUE;\n+            }\n+            \n+            @Override\n+            public FileVisitResult visitFileFailed(Path file, IOException exc) \n+                    throws IOException {\n+                // try to delete the file anyway, even if its attributes\n+                // could not be read, since delete-only access is\n+                // theoretically possible\n+                Files.delete(file);\n+                return FileVisitResult.CONTINUE;\n+            }\n+            \n+            @Override\n+            public FileVisitResult postVisitDirectory(Path dir, IOException exc) \n+                    throws IOException {\n+                if (exc == null) {\n+                    Files.delete(dir);\n+                    return FileVisitResult.CONTINUE;\n+                } else {\n+                    // directory iteration failed; propagate exception\n+                    throw exc;\n+                }\n+            }\n+        });\n+    }\n+    \n+    private static String findJarOnClasspath(String end) {\n+        // http://www.java-tips.org/java-se-tips/java.lang/how-to-print-classpath.html\n+        //Get the System Classloader\n+        ClassLoader sysClassLoader = ClassLoader.getSystemClassLoader();\n+        \n+        //Get the URLs\n+        URL[] urls = ((URLClassLoader)sysClassLoader).getURLs();\n+        \n+        for(URL url : urls) {\n+            final String str = url.toString();\n+            if(str.endsWith(end)) {\n+                return str.replace(\"file:\",\"\");\n+            }\n+        }\n+        System.err.println(\"Unable to find \" + end + \". Make sure it is on your CLASSPATH.\");\n+        return null;\n+    }\n+    \n+    /**\n+     * Write the agent manifest to a file. It extracts the locations of aspectjweaver.jar and\n+     * rvmonitorrt.jar from the classpath that is used when JavaMOP is run.\n+     * @param f The file to write the manifest to.\n+     * @throws IOException If something goes wrong in writing the file.\n+     */\n+    private static void writeAgentManifest(File f) throws IOException {\n+        final String rvmonitorrt = findJarOnClasspath(\"rvmonitorrt.jar\");\n+        final String aspectjweaver = findJarOnClasspath(\"aspectjweaver.jar\");\n+        \n+        final PrintWriter writer = new PrintWriter(f);\n+        writer.println(\"Manifest-Version: 1.0\");\n+        writer.println(\"Name: org/aspectj/weaver/\");\n+        writer.println(\"Specification-Title: AspectJ Weaver Classes\");\n+        writer.println(\"Specification-Version: DEVELOPMENT\");\n+        writer.println(\"Specification-Vendor: aspectj.org\");\n+        writer.println(\"Implementation-Title: org.aspectj.weaver\");\n+        writer.println(\"Implementation-Version: DEVELOPMENT\");\n+        writer.println(\"Implementation-Vendor: aspectj.org\");\n+        writer.println(\"Premain-Class: org.aspectj.weaver.loadtime.Agent\");\n+        writer.println(\"Can-Redefine-Classes: true\");\n+        writer.println(\"Boot-Class-Path: \"+rvmonitorrt+\" \"+aspectjweaver);\n+        writer.flush();\n+        writer.close();\n+    }\n+    \n+    /**\n+     * Write the base aspect to a file.\n+     * @param f The file to write to.\n+     * @throws IOException If something goes wrong in writing the file.\n+     */\n+    private static void writeBaseAspect(File f) throws IOException {\n+        final PrintWriter writer = new PrintWriter(f);\n+        writer.println(\"package mop;\");\n+        writer.println(\"public aspect BaseAspect {\");\n+        writer.println(\"    pointcut notwithin() :\");\n+        writer.println(\"    !within(sun..*) &&\");\n+        writer.println(\"    !within(java..*) &&\");\n+        writer.println(\"    !within(javax..*) &&\");\n+        writer.println(\"    !within(com.sun..*) &&\");\n+        writer.println(\"    !within(org.dacapo.harness..*) &&\");\n+        writer.println(\"    !within(org.apache.commons..*) &&\");\n+        writer.println(\"    !within(org.apache.geronimo..*) &&\");\n+        writer.println(\"    !within(net.sf.cglib..*) &&\");\n+        writer.println(\"    !within(mop..*) &&\");\n+        writer.println(\"    !within(javamoprt..*) &&\");\n+        writer.println(\"    !within(rvmonitorrt..*) &&\");\n+        writer.println(\"    !within(com.runtimeverification..*);\");\n+        writer.println(\"}\");\n+        writer.flush();\n+        writer.close();\n+    }","path":"src/javamop/GenerateAgent.java","position":277,"original_position":277,"commit_id":"607aef5ec955cbd71aee465d2c2136f8fa7d2289","original_commit_id":"607aef5ec955cbd71aee465d2c2136f8fa7d2289","user":{"login":"owolabileg","id":4887692,"avatar_url":"https://avatars.githubusercontent.com/u/4887692?","gravatar_id":"cf5a0924184554cc73119a7c3708cdcd","url":"https://api.github.com/users/owolabileg","html_url":"https://github.com/owolabileg","followers_url":"https://api.github.com/users/owolabileg/followers","following_url":"https://api.github.com/users/owolabileg/following{/other_user}","gists_url":"https://api.github.com/users/owolabileg/gists{/gist_id}","starred_url":"https://api.github.com/users/owolabileg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/owolabileg/subscriptions","organizations_url":"https://api.github.com/users/owolabileg/orgs","repos_url":"https://api.github.com/users/owolabileg/repos","events_url":"https://api.github.com/users/owolabileg/events{/privacy}","received_events_url":"https://api.github.com/users/owolabileg/received_events","type":"User","site_admin":false},"body":"Sounds good to me.","created_at":"2014-07-03T16:39:08Z","updated_at":"2014-07-03T16:39:08Z","html_url":"https://github.com/runtimeverification/javamop/pull/32#discussion_r14524079","pull_request_url":"https://api.github.com/repos/runtimeverification/javamop/pulls/32","_links":{"self":{"href":"https://api.github.com/repos/runtimeverification/javamop/pulls/comments/14524079"},"html":{"href":"https://github.com/runtimeverification/javamop/pull/32#discussion_r14524079"},"pull_request":{"href":"https://api.github.com/repos/runtimeverification/javamop/pulls/32"}}},"pull_request":{"url":"https://api.github.com/repos/runtimeverification/javamop/pulls/32","id":17857839,"html_url":"https://github.com/runtimeverification/javamop/pull/32","diff_url":"https://github.com/runtimeverification/javamop/pull/32.diff","patch_url":"https://github.com/runtimeverification/javamop/pull/32.patch","issue_url":"https://api.github.com/repos/runtimeverification/javamop/issues/32","number":32,"state":"open","title":"Initial implementation of agent generation.","user":{"login":"Databean","id":1892834,"avatar_url":"https://avatars.githubusercontent.com/u/1892834?","gravatar_id":"d5eda338e97b768d4838ad634066ce8e","url":"https://api.github.com/users/Databean","html_url":"https://github.com/Databean","followers_url":"https://api.github.com/users/Databean/followers","following_url":"https://api.github.com/users/Databean/following{/other_user}","gists_url":"https://api.github.com/users/Databean/gists{/gist_id}","starred_url":"https://api.github.com/users/Databean/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Databean/subscriptions","organizations_url":"https://api.github.com/users/Databean/orgs","repos_url":"https://api.github.com/users/Databean/repos","events_url":"https://api.github.com/users/Databean/events{/privacy}","received_events_url":"https://api.github.com/users/Databean/received_events","type":"User","site_admin":false},"body":"This is hardcoded to expect some files in the lib directory in the working directory of the program, obviously a temporary solution for while i was working on it. @pdaian, can you please have the installer put these files together in a predictable location? (BaseAspect.aj  MANIFEST.MF  aspectjrt.jar  aspectjtools.jar  aspectjweaver.jar  rt.jar) from @owolabileg's [build-agent archive](http://fsl.cs.illinois.edu/images/6/6d/Build-agent.tar.gz).\r\n\r\nThis adds the --agent option, where the result of\r\n`javamop --agent directory1 directory2 file1.mop file2.mop -n mopAgent`\r\nreads all the files in directory1 and directory2 and uses file1.mop and file2.mop and produces a file `mopAgent.jar` that can be used as a java agent with existing java code.\r\n\r\nThis still needs some work (deleting intermediate generated files, and refactoring the code), but I'm putting this up now in case @owolabileg, @grosu, or @pdaian have comments.","created_at":"2014-07-01T22:09:07Z","updated_at":"2014-07-03T16:39:08Z","closed_at":null,"merged_at":null,"merge_commit_sha":"69eeff943b9aef470543966a25f53b78b445e7eb","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/runtimeverification/javamop/pulls/32/commits","review_comments_url":"https://api.github.com/repos/runtimeverification/javamop/pulls/32/comments","review_comment_url":"https://api.github.com/repos/runtimeverification/javamop/pulls/comments/{number}","comments_url":"https://api.github.com/repos/runtimeverification/javamop/issues/32/comments","statuses_url":"https://api.github.com/repos/runtimeverification/javamop/statuses/607aef5ec955cbd71aee465d2c2136f8fa7d2289","head":{"label":"runtimeverification:generateAgent","ref":"generateAgent","sha":"607aef5ec955cbd71aee465d2c2136f8fa7d2289","user":{"login":"runtimeverification","id":3732719,"avatar_url":"https://avatars.githubusercontent.com/u/3732719?","gravatar_id":"ec5e3b1d9473514c1720f216a63a467b","url":"https://api.github.com/users/runtimeverification","html_url":"https://github.com/runtimeverification","followers_url":"https://api.github.com/users/runtimeverification/followers","following_url":"https://api.github.com/users/runtimeverification/following{/other_user}","gists_url":"https://api.github.com/users/runtimeverification/gists{/gist_id}","starred_url":"https://api.github.com/users/runtimeverification/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/runtimeverification/subscriptions","organizations_url":"https://api.github.com/users/runtimeverification/orgs","repos_url":"https://api.github.com/users/runtimeverification/repos","events_url":"https://api.github.com/users/runtimeverification/events{/privacy}","received_events_url":"https://api.github.com/users/runtimeverification/received_events","type":"Organization","site_admin":false},"repo":{"id":13277219,"name":"javamop","full_name":"runtimeverification/javamop","owner":{"login":"runtimeverification","id":3732719,"avatar_url":"https://avatars.githubusercontent.com/u/3732719?","gravatar_id":"ec5e3b1d9473514c1720f216a63a467b","url":"https://api.github.com/users/runtimeverification","html_url":"https://github.com/runtimeverification","followers_url":"https://api.github.com/users/runtimeverification/followers","following_url":"https://api.github.com/users/runtimeverification/following{/other_user}","gists_url":"https://api.github.com/users/runtimeverification/gists{/gist_id}","starred_url":"https://api.github.com/users/runtimeverification/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/runtimeverification/subscriptions","organizations_url":"https://api.github.com/users/runtimeverification/orgs","repos_url":"https://api.github.com/users/runtimeverification/repos","events_url":"https://api.github.com/users/runtimeverification/events{/privacy}","received_events_url":"https://api.github.com/users/runtimeverification/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/runtimeverification/javamop","description":"Runtime verification system for Java, using AspectJ for instrumentation.","fork":false,"url":"https://api.github.com/repos/runtimeverification/javamop","forks_url":"https://api.github.com/repos/runtimeverification/javamop/forks","keys_url":"https://api.github.com/repos/runtimeverification/javamop/keys{/key_id}","collaborators_url":"https://api.github.com/repos/runtimeverification/javamop/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/runtimeverification/javamop/teams","hooks_url":"https://api.github.com/repos/runtimeverification/javamop/hooks","issue_events_url":"https://api.github.com/repos/runtimeverification/javamop/issues/events{/number}","events_url":"https://api.github.com/repos/runtimeverification/javamop/events","assignees_url":"https://api.github.com/repos/runtimeverification/javamop/assignees{/user}","branches_url":"https://api.github.com/repos/runtimeverification/javamop/branches{/branch}","tags_url":"https://api.github.com/repos/runtimeverification/javamop/tags","blobs_url":"https://api.github.com/repos/runtimeverification/javamop/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/runtimeverification/javamop/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/runtimeverification/javamop/git/refs{/sha}","trees_url":"https://api.github.com/repos/runtimeverification/javamop/git/trees{/sha}","statuses_url":"https://api.github.com/repos/runtimeverification/javamop/statuses/{sha}","languages_url":"https://api.github.com/repos/runtimeverification/javamop/languages","stargazers_url":"https://api.github.com/repos/runtimeverification/javamop/stargazers","contributors_url":"https://api.github.com/repos/runtimeverification/javamop/contributors","subscribers_url":"https://api.github.com/repos/runtimeverification/javamop/subscribers","subscription_url":"https://api.github.com/repos/runtimeverification/javamop/subscription","commits_url":"https://api.github.com/repos/runtimeverification/javamop/commits{/sha}","git_commits_url":"https://api.github.com/repos/runtimeverification/javamop/git/commits{/sha}","comments_url":"https://api.github.com/repos/runtimeverification/javamop/comments{/number}","issue_comment_url":"https://api.github.com/repos/runtimeverification/javamop/issues/comments/{number}","contents_url":"https://api.github.com/repos/runtimeverification/javamop/contents/{+path}","compare_url":"https://api.github.com/repos/runtimeverification/javamop/compare/{base}...{head}","merges_url":"https://api.github.com/repos/runtimeverification/javamop/merges","archive_url":"https://api.github.com/repos/runtimeverification/javamop/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/runtimeverification/javamop/downloads","issues_url":"https://api.github.com/repos/runtimeverification/javamop/issues{/number}","pulls_url":"https://api.github.com/repos/runtimeverification/javamop/pulls{/number}","milestones_url":"https://api.github.com/repos/runtimeverification/javamop/milestones{/number}","notifications_url":"https://api.github.com/repos/runtimeverification/javamop/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/runtimeverification/javamop/labels{/name}","releases_url":"https://api.github.com/repos/runtimeverification/javamop/releases{/id}","created_at":"2013-10-02T17:09:23Z","updated_at":"2014-06-17T19:20:48Z","pushed_at":"2014-07-02T22:09:58Z","git_url":"git://github.com/runtimeverification/javamop.git","ssh_url":"git@github.com:runtimeverification/javamop.git","clone_url":"https://github.com/runtimeverification/javamop.git","svn_url":"https://github.com/runtimeverification/javamop","homepage":"http://fsl.cs.illinois.edu/javamop","size":18864,"stargazers_count":2,"watchers_count":2,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"forks_count":1,"mirror_url":null,"open_issues_count":22,"forks":1,"open_issues":22,"watchers":2,"default_branch":"master"}},"base":{"label":"runtimeverification:master","ref":"master","sha":"7198ffa5b30953a79066e83da73505684ef627d3","user":{"login":"runtimeverification","id":3732719,"avatar_url":"https://avatars.githubusercontent.com/u/3732719?","gravatar_id":"ec5e3b1d9473514c1720f216a63a467b","url":"https://api.github.com/users/runtimeverification","html_url":"https://github.com/runtimeverification","followers_url":"https://api.github.com/users/runtimeverification/followers","following_url":"https://api.github.com/users/runtimeverification/following{/other_user}","gists_url":"https://api.github.com/users/runtimeverification/gists{/gist_id}","starred_url":"https://api.github.com/users/runtimeverification/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/runtimeverification/subscriptions","organizations_url":"https://api.github.com/users/runtimeverification/orgs","repos_url":"https://api.github.com/users/runtimeverification/repos","events_url":"https://api.github.com/users/runtimeverification/events{/privacy}","received_events_url":"https://api.github.com/users/runtimeverification/received_events","type":"Organization","site_admin":false},"repo":{"id":13277219,"name":"javamop","full_name":"runtimeverification/javamop","owner":{"login":"runtimeverification","id":3732719,"avatar_url":"https://avatars.githubusercontent.com/u/3732719?","gravatar_id":"ec5e3b1d9473514c1720f216a63a467b","url":"https://api.github.com/users/runtimeverification","html_url":"https://github.com/runtimeverification","followers_url":"https://api.github.com/users/runtimeverification/followers","following_url":"https://api.github.com/users/runtimeverification/following{/other_user}","gists_url":"https://api.github.com/users/runtimeverification/gists{/gist_id}","starred_url":"https://api.github.com/users/runtimeverification/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/runtimeverification/subscriptions","organizations_url":"https://api.github.com/users/runtimeverification/orgs","repos_url":"https://api.github.com/users/runtimeverification/repos","events_url":"https://api.github.com/users/runtimeverification/events{/privacy}","received_events_url":"https://api.github.com/users/runtimeverification/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/runtimeverification/javamop","description":"Runtime verification system for Java, using AspectJ for instrumentation.","fork":false,"url":"https://api.github.com/repos/runtimeverification/javamop","forks_url":"https://api.github.com/repos/runtimeverification/javamop/forks","keys_url":"https://api.github.com/repos/runtimeverification/javamop/keys{/key_id}","collaborators_url":"https://api.github.com/repos/runtimeverification/javamop/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/runtimeverification/javamop/teams","hooks_url":"https://api.github.com/repos/runtimeverification/javamop/hooks","issue_events_url":"https://api.github.com/repos/runtimeverification/javamop/issues/events{/number}","events_url":"https://api.github.com/repos/runtimeverification/javamop/events","assignees_url":"https://api.github.com/repos/runtimeverification/javamop/assignees{/user}","branches_url":"https://api.github.com/repos/runtimeverification/javamop/branches{/branch}","tags_url":"https://api.github.com/repos/runtimeverification/javamop/tags","blobs_url":"https://api.github.com/repos/runtimeverification/javamop/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/runtimeverification/javamop/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/runtimeverification/javamop/git/refs{/sha}","trees_url":"https://api.github.com/repos/runtimeverification/javamop/git/trees{/sha}","statuses_url":"https://api.github.com/repos/runtimeverification/javamop/statuses/{sha}","languages_url":"https://api.github.com/repos/runtimeverification/javamop/languages","stargazers_url":"https://api.github.com/repos/runtimeverification/javamop/stargazers","contributors_url":"https://api.github.com/repos/runtimeverification/javamop/contributors","subscribers_url":"https://api.github.com/repos/runtimeverification/javamop/subscribers","subscription_url":"https://api.github.com/repos/runtimeverification/javamop/subscription","commits_url":"https://api.github.com/repos/runtimeverification/javamop/commits{/sha}","git_commits_url":"https://api.github.com/repos/runtimeverification/javamop/git/commits{/sha}","comments_url":"https://api.github.com/repos/runtimeverification/javamop/comments{/number}","issue_comment_url":"https://api.github.com/repos/runtimeverification/javamop/issues/comments/{number}","contents_url":"https://api.github.com/repos/runtimeverification/javamop/contents/{+path}","compare_url":"https://api.github.com/repos/runtimeverification/javamop/compare/{base}...{head}","merges_url":"https://api.github.com/repos/runtimeverification/javamop/merges","archive_url":"https://api.github.com/repos/runtimeverification/javamop/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/runtimeverification/javamop/downloads","issues_url":"https://api.github.com/repos/runtimeverification/javamop/issues{/number}","pulls_url":"https://api.github.com/repos/runtimeverification/javamop/pulls{/number}","milestones_url":"https://api.github.com/repos/runtimeverification/javamop/milestones{/number}","notifications_url":"https://api.github.com/repos/runtimeverification/javamop/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/runtimeverification/javamop/labels{/name}","releases_url":"https://api.github.com/repos/runtimeverification/javamop/releases{/id}","created_at":"2013-10-02T17:09:23Z","updated_at":"2014-06-17T19:20:48Z","pushed_at":"2014-07-02T22:09:58Z","git_url":"git://github.com/runtimeverification/javamop.git","ssh_url":"git@github.com:runtimeverification/javamop.git","clone_url":"https://github.com/runtimeverification/javamop.git","svn_url":"https://github.com/runtimeverification/javamop","homepage":"http://fsl.cs.illinois.edu/javamop","size":18864,"stargazers_count":2,"watchers_count":2,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"forks_count":1,"mirror_url":null,"open_issues_count":22,"forks":1,"open_issues":22,"watchers":2,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/runtimeverification/javamop/pulls/32"},"html":{"href":"https://github.com/runtimeverification/javamop/pull/32"},"issue":{"href":"https://api.github.com/repos/runtimeverification/javamop/issues/32"},"comments":{"href":"https://api.github.com/repos/runtimeverification/javamop/issues/32/comments"},"review_comments":{"href":"https://api.github.com/repos/runtimeverification/javamop/pulls/32/comments"},"review_comment":{"href":"https://api.github.com/repos/runtimeverification/javamop/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/runtimeverification/javamop/pulls/32/commits"},"statuses":{"href":"https://api.github.com/repos/runtimeverification/javamop/statuses/607aef5ec955cbd71aee465d2c2136f8fa7d2289"}}}}