NIFI-3449: Adding Google Cloud Storage Bundle

* Credentials service with tests
* Abstract processor definitions
* GCS-themed processors and their corresponding tests

Signed-off-by: James Wing <[email protected]>

This closes #1482.


Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/897c7029
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/897c7029
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/897c7029

Branch: refs/heads/master
Commit: 897c70298a9049d1a4c743b4eca97f108961b3ae
Parents: febe6da
Author: Gene Peters <[email protected]>
Authored: Mon Feb 6 14:36:32 2017 -0800
Committer: James Wing <[email protected]>
Committed: Sun Feb 12 19:52:38 2017 -0800

----------------------------------------------------------------------
 nifi-assembly/LICENSE                           |  33 +
 nifi-assembly/NOTICE                            |   5 +
 nifi-assembly/pom.xml                           |   5 +
 .../nifi-gcp-bundle/nifi-gcp-nar/pom.xml        |  40 +
 .../src/main/resources/META-INF/LICENSE         | 247 ++++++
 .../src/main/resources/META-INF/NOTICE          |  16 +
 .../nifi-gcp-bundle/nifi-gcp-processors/pom.xml | 111 +++
 .../processors/gcp/AbstractGCPProcessor.java    | 116 +++
 .../factory/CredentialPropertyDescriptors.java  |  89 ++
 .../credentials/factory/CredentialsFactory.java | 104 +++
 .../factory/CredentialsStrategy.java            |  63 ++
 .../AbstractBooleanCredentialsStrategy.java     |  69 ++
 .../strategies/AbstractCredentialsStrategy.java |  88 ++
 ...stractServiceAccountCredentialsStrategy.java |  42 +
 .../ComputeEngineCredentialsStrategy.java       |  42 +
 ...itApplicationDefaultCredentialsStrategy.java |  45 +
 ...itApplicationDefaultCredentialsStrategy.java |  42 +
 ...onFileServiceAccountCredentialsStrategy.java |  49 ++
 ...StringServiceAccountCredentialsStrategy.java |  46 ++
 .../GCPCredentialsControllerService.java        |  96 +++
 .../service/GCPCredentialsService.java          |  41 +
 .../gcp/storage/AbstractGCSProcessor.java       |  80 ++
 .../processors/gcp/storage/DeleteGCSObject.java | 125 +++
 .../processors/gcp/storage/FetchGCSObject.java  | 346 ++++++++
 .../processors/gcp/storage/ListGCSBucket.java   | 409 +++++++++
 .../processors/gcp/storage/PutGCSObject.java    | 538 ++++++++++++
 .../gcp/storage/StorageAttributes.java          |  95 +++
 .../nifi/processors/gcp/storage/Util.java       |  61 ++
 ...org.apache.nifi.controller.ControllerService |  15 +
 .../org.apache.nifi.processor.Processor         |  18 +
 .../processors/gcp/GCPIntegrationTests.java     |  23 +
 .../factory/CredentialsFactoryTest.java         | 141 ++++
 .../MockCredentialsFactoryProcessor.java        |  74 ++
 .../service/GCPCredentialsServiceTest.java      | 154 ++++
 .../MockCredentialsServiceProcessor.java        |  58 ++
 .../processors/gcp/storage/AbstractGCSIT.java   | 177 ++++
 .../processors/gcp/storage/AbstractGCSTest.java |  99 +++
 .../gcp/storage/DeleteGCSObjectIT.java          |  91 ++
 .../gcp/storage/DeleteGCSObjectTest.java        | 148 ++++
 .../gcp/storage/FetchGCSObjectIT.java           | 102 +++
 .../gcp/storage/FetchGCSObjectTest.java         | 614 ++++++++++++++
 .../processors/gcp/storage/ListGCSBucketIT.java | 132 +++
 .../gcp/storage/ListGCSBucketTest.java          | 827 +++++++++++++++++++
 .../processors/gcp/storage/PutGCSObjectIT.java  | 148 ++++
 .../gcp/storage/PutGCSObjectTest.java           | 536 ++++++++++++
 .../gcp/storage/StorageAttributesTest.java      |  34 +
 .../nifi/processors/gcp/storage/UtilTest.java   |  48 ++
 ...ock-gcp-application-default-credentials.json |   6 +
 .../resources/mock-gcp-service-account.json     |  12 +
 .../org.mockito.plugins.MockMaker               |   1 +
 nifi-nar-bundles/nifi-gcp-bundle/pom.xml        |  34 +
 nifi-nar-bundles/pom.xml                        |   1 +
 pom.xml                                         |   6 +
 53 files changed, 6542 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-assembly/LICENSE
----------------------------------------------------------------------
diff --git a/nifi-assembly/LICENSE b/nifi-assembly/LICENSE
index 2191651..7669f9c 100644
--- a/nifi-assembly/LICENSE
+++ b/nifi-assembly/LICENSE
@@ -1760,3 +1760,36 @@ The binary distribution of this product bundles 
'HdrHistogram' which is availabl
     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     THE POSSIBILITY OF SUCH DAMAGE.
+
+
+The binary distribution of this product bundles source from 'Google Auth 
Library' which is available
+under a 3-Clause BSD style license:
+
+  Copyright 2014, Google Inc. All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are
+  met:
+
+     * Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the following disclaimer
+  in the documentation and/or other materials provided with the
+  distribution.
+
+     * Neither the name of Google Inc. nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-assembly/NOTICE
----------------------------------------------------------------------
diff --git a/nifi-assembly/NOTICE b/nifi-assembly/NOTICE
index 5711c65..61e0684 100644
--- a/nifi-assembly/NOTICE
+++ b/nifi-assembly/NOTICE
@@ -1196,6 +1196,11 @@ The derived work is adapted from
   release-1.2.1/ql/src/java/org/apache/hadoop/hive/ql/io/orc/WriterImpl.java
 and can be found in the org.apache.hadoop.hive.ql.io.orc package
 
+  (ASLv2) Google Cloud Java Client
+    The following NOTICE information applies:
+      Google Cloud Java Client
+      Copyright Google Inc. All Rights Reserved.
+
 ************************
 Common Development and Distribution License 1.1
 ************************

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-assembly/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-assembly/pom.xml b/nifi-assembly/pom.xml
index 177d77c..2f798fe 100755
--- a/nifi-assembly/pom.xml
+++ b/nifi-assembly/pom.xml
@@ -423,6 +423,11 @@ language governing permissions and limitations under the 
License. -->
             <artifactId>nifi-tcp-nar</artifactId>
             <type>nar</type>
         </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-gcp-nar</artifactId>
+            <type>nar</type>
+        </dependency>
     </dependencies>
     <profiles>
         <profile>

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-nar/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-nar/pom.xml 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-nar/pom.xml
new file mode 100644
index 0000000..af67c36
--- /dev/null
+++ b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-nar/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements. See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-gcp-bundle</artifactId>
+        <version>1.2.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>nifi-gcp-nar</artifactId>
+    <packaging>nar</packaging>
+    <properties>
+        <maven.javadoc.skip>true</maven.javadoc.skip>
+        <source.skip>true</source.skip>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-gcp-processors</artifactId>
+            <version>1.2.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+</project>

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-nar/src/main/resources/META-INF/LICENSE
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-nar/src/main/resources/META-INF/LICENSE
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-nar/src/main/resources/META-INF/LICENSE
new file mode 100644
index 0000000..204d556
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-nar/src/main/resources/META-INF/LICENSE
@@ -0,0 +1,247 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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.
+
+
+APACHE NIFI SUBCOMPONENTS:
+
+The Apache NiFi project contains subcomponents with separate copyright
+notices and license terms. Your use of the source code for the these
+subcomponents is subject to the terms and conditions of the following
+licenses.
+
+
+  The binary distribution of this product bundles source from 'Google Auth 
Library'.
+  The source is available under a BSD 3-Clause:
+
+  Copyright 2014, Google Inc. All rights reserved.
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are
+  met:
+
+     * Redistributions of source code must retain the above copyright
+  notice, this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the following disclaimer
+  in the documentation and/or other materials provided with the
+  distribution.
+
+     * Neither the name of Google Inc. nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+  The binary distribution of this product bundles source from 'Google Cloud 
Library'.
+  The source is available under an Apache License, Version 2.0
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-nar/src/main/resources/META-INF/NOTICE
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-nar/src/main/resources/META-INF/NOTICE
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-nar/src/main/resources/META-INF/NOTICE
new file mode 100644
index 0000000..74ae8ee
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-nar/src/main/resources/META-INF/NOTICE
@@ -0,0 +1,16 @@
+nifi-gcp-nar
+Copyright 2015-2016 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+******************
+Apache Software License v2
+******************
+
+The following binary components are provided under the Apache Software License 
v2
+
+  (ASLv2) Google Cloud Java Client
+    The following NOTICE information applies:
+      Google Cloud Java Client
+      Copyright Google Inc. All Rights Reserved.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/pom.xml 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/pom.xml
new file mode 100644
index 0000000..f27b91e
--- /dev/null
+++ b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/pom.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements. See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-gcp-bundle</artifactId>
+        <version>1.2.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>nifi-gcp-processors</artifactId>
+    <packaging>jar</packaging>
+
+    <properties>
+        <skipGCPIntegrationTests>true</skipGCPIntegrationTests>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-processor-utils</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-mock</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>2.3.7</version>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-simple</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.11</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.cloud</groupId>
+            <artifactId>google-cloud</artifactId>
+            <version>0.8.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.auth</groupId>
+            <artifactId>google-auth-library-oauth2-http</artifactId>
+            <version>0.6.0</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.rat</groupId>
+                <artifactId>apache-rat-plugin</artifactId>
+                <configuration>
+                    <excludes combine.children="append">
+                        
<exclude>src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker</exclude>
+                        
<exclude>src/test/resources/mock-gcp-service-account.json</exclude>
+                        
<exclude>src/test/resources/mock-gcp-application-default-credentials.json</exclude>
+                    </excludes>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <version>2.19.1</version>
+                <configuration>
+                    
<groups>org.apache.nifi.processors.gcp.GCPIntegrationTests</groups>
+                    <skipITs>${skipGCPIntegrationTests}</skipITs>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.19.1</version>
+                <configuration>
+                    
<excludedGroups>org.apache.nifi.processors.gcp.GCPIntegrationTests</excludedGroups>
+                    <environmentVariables>
+                        
<GOOGLE_APPLICATION_CREDENTIALS>${project.basedir}/src/test/resources/mock-gcp-application-default-credentials.json</GOOGLE_APPLICATION_CREDENTIALS>
+                    </environmentVariables>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/AbstractGCPProcessor.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/AbstractGCPProcessor.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/AbstractGCPProcessor.java
new file mode 100644
index 0000000..08d8b61
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/AbstractGCPProcessor.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import com.google.cloud.HttpServiceOptions;
+import com.google.cloud.Service;
+import com.google.common.collect.ImmutableList;
+import org.apache.nifi.annotation.lifecycle.OnScheduled;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.processor.AbstractProcessor;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.util.StandardValidators;
+import 
org.apache.nifi.processors.gcp.credentials.service.GCPCredentialsService;
+
+import java.util.List;
+
+/**
+ * Abstract base class for gcp processors.
+ *
+ */
+public abstract class AbstractGCPProcessor<
+        CloudService extends Service<CloudServiceOptions>,
+        CloudServiceRpc,
+        CloudServiceOptions extends HttpServiceOptions<CloudService, 
CloudServiceRpc, CloudServiceOptions>> extends AbstractProcessor {
+
+    public static final PropertyDescriptor PROJECT_ID = new PropertyDescriptor
+            .Builder().name("gcp-project-id")
+            .displayName("Project ID")
+            .description("Google Cloud Project ID")
+            .required(true)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .build();
+
+    public static final PropertyDescriptor RETRY_COUNT = new PropertyDescriptor
+            .Builder().name("gcp-retry-count")
+            .displayName("Number of retries")
+            .description("How many retry attempts should be made before 
routing to the failure relationship.")
+            .defaultValue("6")
+            .required(true)
+            .addValidator(StandardValidators.INTEGER_VALIDATOR)
+            .build();
+
+    /**
+     * Links to the {@link GCPCredentialsService} which provides credentials 
for this particular processor.
+     */
+    public static final PropertyDescriptor GCP_CREDENTIALS_PROVIDER_SERVICE = 
new PropertyDescriptor.Builder()
+            .name("gcp-credentials-provider-service")
+            .name("GCP Credentials Provider Service")
+            .description("The Controller Service used to obtain Google Cloud 
Platform credentials.")
+            .required(true)
+            .identifiesControllerService(GCPCredentialsService.class)
+            .build();
+
+
+    protected volatile CloudService cloudService;
+
+    protected CloudService getCloudService() {
+        return cloudService;
+    }
+
+    @Override
+    public List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+        return ImmutableList.of(
+                GCP_CREDENTIALS_PROVIDER_SERVICE,
+                PROJECT_ID,
+                RETRY_COUNT
+        );
+    }
+
+
+    /**
+     * Retrieve credentials from the {@link GCPCredentialsService} attached to 
this processor.
+     * @param context the process context provided on scheduling the processor.
+     * @return GoogleCredentials for the processor to access.
+     * @see  <a 
href="https://developers.google.com/api-client-library/java/google-api-java-client/reference/1.20.0/com/google/api/client/googleapis/auth/oauth2/GoogleCredential";>AuthCredentials</a>
+     */
+    private GoogleCredentials getGoogleCredentials(final ProcessContext 
context) {
+        final GCPCredentialsService gcpCredentialsService =
+                
context.getProperty(GCP_CREDENTIALS_PROVIDER_SERVICE).asControllerService(GCPCredentialsService.class);
+        return gcpCredentialsService.getGoogleCredentials();
+    }
+
+    /**
+     * Assigns the cloud service client on scheduling.
+     * @param context the process context provided on scheduling the processor.
+     */
+    @OnScheduled
+    public void onScheduled(ProcessContext context) {
+        final CloudServiceOptions options = getServiceOptions(context, 
getGoogleCredentials(context));
+        this.cloudService = options.getService();
+    }
+
+    /**
+     * Builds the service-specific options as a necessary step in creating a 
cloud service.
+     * @param context the process context provided on scheduling the processor.
+     * @param credentials valid GoogleCredentials retrieved by the controller 
service.
+     * @return CloudServiceOptions which can be initialized into a cloud 
service.
+     * @see <a 
href="http://googlecloudplatform.github.io/google-cloud-java/0.8.0/apidocs/com/google/cloud/ServiceOptions.html";>ServiceOptions</a>
+     */
+    protected abstract CloudServiceOptions getServiceOptions(ProcessContext 
context, GoogleCredentials credentials);
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/CredentialPropertyDescriptors.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/CredentialPropertyDescriptors.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/CredentialPropertyDescriptors.java
new file mode 100644
index 0000000..bd99dd8
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/CredentialPropertyDescriptors.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp.credentials.factory;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.processor.util.StandardValidators;
+
+/**
+ * Shared definitions of properties that specify various GCP credentials.
+ */
+public final class CredentialPropertyDescriptors {
+
+    private CredentialPropertyDescriptors() {}
+
+    /**
+     * Specifies use of Application Default Credentials
+     *
+     * @see <a 
href="https://developers.google.com/identity/protocols/application-default-credentials";>
+     *     Google Application Default Credentials
+     *     </a>
+     */
+    public static final PropertyDescriptor USE_APPLICATION_DEFAULT_CREDENTIALS 
= new PropertyDescriptor.Builder()
+            .name("application-default-credentials")
+            .displayName("Use Application Default Credentials")
+            .expressionLanguageSupported(false)
+            .required(false)
+            .addValidator(StandardValidators.BOOLEAN_VALIDATOR)
+            .sensitive(false)
+            .allowableValues("true", "false")
+            .defaultValue("false")
+            .description("If true, uses Google Application Default 
Credentials, which checks the " +
+                    "GOOGLE_APPLICATION_CREDENTIALS environment variable for a 
filepath to a service account JSON " +
+                    "key, the config generated by the gcloud sdk, the App 
Engine service account, and the Compute" +
+                    " Engine service account.")
+            .build();
+
+    public static final PropertyDescriptor USE_COMPUTE_ENGINE_CREDENTIALS = 
new PropertyDescriptor.Builder()
+            .name("compute-engine-credentials")
+            .displayName("Use Compute Engine Credentials")
+            .expressionLanguageSupported(false)
+            .required(false)
+            .addValidator(StandardValidators.BOOLEAN_VALIDATOR)
+            .sensitive(false)
+            .allowableValues("true", "false")
+            .defaultValue("false")
+            .description("If true, uses Google Compute Engine Credentials of 
the Compute Engine VM Instance " +
+                    "which NiFi is running on.")
+            .build();
+
+    /**
+     * Specifies use of Service Account Credentials
+     *
+     * @see <a href="https://cloud.google.com/iam/docs/service-accounts";>
+     *     Google Service Accounts
+     *     </a>
+     */
+    public static final PropertyDescriptor SERVICE_ACCOUNT_JSON_FILE = new 
PropertyDescriptor.Builder()
+            .name("service-account-json-file")
+            .displayName("Service Account JSON File")
+            .expressionLanguageSupported(false)
+            .required(false)
+            .addValidator(StandardValidators.FILE_EXISTS_VALIDATOR)
+            .description("Path to a file containing a Service Account key file 
in JSON format.")
+            .build();
+
+    public static final PropertyDescriptor SERVICE_ACCOUNT_JSON = new 
PropertyDescriptor.Builder()
+            .name("service-account-json")
+            .displayName("Service Account JSON")
+            .expressionLanguageSupported(true)
+            .required(false)
+            .addValidator(StandardValidators.NON_EMPTY_VALIDATOR)
+            .description("The raw JSON containing a Service Account keyfile.")
+            .sensitive(true)
+            .build();
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/CredentialsFactory.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/CredentialsFactory.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/CredentialsFactory.java
new file mode 100644
index 0000000..8b9c4f4
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/CredentialsFactory.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp.credentials.factory;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.ValidationContext;
+import org.apache.nifi.components.ValidationResult;
+import 
org.apache.nifi.processors.gcp.credentials.factory.strategies.ComputeEngineCredentialsStrategy;
+import 
org.apache.nifi.processors.gcp.credentials.factory.strategies.ExplicitApplicationDefaultCredentialsStrategy;
+import 
org.apache.nifi.processors.gcp.credentials.factory.strategies.ImplicitApplicationDefaultCredentialsStrategy;
+import 
org.apache.nifi.processors.gcp.credentials.factory.strategies.JsonFileServiceAccountCredentialsStrategy;
+import 
org.apache.nifi.processors.gcp.credentials.factory.strategies.JsonStringServiceAccountCredentialsStrategy;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Generates GCP credentials in the form of GoogleCredential implementations 
for processors
+ * and controller services.  The factory supports a number of strategies for 
specifying and validating
+ * GCP credentials, interpreted as an ordered list of most-preferred to 
least-preferred.
+ *
+ * Additional strategies should implement CredentialsStrategy, then be added 
to the strategies list in the
+ * constructor.
+ *
+ * @see org.apache.nifi.processors.gcp.credentials.factory.strategies
+ */
+public class CredentialsFactory {
+
+    private final List<CredentialsStrategy> strategies = new 
ArrayList<CredentialsStrategy>();
+
+    public CredentialsFactory() {
+        // Primary Credential Strategies
+        strategies.add(new ExplicitApplicationDefaultCredentialsStrategy());
+        strategies.add(new JsonFileServiceAccountCredentialsStrategy());
+        strategies.add(new JsonStringServiceAccountCredentialsStrategy());
+        strategies.add(new ComputeEngineCredentialsStrategy());
+
+        // Implicit Default is the catch-all primary strategy
+        strategies.add(new ImplicitApplicationDefaultCredentialsStrategy());
+    }
+
+    public CredentialsStrategy selectPrimaryStrategy(final 
Map<PropertyDescriptor, String> properties) {
+        for (CredentialsStrategy strategy : strategies) {
+            if (strategy.canCreatePrimaryCredential(properties)) {
+                return strategy;
+            }
+        }
+        return null;
+    }
+
+    public CredentialsStrategy selectPrimaryStrategy(final ValidationContext 
validationContext) {
+        final Map<PropertyDescriptor, String> properties = 
validationContext.getProperties();
+        return selectPrimaryStrategy(properties);
+    }
+
+    /**
+     * Validates GCP credential properties against the configured strategies 
to report any validation errors.
+     * @return Validation errors
+     */
+    public Collection<ValidationResult> validate(final ValidationContext 
validationContext) {
+        final CredentialsStrategy selectedStrategy = 
selectPrimaryStrategy(validationContext);
+        final ArrayList<ValidationResult> validationFailureResults = new 
ArrayList<ValidationResult>();
+
+        for (CredentialsStrategy strategy : strategies) {
+            final Collection<ValidationResult> strategyValidationFailures = 
strategy.validate(validationContext,
+                    selectedStrategy);
+            if (strategyValidationFailures != null) {
+                validationFailureResults.addAll(strategyValidationFailures);
+            }
+        }
+
+        return validationFailureResults;
+    }
+
+    /**
+     * Produces the AuthCredentials according to the given property set and 
the strategies configured in
+     * the factory.
+     * @return AuthCredentials
+     *
+     * @throws IOException if there is an issue accessing the credential files
+     */
+    public GoogleCredentials getGoogleCredentials(final 
Map<PropertyDescriptor, String> properties) throws IOException {
+        final CredentialsStrategy primaryStrategy = 
selectPrimaryStrategy(properties);
+        return primaryStrategy.getGoogleCredentials(properties);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/CredentialsStrategy.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/CredentialsStrategy.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/CredentialsStrategy.java
new file mode 100644
index 0000000..b2a9168
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/CredentialsStrategy.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp.credentials.factory;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.ValidationContext;
+import org.apache.nifi.components.ValidationResult;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Specifies a strategy for validating and creating GCP credentials from a 
list of properties configured on a
+ * Processor, Controller Service, Reporting Service, or other component.  
Supports only primary credentials like
+ * default credentials or API keys.
+ */
+public interface CredentialsStrategy {
+
+    /**
+     * Name of the strategy, suitable for displaying to a user in validation 
messages.
+     * @return strategy name
+     */
+    String getName();
+
+    /**
+     * Determines if this strategy can create primary credentials using the 
given properties.
+     * @return true if primary credentials can be created
+     */
+    boolean canCreatePrimaryCredential(Map<PropertyDescriptor, String> 
properties);
+
+
+    /**
+     * Validates the properties belonging to this strategy, given the selected 
primary strategy.  Errors may result
+     * from individually malformed properties, invalid combinations of 
properties, or inappropriate use of properties
+     * not consistent with the primary strategy.
+     * @param primaryStrategy the prevailing primary strategy
+     * @return validation errors
+     */
+    Collection<ValidationResult> validate(ValidationContext validationContext, 
CredentialsStrategy primaryStrategy);
+
+    /**
+     * Creates an AuthCredentials instance for this strategy, given the 
properties defined by the user.
+     *
+     * @throws IOException if the provided credentials cannot be accessed or 
are invalid
+     */
+    GoogleCredentials getGoogleCredentials(Map<PropertyDescriptor, String> 
properties) throws IOException;
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/AbstractBooleanCredentialsStrategy.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/AbstractBooleanCredentialsStrategy.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/AbstractBooleanCredentialsStrategy.java
new file mode 100644
index 0000000..0f94a2a
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/AbstractBooleanCredentialsStrategy.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp.credentials.factory.strategies;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.ValidationContext;
+import org.apache.nifi.components.ValidationResult;
+import org.apache.nifi.processors.gcp.credentials.factory.CredentialsStrategy;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+
+/**
+ * Partial implementation of CredentialsStrategy to provide support for 
credential strategies specified by
+ * a single boolean property.
+ */
+public abstract class AbstractBooleanCredentialsStrategy extends 
AbstractCredentialsStrategy {
+
+    private PropertyDescriptor strategyProperty;
+
+    public AbstractBooleanCredentialsStrategy(String name, PropertyDescriptor 
strategyProperty) {
+        super(name, new PropertyDescriptor[]{
+                strategyProperty
+        });
+        this.strategyProperty = strategyProperty;
+    }
+
+    @Override
+    public boolean canCreatePrimaryCredential(Map<PropertyDescriptor, String> 
properties) {
+        return (properties.get(this.strategyProperty) != null
+                && 
properties.get(this.strategyProperty).equalsIgnoreCase("true"));
+    }
+
+    @Override
+    public Collection<ValidationResult> validate(final ValidationContext 
validationContext,
+                                                 final CredentialsStrategy 
primaryStrategy) {
+        boolean thisIsSelectedStrategy = this == primaryStrategy;
+        Boolean useStrategy = 
validationContext.getProperty(strategyProperty).asBoolean();
+        if (!thisIsSelectedStrategy && (useStrategy == null ? false : 
useStrategy)) {
+            String failureFormat = "property %1$s cannot be used with %2$s";
+            Collection<ValidationResult> validationFailureResults = new 
ArrayList<ValidationResult>();
+            String message = String.format(failureFormat, 
strategyProperty.getDisplayName(),
+                    primaryStrategy.getName());
+            validationFailureResults.add(new ValidationResult.Builder()
+                    .subject(strategyProperty.getDisplayName())
+                    .valid(false)
+                    .explanation(message).build());
+            return  validationFailureResults;
+        }
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/AbstractCredentialsStrategy.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/AbstractCredentialsStrategy.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/AbstractCredentialsStrategy.java
new file mode 100644
index 0000000..35b365e
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/AbstractCredentialsStrategy.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp.credentials.factory.strategies;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.ValidationContext;
+import org.apache.nifi.components.ValidationResult;
+import org.apache.nifi.processors.gcp.credentials.factory.CredentialsStrategy;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Partial implementation of CredentialsStrategy to support most simple 
property-based strategies.
+ */
+public abstract class AbstractCredentialsStrategy implements 
CredentialsStrategy {
+    private final String name;
+    private final PropertyDescriptor[] requiredProperties;
+
+    public AbstractCredentialsStrategy(String name, PropertyDescriptor[] 
requiredProperties) {
+        this.name = name;
+        this.requiredProperties = requiredProperties;
+    }
+
+    @Override
+    public boolean canCreatePrimaryCredential(Map<PropertyDescriptor, String> 
properties) {
+        for (PropertyDescriptor requiredProperty : requiredProperties) {
+            boolean containsRequiredProperty = 
properties.containsKey(requiredProperty);
+            String propertyValue = properties.get(requiredProperty);
+            boolean containsValue = propertyValue != null;
+            if (!containsRequiredProperty || !containsValue) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public Collection<ValidationResult> validate(final ValidationContext 
validationContext,
+                                                 final CredentialsStrategy 
primaryStrategy) {
+        boolean thisIsSelectedStrategy = this == primaryStrategy;
+        String requiredMessageFormat = "property %1$s must be set with %2$s";
+        String excludedMessageFormat = "property %1$s cannot be used with 
%2$s";
+        String failureFormat = thisIsSelectedStrategy ? requiredMessageFormat 
: excludedMessageFormat;
+        Collection<ValidationResult> validationFailureResults = null;
+
+        for (PropertyDescriptor requiredProperty : requiredProperties) {
+            boolean requiredPropertyIsSet = 
validationContext.getProperty(requiredProperty).isSet();
+            if (requiredPropertyIsSet != thisIsSelectedStrategy) {
+                String message = String.format(failureFormat, 
requiredProperty.getDisplayName(),
+                        primaryStrategy.getName());
+                if (validationFailureResults == null) {
+                    validationFailureResults = new ArrayList<>();
+                }
+                validationFailureResults.add(new ValidationResult.Builder()
+                        .subject(requiredProperty.getDisplayName())
+                        .valid(false)
+                        .explanation(message).build());
+            }
+        }
+
+        return validationFailureResults;
+    }
+
+    @Override
+    public abstract GoogleCredentials 
getGoogleCredentials(Map<PropertyDescriptor, String> properties) throws 
IOException;
+
+    public String getName() {
+        return name;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/AbstractServiceAccountCredentialsStrategy.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/AbstractServiceAccountCredentialsStrategy.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/AbstractServiceAccountCredentialsStrategy.java
new file mode 100644
index 0000000..44f8e71
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/AbstractServiceAccountCredentialsStrategy.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp.credentials.factory.strategies;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import org.apache.nifi.components.PropertyDescriptor;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+/**
+ * Abstract class handling any of the service account related credential 
strategies, whether provided directly to NiFi
+ * or through a flat JSON file.
+ */
+public abstract class AbstractServiceAccountCredentialsStrategy extends 
AbstractCredentialsStrategy {
+    public AbstractServiceAccountCredentialsStrategy(String name, 
PropertyDescriptor[] requiredProperties) {
+        super(name, requiredProperties);
+    }
+
+    protected abstract InputStream 
getServiceAccountJson(Map<PropertyDescriptor, String> properties) throws 
IOException;
+
+    @Override
+    public GoogleCredentials getGoogleCredentials(Map<PropertyDescriptor, 
String> properties) throws IOException {
+        return GoogleCredentials.fromStream(getServiceAccountJson(properties));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/ComputeEngineCredentialsStrategy.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/ComputeEngineCredentialsStrategy.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/ComputeEngineCredentialsStrategy.java
new file mode 100644
index 0000000..5b5034b
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/ComputeEngineCredentialsStrategy.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp.credentials.factory.strategies;
+
+import com.google.auth.oauth2.ComputeEngineCredentials;
+import com.google.auth.oauth2.GoogleCredentials;
+import org.apache.nifi.components.PropertyDescriptor;
+import 
org.apache.nifi.processors.gcp.credentials.factory.CredentialPropertyDescriptors;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Supports Google Compute Engine credentials. Fetches access tokens from the 
Google Compute Engine metadata server.
+ *
+ * @see <a 
href="https://cloud.google.com/compute/docs/access/create-enable-service-accounts-for-instances";>
+ *     Service Accounts for Instances</a>
+ */
+public class ComputeEngineCredentialsStrategy extends 
AbstractBooleanCredentialsStrategy {
+    public ComputeEngineCredentialsStrategy() {
+        super("Compute Engine Credentials", 
CredentialPropertyDescriptors.USE_COMPUTE_ENGINE_CREDENTIALS);
+    }
+
+    @Override
+    public GoogleCredentials getGoogleCredentials(Map<PropertyDescriptor, 
String> properties) throws IOException {
+        return new ComputeEngineCredentials();
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/ExplicitApplicationDefaultCredentialsStrategy.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/ExplicitApplicationDefaultCredentialsStrategy.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/ExplicitApplicationDefaultCredentialsStrategy.java
new file mode 100644
index 0000000..55ebef7
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/ExplicitApplicationDefaultCredentialsStrategy.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp.credentials.factory.strategies;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import org.apache.nifi.components.PropertyDescriptor;
+import 
org.apache.nifi.processors.gcp.credentials.factory.CredentialPropertyDescriptors;
+
+import java.io.IOException;
+import java.util.Map;
+
+
+/**
+ * Supports GCP Application Default Credentials.  Compared to 
ImplicitApplicationDefaultCredentialsStrategy, this
+ * strategy is designed to be visible to the user, and depends on an 
affirmative selection from the user.
+ *
+ * @see <a 
href="https://developers.google.com/identity/protocols/application-default-credentials";>
+ *     Application Default Credentials</a>
+ */
+public class ExplicitApplicationDefaultCredentialsStrategy extends 
AbstractBooleanCredentialsStrategy {
+
+    public ExplicitApplicationDefaultCredentialsStrategy() {
+        super("Application Default Credentials", 
CredentialPropertyDescriptors.USE_APPLICATION_DEFAULT_CREDENTIALS);
+    }
+
+    @Override
+    public GoogleCredentials getGoogleCredentials(Map<PropertyDescriptor, 
String> properties) throws IOException {
+        return GoogleCredentials.getApplicationDefault();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/ImplicitApplicationDefaultCredentialsStrategy.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/ImplicitApplicationDefaultCredentialsStrategy.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/ImplicitApplicationDefaultCredentialsStrategy.java
new file mode 100644
index 0000000..95f9792
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/ImplicitApplicationDefaultCredentialsStrategy.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp.credentials.factory.strategies;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import org.apache.nifi.components.PropertyDescriptor;
+
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * Supports Google Cloud Application Default Credentials.
+ * Compared to ExplicitApplicationDefaultCredentialsStrategy, this strategy is 
always
+ * willing to provide primary credentials, regardless of user input.  It is 
intended to be used as an invisible
+ * fallback or default strategy.
+ */
+public class ImplicitApplicationDefaultCredentialsStrategy extends 
AbstractCredentialsStrategy {
+
+    public ImplicitApplicationDefaultCredentialsStrategy() {
+        super("Application Default Credentials", new PropertyDescriptor[]{});
+    }
+
+    @Override
+    public GoogleCredentials getGoogleCredentials(Map<PropertyDescriptor, 
String> properties) throws IOException {
+        return GoogleCredentials.getApplicationDefault();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/JsonFileServiceAccountCredentialsStrategy.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/JsonFileServiceAccountCredentialsStrategy.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/JsonFileServiceAccountCredentialsStrategy.java
new file mode 100644
index 0000000..924a2ae
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/JsonFileServiceAccountCredentialsStrategy.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp.credentials.factory.strategies;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import 
org.apache.nifi.processors.gcp.credentials.factory.CredentialPropertyDescriptors;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Map;
+
+
+/**
+ * Supports service account credentials in a JSON file.
+ *
+ * @see <a href="https://cloud.google.com/iam/docs/service-accounts";>
+ *     Service Accounts</a>
+ */
+public class JsonFileServiceAccountCredentialsStrategy extends 
AbstractServiceAccountCredentialsStrategy {
+
+    public JsonFileServiceAccountCredentialsStrategy() {
+        super("Service Account Credentials (Json File)", new 
PropertyDescriptor[] {
+                CredentialPropertyDescriptors.SERVICE_ACCOUNT_JSON_FILE
+        });
+    }
+
+    @Override
+    protected InputStream getServiceAccountJson(Map<PropertyDescriptor, 
String> properties) throws IOException {
+        String serviceAccountFile = 
properties.get(CredentialPropertyDescriptors.SERVICE_ACCOUNT_JSON_FILE);
+        return new 
BufferedInputStream(Files.newInputStream(Paths.get(serviceAccountFile)));
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/JsonStringServiceAccountCredentialsStrategy.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/JsonStringServiceAccountCredentialsStrategy.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/JsonStringServiceAccountCredentialsStrategy.java
new file mode 100644
index 0000000..3a40a78
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/factory/strategies/JsonStringServiceAccountCredentialsStrategy.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp.credentials.factory.strategies;
+
+import org.apache.nifi.components.PropertyDescriptor;
+import 
org.apache.nifi.processors.gcp.credentials.factory.CredentialPropertyDescriptors;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Map;
+
+
+/**
+ * Supports service account credentials provided as a JSON string.
+ *
+ * @see <a href="https://cloud.google.com/iam/docs/service-accounts";>
+ *     Service Accounts</a>
+ */
+public class JsonStringServiceAccountCredentialsStrategy extends 
AbstractServiceAccountCredentialsStrategy {
+
+    public JsonStringServiceAccountCredentialsStrategy() {
+        super("Service Account Credentials (Json String)", new 
PropertyDescriptor[] {
+                CredentialPropertyDescriptors.SERVICE_ACCOUNT_JSON
+        });
+    }
+
+    @Override
+    protected InputStream getServiceAccountJson(Map<PropertyDescriptor, 
String> properties) {
+        String serviceAccountJson = 
properties.get(CredentialPropertyDescriptors.SERVICE_ACCOUNT_JSON);
+        return new ByteArrayInputStream(serviceAccountJson.getBytes());
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/service/GCPCredentialsControllerService.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/service/GCPCredentialsControllerService.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/service/GCPCredentialsControllerService.java
new file mode 100644
index 0000000..5031687
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/service/GCPCredentialsControllerService.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp.credentials.service;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.annotation.lifecycle.OnEnabled;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.components.ValidationContext;
+import org.apache.nifi.components.ValidationResult;
+import org.apache.nifi.controller.AbstractControllerService;
+import org.apache.nifi.controller.ConfigurationContext;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.processors.gcp.credentials.factory.CredentialsFactory;
+import org.apache.nifi.reporting.InitializationException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static 
org.apache.nifi.processors.gcp.credentials.factory.CredentialPropertyDescriptors.SERVICE_ACCOUNT_JSON;
+import static 
org.apache.nifi.processors.gcp.credentials.factory.CredentialPropertyDescriptors.SERVICE_ACCOUNT_JSON_FILE;
+import static 
org.apache.nifi.processors.gcp.credentials.factory.CredentialPropertyDescriptors.USE_APPLICATION_DEFAULT_CREDENTIALS;
+import static 
org.apache.nifi.processors.gcp.credentials.factory.CredentialPropertyDescriptors.USE_COMPUTE_ENGINE_CREDENTIALS;
+/**
+ * Implementation of GCPCredentialsService interface
+ *
+ * @see GCPCredentialsService
+ */
+@CapabilityDescription("Defines credentials for Google Cloud Platform 
processors. " +
+        "Uses Application Default credentials without configuration. " +
+        "Application Default credentials support environmental variable 
(GOOGLE_APPLICATION_CREDENTIALS) pointing to " +
+        "a credential file, the config generated by `gcloud auth 
application-default login`, AppEngine/Compute Engine" +
+        " service accounts, etc.")
+@Tags({ "gcp", "credentials","provider" })
+public class GCPCredentialsControllerService extends AbstractControllerService 
implements GCPCredentialsService {
+
+    private static final List<PropertyDescriptor> properties;
+
+    static {
+        final List<PropertyDescriptor> props = new ArrayList<>();
+        props.add(USE_APPLICATION_DEFAULT_CREDENTIALS);
+        props.add(USE_COMPUTE_ENGINE_CREDENTIALS);
+        props.add(SERVICE_ACCOUNT_JSON_FILE);
+        props.add(SERVICE_ACCOUNT_JSON);
+        properties = Collections.unmodifiableList(props);
+    }
+
+    private volatile GoogleCredentials googleCredentials;
+    protected final CredentialsFactory credentialsProviderFactory = new 
CredentialsFactory();
+
+    @Override
+    protected List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+        return properties;
+    }
+
+    public GoogleCredentials getGoogleCredentials() throws ProcessException {
+        return googleCredentials;
+    }
+
+    @Override
+    protected Collection<ValidationResult> customValidate(final 
ValidationContext validationContext) {
+        return credentialsProviderFactory.validate(validationContext);
+    }
+
+    @OnEnabled
+    public void onConfigured(final ConfigurationContext context) throws 
InitializationException {
+        try {
+            googleCredentials = 
credentialsProviderFactory.getGoogleCredentials(context.getProperties());
+        } catch (IOException e) {
+            throw new InitializationException(e);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "GCPCredentialsControllerService[id=" + getIdentifier() + "]";
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/service/GCPCredentialsService.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/service/GCPCredentialsService.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/service/GCPCredentialsService.java
new file mode 100644
index 0000000..9b22b23
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/credentials/service/GCPCredentialsService.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp.credentials.service;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import org.apache.nifi.annotation.documentation.CapabilityDescription;
+import org.apache.nifi.annotation.documentation.Tags;
+import org.apache.nifi.controller.ControllerService;
+import org.apache.nifi.processor.exception.ProcessException;
+
+/**
+ * GCPCredentialsService interface to support getting Google Cloud Platform
+ * GoogleCredentials used for instantiating Google cloud services.
+ *
+ * @see <a 
href="http://google.github.io/google-auth-library-java/releases/0.5.0/apidocs/com/google/auth/oauth2/GoogleCredentials.html";>GoogleCredentials</a>
+ */
+@Tags({"gcp", "security", "credentials", "auth", "session"})
+@CapabilityDescription("Provides GCP GoogleCredentials.")
+public interface GCPCredentialsService extends ControllerService {
+
+    /**
+     * Get Google Credentials
+     * @return Valid Google Credentials suitable for authorizing requests on 
the platform.
+     * @throws ProcessException process exception in case there is problem in 
getting credentials
+     */
+    public GoogleCredentials getGoogleCredentials() throws ProcessException;
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/897c7029/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/storage/AbstractGCSProcessor.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/storage/AbstractGCSProcessor.java
 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/storage/AbstractGCSProcessor.java
new file mode 100644
index 0000000..ff368b5
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-gcp-bundle/nifi-gcp-processors/src/main/java/org/apache/nifi/processors/gcp/storage/AbstractGCSProcessor.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.nifi.processors.gcp.storage;
+
+import com.google.auth.oauth2.GoogleCredentials;
+import com.google.cloud.RetryParams;
+import com.google.cloud.storage.Storage;
+import com.google.cloud.storage.StorageOptions;
+import com.google.cloud.storage.spi.StorageRpc;
+import com.google.common.collect.ImmutableList;
+import org.apache.nifi.components.PropertyDescriptor;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.Relationship;
+import org.apache.nifi.processors.gcp.AbstractGCPProcessor;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Base class for creating processors which connect to Google Cloud Storage.
+ *
+ * Every GCS processor operation requires a bucket, whether it's reading or 
writing from said bucket.
+ */
+public abstract class AbstractGCSProcessor extends 
AbstractGCPProcessor<Storage, StorageRpc, StorageOptions> {
+    public static final Relationship REL_SUCCESS =
+            new Relationship.Builder().name("success")
+                    .description("FlowFiles are routed to this relationship 
after a successful Google Cloud Storage operation.")
+                    .build();
+    public static final Relationship REL_FAILURE =
+            new Relationship.Builder().name("failure")
+                    .description("FlowFiles are routed to this relationship if 
the Google Cloud Storage operation fails.")
+                    .build();
+
+    public static final Set<Relationship> relationships = 
Collections.unmodifiableSet(
+            new HashSet<>(Arrays.asList(REL_SUCCESS, REL_FAILURE)));
+
+    @Override
+    public Set<Relationship> getRelationships() {
+        return relationships;
+    }
+
+    @Override
+    public List<PropertyDescriptor> getSupportedPropertyDescriptors() {
+        return ImmutableList.<PropertyDescriptor>builder()
+                .addAll(super.getSupportedPropertyDescriptors())
+                .build();
+    }
+
+    @Override
+    protected StorageOptions getServiceOptions(ProcessContext context, 
GoogleCredentials credentials) {
+        final String projectId = context.getProperty(PROJECT_ID).getValue();
+        final Integer retryCount = 
Integer.valueOf(context.getProperty(RETRY_COUNT).getValue());
+
+        return StorageOptions.newBuilder()
+                .setCredentials(credentials)
+                .setProjectId(projectId)
+                .setRetryParams(RetryParams.newBuilder()
+                        .setRetryMaxAttempts(retryCount)
+                        .setRetryMinAttempts(retryCount)
+                        .build())
+                .build();
+    }
+}

Reply via email to