From a9b739cb731377f0cbed9e7902532b98e92cf219 Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent <31518063+kurtisvg@users.noreply.github.com> Date: Mon, 15 Oct 2018 09:51:10 -0700 Subject: [PATCH 01/14] Update DLP snippet with proposal for new sample format. --- dlp/pom.xml | 4 +- .../main/java/com/example/dlp/Inspect.java | 182 +----------------- .../main/java/dlp.snippets/InspectFile.java | 91 +++++++++ .../main/java/dlp.snippets/InspectString.java | 86 +++++++++ .../test/java/dlp/snippets/InspectTests.java | 82 ++++++++ 5 files changed, 261 insertions(+), 184 deletions(-) create mode 100644 dlp/src/main/java/dlp.snippets/InspectFile.java create mode 100644 dlp/src/main/java/dlp.snippets/InspectString.java create mode 100644 dlp/src/test/java/dlp/snippets/InspectTests.java diff --git a/dlp/pom.xml b/dlp/pom.xml index 4c533803dfb..654bfc88610 100644 --- a/dlp/pom.xml +++ b/dlp/pom.xml @@ -29,14 +29,12 @@ com.google.cloud.samples shared-configuration - 1.0.9 - + 1.0.10 1.8 1.8 - 0.7.1 UTF-8 diff --git a/dlp/src/main/java/com/example/dlp/Inspect.java b/dlp/src/main/java/com/example/dlp/Inspect.java index 8defeb657c7..7c1ab137178 100644 --- a/dlp/src/main/java/com/example/dlp/Inspect.java +++ b/dlp/src/main/java/com/example/dlp/Inspect.java @@ -72,165 +72,6 @@ public class Inspect { - /** - * [START dlp_inspect_string] Inspect a text for given InfoTypes - * - * @param string String to instpect - * @param minLikelihood The minimum likelihood required before returning a match - * @param maxFindings The maximum number of findings to report (0 = server maximum) - * @param infoTypes The infoTypes of information to match - * @param includeQuote Whether to include the matching string - * @param projectId Google Cloud project ID - */ - private static void inspectString( - String string, - Likelihood minLikelihood, - int maxFindings, - List infoTypes, - List customInfoTypes, - boolean includeQuote, - String projectId) { - // instantiate a client - try (DlpServiceClient dlpServiceClient = DlpServiceClient.create()) { - FindingLimits findingLimits = - FindingLimits.newBuilder().setMaxFindingsPerRequest(maxFindings).build(); - InspectConfig inspectConfig = - InspectConfig.newBuilder() - .addAllInfoTypes(infoTypes) - .addAllCustomInfoTypes(customInfoTypes) - .setMinLikelihood(minLikelihood) - .setLimits(findingLimits) - .setIncludeQuote(includeQuote) - .build(); - - ByteContentItem byteContentItem = - ByteContentItem.newBuilder() - .setType(ByteContentItem.BytesType.TEXT_UTF8) - .setData(ByteString.copyFromUtf8(string)) - .build(); - - ContentItem contentItem = ContentItem.newBuilder().setByteItem(byteContentItem).build(); - - InspectContentRequest request = - InspectContentRequest.newBuilder() - .setParent(ProjectName.of(projectId).toString()) - .setInspectConfig(inspectConfig) - .setItem(contentItem) - .build(); - InspectContentResponse response = dlpServiceClient.inspectContent(request); - - if (response.getResult().getFindingsCount() > 0) { - System.out.println("Findings: "); - for (Finding finding : response.getResult().getFindingsList()) { - if (includeQuote) { - System.out.print("\tQuote: " + finding.getQuote()); - } - System.out.print("\tInfo type: " + finding.getInfoType().getName()); - System.out.println("\tLikelihood: " + finding.getLikelihood()); - } - } else { - System.out.println("No findings."); - } - } catch (Exception e) { - System.out.println("Error in inspectString: " + e.getMessage()); - } - } - // [END dlp_inspect_string] - - // [START dlp_inspect_file] - /** - * Inspect a local file - * - * @param filePath The path to a local file to inspect. Can be a text, JPG, or PNG file. - * @param minLikelihood The minimum likelihood required before returning a match - * @param maxFindings The maximum number of findings to report (0 = server maximum) - * @param infoTypes The infoTypes of information to match - * @param includeQuote Whether to include the matching string - * @param projectId Google Cloud project ID - */ - private static void inspectFile( - String filePath, - Likelihood minLikelihood, - int maxFindings, - List infoTypes, - List customInfoTypes, - boolean includeQuote, - String projectId) { - // Instantiates a client - try (DlpServiceClient dlpServiceClient = DlpServiceClient.create()) { - // detect file mime type, default to application/octet-stream - String mimeType = URLConnection.guessContentTypeFromName(filePath); - if (mimeType == null) { - mimeType = MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(filePath); - } - - ByteContentItem.BytesType bytesType; - switch (mimeType) { - case "image/jpeg": - bytesType = ByteContentItem.BytesType.IMAGE_JPEG; - break; - case "image/bmp": - bytesType = ByteContentItem.BytesType.IMAGE_BMP; - break; - case "image/png": - bytesType = ByteContentItem.BytesType.IMAGE_PNG; - break; - case "image/svg": - bytesType = ByteContentItem.BytesType.IMAGE_SVG; - break; - default: - bytesType = ByteContentItem.BytesType.BYTES_TYPE_UNSPECIFIED; - break; - } - - byte[] data = Files.readAllBytes(Paths.get(filePath)); - ByteContentItem byteContentItem = - ByteContentItem.newBuilder() - .setType(bytesType) - .setData(ByteString.copyFrom(data)) - .build(); - ContentItem contentItem = ContentItem.newBuilder().setByteItem(byteContentItem).build(); - - FindingLimits findingLimits = - FindingLimits.newBuilder().setMaxFindingsPerRequest(maxFindings).build(); - - InspectConfig inspectConfig = - InspectConfig.newBuilder() - .addAllInfoTypes(infoTypes) - .addAllCustomInfoTypes(customInfoTypes) - .setMinLikelihood(minLikelihood) - .setLimits(findingLimits) - .setIncludeQuote(includeQuote) - .build(); - - InspectContentRequest request = - InspectContentRequest.newBuilder() - .setParent(ProjectName.of(projectId).toString()) - .setInspectConfig(inspectConfig) - .setItem(contentItem) - .build(); - - InspectContentResponse response = dlpServiceClient.inspectContent(request); - - InspectResult result = response.getResult(); - if (result.getFindingsCount() > 0) { - System.out.println("Findings: "); - for (Finding finding : result.getFindingsList()) { - if (includeQuote) { - System.out.print("\tQuote: " + finding.getQuote()); - } - System.out.print("\tInfo type: " + finding.getInfoType().getName()); - System.out.println("\tLikelihood: " + finding.getLikelihood()); - } - } else { - System.out.println("No findings."); - } - } catch (Exception e) { - System.out.println("Error in inspectFile: " + e.getMessage()); - } - } - // [END dlp_inspect_file] - // [START dlp_inspect_gcs] /** * Inspect GCS file for Info types and wait on job completion using Google Cloud Pub/Sub @@ -756,28 +597,7 @@ public static void main(String[] args) throws Exception { } // string inspection - if (cmd.hasOption("s")) { - String val = cmd.getOptionValue(stringOption.getOpt()); - inspectString( - val, - minLikelihood, - maxFindings, - infoTypesList, - customInfoTypesList, - includeQuote, - projectId); - } else if (cmd.hasOption("f")) { - String filePath = cmd.getOptionValue(fileOption.getOpt()); - inspectFile( - filePath, - minLikelihood, - maxFindings, - infoTypesList, - customInfoTypesList, - includeQuote, - projectId); - // gcs file inspection - } else if (cmd.hasOption("gcs")) { + if (cmd.hasOption("gcs")) { String bucketName = cmd.getOptionValue(bucketNameOption.getOpt()); String fileName = cmd.getOptionValue(gcsFileNameOption.getOpt()); inspectGcsFile( diff --git a/dlp/src/main/java/dlp.snippets/InspectFile.java b/dlp/src/main/java/dlp.snippets/InspectFile.java new file mode 100644 index 00000000000..88735b54273 --- /dev/null +++ b/dlp/src/main/java/dlp.snippets/InspectFile.java @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google LLC + * + * 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. + */ + +package dlp.snippets; + +// [START dlp_inspect_file] +import com.google.cloud.dlp.v2.DlpServiceClient; +import com.google.privacy.dlp.v2.ByteContentItem; +import com.google.privacy.dlp.v2.ByteContentItem.BytesType; +import com.google.privacy.dlp.v2.ContentItem; +import com.google.privacy.dlp.v2.Finding; +import com.google.privacy.dlp.v2.InfoType; +import com.google.privacy.dlp.v2.InspectConfig; +import com.google.privacy.dlp.v2.InspectContentRequest; +import com.google.privacy.dlp.v2.InspectContentResponse; +import com.google.privacy.dlp.v2.ProjectName; +import com.google.protobuf.ByteString; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.List; + +public class InspectFile { + + // Inspects the specified file. + public static void inspectFile(String projectId, String filePath, String fileType) { + // String projectId = "my-project-id"; + // String filePath = "path/to/image.png"; + // String fileType = "IMAGE" + + // Initialize client with try-with-resources for automatic cleanup of background resources + try (DlpServiceClient dlp = DlpServiceClient.create()) { + // Set project for request + ProjectName project = ProjectName.of(projectId); + + // Set content for request + ByteString fileBytes = ByteString.readFrom(new FileInputStream(filePath)); + ByteContentItem byteItem = ByteContentItem.newBuilder() + .setType(BytesType.valueOf(fileType)) + .setData(fileBytes) + .build(); + ContentItem item = ContentItem.newBuilder() + .setByteItem(byteItem) + .build(); + + // Set required InfoTypes for inspection config + List infoTypes = new ArrayList<>(); + // See https://cloud.google.com/dlp/docs/infotypes-reference for complete list of info types + for (String typeName : new String[] {"PHONE_NUMBER", "EMAIL_ADDRESS", "CREDIT_CARD_NUMBER"}) { + infoTypes.add(InfoType.newBuilder().setName(typeName).build()); + } + + // Set the inspect configuration for request + InspectConfig config = InspectConfig.newBuilder() + .addAllInfoTypes(infoTypes) + .setIncludeQuote(true) + .build(); + + // Construct request + InspectContentRequest request = InspectContentRequest.newBuilder() + .setParent(project.toString()) + .setItem(item) + .setInspectConfig(config) + .build(); + + // Run request and parse response + InspectContentResponse response = dlp.inspectContent(request); + System.out.println("Findings: " + response.getResult().getFindingsCount()); + for (Finding f : response.getResult().getFindingsList()) { + System.out.println("\tQuote: " + f.getQuote()); + System.out.println("\tInfo type: " + f.getInfoType()); + System.out.println("\tLikelihood: " + f.getLikelihood()); + } + } catch (Exception e) { + System.out.println("Error during inspectFile: \n" + e.toString()); + } + } +} +// [START dlp_inspect_file] diff --git a/dlp/src/main/java/dlp.snippets/InspectString.java b/dlp/src/main/java/dlp.snippets/InspectString.java new file mode 100644 index 00000000000..f2fb1a70ece --- /dev/null +++ b/dlp/src/main/java/dlp.snippets/InspectString.java @@ -0,0 +1,86 @@ +/* + * Copyright 2018 Google LLC + * + * 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. + */ + +package dlp.snippets; + +// [START dlp_inspect_string] +import com.google.cloud.dlp.v2.DlpServiceClient; +import com.google.privacy.dlp.v2.ByteContentItem; +import com.google.privacy.dlp.v2.ByteContentItem.BytesType; +import com.google.privacy.dlp.v2.ContentItem; +import com.google.privacy.dlp.v2.Finding; +import com.google.privacy.dlp.v2.InfoType; +import com.google.privacy.dlp.v2.InspectConfig; +import com.google.privacy.dlp.v2.InspectContentRequest; +import com.google.privacy.dlp.v2.InspectContentResponse; +import com.google.privacy.dlp.v2.ProjectName; +import com.google.protobuf.ByteString; +import java.util.ArrayList; +import java.util.List; + +public class InspectString { + + // Inspects the provided text. + public static void inspectString(String projectId, String textToInspect) { + // String projectId = "my-project-id"; + // String textToInspect = "My name is Gary and my email is gary@example.com"; + + // Initialize client with try-with-resources for automatic cleanup of background resources + try (DlpServiceClient dlp = DlpServiceClient.create()) { + // Set project for request + ProjectName project = ProjectName.of(projectId); + + // Set content for request + ByteContentItem byteItem = ByteContentItem.newBuilder() + .setType(BytesType.TEXT_UTF8) + .setData(ByteString.copyFromUtf8(textToInspect)) + .build(); + ContentItem item = ContentItem.newBuilder().setByteItem(byteItem).build(); + + // Set required InfoTypes for inspection config + List infoTypes = new ArrayList<>(); + // See https://cloud.google.com/dlp/docs/infotypes-reference for complete list of info types + for (String typeName : new String[] {"PHONE_NUMBER", "EMAIL_ADDRESS", "CREDIT_CARD_NUMBER"}) { + infoTypes.add(InfoType.newBuilder().setName(typeName).build()); + } + + // Set the inspect configuration for request + InspectConfig config = InspectConfig.newBuilder() + .addAllInfoTypes(infoTypes) + .setIncludeQuote(true) + .build(); + + // Construct request + InspectContentRequest request = InspectContentRequest.newBuilder() + .setParent(project.toString()) + .setItem(item) + .setInspectConfig(config) + .build(); + + // Run request and parse response + InspectContentResponse response = dlp.inspectContent(request); + System.out.println("Findings: " + response.getResult().getFindingsCount()); + for (Finding f : response.getResult().getFindingsList()) { + System.out.println("\tQuote: " + f.getQuote()); + System.out.println("\tInfo type: " + f.getInfoType()); + System.out.println("\tLikelihood: " + f.getLikelihood()); + } + } catch (Exception e) { + System.out.println("Error during inspectString: \n" + e.toString()); + } + } +} +// [END dlp_inspect_string] diff --git a/dlp/src/test/java/dlp/snippets/InspectTests.java b/dlp/src/test/java/dlp/snippets/InspectTests.java new file mode 100644 index 00000000000..94aed84958d --- /dev/null +++ b/dlp/src/test/java/dlp/snippets/InspectTests.java @@ -0,0 +1,82 @@ +/* + * Copyright 2018 Google LLC + * + * 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. + */ + +package dlp.snippets; + +import static junit.framework.TestCase.assertNotNull; +import static org.junit.Assert.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import org.hamcrest.CoreMatchers; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class InspectTests { + + private ByteArrayOutputStream bout; + + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + + private static void requireEnvVar(String varName) { + assertNotNull( + System.getenv(varName), + "Environment variable '%s' is required to perform these tests.".format(varName) + ); + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS"); + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + } + + @Before + public void beforeTest() { + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + } + + @After + public void tearDown() { + System.setOut(null); + bout.reset(); + } + + @Test + public void testInspectString() { + InspectString.inspectString(PROJECT_ID, "I'm Gary and my email is gary@example.com"); + + String output = bout.toString(); + assertThat(output, CoreMatchers.containsString("Info type: PHONE_NUMBER")); + assertThat(output, CoreMatchers.containsString("Info type: EMAIL_ADDRESS")); + } + + @Test + public void testInspectFile() { + InspectFile.inspectFile(PROJECT_ID, "src/test/resources/test.png", "IMAGE"); + + String output = bout.toString(); + assertThat(output, CoreMatchers.containsString("Info type: PHONE_NUMBER")); + assertThat(output, CoreMatchers.containsString("Info type: EMAIL_ADDRESS")); + } + +} From e0b886daf95bf19fd5b726b96898663475cdd98f Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent <31518063+kurtisvg@users.noreply.github.com> Date: Fri, 19 Oct 2018 16:43:38 -0700 Subject: [PATCH 02/14] Fix InspectFile region tag. --- dlp/src/main/java/dlp.snippets/InspectFile.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlp/src/main/java/dlp.snippets/InspectFile.java b/dlp/src/main/java/dlp.snippets/InspectFile.java index 88735b54273..d543e92d8fd 100644 --- a/dlp/src/main/java/dlp.snippets/InspectFile.java +++ b/dlp/src/main/java/dlp.snippets/InspectFile.java @@ -88,4 +88,4 @@ public static void inspectFile(String projectId, String filePath, String fileTyp } } } -// [START dlp_inspect_file] +// [END dlp_inspect_file] From 494f4f9896045c8393ab035b3ad993f88bd39431 Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent <31518063+kurtisvg@users.noreply.github.com> Date: Mon, 22 Oct 2018 13:37:17 -0700 Subject: [PATCH 03/14] Fixed package structure and InspectString test. --- .../main/java/{dlp.snippets => dlp/snippets}/InspectFile.java | 0 .../main/java/{dlp.snippets => dlp/snippets}/InspectString.java | 0 dlp/src/test/java/dlp/snippets/InspectTests.java | 1 - 3 files changed, 1 deletion(-) rename dlp/src/main/java/{dlp.snippets => dlp/snippets}/InspectFile.java (100%) rename dlp/src/main/java/{dlp.snippets => dlp/snippets}/InspectString.java (100%) diff --git a/dlp/src/main/java/dlp.snippets/InspectFile.java b/dlp/src/main/java/dlp/snippets/InspectFile.java similarity index 100% rename from dlp/src/main/java/dlp.snippets/InspectFile.java rename to dlp/src/main/java/dlp/snippets/InspectFile.java diff --git a/dlp/src/main/java/dlp.snippets/InspectString.java b/dlp/src/main/java/dlp/snippets/InspectString.java similarity index 100% rename from dlp/src/main/java/dlp.snippets/InspectString.java rename to dlp/src/main/java/dlp/snippets/InspectString.java diff --git a/dlp/src/test/java/dlp/snippets/InspectTests.java b/dlp/src/test/java/dlp/snippets/InspectTests.java index 94aed84958d..05df8c5f3b4 100644 --- a/dlp/src/test/java/dlp/snippets/InspectTests.java +++ b/dlp/src/test/java/dlp/snippets/InspectTests.java @@ -66,7 +66,6 @@ public void testInspectString() { InspectString.inspectString(PROJECT_ID, "I'm Gary and my email is gary@example.com"); String output = bout.toString(); - assertThat(output, CoreMatchers.containsString("Info type: PHONE_NUMBER")); assertThat(output, CoreMatchers.containsString("Info type: EMAIL_ADDRESS")); } From 9bb5399c4ac4a3d0c91a726e12594886e3be3f50 Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent <31518063+kurtisvg@users.noreply.github.com> Date: Mon, 22 Oct 2018 13:53:50 -0700 Subject: [PATCH 04/14] Reword comments. --- dlp/src/main/java/dlp/snippets/InspectFile.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dlp/src/main/java/dlp/snippets/InspectFile.java b/dlp/src/main/java/dlp/snippets/InspectFile.java index d543e92d8fd..fef3dd4bfab 100644 --- a/dlp/src/main/java/dlp/snippets/InspectFile.java +++ b/dlp/src/main/java/dlp/snippets/InspectFile.java @@ -68,14 +68,14 @@ public static void inspectFile(String projectId, String filePath, String fileTyp .setIncludeQuote(true) .build(); - // Construct request + // Construct the request to be sent by the client InspectContentRequest request = InspectContentRequest.newBuilder() .setParent(project.toString()) .setItem(item) .setInspectConfig(config) .build(); - // Run request and parse response + // Use the client to send the request and parse results InspectContentResponse response = dlp.inspectContent(request); System.out.println("Findings: " + response.getResult().getFindingsCount()); for (Finding f : response.getResult().getFindingsList()) { From 721bf9f9a3b331f6669327e040ae8ac9bd706ea6 Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent <31518063+kurtisvg@users.noreply.github.com> Date: Mon, 22 Oct 2018 14:27:55 -0700 Subject: [PATCH 05/14] Fix unintentional toString. --- dlp/src/main/java/dlp/snippets/InspectFile.java | 2 +- dlp/src/main/java/dlp/snippets/InspectString.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dlp/src/main/java/dlp/snippets/InspectFile.java b/dlp/src/main/java/dlp/snippets/InspectFile.java index fef3dd4bfab..1bb3846ab3e 100644 --- a/dlp/src/main/java/dlp/snippets/InspectFile.java +++ b/dlp/src/main/java/dlp/snippets/InspectFile.java @@ -80,7 +80,7 @@ public static void inspectFile(String projectId, String filePath, String fileTyp System.out.println("Findings: " + response.getResult().getFindingsCount()); for (Finding f : response.getResult().getFindingsList()) { System.out.println("\tQuote: " + f.getQuote()); - System.out.println("\tInfo type: " + f.getInfoType()); + System.out.println("\tInfo type: " + f.getInfoType().getName()); System.out.println("\tLikelihood: " + f.getLikelihood()); } } catch (Exception e) { diff --git a/dlp/src/main/java/dlp/snippets/InspectString.java b/dlp/src/main/java/dlp/snippets/InspectString.java index f2fb1a70ece..68e1cf91a44 100644 --- a/dlp/src/main/java/dlp/snippets/InspectString.java +++ b/dlp/src/main/java/dlp/snippets/InspectString.java @@ -75,7 +75,7 @@ public static void inspectString(String projectId, String textToInspect) { System.out.println("Findings: " + response.getResult().getFindingsCount()); for (Finding f : response.getResult().getFindingsList()) { System.out.println("\tQuote: " + f.getQuote()); - System.out.println("\tInfo type: " + f.getInfoType()); + System.out.println("\tInfo type: " + f.getInfoType().getName()); System.out.println("\tLikelihood: " + f.getLikelihood()); } } catch (Exception e) { From 1a3dcd8582279b1d25b0e0c71098558ac85480d7 Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent Date: Wed, 24 Oct 2018 08:33:57 -0700 Subject: [PATCH 06/14] Seperate API call from response processing. --- dlp/src/main/java/dlp/snippets/InspectFile.java | 4 +++- dlp/src/main/java/dlp/snippets/InspectString.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/dlp/src/main/java/dlp/snippets/InspectFile.java b/dlp/src/main/java/dlp/snippets/InspectFile.java index 1bb3846ab3e..6b1d57fdcda 100644 --- a/dlp/src/main/java/dlp/snippets/InspectFile.java +++ b/dlp/src/main/java/dlp/snippets/InspectFile.java @@ -75,8 +75,10 @@ public static void inspectFile(String projectId, String filePath, String fileTyp .setInspectConfig(config) .build(); - // Use the client to send the request and parse results + // Use the client to send the API request InspectContentResponse response = dlp.inspectContent(request); + + // Parse the response and process results System.out.println("Findings: " + response.getResult().getFindingsCount()); for (Finding f : response.getResult().getFindingsList()) { System.out.println("\tQuote: " + f.getQuote()); diff --git a/dlp/src/main/java/dlp/snippets/InspectString.java b/dlp/src/main/java/dlp/snippets/InspectString.java index 68e1cf91a44..2e8452762b3 100644 --- a/dlp/src/main/java/dlp/snippets/InspectString.java +++ b/dlp/src/main/java/dlp/snippets/InspectString.java @@ -70,8 +70,10 @@ public static void inspectString(String projectId, String textToInspect) { .setInspectConfig(config) .build(); - // Run request and parse response + // Use the client to send the API request InspectContentResponse response = dlp.inspectContent(request); + + // Parse the response and process results System.out.println("Findings: " + response.getResult().getFindingsCount()); for (Finding f : response.getResult().getFindingsList()) { System.out.println("\tQuote: " + f.getQuote()); From 7f8c860683a8c609d12e789bf6a9895fde1d42dd Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent Date: Wed, 7 Nov 2018 10:11:43 -0800 Subject: [PATCH 07/14] Seperate ByteType into two different samples. --- .../java/dlp/snippets/InspectImageFile.java | 93 +++++++++++++++++++ ...{InspectFile.java => InspectTextFile.java} | 8 +- .../test/java/dlp/snippets/InspectTests.java | 14 ++- 3 files changed, 109 insertions(+), 6 deletions(-) create mode 100644 dlp/src/main/java/dlp/snippets/InspectImageFile.java rename dlp/src/main/java/dlp/snippets/{InspectFile.java => InspectTextFile.java} (94%) diff --git a/dlp/src/main/java/dlp/snippets/InspectImageFile.java b/dlp/src/main/java/dlp/snippets/InspectImageFile.java new file mode 100644 index 00000000000..0b7f8778019 --- /dev/null +++ b/dlp/src/main/java/dlp/snippets/InspectImageFile.java @@ -0,0 +1,93 @@ +/* + * Copyright 2018 Google LLC + * + * 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. + */ + +package dlp.snippets; + +// [START dlp_inspect_image_file] +import com.google.cloud.dlp.v2.DlpServiceClient; +import com.google.privacy.dlp.v2.ByteContentItem; +import com.google.privacy.dlp.v2.ByteContentItem.BytesType; +import com.google.privacy.dlp.v2.ContentItem; +import com.google.privacy.dlp.v2.Finding; +import com.google.privacy.dlp.v2.InfoType; +import com.google.privacy.dlp.v2.InspectConfig; +import com.google.privacy.dlp.v2.InspectContentRequest; +import com.google.privacy.dlp.v2.InspectContentResponse; +import com.google.privacy.dlp.v2.ProjectName; +import com.google.protobuf.ByteString; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.List; + +public class InspectImageFile { + + // Inspects the specified image file. + public static void inspectImageFile(String projectId, String filePath) { + // String projectId = "my-project-id"; + // String filePath = "path/to/image.png"; + // String fileType = "IMAGE" + + // Initialize client with try-with-resources for automatic cleanup of background resources + try (DlpServiceClient dlp = DlpServiceClient.create()) { + // Set project for request + ProjectName project = ProjectName.of(projectId); + + // Set content for request + ByteString fileBytes = ByteString.readFrom(new FileInputStream(filePath)); + ByteContentItem byteItem = ByteContentItem.newBuilder() + .setType(BytesType.IMAGE) + .setData(fileBytes) + .build(); + ContentItem item = ContentItem.newBuilder() + .setByteItem(byteItem) + .build(); + + // Set required InfoTypes for inspection config + List infoTypes = new ArrayList<>(); + // See https://cloud.google.com/dlp/docs/infotypes-reference for complete list of info types + for (String typeName : new String[] {"PHONE_NUMBER", "EMAIL_ADDRESS", "CREDIT_CARD_NUMBER"}) { + infoTypes.add(InfoType.newBuilder().setName(typeName).build()); + } + + // Set the inspect configuration for request + InspectConfig config = InspectConfig.newBuilder() + .addAllInfoTypes(infoTypes) + .setIncludeQuote(true) + .build(); + + // Construct the request to be sent by the client + InspectContentRequest request = InspectContentRequest.newBuilder() + .setParent(project.toString()) + .setItem(item) + .setInspectConfig(config) + .build(); + + // Use the client to send the API request + InspectContentResponse response = dlp.inspectContent(request); + + // Parse the response and process results + System.out.println("Findings: " + response.getResult().getFindingsCount()); + for (Finding f : response.getResult().getFindingsList()) { + System.out.println("\tQuote: " + f.getQuote()); + System.out.println("\tInfo type: " + f.getInfoType().getName()); + System.out.println("\tLikelihood: " + f.getLikelihood()); + } + } catch (Exception e) { + System.out.println("Error during inspectFile: \n" + e.toString()); + } + } +} +// [END dlp_inspect_image_file] diff --git a/dlp/src/main/java/dlp/snippets/InspectFile.java b/dlp/src/main/java/dlp/snippets/InspectTextFile.java similarity index 94% rename from dlp/src/main/java/dlp/snippets/InspectFile.java rename to dlp/src/main/java/dlp/snippets/InspectTextFile.java index 6b1d57fdcda..f15d756f2ff 100644 --- a/dlp/src/main/java/dlp/snippets/InspectFile.java +++ b/dlp/src/main/java/dlp/snippets/InspectTextFile.java @@ -32,10 +32,10 @@ import java.util.ArrayList; import java.util.List; -public class InspectFile { +public class InspectTextFile { - // Inspects the specified file. - public static void inspectFile(String projectId, String filePath, String fileType) { + // Inspects the specified text file. + public static void inspectTextFile(String projectId, String filePath) { // String projectId = "my-project-id"; // String filePath = "path/to/image.png"; // String fileType = "IMAGE" @@ -48,7 +48,7 @@ public static void inspectFile(String projectId, String filePath, String fileTyp // Set content for request ByteString fileBytes = ByteString.readFrom(new FileInputStream(filePath)); ByteContentItem byteItem = ByteContentItem.newBuilder() - .setType(BytesType.valueOf(fileType)) + .setType(BytesType.TEXT_UTF8) .setData(fileBytes) .build(); ContentItem item = ContentItem.newBuilder() diff --git a/dlp/src/test/java/dlp/snippets/InspectTests.java b/dlp/src/test/java/dlp/snippets/InspectTests.java index 05df8c5f3b4..e91eb66dc75 100644 --- a/dlp/src/test/java/dlp/snippets/InspectTests.java +++ b/dlp/src/test/java/dlp/snippets/InspectTests.java @@ -70,8 +70,18 @@ public void testInspectString() { } @Test - public void testInspectFile() { - InspectFile.inspectFile(PROJECT_ID, "src/test/resources/test.png", "IMAGE"); + public void textInspectTestFile() { + InspectTextFile.inspectTextFile(PROJECT_ID, "src/test/resources/test.txt"); + + String output = bout.toString(); + assertThat(output, CoreMatchers.containsString("Info type: PHONE_NUMBER")); + assertThat(output, CoreMatchers.containsString("Info type: EMAIL_ADDRESS")); + } + + + @Test + public void testInspectImageFile() { + InspectImageFile.inspectImageFile(PROJECT_ID, "src/test/resources/test.png"); String output = bout.toString(); assertThat(output, CoreMatchers.containsString("Info type: PHONE_NUMBER")); From 25626cf3f23731b260d4df1e0f652b1b4a2b5d22 Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent Date: Fri, 15 Feb 2019 10:11:37 -0800 Subject: [PATCH 08/14] Remove previous tests. --- .../test/java/com/example/dlp/InspectIT.java | 68 ------------------ dlp/src/test/resources/test.png | Bin 21438 -> 5109 bytes dlp/src/test/resources/test.txt | 2 +- 3 files changed, 1 insertion(+), 69 deletions(-) diff --git a/dlp/src/test/java/com/example/dlp/InspectIT.java b/dlp/src/test/java/com/example/dlp/InspectIT.java index 17814cfc395..ae66bacf5d6 100644 --- a/dlp/src/test/java/com/example/dlp/InspectIT.java +++ b/dlp/src/test/java/com/example/dlp/InspectIT.java @@ -53,74 +53,6 @@ public void setUp() { assertNotNull(System.getenv("GOOGLE_APPLICATION_CREDENTIALS")); } - @Test - public void testStringInspectionReturnsInfoTypes() throws Exception { - String text = - "\"My phone number is (234) 456-7890 and my email address is gary@somedomain.com\""; - Inspect.main(new String[] {"-s", text, "-infoTypes", "PHONE_NUMBER", "EMAIL_ADDRESS"}); - String output = bout.toString(); - - assertThat(output, containsString("PHONE_NUMBER")); - assertThat(output, containsString("EMAIL_ADDRESS")); - } - - @Test - public void testStringInspectionReturnsCustomInfoTypes() throws Exception { - String text = - "\"My phone number is (234) 456-7890 and my email address is gary@somedomain.com\""; - Inspect.main( - new String[] { - "-s", - text, - "-customDictionaries", - "gary@somedomain.com", - "-customRegexes", - "\\(\\d{3}\\) \\d{3}-\\d{4}" - }); - String output = bout.toString(); - - assertThat(output, containsString("CUSTOM_DICTIONARY_0")); - assertThat(output, containsString("CUSTOM_REGEX_0")); - } - - @Test - public void testTextFileInspectionReturnsInfoTypes() throws Exception { - Inspect.main( - new String[] { - "-f", "src/test/resources/test.txt", "-infoTypes", "PHONE_NUMBER", "EMAIL_ADDRESS" - }); - String output = bout.toString(); - assertThat(output, containsString("PHONE_NUMBER")); - assertThat(output, containsString("EMAIL_ADDRESS")); - } - - @Test - public void testTextFileInspectionReturnsCustomInfoTypes() throws Exception { - Inspect.main( - new String[] { - "-f", - "src/test/resources/test.txt", - "-customDictionaries", - "gary@somedomain.com", - "-customRegexes", - "\\(\\d{3}\\) \\d{3}-\\d{4}" - }); - String output = bout.toString(); - assertThat(output, containsString("CUSTOM_DICTIONARY_0")); - assertThat(output, containsString("CUSTOM_REGEX_0")); - } - - @Test - public void testImageFileInspectionReturnsInfoTypes() throws Exception { - Inspect.main( - new String[] { - "-f", "src/test/resources/test.png", "-infoTypes", "PHONE_NUMBER", "EMAIL_ADDRESS" - }); - String output = bout.toString(); - assertThat(output, containsString("PHONE_NUMBER")); - assertThat(output, containsString("EMAIL_ADDRESS")); - } - // Requires that bucket by the specified name exists @Test public void testGcsFileInspectionReturnsInfoTypes() throws Exception { diff --git a/dlp/src/test/resources/test.png b/dlp/src/test/resources/test.png index 8f32c825884261083b7d731676375303d49ca6f6..748f46cdcb504479bc1018fa16ab90dfb95aee5e 100644 GIT binary patch literal 5109 zcmVTfl&E-1Qo{DFY7R7DU7 zO(c{MNKZ&eZ=_E$X_LwHH}C%bNWehe8zux-bm#k5J~#KCd(J)IbMCqKy*DTJMGoP zX`a8rY9QAM>))Rp$a!!9w&Rz)w8EGFu=KHwT=mxMAR&54^8PsB42yf`)iDl_a5;51 zmymc=+-qCbz4Q6s{`$CdknUu({kK|>L5IvA1`pH4zXE>okn{AvKl6k*XU7|-%Z*4f ze(9!FK9zeu+I?O38*2AQfU@$^ab64kpu@RCCr+2#*j}v%007c0a^9ktFh55LQa9vY zJ9a3mUW*wU3HRs~E64b{+lz2_Q$hOigK5<&3;*ndb=Wn!_0Eq+U%$+~Q$C0CJ&QCqMFSAyQ z0gz4j)H(NVZNO5GJeP~+b&CTixu|+)->HneemJ@ z(5T_vg zvUTB8mrbC~ZrPUIu zVM~-V5MGPduHc>iV1Km{05~4=-i{;oZvU~2VeLr&>HqT=rO?l;6hthn~!{1rP zS6tlL)041^n6zL~l&>SHtuH*Y=Uh%Rv)dSl6JAqZ`3rgE?en)xKnBlxeUWPSKQdgO zTQ^y(5V+YiUMnV}qCC3Nc5k~}4*-OH)T%YBMmP|P(zClyr8gMaW+#28ZCK5}mMV-M z?Lw z9uIQ4Sl?*2J|OHyEevi*$}v12-KQ1PM#|X73EYsVD1F9P$IF{BfKsDkmxpN+)nf?9 zb66C&=s=YofMaVTZmYUkqr)^*+^93IaI`}N4)j39=W?2jCXlBkS4>$N4gQ%ETn4tjJ5+cd@9QW+oUCc+Z%>WQMnm zUY=RND63au)bssmlLB$iSr{EmTq2odUalb+lxN|R#b8dh_ez(Gxi54xG+YVF2i? z_$fL1=?EE7)naq6?I!7n`7g{aqY@h%D zxsP3zFr<9Pr*FRee<$056PAZddwaU_3Qla_{N;{xX>U*0F;A`zXgjj&ofkjem2MNe zdbBh9&0qiFEXzsga*uz!ztMZN@Y?3DFF|;uCjkIR=H*y@Y|HwOcjem8S~=PonVTKi zheYtwcmDm;cVGMFe3gMY2jkY1Pd_lwbAE6k!||DzFr7^O;KR2Pf7W|@^4V=?vPf6k-CBy*-hcCdzByg0LzpG~vZ!Ph_jEAU-mLeU6Dujp>rGg6T~UG7 ze^>w)fb<*@fb)v#*sC6_uF5aeV4yp5iyJ-s{cR8cU`<8F^)@5cRNkzo9UW{CvJVY# zs>-=qt;3Y6IJuxRD9DEg0Dx6h1*KXHCPlTJa&)jk$YoT7b6M)Sf=(kg$ggHq$^rr% zSa*+p!`b>#9jz*DduMlhd#gs--XV}m2><|1#r4!yBi1)u&aHFv540!D&2Fqt{i#k( z0~os$Z3DUj#We8k+#IBQ&?#zfwV16TF<&UadPDz;7>UED&JC(Nb*9#6rqNJw{2x0$ z{@{nRm-6$fyZgkPL1#dGA=k_!I3)C)K1-0ERHp75#_C%ab{yXQ@wYqo=ISEnu8#BM z0OARGqKIJ0)dQPf`ut#t)7;hLT+Oo%34+H3YO`+EQUCy0*HWBMjeL2-mM>m?A({!R2xZ9*;vCD86^ds2Cp^ri{ShvAjiqwKbWSsuXGp zQ>v1*O1-m_Jpy202r(qwS5TOhDK}zGL+VvC)MloQ#nHjSWG0zx$`1xiG8t_*yC8RQ zo??j(MtTo~^GxbnHk@#Y^cUXDN^dk`ZR7RSIuonyj20RDd$V5RBvUpwQPPpiC)->< zxb5xlv(+LVX7i@D^oLUw!E>KqH(7G|WO5C~Iy*}WV$7fYFo3LxYyzW#TT+hRY|&z% zRMpv4?U*I~vSmecxVQSGs?$rFh1~^m+PkNLZqCorJUz;bTV{xeqziU7nmOBJov!B* zCf4b6SSS+rI8UeR$y-K>A`l6PClOHHYJE?mO06LTVgUjGtT*)5@Fo*YAQA|vjhGue zb^YeY0RVvDVO0xzaoBG-8)%aWz(ms~6AgedA_xEgtWozQO03nWDS=2tnwcGUE0quS z)J$J?dY5d*^!e+T*wFQbXZD`W>0fEz0n%%Ah|ebh?g|*5SInPQIOpy-c%u`WYs8eU zOQq{7zAW_FxO$ZQ{p*U}|L_Dntk)UYD?pA%>=gIhlRvg%=#!wawy8J|003IDj-K#- zV_u;9(R!oagc|d&ubxFEv*>qqVJyG=bvXbMdEZ`Pc~()^hR~p3eTcF6-*x7W&4frI zB>_x;#9}ehX*2+~{d-}JTF3Da^AS)OKq?l|I<<~5k71Qkt;+am+ksmH;aXn-H0JPn z76I{i=I>LGSS%(0On`(UF-KRcrp?Wc0YBjT1axQN)x(8X5!Wta#fpWq{0erLv2H_j zcXOj|tcwEyO?TFv<1%vjGvQ7D-uH9w8(6H3zbK1o(#^%01Vzst#Bp$T>}YCaF94Ci z-OI@{^qH-5dmF;ve%>}voE_&~x$~dj)vIYTDE9RySr4I_ZXI9DM*skbClU-iOsHCVCHq^GqgMHXLhII-#A21fT&4C1R4* zc1DYU!JGCvy-*;a+ZyGL0YRc01tyQsp(0$wmKjL5F$>0N(z8TUmxh<@C{WS^^Cm<7 z?6LnY7Y`sSVpX?_<6$R3@Jp4+oPHnZy=V(w;>L=i{MLY3i-Yw!MNQ_fTt$9k#>=<_ z-(%9Sp$!!k%(s)cqp(8Z7d630fJkY`lnDFsid)PjB;A}{s2cXz;{g&95Gi&H80G6Y zkRv?q=;#o-csL?JqQEFGf%&mQ|FPp`9D?sYakxigd3mR4kh3!a30y*kyV`IOrcEXq zj0U6G6*bis)`$W;?QXk?kcBT5Qw=E$)aLnB3vA#e36syK!jKQvOtK?L7r zWT1<-y;Y5Ykh=THq(Z)}S7hA6faa?=n=$B%3(IXI9~*AN;X93;5}?m3u3?EDo`6TS zD_S))AW29}fDNlQwESkJAvnZOhyd9}jP!Vb8sD<$7yy$kR=!tqd$UsJH&kMlnM^Vn zZMS?um@Q(Y_W(J6FDxET%kwLA;UlAmaFD=d%($T>tL?0~$D3FwZ>I!swO-VP1ao6Pz19v7S85^|Wdx?D53)u?u)i&K$+vXR)Dc%7o zN>A<1RAA=42{)u2{?2aEv+E{_X=UY&@4n6NV(CdYUf;K$7q@)PJ5D@WqpZ(OIhtjG z!gnT8m0UO%zHGyD!xXL6b#mr9^-ky3nl_*KO$!_dMd|6?87&xKaI=#^)7JkvRLBuX zZP2pKeiT)AX3LMcCXx5lnTwy2@_|xT=Kk>QeaZ)YVNPEB)JW%yOL7c=?1o1Vb8#fs zyx3E;((-Gc|NTNYQ=^Koja;~NmXm~s)h(qt2lr;(&et68(E+M!hZ_d|=#{YZow8{5 z5IY{yDr>XPfAd4N9soM?kL{H$UixgJJ*lfNKDpVY3? zS&mM)IVCyk>FMj=8n4o5nrfOl+5JvcTsf37Z{emjlvdN+)@n5O#GD0|MTf;qW>%h& zOF7*bfNr{+ocH|PO<&BT3eRl)GLMPm%rY5mw|qgEEkX?RMof*27-Yy$)mILkk6Zfs zhMAg%jQkqC7pv{;R^9DQsv);v#+=8U3Qw1x`>MQ8zove+bG_!w8>77R#q~~1cV66^ z{oMMw|+Fa%=~-W*f%-e)&719Zwg-b6z0Ij_VzW}Z87 zxw_pzibP1OHuJFX!SOrHpO&0FI1bU1d=%*y?{n_3;#UDyrhfPF!~13mEAzii%ztR& ztguGMqXR9?{^68y zzkl3s^B@DC*!W@;S&_0YrNbH>R#?#&*64V&fO&3{;{W`tn4t8nHX00000NkvXXu0mjfvR)b@ literal 21438 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%0Dk_JRQOqzBh$Z^~#JvUs5?gsH6m;e=MJg zj)gWg^b(F}&Dgt!iGqlNs_qe+fDTUiQbRYOjT~%x%1TzZ-%04Qnf*=nKZ~VOG)V}u zHe!DuOLA?g{{|^>v$zF?1E(U}HGYYx@j5Agw7{sF!wQ z4wr6mIbisG7j|62703?(w~YEouD)^d+)W*nB{BWqiTY339I042YUD;=`l;ntsN2#Gj7lw8Z; z4`C`)M8l-xP*|opM*2?oDVdEM$IepnzpK{-2_hhxWgwSSv3FFMhGgC>NojG5AdHoJnLW_}GCo{oOi~*>$ z2qNgZ;jm7)RjNWDtf%XYhnNY#LWvTNjqMfl@&U5FgMg6&w}k({KmNCGb{vqo6h5RH zc13&2;tlbF!-)~xu$VC0f3F+8y`E3zqU|O5qu3i2CwW`%JsDo%DtxEV{{{5xpAT9z M)pS)Wl`TL24{iKN9{>OV diff --git a/dlp/src/test/resources/test.txt b/dlp/src/test/resources/test.txt index c2ee3815bc9..f30af240c72 100644 --- a/dlp/src/test/resources/test.txt +++ b/dlp/src/test/resources/test.txt @@ -1 +1 @@ -My phone number is (223) 456-7890 and my email address is gary@somedomain.com. \ No newline at end of file +My phone number is (223) 456-7890 and my email address is gary@example.com. \ No newline at end of file From a045ec4d4733d3045400ecbfb8b04264c0dae001 Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent Date: Fri, 15 Feb 2019 13:01:49 -0800 Subject: [PATCH 09/14] Updated Redact sample to new format. --- .../java/dlp/snippets/RedactImageFile.java | 86 ++++++++++++++++++ .../test/java/dlp/snippets/RedactTests.java | 91 +++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 dlp/src/main/java/dlp/snippets/RedactImageFile.java create mode 100644 dlp/src/test/java/dlp/snippets/RedactTests.java diff --git a/dlp/src/main/java/dlp/snippets/RedactImageFile.java b/dlp/src/main/java/dlp/snippets/RedactImageFile.java new file mode 100644 index 00000000000..f0d18f929a3 --- /dev/null +++ b/dlp/src/main/java/dlp/snippets/RedactImageFile.java @@ -0,0 +1,86 @@ +/* + * Copyright 2019 Google LLC + * + * 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. + */ + +package dlp.snippets; + +import com.google.cloud.dlp.v2.DlpServiceClient; +import com.google.privacy.dlp.v2.ByteContentItem; +import com.google.privacy.dlp.v2.ByteContentItem.BytesType; +import com.google.privacy.dlp.v2.InfoType; +import com.google.privacy.dlp.v2.InspectConfig; +import com.google.privacy.dlp.v2.Likelihood; +import com.google.privacy.dlp.v2.ProjectName; +import com.google.privacy.dlp.v2.RedactImageRequest; +import com.google.privacy.dlp.v2.RedactImageResponse; +import com.google.protobuf.ByteString; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.List; + +class RedactImageFile { + + static void redactImageFile(String projectId, String filePath) { + // String projectId = "my-project-id"; + // String filePath = "path/to/image.png"; + + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the "close" method on the client to safely clean up any remaining background resources. + try (DlpServiceClient dlp = DlpServiceClient.create()) { + // Specify the project used for request. + ProjectName project = ProjectName.of(projectId); + + // Specify the content to be inspected. + ByteString fileBytes = ByteString.readFrom(new FileInputStream(filePath)); + ByteContentItem byteItem = + ByteContentItem.newBuilder().setType(BytesType.IMAGE).setData(fileBytes).build(); + + // Specify the type of info and likelihood necessary to redact. + List infoTypes = new ArrayList<>(); + // See https://cloud.google.com/dlp/docs/infotypes-reference for complete list of info types + for (String typeName : new String[] {"PHONE_NUMBER", "EMAIL_ADDRESS", "CREDIT_CARD_NUMBER"}) { + infoTypes.add(InfoType.newBuilder().setName(typeName).build()); + } + InspectConfig config = + InspectConfig.newBuilder() + .addAllInfoTypes(infoTypes) + .setMinLikelihood(Likelihood.LIKELY) + .build(); + + // Construct the Redact request to be sent by the client. + RedactImageRequest request = + RedactImageRequest.newBuilder() + .setParent(project.toString()) + .setByteItem(byteItem) + .setInspectConfig(config) + .build(); + + // Use the client to send the API request. + RedactImageResponse response = dlp.redactImage(request); + + // Parse the response and process results. + String outputPath = "redacted.png"; + FileOutputStream redacted = new FileOutputStream(outputPath); + redacted.write(response.getRedactedImage().toByteArray()); + redacted.close(); + System.out.println("Redacted image written to " + outputPath); + + } catch (Exception e) { + System.out.println("Error during inspectFile: \n" + e.toString()); + } + } +} diff --git a/dlp/src/test/java/dlp/snippets/RedactTests.java b/dlp/src/test/java/dlp/snippets/RedactTests.java new file mode 100644 index 00000000000..3d0299019fc --- /dev/null +++ b/dlp/src/test/java/dlp/snippets/RedactTests.java @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google LLC + * + * 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. + */ + +package dlp.snippets; + +import static junit.framework.TestCase.assertNotNull; +import static org.junit.Assert.assertThat; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import org.hamcrest.CoreMatchers; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class RedactTests { + + private ByteArrayOutputStream bout; + + private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); + + private static void requireEnvVar(String varName) { + assertNotNull( + System.getenv(varName), + "Environment variable '%s' is required to perform these tests.".format(varName) + ); + } + + @BeforeClass + public static void checkRequirements() { + requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS"); + requireEnvVar("GOOGLE_CLOUD_PROJECT"); + } + + @Before + public void beforeTest() { + bout = new ByteArrayOutputStream(); + System.setOut(new PrintStream(bout)); + } + + @After + public void tearDown() { + System.setOut(null); + bout.reset(); + } + + @Test + public void testInspectString() { + InspectString.inspectString(PROJECT_ID, "I'm Gary and my email is gary@example.com"); + + String output = bout.toString(); + assertThat(output, CoreMatchers.containsString("Info type: EMAIL_ADDRESS")); + } + + @Test + public void textInspectTestFile() { + InspectTextFile.inspectTextFile(PROJECT_ID, "src/test/resources/test.txt"); + + String output = bout.toString(); + assertThat(output, CoreMatchers.containsString("Info type: PHONE_NUMBER")); + assertThat(output, CoreMatchers.containsString("Info type: EMAIL_ADDRESS")); + } + + + @Test + public void testInspectImageFile() { + InspectImageFile.inspectImageFile(PROJECT_ID, "src/test/resources/test.png"); + + String output = bout.toString(); + assertThat(output, CoreMatchers.containsString("Info type: PHONE_NUMBER")); + assertThat(output, CoreMatchers.containsString("Info type: EMAIL_ADDRESS")); + } + +} From d7ac740a2204e685b1c9ceae879dd49766b27cde Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent Date: Fri, 15 Feb 2019 13:06:29 -0800 Subject: [PATCH 10/14] Clean up comments. --- .../java/dlp/snippets/InspectImageFile.java | 23 +++++++++-------- .../main/java/dlp/snippets/InspectString.java | 18 +++++++------ .../java/dlp/snippets/InspectTextFile.java | 19 +++++++------- .../test/java/dlp/snippets/RedactTests.java | 25 +++---------------- 4 files changed, 35 insertions(+), 50 deletions(-) diff --git a/dlp/src/main/java/dlp/snippets/InspectImageFile.java b/dlp/src/main/java/dlp/snippets/InspectImageFile.java index 0b7f8778019..7c8dd6d0bd5 100644 --- a/dlp/src/main/java/dlp/snippets/InspectImageFile.java +++ b/dlp/src/main/java/dlp/snippets/InspectImageFile.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Google LLC + * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,14 +38,15 @@ public class InspectImageFile { public static void inspectImageFile(String projectId, String filePath) { // String projectId = "my-project-id"; // String filePath = "path/to/image.png"; - // String fileType = "IMAGE" - // Initialize client with try-with-resources for automatic cleanup of background resources + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the "close" method on the client to safely clean up any remaining background resources. try (DlpServiceClient dlp = DlpServiceClient.create()) { - // Set project for request + // Specify the project used for request. ProjectName project = ProjectName.of(projectId); - // Set content for request + // Specify the type and content to be inspected. ByteString fileBytes = ByteString.readFrom(new FileInputStream(filePath)); ByteContentItem byteItem = ByteContentItem.newBuilder() .setType(BytesType.IMAGE) @@ -55,30 +56,30 @@ public static void inspectImageFile(String projectId, String filePath) { .setByteItem(byteItem) .build(); - // Set required InfoTypes for inspection config + // Specify the type of info the inspection will look for. List infoTypes = new ArrayList<>(); // See https://cloud.google.com/dlp/docs/infotypes-reference for complete list of info types for (String typeName : new String[] {"PHONE_NUMBER", "EMAIL_ADDRESS", "CREDIT_CARD_NUMBER"}) { infoTypes.add(InfoType.newBuilder().setName(typeName).build()); } - // Set the inspect configuration for request + // Construct the configuration for the Inspect request. InspectConfig config = InspectConfig.newBuilder() .addAllInfoTypes(infoTypes) .setIncludeQuote(true) .build(); - // Construct the request to be sent by the client + // Construct the Inspect request to be sent by the client. InspectContentRequest request = InspectContentRequest.newBuilder() .setParent(project.toString()) .setItem(item) .setInspectConfig(config) .build(); - // Use the client to send the API request + // Use the client to send the API request. InspectContentResponse response = dlp.inspectContent(request); - // Parse the response and process results + // Parse the response and process results. System.out.println("Findings: " + response.getResult().getFindingsCount()); for (Finding f : response.getResult().getFindingsList()) { System.out.println("\tQuote: " + f.getQuote()); @@ -86,7 +87,7 @@ public static void inspectImageFile(String projectId, String filePath) { System.out.println("\tLikelihood: " + f.getLikelihood()); } } catch (Exception e) { - System.out.println("Error during inspectFile: \n" + e.toString()); + System.out.println("Error during inspectImageFile: \n" + e.toString()); } } } diff --git a/dlp/src/main/java/dlp/snippets/InspectString.java b/dlp/src/main/java/dlp/snippets/InspectString.java index 2e8452762b3..a6a178dd529 100644 --- a/dlp/src/main/java/dlp/snippets/InspectString.java +++ b/dlp/src/main/java/dlp/snippets/InspectString.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Google LLC + * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,39 +38,41 @@ public static void inspectString(String projectId, String textToInspect) { // String projectId = "my-project-id"; // String textToInspect = "My name is Gary and my email is gary@example.com"; - // Initialize client with try-with-resources for automatic cleanup of background resources + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the "close" method on the client to safely clean up any remaining background resources. try (DlpServiceClient dlp = DlpServiceClient.create()) { - // Set project for request + // Specify the project used for request. ProjectName project = ProjectName.of(projectId); - // Set content for request + // Specify the type and content to be inspected. ByteContentItem byteItem = ByteContentItem.newBuilder() .setType(BytesType.TEXT_UTF8) .setData(ByteString.copyFromUtf8(textToInspect)) .build(); ContentItem item = ContentItem.newBuilder().setByteItem(byteItem).build(); - // Set required InfoTypes for inspection config + // Specify the type of info the inspection will look for. List infoTypes = new ArrayList<>(); // See https://cloud.google.com/dlp/docs/infotypes-reference for complete list of info types for (String typeName : new String[] {"PHONE_NUMBER", "EMAIL_ADDRESS", "CREDIT_CARD_NUMBER"}) { infoTypes.add(InfoType.newBuilder().setName(typeName).build()); } - // Set the inspect configuration for request + // Construct the configuration for the Inspect request. InspectConfig config = InspectConfig.newBuilder() .addAllInfoTypes(infoTypes) .setIncludeQuote(true) .build(); - // Construct request + // Construct the Inspect request to be sent by the client. InspectContentRequest request = InspectContentRequest.newBuilder() .setParent(project.toString()) .setItem(item) .setInspectConfig(config) .build(); - // Use the client to send the API request + // Use the client to send the API request. InspectContentResponse response = dlp.inspectContent(request); // Parse the response and process results diff --git a/dlp/src/main/java/dlp/snippets/InspectTextFile.java b/dlp/src/main/java/dlp/snippets/InspectTextFile.java index f15d756f2ff..335e2fcbe47 100644 --- a/dlp/src/main/java/dlp/snippets/InspectTextFile.java +++ b/dlp/src/main/java/dlp/snippets/InspectTextFile.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Google LLC + * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -38,14 +38,15 @@ public class InspectTextFile { public static void inspectTextFile(String projectId, String filePath) { // String projectId = "my-project-id"; // String filePath = "path/to/image.png"; - // String fileType = "IMAGE" - // Initialize client with try-with-resources for automatic cleanup of background resources + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. After completing all of your requests, call + // the "close" method on the client to safely clean up any remaining background resources. try (DlpServiceClient dlp = DlpServiceClient.create()) { - // Set project for request + // Specify the project used for request. ProjectName project = ProjectName.of(projectId); - // Set content for request + // Specify the type and content to be inspected. ByteString fileBytes = ByteString.readFrom(new FileInputStream(filePath)); ByteContentItem byteItem = ByteContentItem.newBuilder() .setType(BytesType.TEXT_UTF8) @@ -55,27 +56,27 @@ public static void inspectTextFile(String projectId, String filePath) { .setByteItem(byteItem) .build(); - // Set required InfoTypes for inspection config + // Specify the type of info the inspection will look for. List infoTypes = new ArrayList<>(); // See https://cloud.google.com/dlp/docs/infotypes-reference for complete list of info types for (String typeName : new String[] {"PHONE_NUMBER", "EMAIL_ADDRESS", "CREDIT_CARD_NUMBER"}) { infoTypes.add(InfoType.newBuilder().setName(typeName).build()); } - // Set the inspect configuration for request + // Construct the configuration for the Inspect request. InspectConfig config = InspectConfig.newBuilder() .addAllInfoTypes(infoTypes) .setIncludeQuote(true) .build(); - // Construct the request to be sent by the client + // Construct the Inspect request to be sent by the client. InspectContentRequest request = InspectContentRequest.newBuilder() .setParent(project.toString()) .setItem(item) .setInspectConfig(config) .build(); - // Use the client to send the API request + // Use the client to send the API request. InspectContentResponse response = dlp.inspectContent(request); // Parse the response and process results diff --git a/dlp/src/test/java/dlp/snippets/RedactTests.java b/dlp/src/test/java/dlp/snippets/RedactTests.java index 3d0299019fc..defbfd3db5e 100644 --- a/dlp/src/test/java/dlp/snippets/RedactTests.java +++ b/dlp/src/test/java/dlp/snippets/RedactTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Google LLC + * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -62,30 +62,11 @@ public void tearDown() { } @Test - public void testInspectString() { - InspectString.inspectString(PROJECT_ID, "I'm Gary and my email is gary@example.com"); + public void testRedactImage() { + RedactImageFile.redactImageFile(PROJECT_ID, "src/test/resources/test.png"); String output = bout.toString(); assertThat(output, CoreMatchers.containsString("Info type: EMAIL_ADDRESS")); } - @Test - public void textInspectTestFile() { - InspectTextFile.inspectTextFile(PROJECT_ID, "src/test/resources/test.txt"); - - String output = bout.toString(); - assertThat(output, CoreMatchers.containsString("Info type: PHONE_NUMBER")); - assertThat(output, CoreMatchers.containsString("Info type: EMAIL_ADDRESS")); - } - - - @Test - public void testInspectImageFile() { - InspectImageFile.inspectImageFile(PROJECT_ID, "src/test/resources/test.png"); - - String output = bout.toString(); - assertThat(output, CoreMatchers.containsString("Info type: PHONE_NUMBER")); - assertThat(output, CoreMatchers.containsString("Info type: EMAIL_ADDRESS")); - } - } From e0edee30294201b7dfe276022bc553d5e0ce12f7 Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent Date: Fri, 15 Feb 2019 13:09:05 -0800 Subject: [PATCH 11/14] Bump license year. --- dlp/src/test/java/dlp/snippets/InspectTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlp/src/test/java/dlp/snippets/InspectTests.java b/dlp/src/test/java/dlp/snippets/InspectTests.java index e91eb66dc75..6c64a19b9c5 100644 --- a/dlp/src/test/java/dlp/snippets/InspectTests.java +++ b/dlp/src/test/java/dlp/snippets/InspectTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 Google LLC + * Copyright 2019 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 6f1b07672ce99a4b1f96ded0e774666961c2c55a Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent Date: Fri, 15 Feb 2019 13:11:35 -0800 Subject: [PATCH 12/14] Fixed redact test. --- dlp/src/test/java/dlp/snippets/RedactTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlp/src/test/java/dlp/snippets/RedactTests.java b/dlp/src/test/java/dlp/snippets/RedactTests.java index defbfd3db5e..c55f78d7b41 100644 --- a/dlp/src/test/java/dlp/snippets/RedactTests.java +++ b/dlp/src/test/java/dlp/snippets/RedactTests.java @@ -66,7 +66,7 @@ public void testRedactImage() { RedactImageFile.redactImageFile(PROJECT_ID, "src/test/resources/test.png"); String output = bout.toString(); - assertThat(output, CoreMatchers.containsString("Info type: EMAIL_ADDRESS")); + assertThat(output, CoreMatchers.containsString("Redacted image written")); } } From e74f484405550feb04a2ab8b08dda664ce3034db Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent Date: Fri, 15 Feb 2019 13:29:05 -0800 Subject: [PATCH 13/14] Remove old redact snippet and move region tags. --- dlp/src/main/java/com/example/dlp/Redact.java | 189 ------------------ .../main/java/com/example/dlp/Templates.java | 2 +- .../java/dlp/snippets/RedactImageFile.java | 2 + .../test/java/com/example/dlp/RedactIT.java | 75 ------- .../test/java/dlp/snippets/RedactTests.java | 1 + 5 files changed, 4 insertions(+), 265 deletions(-) delete mode 100644 dlp/src/main/java/com/example/dlp/Redact.java delete mode 100644 dlp/src/test/java/com/example/dlp/RedactIT.java diff --git a/dlp/src/main/java/com/example/dlp/Redact.java b/dlp/src/main/java/com/example/dlp/Redact.java deleted file mode 100644 index 1ffd49fc90c..00000000000 --- a/dlp/src/main/java/com/example/dlp/Redact.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright 2017 Google Inc. - * - * 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. - */ - -package com.example.dlp; - -import com.google.cloud.ServiceOptions; -import com.google.cloud.dlp.v2.DlpServiceClient; -import com.google.privacy.dlp.v2.ByteContentItem; -import com.google.privacy.dlp.v2.InfoType; -import com.google.privacy.dlp.v2.InspectConfig; -import com.google.privacy.dlp.v2.Likelihood; -import com.google.privacy.dlp.v2.ProjectName; -import com.google.privacy.dlp.v2.RedactImageRequest; -import com.google.privacy.dlp.v2.RedactImageResponse; -import com.google.protobuf.ByteString; -import java.io.FileOutputStream; -import java.net.URLConnection; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; -import javax.activation.MimetypesFileTypeMap; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.CommandLineParser; -import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.HelpFormatter; -import org.apache.commons.cli.Option; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; - -public class Redact { - - // [START dlp_redact_image] - /* - * Redact sensitive data from an image using the Data Loss Prevention API. - * - * @param filePath The path to a local file to inspect. Can be a JPG or PNG image file. - * @param minLikelihood The minimum likelihood required before redacting a match. - * @param infoTypes The infoTypes of information to redact. - * @param outputPath The local path to save the resulting image to. - * @param projectId The project ID to run the API call under. - */ - private static void redactImage( - String filePath, - Likelihood minLikelihood, - List infoTypes, - String outputPath, - String projectId) - throws Exception { - - // Instantiate the DLP client - try (DlpServiceClient dlpClient = DlpServiceClient.create()) { - String mimeType = URLConnection.guessContentTypeFromName(filePath); - if (mimeType == null) { - mimeType = MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(filePath); - } - - ByteContentItem.BytesType bytesType; - switch (mimeType) { - case "image/jpeg": - bytesType = ByteContentItem.BytesType.IMAGE_JPEG; - break; - case "image/bmp": - bytesType = ByteContentItem.BytesType.IMAGE_BMP; - break; - case "image/png": - bytesType = ByteContentItem.BytesType.IMAGE_PNG; - break; - case "image/svg": - bytesType = ByteContentItem.BytesType.IMAGE_SVG; - break; - default: - bytesType = ByteContentItem.BytesType.BYTES_TYPE_UNSPECIFIED; - break; - } - - byte[] data = Files.readAllBytes(Paths.get(filePath)); - - InspectConfig inspectConfig = - InspectConfig.newBuilder() - .addAllInfoTypes(infoTypes) - .setMinLikelihood(minLikelihood) - .build(); - - ByteContentItem byteContentItem = - ByteContentItem.newBuilder() - .setType(bytesType) - .setData(ByteString.copyFrom(data)) - .build(); - - List imageRedactionConfigs = - infoTypes - .stream() - .map( - infoType -> - RedactImageRequest.ImageRedactionConfig.newBuilder() - .setInfoType(infoType) - .build()) - .collect(Collectors.toList()); - - RedactImageRequest redactImageRequest = - RedactImageRequest.newBuilder() - .setParent(ProjectName.of(projectId).toString()) - .addAllImageRedactionConfigs(imageRedactionConfigs) - .setByteItem(byteContentItem) - .setInspectConfig(inspectConfig) - .build(); - - RedactImageResponse redactImageResponse = dlpClient.redactImage(redactImageRequest); - - // redacted image data - ByteString redactedImageData = redactImageResponse.getRedactedImage(); - FileOutputStream outputStream = new FileOutputStream(outputPath); - outputStream.write(redactedImageData.toByteArray()); - outputStream.close(); - } - } - // [END dlp_redact_image] - - /** Command line application to redact strings, images using the Data Loss Prevention API. */ - public static void main(String[] args) throws Exception { - - Options commandLineOptions = new Options(); - - Option minLikelihoodOption = - Option.builder("minLikelihood").hasArg(true).required(false).build(); - - commandLineOptions.addOption(minLikelihoodOption); - - Option infoTypesOption = Option.builder("infoTypes").hasArg(true).required(false).build(); - infoTypesOption.setArgs(Option.UNLIMITED_VALUES); - commandLineOptions.addOption(infoTypesOption); - - Option inputFilePathOption = - Option.builder("f").hasArg(true).longOpt("inputFilePath").required(false).build(); - commandLineOptions.addOption(inputFilePathOption); - - Option outputFilePathOption = - Option.builder("o").hasArg(true).longOpt("outputFilePath").required(false).build(); - - commandLineOptions.addOption(outputFilePathOption); - - Option projectIdOption = Option.builder("projectId").hasArg(true).required(false).build(); - CommandLineParser parser = new DefaultParser(); - HelpFormatter formatter = new HelpFormatter(); - CommandLine cmd; - - try { - cmd = parser.parse(commandLineOptions, args); - } catch (ParseException e) { - System.out.println(e.getMessage()); - formatter.printHelp(Redact.class.getName(), commandLineOptions); - System.exit(1); - return; - } - - List infoTypesList = new ArrayList<>(); - String[] infoTypes = cmd.getOptionValues(infoTypesOption.getOpt()); - if (infoTypes != null) { - for (String infoType : infoTypes) { - infoTypesList.add(InfoType.newBuilder().setName(infoType).build()); - } - } - Likelihood minLikelihood = - Likelihood.valueOf( - cmd.getOptionValue( - minLikelihoodOption.getOpt(), Likelihood.LIKELIHOOD_UNSPECIFIED.name())); - - String inputFilePath = cmd.getOptionValue(inputFilePathOption.getOpt()); - String outputFilePath = cmd.getOptionValue(outputFilePathOption.getOpt()); - String projectId = - cmd.getOptionValue(projectIdOption.getOpt(), ServiceOptions.getDefaultProjectId()); - redactImage(inputFilePath, minLikelihood, infoTypesList, outputFilePath, projectId); - } -} diff --git a/dlp/src/main/java/com/example/dlp/Templates.java b/dlp/src/main/java/com/example/dlp/Templates.java index da4c5eb88c6..72e2cb6cf6d 100644 --- a/dlp/src/main/java/com/example/dlp/Templates.java +++ b/dlp/src/main/java/com/example/dlp/Templates.java @@ -218,7 +218,7 @@ public static void main(String[] args) throws Exception { cmd = parser.parse(commandLineOptions, args); } catch (ParseException e) { System.out.println(e.getMessage()); - formatter.printHelp(Redact.class.getName(), commandLineOptions); + formatter.printHelp("dlp_snippets", commandLineOptions); System.exit(1); return; } diff --git a/dlp/src/main/java/dlp/snippets/RedactImageFile.java b/dlp/src/main/java/dlp/snippets/RedactImageFile.java index f0d18f929a3..bbf4bc53184 100644 --- a/dlp/src/main/java/dlp/snippets/RedactImageFile.java +++ b/dlp/src/main/java/dlp/snippets/RedactImageFile.java @@ -16,6 +16,7 @@ package dlp.snippets; +// [START dlp_redact_image] import com.google.cloud.dlp.v2.DlpServiceClient; import com.google.privacy.dlp.v2.ByteContentItem; import com.google.privacy.dlp.v2.ByteContentItem.BytesType; @@ -84,3 +85,4 @@ static void redactImageFile(String projectId, String filePath) { } } } +// [END dlp_redact_image] diff --git a/dlp/src/test/java/com/example/dlp/RedactIT.java b/dlp/src/test/java/com/example/dlp/RedactIT.java deleted file mode 100644 index 5708fae6211..00000000000 --- a/dlp/src/test/java/com/example/dlp/RedactIT.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2017 Google Inc. - * - * 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. - */ - -package com.example.dlp; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.hamcrest.CoreMatchers.not; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; - -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -@RunWith(JUnit4.class) -// CHECKSTYLE OFF: AbbreviationAsWordInName -public class RedactIT { - - // CHECKSTYLE ON: AbbreviationAsWordInName - private ByteArrayOutputStream bout; - private PrintStream out; - - @Before - public void setUp() { - bout = new ByteArrayOutputStream(); - out = new PrintStream(bout); - System.setOut(out); - assertNotNull(System.getenv("GOOGLE_APPLICATION_CREDENTIALS")); - } - - @Test - public void testRedactImage() throws Exception { - // InspectIT Tests verify original has PII present - String outputFilePath = "src/test/resources/output.png"; - - // Restrict phone number, but not email - Redact.main( - new String[] { - "-f", "src/test/resources/test.png", - "-infoTypes", "PHONE_NUMBER", - "-o", outputFilePath - }); - bout.reset(); - - // Verify that phone_number is missing but email is present - Inspect.main( - new String[] {"-f", outputFilePath, "-infoTypes", "PHONE_NUMBER", "EMAIL_ADDRESS"}); - String output = bout.toString(); - assertThat(output, not(containsString("PHONE_NUMBER"))); - assertThat(output, containsString("EMAIL_ADDRESS")); - } - - @After - public void tearDown() { - System.setOut(null); - bout.reset(); - } -} diff --git a/dlp/src/test/java/dlp/snippets/RedactTests.java b/dlp/src/test/java/dlp/snippets/RedactTests.java index c55f78d7b41..548ad35effa 100644 --- a/dlp/src/test/java/dlp/snippets/RedactTests.java +++ b/dlp/src/test/java/dlp/snippets/RedactTests.java @@ -16,6 +16,7 @@ package dlp.snippets; +// [START dlp_redact_image] import static junit.framework.TestCase.assertNotNull; import static org.junit.Assert.assertThat; From e2386838b6549ddb668752e0b7529347b491b5c3 Mon Sep 17 00:00:00 2001 From: Kurtis Van Gent Date: Mon, 25 Feb 2019 13:50:39 -0800 Subject: [PATCH 14/14] Remove region tag. --- dlp/src/test/java/dlp/snippets/RedactTests.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/dlp/src/test/java/dlp/snippets/RedactTests.java b/dlp/src/test/java/dlp/snippets/RedactTests.java index 548ad35effa..475b9485a8d 100644 --- a/dlp/src/test/java/dlp/snippets/RedactTests.java +++ b/dlp/src/test/java/dlp/snippets/RedactTests.java @@ -16,7 +16,6 @@ package dlp.snippets; -// [START dlp_redact_image] import static junit.framework.TestCase.assertNotNull; import static org.junit.Assert.assertThat; @@ -40,8 +39,7 @@ public class RedactTests { private static void requireEnvVar(String varName) { assertNotNull( System.getenv(varName), - "Environment variable '%s' is required to perform these tests.".format(varName) - ); + "Environment variable '%s' is required to perform these tests.".format(varName)); } @BeforeClass @@ -64,10 +62,9 @@ public void tearDown() { @Test public void testRedactImage() { - RedactImageFile.redactImageFile(PROJECT_ID, "src/test/resources/test.png"); + RedactImageFile.redactImageFile(PROJECT_ID, "src/test/resources/test.png"); String output = bout.toString(); assertThat(output, CoreMatchers.containsString("Redacted image written")); } - }