├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── pom.xml
├── samples
├── Drupal10
│ ├── DevPortal
│ │ ├── apicatalog-config.json
│ │ ├── pom.xml
│ │ ├── shared-pom.xml
│ │ └── specs
│ │ │ ├── Petstore.yaml
│ │ │ └── pets.jpeg
│ ├── README.md
│ └── media
│ │ ├── screenshot1.png
│ │ └── screenshot2.png
├── Drupal7
│ ├── DevPortal
│ │ ├── pom.xml
│ │ ├── shared-pom.xml
│ │ └── specs
│ │ │ └── mock.yaml
│ ├── README.md
│ └── images
│ │ ├── Fake-Company.png
│ │ ├── Field-Company.png
│ │ ├── Service-Edit.png
│ │ ├── Service-Endpoints-Advanced.png
│ │ ├── Service-Endpoints-User.png
│ │ ├── Service-Endpoints.png
│ │ └── Service-Listing.png
└── README.md
└── src
└── main
├── java
└── com
│ └── apigee
│ └── smartdocs
│ └── config
│ ├── mavenplugin
│ ├── APIDocsMojo.java
│ └── PortalAbstractMojo.java
│ ├── rest
│ ├── FakeHostnameVerifier.java
│ ├── PortalRestUtil.java
│ └── XTrustProvider.java
│ └── utils
│ ├── PortalField.java
│ ├── PrintUtil.java
│ └── ServerProfile.java
└── resources
└── log4j2.properties
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | target/
3 | bin/
4 | .settings
5 | .classpath
6 | .project
7 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We'd love to accept your patches and contributions to this project. There are
4 | just a few small guidelines you need to follow.
5 |
6 | ## Contributor License Agreement
7 |
8 | Contributions to this project must be accompanied by a Contributor License
9 | Agreement. You (or your employer) retain the copyright to your contribution,
10 | this simply gives us permission to use and redistribute your contributions as
11 | part of the project. Head over to to see
12 | your current agreements on file or to sign a new one.
13 |
14 | You generally only need to submit a CLA once, so if you've already submitted one
15 | (even if it was for a different project), you probably don't need to do it
16 | again.
17 |
18 | ## Code reviews
19 |
20 | All submissions, including submissions by project members, require review. We
21 | use GitHub pull requests for this purpose. Consult
22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
23 | information on using pull requests.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
5 | 1. Definitions.
6 | "License" shall mean the terms and conditions for use, reproduction,
7 | and distribution as defined by Sections 1 through 9 of this document.
8 | "Licensor" shall mean the copyright owner or entity authorized by
9 | the copyright owner that is granting the License.
10 | "Legal Entity" shall mean the union of the acting entity and all
11 | other entities that control, are controlled by, or are under common
12 | control with that entity. For the purposes of this definition,
13 | "control" means (i) the power, direct or indirect, to cause the
14 | direction or management of such entity, whether by contract or
15 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
16 | outstanding shares, or (iii) beneficial ownership of such entity.
17 | "You" (or "Your") shall mean an individual or Legal Entity
18 | exercising permissions granted by this License.
19 | "Source" form shall mean the preferred form for making modifications,
20 | including but not limited to software source code, documentation
21 | source, and configuration files.
22 | "Object" form shall mean any form resulting from mechanical
23 | transformation or translation of a Source form, including but
24 | not limited to compiled object code, generated documentation,
25 | and conversions to other media types.
26 | "Work" shall mean the work of authorship, whether in Source or
27 | Object form, made available under the License, as indicated by a
28 | copyright notice that is included in or attached to the work
29 | (an example is provided in the Appendix below).
30 | "Derivative Works" shall mean any work, whether in Source or Object
31 | form, that is based on (or derived from) the Work and for which the
32 | editorial revisions, annotations, elaborations, or other modifications
33 | represent, as a whole, an original work of authorship. For the purposes
34 | of this License, Derivative Works shall not include works that remain
35 | separable from, or merely link (or bind by name) to the interfaces of,
36 | the Work and Derivative Works thereof.
37 | "Contribution" shall mean any work of authorship, including
38 | the original version of the Work and any modifications or additions
39 | to that Work or Derivative Works thereof, that is intentionally
40 | submitted to Licensor for inclusion in the Work by the copyright owner
41 | or by an individual or Legal Entity authorized to submit on behalf of
42 | the copyright owner. For the purposes of this definition, "submitted"
43 | means any form of electronic, verbal, or written communication sent
44 | to the Licensor or its representatives, including but not limited to
45 | communication on electronic mailing lists, source code control systems,
46 | and issue tracking systems that are managed by, or on behalf of, the
47 | Licensor for the purpose of discussing and improving the Work, but
48 | excluding communication that is conspicuously marked or otherwise
49 | designated in writing by the copyright owner as "Not a Contribution."
50 | "Contributor" shall mean Licensor and any individual or Legal Entity
51 | on behalf of whom a Contribution has been received by Licensor and
52 | subsequently incorporated within the Work.
53 | 2. Grant of Copyright License. Subject to the terms and conditions of
54 | this License, each Contributor hereby grants to You a perpetual,
55 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
56 | copyright license to reproduce, prepare Derivative Works of,
57 | publicly display, publicly perform, sublicense, and distribute the
58 | Work and such Derivative Works in Source or Object form.
59 | 3. Grant of Patent License. Subject to the terms and conditions of
60 | this License, each Contributor hereby grants to You a perpetual,
61 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
62 | (except as stated in this section) patent license to make, have made,
63 | use, offer to sell, sell, import, and otherwise transfer the Work,
64 | where such license applies only to those patent claims licensable
65 | by such Contributor that are necessarily infringed by their
66 | Contribution(s) alone or by combination of their Contribution(s)
67 | with the Work to which such Contribution(s) was submitted. If You
68 | institute patent litigation against any entity (including a
69 | cross-claim or counterclaim in a lawsuit) alleging that the Work
70 | or a Contribution incorporated within the Work constitutes direct
71 | or contributory patent infringement, then any patent licenses
72 | granted to You under this License for that Work shall terminate
73 | as of the date such litigation is filed.
74 | 4. Redistribution. You may reproduce and distribute copies of the
75 | Work or Derivative Works thereof in any medium, with or without
76 | modifications, and in Source or Object form, provided that You
77 | meet the following conditions:
78 | (a) You must give any other recipients of the Work or
79 | Derivative Works a copy of this License; and
80 | (b) You must cause any modified files to carry prominent notices
81 | stating that You changed the files; and
82 | (c) You must retain, in the Source form of any Derivative Works
83 | that You distribute, all copyright, patent, trademark, and
84 | attribution notices from the Source form of the Work,
85 | excluding those notices that do not pertain to any part of
86 | the Derivative Works; and
87 | (d) If the Work includes a "NOTICE" text file as part of its
88 | distribution, then any Derivative Works that You distribute must
89 | include a readable copy of the attribution notices contained
90 | within such NOTICE file, excluding those notices that do not
91 | pertain to any part of the Derivative Works, in at least one
92 | of the following places: within a NOTICE text file distributed
93 | as part of the Derivative Works; within the Source form or
94 | documentation, if provided along with the Derivative Works; or,
95 | within a display generated by the Derivative Works, if and
96 | wherever such third-party notices normally appear. The contents
97 | of the NOTICE file are for informational purposes only and
98 | do not modify the License. You may add Your own attribution
99 | notices within Derivative Works that You distribute, alongside
100 | or as an addendum to the NOTICE text from the Work, provided
101 | that such additional attribution notices cannot be construed
102 | as modifying the License.
103 | You may add Your own copyright statement to Your modifications and
104 | may provide additional or different license terms and conditions
105 | for use, reproduction, or distribution of Your modifications, or
106 | for any such Derivative Works as a whole, provided Your use,
107 | reproduction, and distribution of the Work otherwise complies with
108 | the conditions stated in this License.
109 | 5. Submission of Contributions. Unless You explicitly state otherwise,
110 | any Contribution intentionally submitted for inclusion in the Work
111 | by You to the Licensor shall be under the terms and conditions of
112 | this License, without any additional terms or conditions.
113 | Notwithstanding the above, nothing herein shall supersede or modify
114 | the terms of any separate license agreement you may have executed
115 | with Licensor regarding such Contributions.
116 | 6. Trademarks. This License does not grant permission to use the trade
117 | names, trademarks, service marks, or product names of the Licensor,
118 | except as required for reasonable and customary use in describing the
119 | origin of the Work and reproducing the content of the NOTICE file.
120 | 7. Disclaimer of Warranty. Unless required by applicable law or
121 | agreed to in writing, Licensor provides the Work (and each
122 | Contributor provides its Contributions) on an "AS IS" BASIS,
123 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
124 | implied, including, without limitation, any warranties or conditions
125 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
126 | PARTICULAR PURPOSE. You are solely responsible for determining the
127 | appropriateness of using or redistributing the Work and assume any
128 | risks associated with Your exercise of permissions under this License.
129 | 8. Limitation of Liability. In no event and under no legal theory,
130 | whether in tort (including negligence), contract, or otherwise,
131 | unless required by applicable law (such as deliberate and grossly
132 | negligent acts) or agreed to in writing, shall any Contributor be
133 | liable to You for damages, including any direct, indirect, special,
134 | incidental, or consequential damages of any character arising as a
135 | result of this License or out of the use or inability to use the
136 | Work (including but not limited to damages for loss of goodwill,
137 | work stoppage, computer failure or malfunction, or any and all
138 | other commercial damages or losses), even if such Contributor
139 | has been advised of the possibility of such damages.
140 | 9. Accepting Warranty or Additional Liability. While redistributing
141 | the Work or Derivative Works thereof, You may choose to offer,
142 | and charge a fee for, acceptance of support, warranty, indemnity,
143 | or other liability obligations and/or rights consistent with this
144 | License. However, in accepting such obligations, You may act only
145 | on Your own behalf and on Your sole responsibility, not on behalf
146 | of any other Contributor, and only if You agree to indemnify,
147 | defend, and hold each Contributor harmless for any liability
148 | incurred by, or claims asserted against, such Contributor by reason
149 | of your accepting any such warranty or additional liability.
150 | END OF TERMS AND CONDITIONS
151 | APPENDIX: How to apply the Apache License to your work.
152 | To apply the Apache License to your work, attach the following
153 | boilerplate notice, with the fields enclosed by brackets "[]"
154 | replaced with your own identifying information. (Don't include
155 | the brackets!) The text should be enclosed in the appropriate
156 | comment syntax for the file format. We also recommend that a
157 | file or class name and description of purpose be included on the
158 | same "printed page" as the copyright notice for easier
159 | identification within third-party archives.
160 | Copyright [yyyy] [name of copyright owner]
161 | Licensed under the Apache License, Version 2.0 (the "License");
162 | you may not use this file except in compliance with the License.
163 | You may obtain a copy of the License at
164 | http://www.apache.org/licenses/LICENSE-2.0
165 | Unless required by applicable law or agreed to in writing, software
166 | distributed under the License is distributed on an "AS IS" BASIS,
167 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
168 | See the License for the specific language governing permissions and
169 | limitations under the License.
170 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # apigee-smartdocs-maven-plugin
2 |
3 | ----------------
4 | About the Plugin
5 | ----------------
6 |
7 | apigee-smartdocs-maven-plugin is a utility for creating API models and pushing an OpenAPI spec document into the API Catalog module for a Drupal 10-based developer portal, where it can then be rendered into documentation using SmartDocs or another renderer.
8 |
9 | The code is distributed under the Apache License 2.0.
10 |
11 | **NOTE:** Log4J libraries are upgraded to v2.17.1 in v2.2.2
12 |
13 | ------------
14 | TL;DR
15 | ------------
16 |
17 | - Version **1.x** of this plugin should be used for **Drupal 7** version of the Developer portal and the goal is `apimodel`. For example in your pom.xml
18 | ```xml
19 |
20 | com.apigee.smartdocs.config
21 | apigee-smartdocs-maven-plugin
22 | 1.0.8
23 |
24 |
25 | smartdocs-deploy
26 | install
27 |
28 | apimodel
29 |
30 |
31 |
32 |
33 | ```
34 | - Version **2.x** of this plugin should be used for **Drupal 10** version of the Developer portal and the goal is `apidoc`. For example in your pom.xml
35 | ```xml
36 |
37 | com.apigee.smartdocs.config
38 | apigee-smartdocs-maven-plugin
39 | 2.1.0
40 |
41 |
42 | smartdocs-deploy
43 | install
44 |
45 | apidoc
46 |
47 |
48 |
49 |
50 | ```
51 |
52 | The [samples folder](https://github.com/apigee/apigee-smartdocs-maven-plugin/tree/master/samples) provides a Readme with Getting Started steps and commands to hit the ground quickly. Contains samples for Drupal 7 and Drupal 10 version of Developer portal
53 |
54 |
55 | ## Support
56 | * Please send feature requests using [issues](https://github.com/apigee/apigee-smartdocs-maven-plugin/issues)
57 | * Post a question in [Apigee community](https://community.apigee.com/index.html)
58 | * Create an [issue](https://github.com/apigee/apigee-smartdocs-maven-plugin/issues/new)
59 |
60 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 |
5 | org.sonatype.oss
6 | oss-parent
7 | 7
8 |
9 |
10 | com.apigee.smartdocs.config
11 | apigee-smartdocs-maven-plugin
12 | 2.2.5-SNAPSHOT
13 | maven-plugin
14 | apigee-smartdocs-maven-plugin
15 | Plugin to manage configuration for Smartdocs in Apigee Drupal developer portal
16 | https://github.com/apigee/apigee-smartdocs-maven-plugin
17 |
18 |
19 |
20 | The Apache Software License, Version 2.0
21 | http://www.apache.org/licenses/LICENSE-2.0.txt
22 |
23 |
24 |
25 |
26 |
27 | Sai Saran Vaidyanathan
28 | ssvaidyanathan@google.com
29 | Google
30 | www.google.com
31 |
32 |
33 | Gitesh Koli
34 | gkoli@google.com
35 | Google
36 | www.google.com
37 |
38 |
39 |
40 |
41 | git@github.com:apigee/apigee-smartdocs-maven-plugin.git
42 | scm:git:https://github.com/apigee/apigee-smartdocs-maven-plugin.git
43 | scm:git:ssh://git@github.com/apigee/apigee-smartdocs-maven-plugin.git
44 |
45 |
46 |
47 | 1.8
48 | 1.8
49 | UTF-8
50 | 5.3.26
51 | 2.17.1
52 |
53 |
54 |
55 |
56 | org.apache.maven
57 | maven-plugin-api
58 | 2.0
59 |
60 |
61 | org.apache.maven.plugin-tools
62 | maven-plugin-annotations
63 | 3.2
64 | provided
65 |
66 |
67 | org.codehaus.plexus
68 | plexus-utils
69 | 3.0.24
70 |
71 |
72 | junit
73 | junit
74 | 4.13.1
75 | test
76 |
77 |
78 | org.apache.axis2
79 | axis2-kernel
80 | 1.3
81 | jar
82 | compile
83 |
84 |
85 | jakarta-httpcore-niossl
86 | httpcomponents-httpcore
87 |
88 |
89 | httpcore
90 | org.apache.httpcomponents
91 |
92 |
93 | org.apache.httpcomponents
94 | httpcore-niossl
95 |
96 |
97 | org.apache.httpcomponents
98 | httpcore-nio
99 |
100 |
101 | woden
102 | org.apache.woden
103 |
104 |
105 | log4j
106 | log4j
107 |
108 |
109 |
110 |
111 | org.apache.axis2
112 | axis2-metadata
113 | 1.3
114 | jar
115 | compile
116 |
117 |
118 | woden
119 | org.apache.woden
120 |
121 |
122 | log4j
123 | log4j
124 |
125 |
126 |
127 |
128 | com.google.http-client
129 | google-http-client
130 | 1.23.0
131 |
132 |
133 | com.google.http-client
134 | google-http-client-jackson
135 | 1.23.0
136 |
137 |
138 | com.google.code.gson
139 | gson
140 | 2.8.9
141 |
142 |
143 | org.apache.logging.log4j
144 | log4j-api
145 | ${log4j.version}
146 |
147 |
148 | org.apache.logging.log4j
149 | log4j-core
150 | ${log4j.version}
151 |
152 |
153 | org.eclipse.jgit
154 | org.eclipse.jgit
155 | 3.5.3.201412180710-r
156 |
157 |
158 |
159 | com.googlecode.json-simple
160 | json-simple
161 | 1.1.1
162 |
163 |
164 |
165 | org.springframework
166 | spring-core
167 | ${spring.version}
168 |
169 |
170 | org.springframework
171 | spring-context
172 | ${spring.version}
173 |
174 |
175 | org.springframework
176 | spring-web
177 | ${spring.version}
178 |
179 |
180 | cglib
181 | cglib
182 | 2.2.2
183 |
184 |
185 | org.yaml
186 | snakeyaml
187 | 2.0
188 |
189 |
190 | com.auth0
191 | java-jwt
192 | 3.1.0
193 |
194 |
195 |
196 | org.apache.commons
197 | commons-text
198 | 1.2
199 |
200 |
201 | com.fasterxml.jackson.core
202 | jackson-databind
203 | 2.13.4.2
204 |
205 |
206 |
207 |
208 |
209 |
210 | org.apache.maven.plugins
211 | maven-javadoc-plugin
212 | 2.10.2
213 |
214 |
215 | attach-javadocs
216 |
217 | jar
218 |
219 |
220 | -Xdoclint:none
221 |
222 |
223 |
224 |
225 |
226 | org.apache.maven.plugins
227 | maven-plugin-plugin
228 | 3.5
229 |
230 | apigee-smartdocs
231 | true
232 |
233 |
234 |
235 | mojo-descriptor
236 |
237 | descriptor
238 |
239 |
240 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 | run-its
254 |
255 |
256 |
257 | org.apache.maven.plugins
258 | maven-invoker-plugin
259 | 1.7
260 |
261 | true
262 | ${project.build.directory}/it
263 |
264 | */pom.xml
265 |
266 | verify
267 | ${project.build.directory}/local-repo
268 | src/it/settings.xml
269 |
270 | clean
271 | test-compile
272 |
273 |
274 |
275 |
276 | integration-test
277 |
278 | install
279 | integration-test
280 | verify
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 | default
290 |
291 | true
292 |
293 |
294 | ${org}
295 | ${env}
296 | ${username}
297 | ${password}
298 | true
299 |
300 |
301 |
302 | release-sign-artifacts
303 |
304 |
305 | performRelease
306 | true
307 |
308 |
309 |
310 | ${org}
311 | ${env}
312 | ${username}
313 | ${password}
314 | true
315 |
316 |
317 |
318 |
319 | org.apache.maven.plugins
320 | maven-source-plugin
321 |
322 |
323 | attach-sources
324 |
325 | jar
326 |
327 |
328 |
329 |
330 |
331 | org.apache.maven.plugins
332 | maven-javadoc-plugin
333 |
334 |
335 | attach-javadocs
336 |
337 | jar
338 |
339 |
340 |
341 |
342 |
343 | org.apache.maven.plugins
344 | maven-gpg-plugin
345 | 1.4
346 |
347 |
348 | sign-artifacts
349 | verify
350 |
351 | sign
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 |
360 |
361 |
362 |
--------------------------------------------------------------------------------
/samples/Drupal10/DevPortal/apicatalog-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "fields":{
3 | "field_image": "pets.jpeg",
4 | "field_api_product":[
5 | "demo"
6 | ]
7 | }
8 | }
--------------------------------------------------------------------------------
/samples/Drupal10/DevPortal/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | apigee
5 | parent-pom
6 | 1.0
7 | shared-pom.xml
8 |
9 | 4.0.0
10 | Apigee
11 | DeveloperPortal
12 | 1.0
13 | DeveloperPortal
14 | pom
15 |
16 |
17 | dev
18 |
19 | ${purl}
20 | ${pusername}
21 | ${ppassword}
22 | yaml
23 | basic_html
24 | ./specs
25 | ./apicatalog-config.json
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/samples/Drupal10/DevPortal/shared-pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | apigee
5 | parent-pom
6 | pom
7 | 1.0
8 |
9 |
10 | central
11 | Maven Plugin Repository
12 | https://repo1.maven.org/maven2
13 | default
14 |
15 | false
16 |
17 |
18 | never
19 |
20 |
21 |
22 |
24 |
25 |
26 |
27 | com.apigee.smartdocs.config
28 | apigee-smartdocs-maven-plugin
29 | 2.2.4
30 |
31 |
32 | smartdocs-deploy
33 | install
34 |
35 | apidoc
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | junit
45 | junit
46 | 4.8.2
47 | test
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/samples/Drupal10/DevPortal/specs/Petstore.yaml:
--------------------------------------------------------------------------------
1 | openapi: "3.0.0"
2 | info:
3 | version: 1.0.0
4 | title: Swagger Petstore
5 | description: Swagger Petstore Description
6 | license:
7 | name: MIT
8 | servers:
9 | - url: http://petstore.swagger.io/v1
10 | paths:
11 | /pets:
12 | get:
13 | summary: List all pets
14 | operationId: listPets
15 | tags:
16 | - pets
17 | parameters:
18 | - name: limit
19 | in: query
20 | description: How many items to return at one time (max 100)
21 | required: false
22 | schema:
23 | type: integer
24 | format: int32
25 | responses:
26 | '200':
27 | description: A paged array of pets
28 | headers:
29 | x-next:
30 | description: A link to the next page of responses
31 | schema:
32 | type: string
33 | content:
34 | application/json:
35 | schema:
36 | $ref: "#/components/schemas/Pets"
37 | default:
38 | description: unexpected error
39 | content:
40 | application/json:
41 | schema:
42 | $ref: "#/components/schemas/Error"
43 | post:
44 | summary: Create a pet
45 | operationId: createPets
46 | tags:
47 | - pets
48 | responses:
49 | '201':
50 | description: Null response
51 | default:
52 | description: unexpected error
53 | content:
54 | application/json:
55 | schema:
56 | $ref: "#/components/schemas/Error"
57 | /pets/{petId}:
58 | get:
59 | summary: Info for a specific pet
60 | operationId: showPetById
61 | tags:
62 | - pets
63 | parameters:
64 | - name: petId
65 | in: path
66 | required: true
67 | description: The id of the pet to retrieve
68 | schema:
69 | type: string
70 | responses:
71 | '200':
72 | description: Expected response to a valid request
73 | content:
74 | application/json:
75 | schema:
76 | $ref: "#/components/schemas/Pet"
77 | default:
78 | description: unexpected error
79 | content:
80 | application/json:
81 | schema:
82 | $ref: "#/components/schemas/Error"
83 | components:
84 | schemas:
85 | Pet:
86 | type: object
87 | required:
88 | - id
89 | - name
90 | properties:
91 | id:
92 | type: integer
93 | format: int64
94 | name:
95 | type: string
96 | tag:
97 | type: string
98 | Pets:
99 | type: array
100 | items:
101 | $ref: "#/components/schemas/Pet"
102 | Error:
103 | type: object
104 | required:
105 | - code
106 | - message
107 | properties:
108 | code:
109 | type: integer
110 | format: int32
111 | message:
112 | type: string
--------------------------------------------------------------------------------
/samples/Drupal10/DevPortal/specs/pets.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigee/apigee-smartdocs-maven-plugin/2d14d6b171419062a8d6880c53d54321a73ffec7/samples/Drupal10/DevPortal/specs/pets.jpeg
--------------------------------------------------------------------------------
/samples/Drupal10/README.md:
--------------------------------------------------------------------------------
1 | ------------
2 | Plugin Usage
3 | ------------
4 | ```
5 | mvn install -Pdev -Dapigee.smartdocs.config.options=create
6 |
7 | # Options
8 |
9 | -P
10 | Pick a profile in the parent pom.xml (shared-pom.xml in the example).
11 | Apigee org and env information comes from the profile.
12 |
13 | -Dapigee.smartdocs.config.options
14 | none - No action (default)
15 | create - Creates the doc found in the OpenAPI Spec directory
16 | update - Updates the doc found in the OpenAPI Spec directory
17 | delete - Deletes the doc found in the OpenAPI Spec directory
18 | sync - executes delete and update options mentioned above
19 |
20 | ```
21 |
22 |
23 | # Samples
24 |
25 | ## Prerequisites (Developer Portal setup)
26 | - This sample is for **Drupal 10 version of Developer portal**. The version of the plugin used in the pom **should be 2.x**
27 | - If you are using Drupal 7 version of Developer portal, please follow the instructions [here](https://github.com/apigee/apigee-smartdocs-maven-plugin/tree/master/samples/Drupal7)
28 | - To utilize this example, you will need a working developer portal instance with the [API Docs](https://www.drupal.org/docs/8/modules/apigee-api-catalog/expose-rest-apis-to-interact-with-api-docs#s-prerequisites) installed and enabled. That module will expose endpoints for use by the SmartDocs Maven Plugin.
29 | - For Apigee API Catalog 1.x module, use version 2.0.1 (Apigee API Catalog 1.x which is already deprecated)
30 | ```xml
31 |
32 | com.apigee.smartdocs.config
33 | apigee-smartdocs-maven-plugin
34 | 2.0.1
35 |
36 | ```
37 | - For Apigee API Catalog 2.x module, use version 2.1.0 or later
38 | ```xml
39 |
40 | com.apigee.smartdocs.config
41 | apigee-smartdocs-maven-plugin
42 | 2.1.0
43 |
44 | ```
45 |
46 | ## DevPortal
47 |
48 | ### Basic Implementation
49 |
50 | **Please ensure all prerequisites have been followed prior to continuing.**
51 |
52 | Goal: Import OpenAPI specs and create API Docs in the developer portal instance.
53 |
54 | ```
55 | /samples/DevPortal
56 | ```
57 |
58 | This project demonstrates use of apigee-smartdocs-maven-plugin to create API Docs using OpenAPI specs to a developer portal.
59 |
60 | To use, edit samples/DevPortal/pom.xml and update portal values as specified.
61 |
62 | ${purl}
63 | ${pusername}
64 | ${ppassword}
65 | yaml
66 | basic_html
67 | ${pdirectory}
68 |
69 | **NOTE:** Please provide the url of the developer portal without the trailing "/"
70 |
71 | To run, jump to the sample project `cd /samples/DevPortal` and run
72 |
73 | `mvn install -Pdev -Dapigee.smartdocs.config.options=create`
74 |
75 | ### Advanced Implementation (available on v2.1.0 or later)
76 |
77 | **To use these features make sure you have the Apigee API Catalog module version apigee_api_catalog 3.0.4 or higher. Please read through the [release notes](https://www.drupal.org/project/apigee_api_catalog/releases/3.0.4).**
78 |
79 | If you want to configure/manage fields and taxonomy, you can create a json file and pass that as `apigee.smartdocs.config.file` argument. A simple example below:
80 |
81 | **NOTE: The fields should be pre-configured on the API Doc content type in the portal**
82 |
83 | #### Sample
84 |
85 | 
86 |
87 | Types of fields supported :
88 | - Text (single or multivalued textfields or dropdowns)
89 | - Entity Reference (Taxonomy)
90 |
91 | To use Taxonomy reference fields make sure that you are using a term already defined in the Vocabulary. In the config file, we will need to specify the vocabulary name for every taxonomy field that is being used. Additionally we have to ensure that the JSONAPIs for the related taxonomy terms are enabled.
92 |
93 | 
94 |
95 | For example, the default Categories field on API Doc is associated with the "API Category" Vocabulary and has Data Append, Identity, Mobile, Payments , etc as acceptable term values.
96 |
97 | Here is a sample metadata file (apicatalog-config.json) :
98 |
99 | **NOTE: Support for API spec image is available from v2.1.2. Make sure the image is in the same folder as the spec and include the name of the file in the config file (see below)**
100 |
101 | ```
102 | {
103 | "fields":{
104 | "field_image": "pets.jpeg",
105 | "field_api_product":[
106 | "demo"
107 | ],
108 | "field_business_unit": "ABC",
109 | "field_multi_value":[
110 | "item1",
111 | "item2"
112 | ]
113 | },
114 | "taxonomy_terms":[
115 | {
116 | "vocabulary":"capability",
117 | "field":"field_capability",
118 | "data":[
119 | "Capability1",
120 | "Capability2"
121 | ]
122 | },
123 | {
124 | "vocabulary":"api_category",
125 | "field":"field_categories",
126 | "data":[
127 | "Mobile"
128 | ]
129 | }
130 | ]
131 | }
132 |
133 | ```
134 |
135 | NOTE: The fields and taxonomy should be pre-configured in the portal. Please provide the correct field, vocabulary names.
136 |
137 | `mvn install -Pdev -Dapigee.smartdocs.config.options=create -Dapigee.smartdocs.config.file=./apicatalog-config.json`
138 |
139 |
140 | ### Troubleshooting
141 |
142 | #### 404 Error
143 | Validate that the module is installed and enabled as described in the prerequisites. If you are still encountering errors, try downloading an app such as [Postman](https://www.getpostman.com/) and making a direct request to endpoints defined [here](https://www.drupal.org/docs/8/modules/apigee-api-catalog/expose-rest-apis-to-interact-with-api-docs#s-interacting-with-the-rest-api).
144 |
145 | #### Handshake_failure
146 | If you receive a handshake failure, it is likely an issue with TLS mismatch between your machine and the server. Add the following to the end of the `mvn install ...` line: `-Dhttps.protocols=TLSv1.2`
147 |
148 | e.g. `mvn install -Pdev -Dapigee.smartdocs.config.options=create -Dhttps.protocols=TLSv1.2`
149 |
--------------------------------------------------------------------------------
/samples/Drupal10/media/screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigee/apigee-smartdocs-maven-plugin/2d14d6b171419062a8d6880c53d54321a73ffec7/samples/Drupal10/media/screenshot1.png
--------------------------------------------------------------------------------
/samples/Drupal10/media/screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigee/apigee-smartdocs-maven-plugin/2d14d6b171419062a8d6880c53d54321a73ffec7/samples/Drupal10/media/screenshot2.png
--------------------------------------------------------------------------------
/samples/Drupal7/DevPortal/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | apigee
5 | parent-pom
6 | 1.0
7 | shared-pom.xml
8 |
9 | 4.0.0
10 | Apigee
11 | DeveloperPortal
12 | 1.0
13 | DeveloperPortal
14 | pom
15 |
16 |
17 | dev
18 |
19 | ${pusername}
20 | ${ppassword}
21 | ./specs
22 | ${purl}
23 | ${ppath}
24 | ${pcronkey}
25 | yaml
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/samples/Drupal7/DevPortal/shared-pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | apigee
5 | parent-pom
6 | pom
7 | 1.0
8 |
9 |
10 | central
11 | Maven Plugin Repository
12 | https://repo1.maven.org/maven2
13 | default
14 |
15 | false
16 |
17 |
18 | never
19 |
20 |
21 |
22 |
24 |
25 |
26 |
27 | com.apigee.smartdocs.config
28 | apigee-smartdocs-maven-plugin
29 | 1.0.5
30 |
45 |
61 |
62 |
63 | smartdocs-deploy
64 | install
65 |
66 | apimodel
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | junit
76 | junit
77 | 4.8.2
78 | test
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/samples/Drupal7/DevPortal/specs/mock.yaml:
--------------------------------------------------------------------------------
1 | swagger: '2.0'
2 | info:
3 | description: 'OpenAPI Specification for the Apigee mock target service endpoint. This is a "test" description'
4 | version: 1.0.0
5 | title: Mock Target API
6 | host: mocktarget.apigee.net
7 | schemes:
8 | - http
9 | - https
10 | securityDefinitions:
11 | basicAuth:
12 | type: basic
13 | description: HTTP Basic Authentication.
14 | paths:
15 | /:
16 | get:
17 | summary: View personalized greeting
18 | operationId: View a personalized greeting
19 | description: View a personalized greeting for the specified or guest user.
20 | produces:
21 | - text/plain
22 | parameters:
23 | - name: user
24 | in: query
25 | description: Your user name.
26 | required: false
27 | type: string
28 | responses:
29 | '200':
30 | description: Success
31 | /help:
32 | get:
33 | summary: Get help
34 | operationId: Get help
35 | description: View help information about available resources in HTML format.
36 | produces:
37 | - text/html
38 | responses:
39 | '200':
40 | description: Success
41 | /user:
42 | get:
43 | summary: View personalized greeting
44 | operationId: View personalized greeting
45 | description: View a personalized greeting for the specified or guest user.
46 | produces:
47 | - text/plain
48 | parameters:
49 | - name: user
50 | in: query
51 | description: Your user name.
52 | required: false
53 | type: string
54 | responses:
55 | '200':
56 | description: Success
57 | /iloveapis:
58 | get:
59 | summary: View API affirmation
60 | operationId: View API affirmation
61 | description: View API affirmation in HTML format.
62 | produces:
63 | - text/html
64 | responses:
65 | '200':
66 | description: Success
67 | /ip:
68 | get:
69 | summary: View IP address
70 | operationId: View IP address
71 | description: View the IP address of the client in JSON format.
72 | produces:
73 | - application/json
74 | responses:
75 | '200':
76 | description: Success
77 | /xml:
78 | get:
79 | summary: View XML response
80 | operationId: View XML response
81 | description: View a sample response in XML format.
82 | produces:
83 | - application/xml
84 | responses:
85 | '200':
86 | description: Success
87 | /json:
88 | get:
89 | summary: View JSON response
90 | operationId: View JSON response
91 | description: View a sample response in JSON format.
92 | produces:
93 | - application/json
94 | responses:
95 | '200':
96 | description: Success
97 | /echo:
98 | get:
99 | summary: View request headers and body
100 | operationId: View request headers and body
101 | description: View the request headers and body in JSON format.
102 | produces:
103 | - application/json
104 | responses:
105 | '200':
106 | description: Success
107 | post:
108 | summary: Send request and view request headers and body
109 | produces:
110 | - application/json
111 | - application/xml
112 | - application/x-www-form-urlencoded
113 | operationId: Send request and view request headers and body
114 | description: 'Send a request and view the resulting request headers and body in JSON format.
The request payload can be specified using one of the following formats: application/json, application/x-www-form-urlencoded, or application/xml.'
115 | parameters:
116 | - name: body
117 | in: body
118 | description: 'Request payload in application/json, application/x-www-form-urlencoded, or application/xml format.'
119 | required: true
120 | schema:
121 | $ref: '#/definitions/request-body'
122 | responses:
123 | '200':
124 | description: Success
125 | /statuscode/{code}:
126 | get:
127 | summary: View status code and message
128 | operationId: View status code and message
129 | description: View status code and message for the specified value.
130 | produces:
131 | - application/json
132 | parameters:
133 | - name: code
134 | in: path
135 | description: HTTP status code.
136 | required: true
137 | type: string
138 | responses:
139 | '200':
140 | description: Success
141 | /auth:
142 | get:
143 | security:
144 | - basicAuth: []
145 | summary: Validate access using basic authentication
146 | operationId: Validate access using basic authentication
147 | description: Validate access using basic authentication.
148 | produces:
149 | - application/json
150 | responses:
151 | '200':
152 | description: Success
153 | definitions:
154 | request-body:
155 | properties:
156 | replace-me:
157 | type: object
158 | description: 'Replace with request payload in application/json, application/x-www-form-urlencoded, or application/xml format.'
--------------------------------------------------------------------------------
/samples/Drupal7/README.md:
--------------------------------------------------------------------------------
1 | ------------
2 | Plugin Usage
3 | ------------
4 | ```
5 | mvn install -Pdev -Dapigee.smartdocs.config.options=create
6 |
7 | # Options
8 |
9 | -P
10 | Pick a profile in the parent pom.xml (shared-pom.xml in the example).
11 | Apigee org and env information comes from the profile.
12 |
13 | -Dapigee.smartdocs.config.options
14 | none - No action (default)
15 | create - Creates the model found in the OpenAPI Spec directory
16 | update - Updates the model found in the OpenAPI Spec directory
17 | delete - Deletes all models not found in the OpenAPI Spec directory
18 | deleteAPIModel - Deletes all models from dev portal found in the OpenAPI Spec directory (available on v1.0.4 or later)
19 | render - Renders the smart docs
20 | sync - executes the delete option (mentioned above) and recreates the models found in the OpenAPI Spec directory. This also renders the smart docs as well
21 |
22 | If you use create or update option, you will need to run the command again with option as render
23 | ```
24 |
25 |
26 | # Samples
27 |
28 | ## Prerequisites (Developer Portal setup)
29 |
30 | - This sample is for **Drupal 7 version of Developer portal**. The version of the plugin used in the pom **should be 1.x**
31 | - If you are using Drupal 10 version of Developer portal, please follow the instructions [here](https://github.com/apigee/apigee-smartdocs-maven-plugin/tree/master/samples/Drupal10)
32 | - To utilize this example, you will need a working developer portal instance with the [smartdocs_service module](https://github.com/apigeecs/smartdocs_service) installed and enabled. That module will expose endpoints for use by the SmartDocs Maven Plugin. For advanced configuration/setup please consult an expert. See [here](https://www.drupal.org/docs/7/extending-drupal-7/installing-drupal-7-contributed-modules#import_mod--manual) for more information on installing modules into the Developer Portal.
33 |
34 | When the module has been installed in the codebase, go to http://[yoursite.com]/admin/modules, select the smartdocs_service module and click "Save configuration". This will enable your module.
35 |
36 | When smartdocs_service module is installed and enabled, you should see 1 available service labeled smartdocs_service on the page located at http://[yoursite.com]/admin/structure/services.
37 |
38 | ### Service Listing
39 | 
40 |
41 | From this page, first, click the down arrow by "Edit Resources" and choose "Edit".
42 |
43 | ### Service Edit
44 |
45 | 
46 |
47 | Note the "Path to endpoint" field. The value set here is what we will set in the pom.xml as the "portal.path" value. You can change this value, so long as you note it for use in the pom.xml file
48 |
49 | You will need to change Authentication from "HTTP basic authentication" to "Session authentication as depicted in the image above.
50 |
51 | ### Resource Edit
52 |
53 | 
54 |
55 | Leave all smartdocs endpoints enabled. The Smartdocs Maven Plugin makes use of all but queue_status and index at present. DELETE and DO NOT ADD any aliases -- utilizing an alias will cause the system not to function.
56 |
57 | 
58 |
59 | Enable the user login endpoint. This will us to authenticate against the system and perform updates.
60 |
61 | Note that it is recommended that you create a special user for the integration and limit the permissions of the user accordingly.
62 |
63 | ### Resource Edit (Advanced implementation)
64 |
65 | If you plan to followed the advanced implementation model and import metadata with your models, you will need to enable the taxonomy_term update endpoint and the retrieveMachineName and getTree endpoints as depicted in the image below.
66 |
67 | 
68 |
69 |
70 | ## DevPortal
71 |
72 | ### Basic Implementation (Model import)
73 |
74 | **Please ensure all prerequisites have been followed prior to continuing.**
75 |
76 | Goal: Create models and import OpenAPI specs to a developer portal instance.
77 |
78 | ```
79 | /samples/DevPortal
80 | ```
81 |
82 | This project demonstrates use of apigee-smartdocs-maven-plugin to create models and import OpenAPI specs to a developer portal. The example project performs a data import defined in pom.xml
83 |
84 | To use, edit samples/DevPortal/pom.xml and update portal values as specified.
85 |
86 | ${pusername}
87 | ${ppassword}
88 | ${pdirectory}
89 | ${purl}
90 | ${ppath}
91 | json
92 |
93 | To run, jump to the sample project `cd /samples/DevPortal` and run
94 |
95 | `mvn install -Pdev -Dapigee.smartdocs.config.options=create`
96 |
97 |
98 | ### Advanced Implementation (Model metadata import)
99 |
100 | **Please ensure the prerequisites and basic implementation have been followed prior to continuing.**
101 |
102 | Goal: Add field data to models in a developer portal instance.
103 |
104 | ```
105 | /samples/DevPortal
106 | ```
107 |
108 | This project demonstrates use of apigee-smartdocs-maven-plugin to add field data to a model in a developer portal. The example project performs a data import defined in shared-pom.xml
109 |
110 | To use, edit samples/DevPortal/shared-pom.xml, uncomment, and update portal values as needed.
111 |
112 |
113 | ${model_vocabulary}
114 |
115 |
116 | contact|company
117 | field_company
118 |
119 |
120 |
121 |
122 | The path value signifies the path to data stored within the info object.
123 | The pipe character can be used to traverse into sub-items. For instance, with a OpenAPI document containing { "info": { "contact": { "company": "Google" } } }, you could be access the data by setting the path to contact|company.
124 | In the example above, "Google" would be mapped to the field_company field within the model related to the OpenAPI document definition.
125 |
126 | Example of a field_company value set within the OpenApi specification:
127 | 
128 |
129 | Before using, you will need to create fields on the smartdocs_model taxonomy page within the developer portal. field_company would relate to a field your create on the page located at http://[yoursite.com]/admin/structure/taxonomy/smartdocs_models/fields. Note that the current sytem currently only supports the Field type of "Text".
130 | 
131 |
132 | To run jump to samples project `cd /samples/DevPortal` and run
133 |
134 | `mvn install -Pdev -Dapigee.smartdocs.config.options=create`
135 |
136 | #### Configuring the model name on the Developer Portal (Optional)
137 |
138 | The default model name without this configuration is the title field from the info object.
139 |
140 | If you would like to configure the model name of the SmartDoc on the developer portal, you can use additional fields from the OpenAPI specification. The default model name is based on the title.
141 |
142 | In order to configure it to generate a unique model name, you will need to specify the format in the shared-pom.xml
143 |
144 |
145 | ...
146 | contact|x-country^title
147 | ...
148 |
149 |
150 | The caret symbol (^) is used to separate which fields you want extracted from the info object and it will be replaced with dash (-) in the name
151 |
152 | Additionally, spaces and periods are converted to dashes
153 |
154 | The example config above would generate a model name based on the info object OpenAPI document. For instance, an OpenAPI document containing:
155 | ```json
156 | {
157 | "info": {
158 | "title": "Hello World API",
159 | "contact": {
160 | "x-country": "Canada"
161 | }
162 | }
163 | }
164 | ```
165 | The model name would be `Canada-Hello-World-API`
166 |
167 | ### Troubleshooting
168 |
169 | #### 404 Error
170 | Validate that the module is installed and enabled and that resource endpoints are set as described in the prerequisites. If you are still encountering errors, try downloading an app such as [Postman](https://www.getpostman.com/) and making a direct request to endpoints defined on the service endpoint page.
171 |
172 | #### Handshake_failure
173 | If you receive a handshake failure, it is likely an issue with TLS mismatch between your machine and the server. Add the following to the end of the `mvn install ...` line: `-Dhttps.protocols=TLSv1.2`
174 |
175 | e.g. `mvn install -Pdev -Dapigee.smartdocs.config.options=create -Dhttps.protocols=TLSv1.2`
176 |
177 | #### Render error
178 | While the system is capable of telling the Developer Portal to "render" the content - making them visible to end users - the Developer Portal will not render the content until after a "cron" run has occurred. If you believe the content should be rendered and it has not, please validate that cron has run
179 |
--------------------------------------------------------------------------------
/samples/Drupal7/images/Fake-Company.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigee/apigee-smartdocs-maven-plugin/2d14d6b171419062a8d6880c53d54321a73ffec7/samples/Drupal7/images/Fake-Company.png
--------------------------------------------------------------------------------
/samples/Drupal7/images/Field-Company.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigee/apigee-smartdocs-maven-plugin/2d14d6b171419062a8d6880c53d54321a73ffec7/samples/Drupal7/images/Field-Company.png
--------------------------------------------------------------------------------
/samples/Drupal7/images/Service-Edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigee/apigee-smartdocs-maven-plugin/2d14d6b171419062a8d6880c53d54321a73ffec7/samples/Drupal7/images/Service-Edit.png
--------------------------------------------------------------------------------
/samples/Drupal7/images/Service-Endpoints-Advanced.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigee/apigee-smartdocs-maven-plugin/2d14d6b171419062a8d6880c53d54321a73ffec7/samples/Drupal7/images/Service-Endpoints-Advanced.png
--------------------------------------------------------------------------------
/samples/Drupal7/images/Service-Endpoints-User.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigee/apigee-smartdocs-maven-plugin/2d14d6b171419062a8d6880c53d54321a73ffec7/samples/Drupal7/images/Service-Endpoints-User.png
--------------------------------------------------------------------------------
/samples/Drupal7/images/Service-Endpoints.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigee/apigee-smartdocs-maven-plugin/2d14d6b171419062a8d6880c53d54321a73ffec7/samples/Drupal7/images/Service-Endpoints.png
--------------------------------------------------------------------------------
/samples/Drupal7/images/Service-Listing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigee/apigee-smartdocs-maven-plugin/2d14d6b171419062a8d6880c53d54321a73ffec7/samples/Drupal7/images/Service-Listing.png
--------------------------------------------------------------------------------
/samples/README.md:
--------------------------------------------------------------------------------
1 | # Samples
2 |
3 | - [Drupal 7](https://github.com/apigee/apigee-smartdocs-maven-plugin/tree/master/samples/Drupal7)
4 | - [Drupal 10](https://github.com/apigee/apigee-smartdocs-maven-plugin/tree/master/samples/Drupal10)
--------------------------------------------------------------------------------
/src/main/java/com/apigee/smartdocs/config/mavenplugin/APIDocsMojo.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2019 Google Inc.
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 | * http://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 |
17 | package com.apigee.smartdocs.config.mavenplugin;
18 |
19 | import java.io.File;
20 | import java.io.FilenameFilter;
21 | import java.io.IOException;
22 |
23 | import org.apache.maven.plugin.MojoExecutionException;
24 | import org.apache.maven.plugin.MojoFailureException;
25 | import org.apache.logging.log4j.LogManager;
26 | import org.apache.logging.log4j.Logger;
27 | import com.apigee.smartdocs.config.rest.PortalRestUtil;
28 | import com.apigee.smartdocs.config.utils.ServerProfile;
29 |
30 | /** ¡¡
31 | * Goal to create API Docs in Apigee Developer Portal
32 | * scope: org
33 | *
34 | * @author ssvaidyanathan
35 | * @goal apidoc
36 | * @phase install
37 | */
38 |
39 | public class APIDocsMojo extends PortalAbstractMojo {
40 | static Logger logger = LogManager.getLogger(APIDocsMojo.class);
41 | private static File[] files = null;
42 |
43 | public static final String ____ATTENTION_MARKER____ =
44 | "************************************************************************";
45 |
46 | enum OPTIONS {
47 | none, create, update, delete, sync
48 | }
49 |
50 | OPTIONS buildOption = OPTIONS.none;
51 |
52 | private ServerProfile serverProfile;
53 |
54 | /**
55 | * Constructor.
56 | */
57 | public APIDocsMojo() {
58 | super();
59 | }
60 |
61 | public void init() throws MojoExecutionException, MojoFailureException {
62 | try {
63 | logger.info(____ATTENTION_MARKER____);
64 | logger.info("API Docs");
65 | logger.info(____ATTENTION_MARKER____);
66 |
67 | String options="";
68 | serverProfile = super.getProfile();
69 |
70 | options = super.getOptions();
71 | if (options != null) {
72 | buildOption = OPTIONS.valueOf(options);
73 | }
74 | if (buildOption == OPTIONS.none) {
75 | logger.info("Skipping APIDoc (default action)");
76 | return;
77 | }
78 |
79 | logger.debug("Build option " + buildOption.name());
80 |
81 | if (serverProfile.getPortalURL() == null) {
82 | throw new MojoExecutionException(
83 | "Developer portal URL not found in profile");
84 | }
85 | if (serverProfile.getPortalURL() != null && serverProfile.getPortalURL().endsWith("/")) {
86 | throw new MojoExecutionException(
87 | "Please provide the url of the developer portal without the trailing \"/\"");
88 | }
89 | if (serverProfile.getPortalUserName() == null) {
90 | throw new MojoExecutionException(
91 | "Developer portal username not found in profile");
92 | }
93 | if (serverProfile.getPortalPassword() == null) {
94 | throw new MojoExecutionException(
95 | "Developer portal password not found in profile");
96 | }
97 | if (serverProfile.getPortalFormat() == null) {
98 | throw new MojoExecutionException(
99 | "Developer portal file format not found in profile");
100 | }
101 | if (serverProfile.getPortalAPIDocFormat() == null) {
102 | throw new MojoExecutionException(
103 | "Developer portal API Doc format not found in profile");
104 | }
105 |
106 | // Scan to make sure there are swagger files to send.
107 | getOpenAPISpecs();
108 |
109 | } catch (IllegalArgumentException e) {
110 | throw new RuntimeException("Invalid apigee.option provided");
111 | } catch (RuntimeException e) {
112 | throw e;
113 | } catch (MojoExecutionException e) {
114 | throw e;
115 | }
116 |
117 | }
118 |
119 | /**
120 | * Entry point for the mojo.
121 | */
122 | public void execute() throws MojoExecutionException, MojoFailureException {
123 | if (super.isSkip()) {
124 | getLog().info("Skipping");
125 | return;
126 | }
127 |
128 | try {
129 | init();
130 | if (buildOption == OPTIONS.none) {
131 | return;
132 | }
133 |
134 | if (buildOption == OPTIONS.create){
135 | doUpdate(true);
136 | }
137 |
138 | if (buildOption == OPTIONS.update) {
139 | doUpdate(false);
140 | }
141 |
142 | if (buildOption == OPTIONS.delete) {
143 | doDelete();
144 | }
145 |
146 | if (buildOption == OPTIONS.sync) {
147 | doDelete();
148 | doUpdate(true);
149 | }
150 |
151 | } catch (MojoFailureException e) {
152 | throw e;
153 | } catch (RuntimeException e) {
154 | throw e;
155 | }
156 | }
157 |
158 | /**
159 | * Posts an update based on available OpenAPI specs. Will update base
160 | * information, then upload the current OpenAPI spec.
161 | * @throws MojoExecutionException
162 | */
163 | public void doUpdate(boolean isCreate) throws MojoExecutionException {
164 | try {
165 | for (File file : files) {
166 | PortalRestUtil.postAPIDoc(serverProfile, file, isCreate);
167 | }
168 | }
169 | catch (IOException e) {
170 | throw new RuntimeException("Update failure: " + e.getMessage());
171 | }
172 | }
173 |
174 | /**
175 | * Deletes API Doc that exist in the API and not in the file system.
176 | * @throws MojoExecutionException
177 | */
178 | public void doDelete() throws MojoExecutionException {
179 | try {
180 | for (File file : files) {
181 | PortalRestUtil.deleteAPIDoc(serverProfile, file);
182 | }
183 | }
184 | catch (IOException e) {
185 | throw new RuntimeException("Delete failure: " + e.getMessage());
186 | }
187 | }
188 |
189 | /**
190 | * Pulls a list of OpenAPI specs frpm a directory to be sent
191 | * to a Developer Portal instance.
192 | *
193 | * @throws MojoExecutionException
194 | */
195 | public void getOpenAPISpecs() throws MojoExecutionException {
196 | // Ensure we have a directory to read.
197 | if (serverProfile.getPortalDirectory() == null) {
198 | throw new MojoExecutionException(
199 | "Developer portal directory not found in profile");
200 | }
201 |
202 | // Scan the directory for files.
203 | String directory = serverProfile.getPortalDirectory();
204 | logger.info("Get OpenAPI Specs from " + directory);
205 | files = new File(directory).listFiles(new FilenameFilter() {
206 | @Override
207 | public boolean accept(File dir, String name) {
208 | return name.endsWith(".yaml") || name.endsWith(".yml") || name.endsWith(".json");
209 | }
210 | });
211 | }
212 | }
213 |
214 |
215 |
216 |
217 |
--------------------------------------------------------------------------------
/src/main/java/com/apigee/smartdocs/config/mavenplugin/PortalAbstractMojo.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc.
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 | * http://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 |
17 | package com.apigee.smartdocs.config.mavenplugin;
18 |
19 | import java.io.File;
20 | import java.util.Map;
21 | import org.apache.maven.plugin.AbstractMojo;
22 | import com.apigee.smartdocs.config.utils.ServerProfile;
23 | import com.apigee.smartdocs.config.utils.PortalField;
24 |
25 | public abstract class PortalAbstractMojo extends AbstractMojo {
26 |
27 | /**
28 | * Directory containing the build files.
29 | *
30 | * @parameter property="project.build.directory"
31 | */
32 | private File buildDirectory;
33 |
34 | /**
35 | * Base directory of the project.
36 | *
37 | * @parameter property="basedir"
38 | */
39 | private File baseDirectory;
40 |
41 | /**
42 | * Project Name
43 | *
44 | * @parameter property="project.name"
45 | */
46 | private String projectName;
47 |
48 | /**
49 | * Project version
50 | *
51 | * @parameter property="project.version"
52 | */
53 | private String projectVersion;
54 |
55 | /**
56 | * Project artifact id
57 | *
58 | * @parameter property="project.artifactId"
59 | */
60 | private String artifactId;
61 |
62 | /**
63 | * Profile id
64 | *
65 | * @parameter property="apigee.profile"
66 | */
67 | private String id;
68 |
69 | /**
70 | * Build option
71 | *
72 | * @parameter property="build.option"
73 | */
74 | private String buildOption;
75 |
76 | /**
77 | * Gateway options
78 | *
79 | * @parameter property="apigee.smartdocs.config.options"
80 | */
81 | private String options;
82 |
83 | /**
84 | * Config File
85 | *
86 | * @parameter property="apigee.smartdocs.config.file"
87 | */
88 | private String configFile;
89 |
90 | /**
91 | * Portal User Name
92 | *
93 | * @parameter property="portal.username"
94 | */
95 | private String portalUserName;
96 |
97 | /**
98 | * Portal Password
99 | *
100 | * @parameter property="portal.password"
101 | */
102 | private String portalPassword;
103 |
104 | /**
105 | * OpenAPI Spec Directory
106 | *
107 | * @parameter property="portal.directory"
108 | */
109 | private String portalDirectory;
110 |
111 | /**
112 | * Portal URL
113 | *
114 | * @parameter property="portal.url"
115 | */
116 | private String portalURL;
117 |
118 | /**
119 | * Portal Path
120 | *
121 | * @parameter property="portal.path"
122 | */
123 | private String portalPath;
124 |
125 | /**
126 | * Portal Format
127 | *
128 | * @parameter property="portal.format"
129 | */
130 | private String portalFormat;
131 |
132 | /**
133 | * Portal Format
134 | *
135 | * @parameter alias="portal.model.vocabulary"
136 | */
137 | private String portalModelVocabulary;
138 |
139 | /**
140 | * Portal Model Fields
141 | *
142 | * @parameter alias="portal.model.fields"
143 | */
144 | private Map portalModelFields;
145 |
146 | /**
147 | * Portal Cron Key
148 | *
149 | * @parameter property="portal.cronkey"
150 | */
151 | private String portalCronKey;
152 |
153 | /**
154 | * Portal Model Name Config
155 | *
156 | * @parameter alias="portal.model.config.name"
157 | */
158 | private String portalModelNameConfig;
159 |
160 | /**
161 | * Portal API Doc Format
162 | *
163 | * @parameter property="portal.api.doc.format"
164 | */
165 | private String portalAPIDocFormat;
166 |
167 | /**
168 | * Skip running this plugin. Default is false.
169 | *
170 | * @parameter default-value="false"
171 | */
172 | private boolean skip = false;
173 |
174 | public ServerProfile buildProfile;
175 |
176 | public PortalAbstractMojo() {
177 | super();
178 | }
179 |
180 | public ServerProfile getProfile() {
181 | this.buildProfile = new ServerProfile();
182 | this.buildProfile.setOptions(this.options);
183 | this.buildProfile.setConfigFile(this.configFile);
184 | this.buildProfile.setPortalUserName(this.portalUserName);
185 | this.buildProfile.setPortalPassword(this.portalPassword);
186 | this.buildProfile.setPortalDirectory(this.portalDirectory);
187 | this.buildProfile.setPortalURL(this.portalURL);
188 | this.buildProfile.setPortalPath(this.portalPath);
189 | this.buildProfile.setPortalFormat(this.portalFormat);
190 | this.buildProfile.setPortalModelFields(this.portalModelFields);
191 | this.buildProfile.setPortalModelVocabulary(this.portalModelVocabulary);
192 | this.buildProfile.setPortalCronKey(this.portalCronKey);
193 | this.buildProfile.setPortalModelNameConfig(this.portalModelNameConfig);
194 | this.buildProfile.setPortalAPIDocFormat(this.portalAPIDocFormat);
195 | return buildProfile;
196 | }
197 |
198 | public void setProfile(ServerProfile profile) {
199 | this.buildProfile = profile;
200 | }
201 |
202 | public void setBaseDirectory(File baseDirectory) {
203 | this.baseDirectory = baseDirectory;
204 | }
205 |
206 | public String getBuildDirectory() {
207 | return this.buildDirectory.getAbsolutePath();
208 | }
209 |
210 | public String getBaseDirectoryPath() {
211 | return this.baseDirectory.getAbsolutePath();
212 | }
213 |
214 | public String getBuildOption() {
215 | return buildOption;
216 | }
217 |
218 | public void setBuildOption(String buildOption) {
219 | this.buildOption = buildOption;
220 | }
221 |
222 | public String getOptions() {
223 | return options;
224 | }
225 |
226 | public void setOptions(String options) {
227 | this.options = options;
228 | }
229 |
230 | public void setConfigFile(String configFile) {
231 | this.configFile = configFile;
232 | }
233 |
234 | public String getConfigFile() {
235 | return configFile;
236 | }
237 |
238 | /**
239 | * @return the id
240 | */
241 | public String getId() {
242 | return id;
243 | }
244 |
245 | /**
246 | * @param id the id to set
247 | */
248 | public void setId(String id) {
249 | this.id = id;
250 | }
251 |
252 | public boolean isSkip() {
253 | return skip;
254 | }
255 |
256 | public void setSkip(boolean skip) {
257 | this.skip = skip;
258 | }
259 |
260 | }
261 |
--------------------------------------------------------------------------------
/src/main/java/com/apigee/smartdocs/config/rest/FakeHostnameVerifier.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc.
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 | * http://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 |
17 | package com.apigee.smartdocs.config.rest;
18 |
19 | import java.io.IOException;
20 | import java.security.cert.X509Certificate;
21 |
22 | import javax.net.ssl.SSLException;
23 | import javax.net.ssl.SSLSession;
24 | import javax.net.ssl.SSLSocket;
25 |
26 | import org.apache.axis2.transport.nhttp.HostnameVerifier;
27 |
28 | public class FakeHostnameVerifier implements HostnameVerifier {
29 |
30 | public void check(String arg0, SSLSocket arg1) throws IOException {
31 | // TODO Auto-generated method stub
32 |
33 | }
34 |
35 | public void check(String arg0, X509Certificate arg1) throws SSLException {
36 | // TODO Auto-generated method stub
37 |
38 | }
39 |
40 | public void check(String[] arg0, SSLSocket arg1) throws IOException {
41 | // TODO Auto-generated method stub
42 |
43 | }
44 |
45 | public void check(String[] arg0, X509Certificate arg1) throws SSLException {
46 | // TODO Auto-generated method stub
47 |
48 | }
49 |
50 | public void check(String arg0, String[] arg1, String[] arg2)
51 | throws SSLException {
52 | // TODO Auto-generated method stub
53 |
54 | }
55 |
56 | public void check(String[] arg0, String[] arg1, String[] arg2)
57 | throws SSLException {
58 | // TODO Auto-generated method stub
59 |
60 | }
61 |
62 | public boolean verify(String arg0, SSLSession arg1) {
63 | // TODO Auto-generated method stub
64 | return true;
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/com/apigee/smartdocs/config/rest/PortalRestUtil.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright 2017 Google Inc.
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 | * http://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 |
17 | package com.apigee.smartdocs.config.rest;
18 |
19 | import java.io.File;
20 | import java.io.FileNotFoundException;
21 | import java.io.IOException;
22 | import java.io.InputStream;
23 | import java.io.InputStreamReader;
24 | import java.io.Reader;
25 | import java.io.StringReader;
26 | import java.nio.file.Files;
27 | import java.util.ArrayList;
28 | import java.util.HashMap;
29 | import java.util.Iterator;
30 | import java.util.List;
31 | import java.util.Map;
32 |
33 | import javax.net.ssl.HttpsURLConnection;
34 |
35 | import org.apache.commons.text.StringEscapeUtils;
36 | import org.apache.logging.log4j.LogManager;
37 | import org.apache.logging.log4j.Logger;
38 | import org.json.simple.JSONValue;
39 | import org.yaml.snakeyaml.Yaml;
40 |
41 | import com.apigee.smartdocs.config.utils.ServerProfile;
42 | import com.fasterxml.jackson.databind.ObjectMapper;
43 | import com.google.api.client.http.ByteArrayContent;
44 | import com.google.api.client.http.FileContent;
45 | import com.google.api.client.http.GenericUrl;
46 | import com.google.api.client.http.HttpHeaders;
47 | import com.google.api.client.http.HttpMethods;
48 | import com.google.api.client.http.HttpRequest;
49 | import com.google.api.client.http.HttpRequestFactory;
50 | import com.google.api.client.http.HttpRequestInitializer;
51 | import com.google.api.client.http.HttpResponse;
52 | import com.google.api.client.http.HttpResponseException;
53 | import com.google.api.client.http.HttpTransport;
54 | import com.google.api.client.http.apache.ApacheHttpTransport;
55 | import com.google.api.client.http.javanet.NetHttpTransport;
56 | import com.google.api.client.json.JsonFactory;
57 | import com.google.api.client.json.jackson.JacksonFactory;
58 | import com.google.api.client.util.Key;
59 | import com.google.gson.Gson;
60 | import com.google.gson.JsonArray;
61 | import com.google.gson.JsonObject;
62 | import com.google.gson.internal.LinkedTreeMap;
63 |
64 | public class PortalRestUtil {
65 |
66 | static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
67 | static final HttpTransport APACHE_HTTP_TRANSPORT = new ApacheHttpTransport();
68 | static final JsonFactory JSON_FACTORY = new JacksonFactory();
69 | static String versionRevision;
70 | static Logger logger = LogManager.getLogger(PortalRestUtil.class);
71 | static String accessToken = null;
72 |
73 | static HttpRequestFactory REQUEST_FACTORY = HTTP_TRANSPORT
74 | .createRequestFactory(new HttpRequestInitializer() {
75 | // @Override
76 | public void initialize(HttpRequest request) {
77 | request.setParser(JSON_FACTORY.createJsonObjectParser());
78 | XTrustProvider.install();
79 | FakeHostnameVerifier _hostnameVerifier = new FakeHostnameVerifier();
80 | // Install the all-trusting host name verifier:
81 | HttpsURLConnection.setDefaultHostnameVerifier(_hostnameVerifier);
82 | }
83 | });
84 |
85 | static HttpRequestFactory APACHE_REQUEST_FACTORY = APACHE_HTTP_TRANSPORT
86 | .createRequestFactory(new HttpRequestInitializer() {
87 | // @Override
88 | public void initialize(HttpRequest request) {
89 | request.setParser(JSON_FACTORY.createJsonObjectParser());
90 | XTrustProvider.install();
91 | FakeHostnameVerifier _hostnameVerifier = new FakeHostnameVerifier();
92 | // Install the all-trusting host name verifier:
93 | HttpsURLConnection.setDefaultHostnameVerifier(_hostnameVerifier);
94 | }
95 | });
96 |
97 |
98 | // Header values to ensure headers are set and then stored.
99 | public static Boolean headersSet = false;
100 | public static HttpHeaders headers = null;
101 |
102 | // Class to handle our authentication response.
103 | public static class AuthObject {
104 |
105 | @Key
106 | public String token;
107 | public String sessid;
108 | public String session_name;
109 | }
110 |
111 | public static class SpecObject {
112 |
113 | public LinkedTreeMap info;
114 |
115 | public String getName(String portalModelNameConfig) {
116 | if(portalModelNameConfig == null) {
117 | return info.get("title").toString().replace(" ", "-");
118 | } else {
119 | return getConfigModelName(portalModelNameConfig);
120 | }
121 | }
122 |
123 | private String getConfigModelName(String portalModelNameConfig) {
124 | //default return
125 | String returnString = getName(null);
126 | if(portalModelNameConfig == null) {
127 | return returnString;
128 | }
129 | //Generate Model Name From Config
130 | ArrayList al = new ArrayList();
131 | String[] nameParts = portalModelNameConfig.split("\\^");
132 | LinkedTreeMap jo = info;
133 | for (String namePart : nameParts) {
134 | //Reset head of tree to info
135 | jo = info;
136 | //Split each config name into model information
137 | String[] namePartPaths = namePart.split("\\|");
138 | for (String namePartPath : namePartPaths) {
139 | // Only traverse down if the key exists.
140 | if (jo.containsKey(namePartPath)) {
141 | Object o = jo.get(namePartPath);
142 | // If we still need to go deeper, we have a tree.
143 | if (o instanceof LinkedTreeMap) {
144 | jo = (LinkedTreeMap) o;
145 | } else {
146 | // Otherwise, store the value in our ArrayList
147 | al.add(o.toString().replace(".", "-").replace(" ","-"));
148 | }
149 | }
150 | }
151 | }
152 | if(al.isEmpty()) {
153 | return returnString;
154 | }
155 | returnString = "";
156 | Iterator it = al.iterator();
157 | while (it.hasNext()) {
158 | String namePart = (String) it.next();
159 | returnString += namePart;
160 | //Separate fields with dash
161 | if(it.hasNext()) {
162 | returnString += "-";
163 | }
164 | }
165 | //Clean the return string to only include Alphanumeric characters and the dash character
166 | returnString = returnString.replaceAll("[^A-Za-z0-9-]","");
167 | //set Max length to be 255
168 | if(returnString.length() > 255) {
169 | returnString = returnString.substring(0,255);
170 | }
171 | logger.debug("API Model Name: " + returnString);
172 | return returnString;
173 | }
174 |
175 | public String getTitle() {
176 | return info.get("title").toString();
177 | }
178 |
179 | public String getDescription() {
180 | if (info.get("description") != null) {
181 | return info.get("description").toString();
182 | }
183 | return "";
184 | }
185 |
186 | @Override
187 | public String toString() {
188 | return "(SpecObject) Name: " + getName(null) + "; Title: " + getTitle();
189 | }
190 | }
191 |
192 |
193 | public static class APIDocResponseObject {
194 |
195 | public JSONAPI jsonapi;
196 | public List data;
197 | public Object links;
198 | }
199 |
200 | public static class APIDocObject {
201 | public JSONAPI jsonapi;
202 | public Data data;
203 | public Object links;
204 | }
205 |
206 | public static class ImageDocObject {
207 | public JSONAPI jsonapi;
208 | public Data data;
209 | public Object links;
210 | }
211 |
212 | public static class APIErrorObject {
213 | public JSONAPI jsonapi;
214 | public List errors;
215 | }
216 |
217 | public static class JSONAPI {
218 | public String version;
219 | public Object meta;
220 | }
221 |
222 | public static class Error{
223 | public String title;
224 | public String status;
225 | public String detail;
226 | }
227 |
228 | public static class Data {
229 | public String type;
230 | public String id;
231 | public Attributes attributes;
232 | public Relationships relationships;
233 | public Object links;
234 | }
235 |
236 | public static class Attributes {
237 | public boolean status;
238 | public String title;
239 | public String name;
240 | public Body body;
241 | public String field_apidoc_spec_file_source;
242 | public Object relationships;
243 | public FileLink file_link;
244 | public Object links;
245 | }
246 |
247 | public static class Body{
248 | public String value;
249 | public String format;
250 | }
251 |
252 | public static class Relationships{
253 | public Relationships_Spec field_apidoc_spec;
254 | public Relationships_Spec field_image;
255 | }
256 |
257 | public static class Relationships_Data{
258 | public String type;
259 | public String id;
260 | }
261 |
262 | public static class Relationships_Spec{
263 | public Relationships_Data data;
264 | }
265 |
266 | public static class FileLink{
267 | public String uri;
268 | }
269 |
270 | // Get headers that have been set.
271 | public static HttpHeaders getHeaders() {
272 | return headers;
273 | }
274 |
275 | // Store/update headers.
276 | public static HttpHeaders setHeaders(HttpHeaders tempHeaders) {
277 | headers = tempHeaders;
278 | return headers;
279 | }
280 |
281 | /**
282 | * Authenticate against the Developer portal and set necessary headers to
283 | * facilitate additional transactions.
284 | */
285 | public static HttpResponse authenticate(ServerProfile profile) throws IOException {
286 | HttpResponse response = null;
287 | if (headersSet == false) {
288 | String payload = "{\"username\": \"" + profile.getPortalUserName()
289 | + "\", \"password\":\"" + profile.getPortalPassword() + "\"}";
290 | ByteArrayContent content = new ByteArrayContent("application/json",
291 | payload.getBytes());
292 |
293 | HttpRequest restRequest = REQUEST_FACTORY
294 | .buildPostRequest(new GenericUrl(
295 | profile.getPortalURL() + "/" + profile.getPortalPath()
296 | + "/user/login.json"), content);
297 | restRequest.setReadTimeout(0);
298 |
299 | try {
300 | // Call execute directly since we don't have headers yet.
301 | response = restRequest.execute();
302 |
303 | InputStream source = response.getContent(); //Get the data in the entity
304 | Reader reader = new InputStreamReader(source);
305 |
306 | Gson gson = new Gson();
307 | AuthObject auth = gson.fromJson(reader, AuthObject.class);
308 | headersSet = true;
309 |
310 | HttpHeaders tempHeaders = new HttpHeaders();
311 | tempHeaders.setCookie(auth.session_name + "=" + auth.sessid);
312 | tempHeaders.set("X-CSRF-Token", auth.token);
313 | setHeaders(tempHeaders);
314 |
315 | } catch (HttpResponseException e) {
316 | logger.error(e.getMessage());
317 | // Throw an error as there is no point in continuing.
318 | throw e;
319 | }
320 | }
321 |
322 | return response;
323 | }
324 |
325 |
326 | /**
327 | * Run Cron
328 | */
329 | public static void runCron(ServerProfile profile) throws IOException {
330 | try {
331 | // First authenticate.
332 | authenticate(profile);
333 |
334 | HttpRequest restRequest = REQUEST_FACTORY
335 | .buildGetRequest(new GenericUrl(profile.getPortalURL() + "/cron.php?cron_key="+ profile.getPortalCronKey()));
336 | restRequest.setReadTimeout(0);
337 | logger.info("Running Cron");
338 |
339 | PortalRestUtil.executeRequest(restRequest);
340 | } catch (HttpResponseException e) {
341 | throw e;
342 | }
343 | }
344 |
345 |
346 | /**
347 | * Helper function to build the body for API Doc creations and updates.
348 | */
349 | private static ByteArrayContent constructAPIDocRequestBody(ServerProfile profile, SpecObject spec, String uuid, String docId, String imageId, boolean isUpdate) throws IOException {
350 | boolean hasImage = false;
351 | boolean hasAPIProducts = false;
352 | File imageFile = null;
353 | List apiProducts = null;
354 | Gson gson = new Gson();
355 | JsonObject body = new JsonObject();
356 | if (spec.getDescription() != null) {
357 | body.addProperty("value", StringEscapeUtils.escapeJava(spec.getDescription()));
358 | }
359 | body.addProperty("format", profile.getPortalAPIDocFormat());
360 |
361 | JsonObject attributes = new JsonObject();
362 | attributes.addProperty("status", true);
363 | attributes.addProperty("title", spec.getTitle());
364 | attributes.add("body", body);
365 | attributes.addProperty("field_apidoc_spec_file_source", "file");
366 |
367 | JsonObject relationships = new JsonObject();
368 |
369 | //config
370 | if(profile.getConfigFile()!=null && !profile.getConfigFile().equalsIgnoreCase("")) {
371 | FileContent tempFileContent = new FileContent("application/json", new File(profile.getConfigFile()).getAbsoluteFile());
372 | Reader reader = new InputStreamReader(tempFileContent.getInputStream());
373 | Map result = new ObjectMapper().readValue(reader, HashMap.class);
374 | if(result!=null && result.size()>0) {
375 | //For Custom Fields
376 | Map fieldsMap = (Map) result.get("fields");
377 | if(fieldsMap!=null && fieldsMap.size()>0) {
378 | for (String key : fieldsMap.keySet()) {
379 | if (key!=null && key.equals("field_api_product")){
380 | hasAPIProducts = true;
381 | apiProducts = new ArrayList();
382 | apiProducts = (List)fieldsMap.get(key);
383 | }
384 | //no need to add to attributes for "field_image"
385 | else if (key!=null && key.equals("field_image")){
386 | hasImage = true;
387 | imageFile = new File(profile.getPortalDirectory()+"/"+(String)fieldsMap.get(key));
388 | }
389 | else if(fieldsMap.get(key) instanceof List){
390 | attributes.add(key, gson.toJsonTree(fieldsMap.get(key)));
391 | }
392 | else
393 | attributes.addProperty(key, (String)fieldsMap.get(key));
394 | }
395 | }
396 |
397 | //For Custom taxonomy_terms
398 | List