Skip to content

Commit 66fa835

Browse files
authored
Changes for release v4. (#307)
1 parent df209de commit 66fa835

4,130 files changed

Lines changed: 1721744 additions & 7124 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
6.0.0 - 2020-07-17
2+
------------------
3+
- Added support for Google Ads API v4_0.
4+
- Moved documentation. Now hosted at:
5+
https://developers.google.com/google-ads/api/docs/client-libs/java.
6+
- Added examples demonstrating:
7+
- Drafts and experiments.
8+
- Parallel report download.
9+
- CPC bid simulations.
10+
- Programmatic library configuration.
11+
- Keyword policy violation handling.
12+
- Updating expanded text ads.
13+
- Removed vulnerable dependency on log4j 1.2.16.
14+
- Added support for linked-customer-id header. This is needed for an extremely
15+
narrow authentication use-case. Any developer who requires this to be set
16+
will be advised. It is otherwise safe to ignore.
17+
118
5.1.0 - 2020-05-06
219
------------------
320
- Added support for Google Ads API v3_1.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<!--
2+
* Copyright 2019 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
-->
16+
<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/maven-v4_0_0.xsd">
17+
18+
<parent>
19+
<groupId>com.google.api-ads</groupId>
20+
<artifactId>google-ads-parent</artifactId>
21+
<version>5.1.1-SNAPSHOT</version>
22+
<relativePath>../pom.xml</relativePath>
23+
</parent>
24+
25+
<modelVersion>4.0.0</modelVersion>
26+
<groupId>com.google.api-ads</groupId>
27+
<artifactId>google-ads-annotation-processing</artifactId>
28+
<packaging>jar</packaging>
29+
<version>5.1.1-SNAPSHOT</version>
30+
<name>Google Ads API client library for Java annotation processor</name>
31+
<description>
32+
Handles code generation for with annotation processing for the client libraries for Java.
33+
</description>
34+
35+
<build>
36+
<plugins>
37+
<plugin>
38+
<groupId>org.codehaus.mojo</groupId>
39+
<artifactId>exec-maven-plugin</artifactId>
40+
<version>1.6.0</version>
41+
<configuration>
42+
<!-- Do not clean up daemon threads. See the following issue for more details:
43+
https://github.com/googleads/google-ads-java/issues/2 -->
44+
<cleanupDaemonThreads>false</cleanupDaemonThreads>
45+
</configuration>
46+
</plugin>
47+
</plugins>
48+
</build>
49+
50+
<dependencies>
51+
<dependency>
52+
<groupId>com.squareup</groupId>
53+
<artifactId>javapoet</artifactId>
54+
<version>1.11.1</version>
55+
</dependency>
56+
<dependency>
57+
<groupId>com.google.auto.service</groupId>
58+
<artifactId>auto-service</artifactId>
59+
<version>1.0-rc1</version>
60+
<optional>true</optional>
61+
</dependency>
62+
<dependency>
63+
<groupId>com.google.api</groupId>
64+
<artifactId>gax</artifactId>
65+
<version>1.50.1</version>
66+
</dependency>
67+
<dependency>
68+
<groupId>com.google.guava</groupId>
69+
<artifactId>guava</artifactId>
70+
<version>26.0-android</version>
71+
</dependency>
72+
<dependency>
73+
<groupId>javax.annotation</groupId>
74+
<artifactId>javax.annotation-api</artifactId>
75+
<version>1.3.2</version>
76+
</dependency>
77+
</dependencies>
78+
</project>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2020 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.ads.googleads.annotations.api;
16+
17+
/**
18+
* The default value for the googleAdsExceptionFactory method in VersionDescriptor.java. Ensures
19+
* that all VersionDescriptor annotations contain a googleAdsExceptionFactory parameter.
20+
*/
21+
class DefaultExceptionFactory {
22+
public DefaultExceptionFactory() throws Exception {
23+
throw new Exception(
24+
"VersionDescriptor annotation missing googleAdsExceptionFactory parameter.");
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
// Copyright 2020 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.ads.googleads.annotations.api;
16+
17+
import static java.lang.Math.max;
18+
19+
import com.google.ads.googleads.annotations.impl.AbstractGoogleAdsClientCodeGenerator;
20+
import com.google.ads.googleads.annotations.impl.GeneratedCatalogCodeGenerator;
21+
import com.google.ads.googleads.annotations.impl.GoogleAdsAllVersionsCodeGenerator;
22+
import com.google.ads.googleads.annotations.impl.VersionCatalogCodeGenerator;
23+
import com.google.auto.service.AutoService;
24+
import com.google.common.collect.SortedSetMultimap;
25+
import com.google.common.collect.TreeMultimap;
26+
import java.util.Collections;
27+
import java.util.Map.Entry;
28+
import java.util.Set;
29+
import javax.annotation.processing.AbstractProcessor;
30+
import javax.annotation.processing.Filer;
31+
import javax.annotation.processing.Messager;
32+
import javax.annotation.processing.ProcessingEnvironment;
33+
import javax.annotation.processing.Processor;
34+
import javax.annotation.processing.RoundEnvironment;
35+
import javax.lang.model.SourceVersion;
36+
import javax.lang.model.element.AnnotationMirror;
37+
import javax.lang.model.element.AnnotationValue;
38+
import javax.lang.model.element.Element;
39+
import javax.lang.model.element.ExecutableElement;
40+
import javax.lang.model.element.TypeElement;
41+
import javax.lang.model.type.DeclaredType;
42+
import javax.lang.model.util.Elements;
43+
44+
/**
45+
* Processes annotations and dynamically generates several classes and interfaces required to define
46+
* the services available in each version of API. The generated classes and interfaces are listed
47+
* below:
48+
*
49+
* <ul>
50+
* <li>GeneratedCatalog
51+
* <li>VersionCatalog
52+
* <li>AbstractGoogleAdsClient
53+
* <li>GoogleAdsAllVersions
54+
* </ul>
55+
*
56+
* <p>The annotation processor dynamically creates a set of the available versions of the Google Ads
57+
* API by finding all of the unique versionName parameters (e.g. "v1" or "v2") and catalogs by
58+
* finding all of the unique catalogName parameters included in @VersionDescriptor annotations
59+
* throughout the library. More information regarding the catalog system can be found in the
60+
* documentation of the VersionDescriptor.java class. Upon finding all versions and catalogs, this
61+
* class writes one version of each of the classes listed above for each unique combination of
62+
* version and catalog.
63+
*/
64+
@AutoService(Processor.class)
65+
public class GoogleAdsCatalogAnnotationProcessor extends AbstractProcessor {
66+
67+
private Elements elementUtils;
68+
private Filer filer;
69+
private Messager messager;
70+
private boolean hasWrittenFiles;
71+
72+
@Override
73+
public synchronized void init(ProcessingEnvironment processingEnv) {
74+
super.init(processingEnv);
75+
elementUtils = processingEnv.getElementUtils();
76+
filer = processingEnv.getFiler();
77+
messager = processingEnv.getMessager();
78+
}
79+
80+
@Override
81+
public Set<String> getSupportedAnnotationTypes() {
82+
return Collections.singleton(VersionDescriptor.class.getCanonicalName());
83+
}
84+
85+
@Override
86+
public SourceVersion getSupportedSourceVersion() {
87+
return SourceVersion.latestSupported();
88+
}
89+
90+
@Override
91+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
92+
// Ensures the annotation processor prints useful information when compiling fails.
93+
try {
94+
return doProcess(roundEnv);
95+
} catch (RuntimeException e) {
96+
e.printStackTrace();
97+
throw e;
98+
}
99+
}
100+
101+
/**
102+
* Processes annotations and generates files.
103+
*
104+
* @param roundEnv the processing round environment.
105+
*/
106+
private boolean doProcess(RoundEnvironment roundEnv) {
107+
// Ensures the code below runs only once. Because processing needs to be completed in the final
108+
// round that depends on the code generated below, this code should not run in the final
109+
// processing run.
110+
if (!hasWrittenFiles) {
111+
SortedSetMultimap<String, Integer> catalogVersionsMap =
112+
generateVersionsFromAnnotations(roundEnv);
113+
114+
if (!catalogVersionsMap.isEmpty()) {
115+
for (String catalogName : catalogVersionsMap.keySet()) {
116+
Set<Integer> versions = catalogVersionsMap.get(catalogName);
117+
int latestVersion = getLatestVersion(versions);
118+
119+
if (!versions.isEmpty()) {
120+
GeneratedCatalogCodeGenerator.generate(
121+
versions, latestVersion, catalogName, elementUtils, messager, filer);
122+
VersionCatalogCodeGenerator.generate(versions, catalogName, messager, filer);
123+
AbstractGoogleAdsClientCodeGenerator.generate(
124+
versions, latestVersion, catalogName, messager, filer);
125+
GoogleAdsAllVersionsCodeGenerator.generate(
126+
versions, latestVersion, catalogName, messager, filer);
127+
}
128+
}
129+
hasWrittenFiles = true;
130+
}
131+
}
132+
return false;
133+
}
134+
135+
/**
136+
* Dynamically creates a SortedSetMultimap of the available versions of the Google Ads API, that
137+
* is mapped by catalog name, by finding all of the unique catalogName (e.g. "v1" or "v1_v2") and
138+
* versionName (e.g. "v1" or "v2") descriptors included in @VersionDescriptor annotations
139+
* throughout the library. Each set of versions is mapped to its specified catalog name.
140+
*
141+
* @param roundEnv the environment of the processing round.
142+
* @return a set of the available versions in the library.
143+
*/
144+
private static SortedSetMultimap<String, Integer> generateVersionsFromAnnotations(
145+
RoundEnvironment roundEnv) {
146+
SortedSetMultimap<String, Integer> versionsMap = TreeMultimap.create();
147+
148+
for (Element annotatedElement : roundEnv.getElementsAnnotatedWith(VersionDescriptor.class)) {
149+
TypeElement typeElement = (TypeElement) annotatedElement;
150+
String validExceptionFactoryType = "BaseGoogleAdsException.Factory";
151+
if (!isValidExceptionFactory(typeElement, validExceptionFactoryType)) {
152+
throw new IllegalArgumentException(
153+
String.format(
154+
"googleAdsExceptionFactory parameters in VersionDescriptor either be of class"
155+
+ " type %s or directly extend %s.",
156+
validExceptionFactoryType, validExceptionFactoryType));
157+
}
158+
159+
VersionDescriptor annotation = typeElement.getAnnotation(VersionDescriptor.class);
160+
if (annotation.versionName().charAt(0) == 'v') {
161+
int version = Integer.parseInt(annotation.versionName().substring(1));
162+
versionsMap.put(annotation.catalogName(), version);
163+
} else {
164+
throw new IllegalArgumentException(
165+
"versionName parameters in VersionDescriptor annotations must be in"
166+
+ " the format 'vX' where X is an integer.");
167+
}
168+
}
169+
return versionsMap;
170+
}
171+
172+
/**
173+
* Checks if the googleAdsExceptionFactory is of a valid type. In order to be valid, the provided
174+
* googleAdsExceptionFactory must be either equal to or a direct child of the provided type.
175+
*
176+
* @param typeElement the annotated element.
177+
* @param validExceptionFactoryType the simple class name of the valid type against which to check
178+
* validity.
179+
* @return true if the googleAdsExceptionFactory is of a valid type or false if not.
180+
*/
181+
private static boolean isValidExceptionFactory(
182+
TypeElement typeElement, String validExceptionFactoryType) {
183+
TypeElement exceptionFactoryElement = getExceptionFactoryElement(typeElement);
184+
if (isClassNameValid(
185+
exceptionFactoryElement.getQualifiedName().toString(), validExceptionFactoryType)) {
186+
return true;
187+
}
188+
189+
String superClass = exceptionFactoryElement.getSuperclass().toString();
190+
return isClassNameValid(superClass, validExceptionFactoryType);
191+
}
192+
193+
/**
194+
* Gets the value of the googleAdsExceptionFactory field of a VersionDescriptor as a TypeElement.
195+
*
196+
* @param typeElement the annotated element.
197+
* @return the TypeElement of the googleAdsExceptionFactory value in the annotation.
198+
*/
199+
private static TypeElement getExceptionFactoryElement(TypeElement typeElement) {
200+
for (AnnotationMirror annotationMirror : typeElement.getAnnotationMirrors()) {
201+
for (Entry<? extends ExecutableElement, ? extends AnnotationValue> entry :
202+
annotationMirror.getElementValues().entrySet()) {
203+
if (entry.getKey().getSimpleName().toString().equals("googleAdsExceptionFactory")) {
204+
DeclaredType exceptionFactoryMirror = (DeclaredType) entry.getValue().getValue();
205+
return (TypeElement) exceptionFactoryMirror.asElement();
206+
}
207+
}
208+
}
209+
return null;
210+
}
211+
212+
/**
213+
* Checks if the provided class name is of a valid type.
214+
*
215+
* @param className the String representation of the class name.
216+
* @param validExceptionFactoryType the simple class name of the valid type against which to check
217+
* validity.
218+
* @return true if the googleAdsExceptionFactory is of a valid type or false if not.
219+
*/
220+
private static boolean isClassNameValid(String className, String validExceptionFactoryType) {
221+
int end = className.indexOf("<");
222+
if (end != -1) {
223+
className = className.substring(0, end);
224+
}
225+
if (className.endsWith(validExceptionFactoryType)) {
226+
return true;
227+
}
228+
return false;
229+
}
230+
231+
/**
232+
* Gets the latest production version.
233+
*
234+
* @param versions list of versions.
235+
* @return the latest available version of the Google Ads library.
236+
*/
237+
private static int getLatestVersion(Set<Integer> versions) {
238+
int latestVersion = 0;
239+
for (int version : versions) {
240+
if (version != 999) {
241+
latestVersion = max(latestVersion, version);
242+
}
243+
}
244+
return latestVersion;
245+
}
246+
}

0 commit comments

Comments
 (0)