{"action":"created","comment":{"url":"https://api.github.com/repos/broadinstitute/cromwell/pulls/comments/34114081","id":34114081,"diff_hunk":"@@ -0,0 +1,112 @@\n+package cromwell.util\n+\n+import java.io._\n+\n+import com.google.api.client.auth.oauth2.Credential\n+import com.google.api.client.extensions.java6.auth.oauth2.{AuthorizationCodeInstalledApp, VerificationCodeReceiver}\n+import com.google.api.client.googleapis.auth.oauth2.{GoogleAuthorizationCodeFlow, GoogleClientSecrets}\n+import com.google.api.client.googleapis.extensions.java6.auth.oauth2.GooglePromptReceiver\n+import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport\n+import com.google.api.client.http.{InputStreamContent, HttpTransport}\n+import com.google.api.client.json.JsonFactory\n+import com.google.api.client.json.jackson2.JacksonFactory\n+import com.google.api.client.util.store.FileDataStoreFactory\n+import com.google.api.services.storage.model.Bucket\n+import com.google.api.services.storage.{Storage, StorageScopes}\n+\n+/**\n+ * Provides a connector which can authenticate with Google and provide access to Google Cloud Storage\n+ *\n+ * @param applicationName The application name to run under\n+ * @param secretFile The path to the secret file - must be local and must be JSON\n+ */\n+class GcsConnector(applicationName: String, secretFile: String) {\n+\n+  // Create the data store directory:\n+  private final val DATA_STORE_DIR: File = new File(System.getProperty(\"user.home\"), \".store/storage_sample\")\n+\n+  // Create the JSON factory:\n+  private final val JSON_FACTORY: JsonFactory = JacksonFactory.getDefaultInstance\n+\n+  // Initialise the transport:\n+  private final val httpTransport: HttpTransport = GoogleNetHttpTransport.newTrustedTransport()\n+\n+  // Initialise the data store factory:\n+  private final val dataStoreFactory: FileDataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR)\n+\n+  // Authorise:\n+  private final val credential: Credential = authorise()\n+\n+  private final val client: Storage = new Storage.Builder(httpTransport, JSON_FACTORY, credential)\n+    .setApplicationName(this.applicationName)\n+    .build()\n+\n+  private def authorise(): Credential =\n+  {\n+    val clientSecretsStream = new FileInputStream(secretFile)\n+\n+    val clientSecrets: GoogleClientSecrets = GoogleClientSecrets.load(\n+      JSON_FACTORY,\n+      new InputStreamReader(clientSecretsStream))\n+\n+\n+    if(clientSecrets.getDetails.getClientId == null || clientSecrets.getDetails.getClientSecret == null)\n+      {\n+        throw new Exception(\"client_secrets not well formed\")\n+      }\n+\n+    val scopes: java.util.Set[String] = new java.util.HashSet[String]()\n+    scopes.add(StorageScopes.DEVSTORAGE_READ_WRITE)\n+\n+    val flow: GoogleAuthorizationCodeFlow = new GoogleAuthorizationCodeFlow.Builder(\n+      httpTransport,\n+      JSON_FACTORY,\n+      clientSecrets,\n+      scopes\n+    )\n+      .setDataStoreFactory(dataStoreFactory)\n+      .build()\n+\n+    val receiver: VerificationCodeReceiver = new GooglePromptReceiver()\n+\n+    new AuthorizationCodeInstalledApp(flow, receiver).authorize(\"user\")\n+  }\n+\n+  def listBucket(bucketName: String): GcsBucketInfo =\n+  {\n+    val getBucket = client.buckets().get(bucketName)\n+    getBucket.setProjection(\"full\")\n+    val bucket: Bucket = getBucket.execute()\n+\n+    new GcsBucketInfo(bucketName, bucket.getLocation, bucket.getTimeCreated, bucket.getOwner)\n+  }\n+\n+  def uploadObject(gcsPath: GoogleCloudStoragePath, inputStream: InputStream, byteCount: Long) =\n+  {\n+    val mediaContent: InputStreamContent = new InputStreamContent(\"application/octet-stream\", inputStream)\n+    mediaContent.setLength(byteCount)\n+\n+    val insertObject = client.objects.insert(gcsPath.bucket, null, mediaContent)\n+    insertObject.setName(gcsPath.objectName)\n+    if(mediaContent.getLength > 0 && mediaContent.getLength <= 2 * 1000 * 1000)","path":"src/main/scala/cromwell/util/GcsConnector.scala","position":91,"original_position":91,"commit_id":"3ffc21641587d2cd0ad38490edac4cb0f7490730","original_commit_id":"3ffc21641587d2cd0ad38490edac4cb0f7490730","user":{"login":"geoffjentry","id":961771,"avatar_url":"https://avatars.githubusercontent.com/u/961771?v=3","gravatar_id":"","url":"https://api.github.com/users/geoffjentry","html_url":"https://github.com/geoffjentry","followers_url":"https://api.github.com/users/geoffjentry/followers","following_url":"https://api.github.com/users/geoffjentry/following{/other_user}","gists_url":"https://api.github.com/users/geoffjentry/gists{/gist_id}","starred_url":"https://api.github.com/users/geoffjentry/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/geoffjentry/subscriptions","organizations_url":"https://api.github.com/users/geoffjentry/orgs","repos_url":"https://api.github.com/users/geoffjentry/repos","events_url":"https://api.github.com/users/geoffjentry/events{/privacy}","received_events_url":"https://api.github.com/users/geoffjentry/received_events","type":"User","site_admin":false},"body":"Comment magical numeric expressions like `<= 2 * 1000 * 1000`","created_at":"2015-07-08T03:49:08Z","updated_at":"2015-07-08T03:49:08Z","html_url":"https://github.com/broadinstitute/cromwell/pull/82#discussion_r34114081","pull_request_url":"https://api.github.com/repos/broadinstitute/cromwell/pulls/82","_links":{"self":{"href":"https://api.github.com/repos/broadinstitute/cromwell/pulls/comments/34114081"},"html":{"href":"https://github.com/broadinstitute/cromwell/pull/82#discussion_r34114081"},"pull_request":{"href":"https://api.github.com/repos/broadinstitute/cromwell/pulls/82"}}},"pull_request":{"url":"https://api.github.com/repos/broadinstitute/cromwell/pulls/82","id":39424052,"html_url":"https://github.com/broadinstitute/cromwell/pull/82","diff_url":"https://github.com/broadinstitute/cromwell/pull/82.diff","patch_url":"https://github.com/broadinstitute/cromwell/pull/82.patch","issue_url":"https://api.github.com/repos/broadinstitute/cromwell/issues/82","number":82,"state":"open","locked":false,"title":"DontMergeYet! Added connection class to GCS and tied in with new JES backend engine functions.","user":{"login":"cjllanwarne","id":13006282,"avatar_url":"https://avatars.githubusercontent.com/u/13006282?v=3","gravatar_id":"","url":"https://api.github.com/users/cjllanwarne","html_url":"https://github.com/cjllanwarne","followers_url":"https://api.github.com/users/cjllanwarne/followers","following_url":"https://api.github.com/users/cjllanwarne/following{/other_user}","gists_url":"https://api.github.com/users/cjllanwarne/gists{/gist_id}","starred_url":"https://api.github.com/users/cjllanwarne/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cjllanwarne/subscriptions","organizations_url":"https://api.github.com/users/cjllanwarne/orgs","repos_url":"https://api.github.com/users/cjllanwarne/repos","events_url":"https://api.github.com/users/cjllanwarne/events{/privacy}","received_events_url":"https://api.github.com/users/cjllanwarne/received_events","type":"User","site_admin":false},"body":"Some known hard-coded files and values (e.g. client_secrets.json) - may be OK if to-be-superceded...","created_at":"2015-07-07T22:30:44Z","updated_at":"2015-07-08T03:49:08Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c79e181fbf913c3ea8c7d494c078e6e7617ecf3f","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/broadinstitute/cromwell/pulls/82/commits","review_comments_url":"https://api.github.com/repos/broadinstitute/cromwell/pulls/82/comments","review_comment_url":"https://api.github.com/repos/broadinstitute/cromwell/pulls/comments{/number}","comments_url":"https://api.github.com/repos/broadinstitute/cromwell/issues/82/comments","statuses_url":"https://api.github.com/repos/broadinstitute/cromwell/statuses/3ffc21641587d2cd0ad38490edac4cb0f7490730","head":{"label":"broadinstitute:chrisl_jes_backend_functions_cherrypick","ref":"chrisl_jes_backend_functions_cherrypick","sha":"3ffc21641587d2cd0ad38490edac4cb0f7490730","user":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars.githubusercontent.com/u/393552?v=3","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"repo":{"id":34136406,"name":"cromwell","full_name":"broadinstitute/cromwell","owner":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars.githubusercontent.com/u/393552?v=3","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/broadinstitute/cromwell","description":"Workflow Execution Engine using WDL","fork":false,"url":"https://api.github.com/repos/broadinstitute/cromwell","forks_url":"https://api.github.com/repos/broadinstitute/cromwell/forks","keys_url":"https://api.github.com/repos/broadinstitute/cromwell/keys{/key_id}","collaborators_url":"https://api.github.com/repos/broadinstitute/cromwell/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/broadinstitute/cromwell/teams","hooks_url":"https://api.github.com/repos/broadinstitute/cromwell/hooks","issue_events_url":"https://api.github.com/repos/broadinstitute/cromwell/issues/events{/number}","events_url":"https://api.github.com/repos/broadinstitute/cromwell/events","assignees_url":"https://api.github.com/repos/broadinstitute/cromwell/assignees{/user}","branches_url":"https://api.github.com/repos/broadinstitute/cromwell/branches{/branch}","tags_url":"https://api.github.com/repos/broadinstitute/cromwell/tags","blobs_url":"https://api.github.com/repos/broadinstitute/cromwell/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/broadinstitute/cromwell/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/broadinstitute/cromwell/git/refs{/sha}","trees_url":"https://api.github.com/repos/broadinstitute/cromwell/git/trees{/sha}","statuses_url":"https://api.github.com/repos/broadinstitute/cromwell/statuses/{sha}","languages_url":"https://api.github.com/repos/broadinstitute/cromwell/languages","stargazers_url":"https://api.github.com/repos/broadinstitute/cromwell/stargazers","contributors_url":"https://api.github.com/repos/broadinstitute/cromwell/contributors","subscribers_url":"https://api.github.com/repos/broadinstitute/cromwell/subscribers","subscription_url":"https://api.github.com/repos/broadinstitute/cromwell/subscription","commits_url":"https://api.github.com/repos/broadinstitute/cromwell/commits{/sha}","git_commits_url":"https://api.github.com/repos/broadinstitute/cromwell/git/commits{/sha}","comments_url":"https://api.github.com/repos/broadinstitute/cromwell/comments{/number}","issue_comment_url":"https://api.github.com/repos/broadinstitute/cromwell/issues/comments{/number}","contents_url":"https://api.github.com/repos/broadinstitute/cromwell/contents/{+path}","compare_url":"https://api.github.com/repos/broadinstitute/cromwell/compare/{base}...{head}","merges_url":"https://api.github.com/repos/broadinstitute/cromwell/merges","archive_url":"https://api.github.com/repos/broadinstitute/cromwell/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/broadinstitute/cromwell/downloads","issues_url":"https://api.github.com/repos/broadinstitute/cromwell/issues{/number}","pulls_url":"https://api.github.com/repos/broadinstitute/cromwell/pulls{/number}","milestones_url":"https://api.github.com/repos/broadinstitute/cromwell/milestones{/number}","notifications_url":"https://api.github.com/repos/broadinstitute/cromwell/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/broadinstitute/cromwell/labels{/name}","releases_url":"https://api.github.com/repos/broadinstitute/cromwell/releases{/id}","created_at":"2015-04-17T19:39:36Z","updated_at":"2015-06-17T07:32:01Z","pushed_at":"2015-07-08T03:31:27Z","git_url":"git://github.com/broadinstitute/cromwell.git","ssh_url":"git@github.com:broadinstitute/cromwell.git","clone_url":"https://github.com/broadinstitute/cromwell.git","svn_url":"https://github.com/broadinstitute/cromwell","homepage":"http://broadinstitute.github.io/cromwell/","size":2916,"stargazers_count":4,"watchers_count":4,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":5,"forks":0,"open_issues":5,"watchers":4,"default_branch":"master"}},"base":{"label":"broadinstitute:develop","ref":"develop","sha":"81a2cab829a6f3ad34858eaac1df8da7ca06ed50","user":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars.githubusercontent.com/u/393552?v=3","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"repo":{"id":34136406,"name":"cromwell","full_name":"broadinstitute/cromwell","owner":{"login":"broadinstitute","id":393552,"avatar_url":"https://avatars.githubusercontent.com/u/393552?v=3","gravatar_id":"","url":"https://api.github.com/users/broadinstitute","html_url":"https://github.com/broadinstitute","followers_url":"https://api.github.com/users/broadinstitute/followers","following_url":"https://api.github.com/users/broadinstitute/following{/other_user}","gists_url":"https://api.github.com/users/broadinstitute/gists{/gist_id}","starred_url":"https://api.github.com/users/broadinstitute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/broadinstitute/subscriptions","organizations_url":"https://api.github.com/users/broadinstitute/orgs","repos_url":"https://api.github.com/users/broadinstitute/repos","events_url":"https://api.github.com/users/broadinstitute/events{/privacy}","received_events_url":"https://api.github.com/users/broadinstitute/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/broadinstitute/cromwell","description":"Workflow Execution Engine using WDL","fork":false,"url":"https://api.github.com/repos/broadinstitute/cromwell","forks_url":"https://api.github.com/repos/broadinstitute/cromwell/forks","keys_url":"https://api.github.com/repos/broadinstitute/cromwell/keys{/key_id}","collaborators_url":"https://api.github.com/repos/broadinstitute/cromwell/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/broadinstitute/cromwell/teams","hooks_url":"https://api.github.com/repos/broadinstitute/cromwell/hooks","issue_events_url":"https://api.github.com/repos/broadinstitute/cromwell/issues/events{/number}","events_url":"https://api.github.com/repos/broadinstitute/cromwell/events","assignees_url":"https://api.github.com/repos/broadinstitute/cromwell/assignees{/user}","branches_url":"https://api.github.com/repos/broadinstitute/cromwell/branches{/branch}","tags_url":"https://api.github.com/repos/broadinstitute/cromwell/tags","blobs_url":"https://api.github.com/repos/broadinstitute/cromwell/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/broadinstitute/cromwell/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/broadinstitute/cromwell/git/refs{/sha}","trees_url":"https://api.github.com/repos/broadinstitute/cromwell/git/trees{/sha}","statuses_url":"https://api.github.com/repos/broadinstitute/cromwell/statuses/{sha}","languages_url":"https://api.github.com/repos/broadinstitute/cromwell/languages","stargazers_url":"https://api.github.com/repos/broadinstitute/cromwell/stargazers","contributors_url":"https://api.github.com/repos/broadinstitute/cromwell/contributors","subscribers_url":"https://api.github.com/repos/broadinstitute/cromwell/subscribers","subscription_url":"https://api.github.com/repos/broadinstitute/cromwell/subscription","commits_url":"https://api.github.com/repos/broadinstitute/cromwell/commits{/sha}","git_commits_url":"https://api.github.com/repos/broadinstitute/cromwell/git/commits{/sha}","comments_url":"https://api.github.com/repos/broadinstitute/cromwell/comments{/number}","issue_comment_url":"https://api.github.com/repos/broadinstitute/cromwell/issues/comments{/number}","contents_url":"https://api.github.com/repos/broadinstitute/cromwell/contents/{+path}","compare_url":"https://api.github.com/repos/broadinstitute/cromwell/compare/{base}...{head}","merges_url":"https://api.github.com/repos/broadinstitute/cromwell/merges","archive_url":"https://api.github.com/repos/broadinstitute/cromwell/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/broadinstitute/cromwell/downloads","issues_url":"https://api.github.com/repos/broadinstitute/cromwell/issues{/number}","pulls_url":"https://api.github.com/repos/broadinstitute/cromwell/pulls{/number}","milestones_url":"https://api.github.com/repos/broadinstitute/cromwell/milestones{/number}","notifications_url":"https://api.github.com/repos/broadinstitute/cromwell/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/broadinstitute/cromwell/labels{/name}","releases_url":"https://api.github.com/repos/broadinstitute/cromwell/releases{/id}","created_at":"2015-04-17T19:39:36Z","updated_at":"2015-06-17T07:32:01Z","pushed_at":"2015-07-08T03:31:27Z","git_url":"git://github.com/broadinstitute/cromwell.git","ssh_url":"git@github.com:broadinstitute/cromwell.git","clone_url":"https://github.com/broadinstitute/cromwell.git","svn_url":"https://github.com/broadinstitute/cromwell","homepage":"http://broadinstitute.github.io/cromwell/","size":2916,"stargazers_count":4,"watchers_count":4,"language":"Java","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":5,"forks":0,"open_issues":5,"watchers":4,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/broadinstitute/cromwell/pulls/82"},"html":{"href":"https://github.com/broadinstitute/cromwell/pull/82"},"issue":{"href":"https://api.github.com/repos/broadinstitute/cromwell/issues/82"},"comments":{"href":"https://api.github.com/repos/broadinstitute/cromwell/issues/82/comments"},"review_comments":{"href":"https://api.github.com/repos/broadinstitute/cromwell/pulls/82/comments"},"review_comment":{"href":"https://api.github.com/repos/broadinstitute/cromwell/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/broadinstitute/cromwell/pulls/82/commits"},"statuses":{"href":"https://api.github.com/repos/broadinstitute/cromwell/statuses/3ffc21641587d2cd0ad38490edac4cb0f7490730"}}}}