diff --git a/appengine/CONTRIBUTING.md b/appengine/CONTRIBUTING.md new file mode 100644 index 00000000000..d9365cc8f82 --- /dev/null +++ b/appengine/CONTRIBUTING.md @@ -0,0 +1,35 @@ +# How to become a contributor and submit your own code + +## Contributor License Agreements + +We'd love to accept your patches! Before we can take them, we +have to jump a couple of legal hurdles. + +Please fill out either the individual or corporate Contributor License Agreement +(CLA). + + * If you are an individual writing original source code and you're sure you + own the intellectual property, then you'll need to sign an [individual CLA] + (https://developers.google.com/open-source/cla/individual). + * If you work for a company that wants to allow you to contribute your work, + then you'll need to sign a [corporate CLA] + (https://developers.google.com/open-source/cla/corporate). + +Follow either of the two links above to access the appropriate CLA and +instructions for how to sign and return it. Once we receive it, we'll be able to +accept your pull requests. + +## Contributing A Patch + +1. Submit an issue describing your proposed change to the repo in question. +1. The repo owner will respond to your issue promptly. +1. If your proposed change is accepted, and you haven't already done so, sign a + Contributor License Agreement (see details above). +1. Fork the desired repo, develop and test your code changes. +1. Ensure that your code adheres to the existing style in the sample to which + you are contributing. Refer to the + [Google Cloud Platform Samples Style Guide] + (https://github.com/GoogleCloudPlatform/Template/wiki/style.html) for the + recommended coding standards for this organization. +1. Ensure that your code has an appropriate set of unit tests which all pass. +1. Submit a pull request. diff --git a/appengine/LICENSE b/appengine/LICENSE new file mode 100644 index 00000000000..57bc88a15a0 --- /dev/null +++ b/appengine/LICENSE @@ -0,0 +1,202 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/appengine/README.md b/appengine/README.md new file mode 100644 index 00000000000..2d3368f5333 --- /dev/null +++ b/appengine/README.md @@ -0,0 +1,54 @@ +## Google Managed VMs Java Samples + +This is a repository that contains Java code samples for Google Managed VMs + +See our other [Google Cloud Platform github +repos](https://github.com/GoogleCloudPlatform) for sample applications and +scaffolding for other frameworks and use cases. + +## Run Locally +1. Install the [Google Cloud SDK](https://cloud.google.com/sdk/), including the [gcloud tool](https://cloud.google.com/sdk/gcloud/), and [gcloud app component](https://cloud.google.com/sdk/gcloud-app). +1. Setup the gcloud tool. + + ``` + gcloud init + ``` + +1. Clone this repo. + + ``` + git clone https://github.com/GoogleCloudPlatform/.git + ``` + +1. Run this project locally from the command line. + + ``` + mvn clean jetty:run + ``` + +1. Visit the application at [http://localhost:8080](http://localhost:8080). + +## Deploying + +1. Use the [Cloud Developer Console](https://console.developer.google.com) to create a project/app id. (App id and project id are identical) +1. Setup the gcloud tool. + + ``` + gcloud init + ``` +1. Use the [Admin Console](https://appengine.google.com) to view data, queues, and other App Engine specific administration tasks. +1. Use gcloud to deploy your app. + + ``` + mvn clean gcloud:deploy + ``` + +1. Congratulations! Your application is now live at your-app-id.appspot.com + +## Contributing changes + +* See [CONTRIBUTING.md](CONTRIBUTING.md) + +## Licensing + +* See [LICENSE](LICENSE) diff --git a/appengine/analytics/pom.xml b/appengine/analytics/pom.xml new file mode 100644 index 00000000000..1c2783c9430 --- /dev/null +++ b/appengine/analytics/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.managedvms + analytics + + + org.apache.httpcomponents + httpclient + 4.5.1 + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + false + + + + org.apache.maven.plugins + 3.3 + maven-compiler-plugin + + 1.7 + 1.7 + + + + com.google.appengine + gcloud-maven-plugin + 2.0.9.89.v20151202 + + true + + + + + diff --git a/appengine/analytics/src/main/java/com/example/managedvms/analytics/AnalyticsServlet.java b/appengine/analytics/src/main/java/com/example/managedvms/analytics/AnalyticsServlet.java new file mode 100644 index 00000000000..40e19e06590 --- /dev/null +++ b/appengine/analytics/src/main/java/com/example/managedvms/analytics/AnalyticsServlet.java @@ -0,0 +1,65 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.analytics; + +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.utils.URIBuilder; +import org.apache.http.impl.client.HttpClientBuilder; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START example] +@SuppressWarnings("serial") +@WebServlet(name = "analytics", value = "/*") +public class AnalyticsServlet extends HttpServlet { + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, + ServletException { + String trackingId = System.getenv("GA_TRACKING_ID"); + HttpClient client = HttpClientBuilder.create().build(); + URIBuilder builder = new URIBuilder(); + builder.setScheme("http").setHost("www.google-analytics.com").setPath("/collect") + .addParameter("v", "1") // API Version. + .addParameter("tid", trackingId) // Tracking ID / Property ID. + // Anonymous Client Identifier. Ideally, this should be a UUID that + // is associated with particular user, device, or browser instance. + .addParameter("cid", "555") + .addParameter("t", "event") // Event hit type. + .addParameter("ec", "example") // Event category. + .addParameter("ea", "test action"); // Event action. + URI uri = null; + try { + uri = builder.build(); + } catch (URISyntaxException e) { + throw new ServletException("Problem building URI", e); + } + HttpPost request = new HttpPost(uri); + client.execute(request); + resp.getWriter().println("Event tracked."); + } +} +// [END example] diff --git a/appengine/analytics/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/analytics/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..97f782ee54c --- /dev/null +++ b/appengine/analytics/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,12 @@ + + + true + true + + + + + + + + diff --git a/appengine/cloudsql/README.md b/appengine/cloudsql/README.md new file mode 100644 index 00000000000..fbbbd58dd81 --- /dev/null +++ b/appengine/cloudsql/README.md @@ -0,0 +1,16 @@ +# Cloud SQL sample for Google Managed VMs +This sample demonstrates how to use [Cloud SQL](https://cloud.google.com/sql/) on Google Managed VMs +## Setup +Before you can run or deploy the sample, you will need to do the following: +1. Create a Cloud SQL instance. You can do this from the [Google Developers Console](https://console.developers.google.com) or via the [Cloud SDK](https://cloud.google.com/sdk). To create it via the SDK use the following command: + $ gcloud sql instances create [your-instance-name] \ + --assign-ip \ + --authorized-networks 0.0.0.0/0 \ + --tier D0 +1. Create a new user and database for the application. The easiest way to do this is via the [Google Developers Console](https://console.developers.google.com/project/_/sql/instances/example-instance2/access-control/users). Alternatively, you can use MySQL tools such as the command line client or workbench. +## Running locally +1. Update the connection string in ``appengine-web.xml`` with your local MySQL instance values. + $ mvn clean jetty:run +## Deploying +1. Update the connection string in ``appengine-web.xml`` with your Cloud SQL instance values. + $ mvn clean gcloud:deploy diff --git a/appengine/cloudsql/pom.xml b/appengine/cloudsql/pom.xml new file mode 100644 index 00000000000..2acbffff685 --- /dev/null +++ b/appengine/cloudsql/pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.managedvms + cloudsql + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + + mysql + mysql-connector-java + 5.1.38 + + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + false + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.7 + 1.7 + + + + com.google.appengine + gcloud-maven-plugin + 2.0.9.89.v20151202 + + true + + + + + diff --git a/appengine/cloudsql/src/main/java/com/example/managedvms/cloudsql/CloudSqlServlet.java b/appengine/cloudsql/src/main/java/com/example/managedvms/cloudsql/CloudSqlServlet.java new file mode 100644 index 00000000000..08971343dd7 --- /dev/null +++ b/appengine/cloudsql/src/main/java/com/example/managedvms/cloudsql/CloudSqlServlet.java @@ -0,0 +1,71 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.cloudsql; + +import java.io.IOException; +import java.io.PrintWriter; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Date; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START example] +@SuppressWarnings("serial") +@WebServlet(name = "cloudsql", value = "/*") +public class CloudSqlServlet extends HttpServlet { + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, + ServletException { + final String createTableSql = "CREATE TABLE IF NOT EXISTS visits ( visit_id INT NOT NULL " + + "AUTO_INCREMENT, user_ip VARCHAR(46) NOT NULL, timestamp DATETIME NOT NULL, " + + "PRIMARY KEY (visit_id) )"; + final String createVisitSql = "INSERT INTO visits (user_ip, timestamp) VALUES (?, ?)"; + final String selectSql = "SELECT user_ip, timestamp FROM visits ORDER BY timestamp DESC " + + "LIMIT 10"; + PrintWriter out = resp.getWriter(); + resp.setContentType("text/plain"); + String url = System.getenv("SQL_DATABASE_URL"); + try (Connection conn = DriverManager.getConnection(url); + PreparedStatement statementCreateVisit = conn.prepareStatement(createVisitSql)) { + conn.createStatement().executeUpdate(createTableSql); + statementCreateVisit.setString(1, req.getRemoteAddr()); + statementCreateVisit.setTimestamp(2, new Timestamp(new Date().getTime())); + statementCreateVisit.executeUpdate(); + try (ResultSet rs = conn.prepareStatement(selectSql).executeQuery()) { + out.print("Last 10 visits:\n"); + while (rs.next()) { + String userIp = rs.getString("user_ip"); + String timeStamp = rs.getString("timestamp"); + out.print("Time: " + timeStamp + " Addr: " + userIp + "\n"); + } + } + } catch (SQLException e) { + throw new ServletException("SQL error", e); + } + } +} +// [END example] diff --git a/appengine/cloudsql/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/cloudsql/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..fe4ae8c5ea1 --- /dev/null +++ b/appengine/cloudsql/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,12 @@ + + + true + true + + + + + + + + diff --git a/appengine/cloudstorage/README.md b/appengine/cloudstorage/README.md new file mode 100644 index 00000000000..f317aa0f953 --- /dev/null +++ b/appengine/cloudstorage/README.md @@ -0,0 +1,14 @@ +# Cloud Storage sample for Google Maanged VMs +This sample demonstrates how to use [Cloud Storage](https://cloud.google.com/storage/) on Google Managed VMs +## Setup +Before you can run or deploy the sample, you will need to do the following: +1. Enable the Cloud Storage API in the [Google Developers Console](https://console.developers.google.com/project/_/apiui/apiview/storage/overview). +1. Create a Cloud Storage Bucket. You can do this with the [Google Cloud SDK](https://cloud.google.com/sdk) with the following command: + $ gsutil mb gs://[your-bucket-name] +1. Set the default ACL on your bucket to public read in order to serve files directly from Cloud Storage. You can do this with the [Google Cloud SDK](https://cloud.google.com/sdk) with the following command: + $ gsutil defacl set public-read gs://[your-bucket-name] +1. Update the bucket name in ``src/main/appengine/app.yaml``. +## Running locally + $ mvn clean jetty:run +## Deploying + $ mvn clean gcloud:deploy diff --git a/appengine/cloudstorage/pom.xml b/appengine/cloudstorage/pom.xml new file mode 100644 index 00000000000..5666b212afe --- /dev/null +++ b/appengine/cloudstorage/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.managedvms + cloudstorage + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + com.google.gcloud + gcloud-java-storage + 0.1.1 + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + false + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.7 + 1.7 + + + + com.google.appengine + gcloud-maven-plugin + 2.0.9.89.v20151202 + + true + + + + + diff --git a/appengine/cloudstorage/src/main/java/com/example/managedvms/cloudstorage/UploadServlet.java b/appengine/cloudstorage/src/main/java/com/example/managedvms/cloudstorage/UploadServlet.java new file mode 100644 index 00000000000..6150f2e78dc --- /dev/null +++ b/appengine/cloudstorage/src/main/java/com/example/managedvms/cloudstorage/UploadServlet.java @@ -0,0 +1,65 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.cloudstorage; + +import com.google.common.io.ByteStreams; +import com.google.gcloud.storage.BlobInfo; +import com.google.gcloud.storage.BlobWriteChannel; +import com.google.gcloud.storage.Storage; +import com.google.gcloud.storage.StorageOptions; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.channels.Channels; + +import javax.servlet.ServletException; +import javax.servlet.annotation.MultipartConfig; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.Part; + +// [START example] +@SuppressWarnings("serial") +@WebServlet(name = "upload", value = "/upload") +@MultipartConfig() +public class UploadServlet extends HttpServlet { + + private static final String BUCKET_NAME = System.getenv("BUCKET_NAME"); + private static Storage storage = null; + + @Override + public void init() { + storage = StorageOptions.defaultInstance().service(); + } + + @Override + public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException, + ServletException { + final Part filePart = req.getPart("file"); + final String fileName = filePart.getSubmittedFileName(); + BlobInfo blobInfo = BlobInfo.builder(BUCKET_NAME, fileName).build(); + InputStream filecontent = filePart.getInputStream(); + BlobWriteChannel blobWriter = storage.writer(blobInfo); + ByteStreams.copy(filecontent, Channels.newOutputStream(blobWriter)); + blobWriter.close(); + blobInfo = storage.get(BUCKET_NAME, fileName); + resp.getWriter().print(blobInfo.mediaLink()); + } +} +// [END example] diff --git a/appengine/cloudstorage/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/cloudstorage/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..e1ca376557f --- /dev/null +++ b/appengine/cloudstorage/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,12 @@ + + + true + true + + + + + + + + diff --git a/appengine/cloudstorage/src/main/webapp/index.html b/appengine/cloudstorage/src/main/webapp/index.html new file mode 100644 index 00000000000..78e9c675a9b --- /dev/null +++ b/appengine/cloudstorage/src/main/webapp/index.html @@ -0,0 +1,9 @@ + + Google Managed VMs Cloud Storage Sample + +

Select a file to upload to your Google Cloud Storage bucket.

+
+ +
+ + diff --git a/appengine/datastore/pom.xml b/appengine/datastore/pom.xml new file mode 100644 index 00000000000..96362d04d10 --- /dev/null +++ b/appengine/datastore/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.managedvms + datastore + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + com.google.gcloud + gcloud-java-datastore + 0.1.1 + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + false + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.7 + 1.7 + + + + com.google.appengine + gcloud-maven-plugin + 2.0.9.89.v20151202 + + true + + + + + diff --git a/appengine/datastore/src/main/java/com/example/managedvms/datastore/DatastoreServlet.java b/appengine/datastore/src/main/java/com/example/managedvms/datastore/DatastoreServlet.java new file mode 100644 index 00000000000..c5043d95ac1 --- /dev/null +++ b/appengine/datastore/src/main/java/com/example/managedvms/datastore/DatastoreServlet.java @@ -0,0 +1,72 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.datastore; + +import com.google.gcloud.datastore.Datastore; +import com.google.gcloud.datastore.DatastoreOptions; +import com.google.gcloud.datastore.DateTime; +import com.google.gcloud.datastore.Entity; +import com.google.gcloud.datastore.FullEntity; +import com.google.gcloud.datastore.IncompleteKey; +import com.google.gcloud.datastore.KeyFactory; +import com.google.gcloud.datastore.Query; +import com.google.gcloud.datastore.QueryResults; +import com.google.gcloud.datastore.StructuredQuery; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START example] +@SuppressWarnings("serial") +@WebServlet(name = "datastore", value = "/*") +public class DatastoreServlet extends HttpServlet { + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, + ServletException { + Datastore datastore = DatastoreOptions + .builder() + .projectId(System.getenv("PROJECT_ID")) + .build() + .service(); + KeyFactory keyFactory = datastore.newKeyFactory().kind("visit"); + IncompleteKey key = keyFactory.kind("visit").newKey(); + // Record a visit to the datastore, storing the IP and timestamp. + FullEntity curVisit = FullEntity.builder(key) + .set("user_ip", req.getRemoteAddr()).set("timestamp", DateTime.now()).build(); + datastore.add(curVisit); + // Retrieve the last 10 visits from the datastore, ordered by timestamp. + Query query = Query.entityQueryBuilder().kind("visit") + .orderBy(StructuredQuery.OrderBy.desc("timestamp")).limit(10).build(); + QueryResults results = datastore.run(query); + resp.setContentType("text/plain"); + PrintWriter out = resp.getWriter(); + out.print("Last 10 visits:\n"); + while (results.hasNext()) { + Entity entity = results.next(); + out.format("Time: %s Addr: %s\n", entity.getDateTime("timestamp"), + entity.getString("user_ip")); + } + } +} +// [END example] diff --git a/appengine/datastore/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/datastore/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..181a7408d5b --- /dev/null +++ b/appengine/datastore/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,12 @@ + + + true + true + + + + + + + + diff --git a/appengine/disk/pom.xml b/appengine/disk/pom.xml new file mode 100644 index 00000000000..61a8677ac56 --- /dev/null +++ b/appengine/disk/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.managedvms + disk + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + false + + + + org.apache.maven.plugins + 3.3 + maven-compiler-plugin + + 1.7 + 1.7 + + + + com.google.appengine + gcloud-maven-plugin + 2.0.9.89.v20151202 + + + + diff --git a/appengine/disk/src/main/java/com/example/managedvms/disk/DiskServlet.java b/appengine/disk/src/main/java/com/example/managedvms/disk/DiskServlet.java new file mode 100644 index 00000000000..7f711ad060a --- /dev/null +++ b/appengine/disk/src/main/java/com/example/managedvms/disk/DiskServlet.java @@ -0,0 +1,56 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.disk; + +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.List; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START example] +@SuppressWarnings("serial") +@WebServlet(name = "disk", value = "/*") +public class DiskServlet extends HttpServlet { + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String instanceId = + System.getenv().containsKey("GAE_MODULE_INSTANCE") + ? System.getenv("GAE_MODULE_INSTANCE") : "1"; + String userId = req.getRemoteAddr() + "\n"; + Path tmpFile = Paths.get("/tmp/seen.txt"); + Files.write(tmpFile, userId.getBytes(), StandardOpenOption.CREATE, StandardOpenOption.APPEND); + StringBuffer sb = new StringBuffer(); + List strings = Files.readAllLines(tmpFile, StandardCharsets.US_ASCII); + for (String s : strings) { + sb.append(s+"\n"); + } + PrintWriter out = resp.getWriter(); + resp.setContentType("text/plain"); + out.print("Instance: " + instanceId + "\nSeen:\n" + sb.toString()); + } +} +// [END example] diff --git a/appengine/disk/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/disk/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..dba606c1666 --- /dev/null +++ b/appengine/disk/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,9 @@ + + + true + true + + + + + diff --git a/appengine/extending-runtime/README.md b/appengine/extending-runtime/README.md new file mode 100644 index 00000000000..95290cfb3f9 --- /dev/null +++ b/appengine/extending-runtime/README.md @@ -0,0 +1,4 @@ +# Java extending runtime sample for Google Managed VMs +This sample demonstrates how to use custom runtime on Google Managed VMs +## Setup +Before you can run this sample locally, you will have to edit the and properties in the pom.xml diff --git a/appengine/extending-runtime/pom.xml b/appengine/extending-runtime/pom.xml new file mode 100644 index 00000000000..bbfd562344c --- /dev/null +++ b/appengine/extending-runtime/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.managedvms + extendingruntime + + + + + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + false + + + + org.apache.maven.plugins + 3.3 + maven-compiler-plugin + + 1.7 + 1.7 + + + + com.google.appengine + gcloud-maven-plugin + 2.0.9.89.v20151202 + + + java + -Dgcloud.java.application=${project.build.directory}/${project.build.finalName} + -Dcom.google.apphosting.vmruntime.VmRuntimeFileLogHandler.pattern=${writeable.directory}/log.%g + -Djetty.home=${gcloud.sdk.directory}/google-cloud-sdk/platform/google_appengine/google/appengine/tools/java/lib/java-managed-vm/appengine-java-vmruntime + -Djetty.base=${gcloud.sdk.directory}/google-cloud-sdk/platform/google_appengine/google/appengine/tools/java/lib/jetty-base-sdk + -jar + ${gcloud.sdk.directory}/google-cloud-sdk/platform/google_appengine/google/appengine/tools/java/lib/java-managed-vm/appengine-java-vmruntime/start.jar + -module=http + jetty.port={port} + + + + + + diff --git a/appengine/extending-runtime/src/main/java/com/example/managedvms/extendingruntime/FortuneServlet.java b/appengine/extending-runtime/src/main/java/com/example/managedvms/extendingruntime/FortuneServlet.java new file mode 100644 index 00000000000..7c6a5115b21 --- /dev/null +++ b/appengine/extending-runtime/src/main/java/com/example/managedvms/extendingruntime/FortuneServlet.java @@ -0,0 +1,66 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.extendingruntime; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START example] +@SuppressWarnings("serial") +@WebServlet(name = "fortune", value = "/*") +public class FortuneServlet extends HttpServlet { + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + PrintWriter out = resp.getWriter(); + String fortune = getFortune(); + out.println(fortune); + } + + private String getFortune() throws IOException { + File fort = new File("/usr/games/fortune"); + if (!fort.exists()) { + return "It seems that the /usr/games/fortune application is not installed on your system."; + } + ProcessBuilder pb = new ProcessBuilder(fort.getAbsolutePath()); + File file = File.createTempFile("tmp_fortune", null); + pb.redirectOutput(file); + Process process = pb.start(); + try { + process.waitFor(); + } catch (InterruptedException ex) { + return ex.getMessage(); + } + String fortune = ""; + String line; + BufferedReader br = new BufferedReader(new FileReader(file)); + while ((line = br.readLine()) != null) { + fortune = fortune + "
" + line; + } + br.close(); + return fortune; + } +} +// [END example] diff --git a/appengine/extending-runtime/src/main/webapp/Dockerfile b/appengine/extending-runtime/src/main/webapp/Dockerfile new file mode 100644 index 00000000000..3ac0a7eb2c3 --- /dev/null +++ b/appengine/extending-runtime/src/main/webapp/Dockerfile @@ -0,0 +1,4 @@ +FROM gcr.io/google_appengine/jetty9-compat +RUN apt-get update && apt-get install -y fortunes + +ADD . /app diff --git a/appengine/extending-runtime/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/extending-runtime/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..dba606c1666 --- /dev/null +++ b/appengine/extending-runtime/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,9 @@ + + + true + true + + + + + diff --git a/appengine/helloworld-mvm/README.md b/appengine/helloworld-mvm/README.md new file mode 100644 index 00000000000..cab559c289d --- /dev/null +++ b/appengine/helloworld-mvm/README.md @@ -0,0 +1,11 @@ +# Appengine Helloworld sample for Google App Engine +This sample demonstrates how to deploy an application on Google App Engine +## Setup +1. Update the tag in src/main/webapp/WEB-INF/appengine-web.xml with your project name +1. Update the tag in src/main/webapp/WEB-INF/appengine-web.xml with your version name + +## Running locally + $ mvn appengine:devserver + +## Deploying + $ mvn appengine:update diff --git a/appengine/helloworld-mvm/pom.xml b/appengine/helloworld-mvm/pom.xml new file mode 100644 index 00000000000..ff20c7efee6 --- /dev/null +++ b/appengine/helloworld-mvm/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.managedvms + helloworld + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + false + + + + org.apache.maven.plugins + 3.3 + maven-compiler-plugin + + 1.7 + 1.7 + + + + com.google.appengine + gcloud-maven-plugin + 2.0.9.89.v20151202 + + + + diff --git a/appengine/helloworld-mvm/src/main/java/com/example/appengine/helloworld/HelloServlet.java b/appengine/helloworld-mvm/src/main/java/com/example/appengine/helloworld/HelloServlet.java new file mode 100644 index 00000000000..d9135a0ce63 --- /dev/null +++ b/appengine/helloworld-mvm/src/main/java/com/example/appengine/helloworld/HelloServlet.java @@ -0,0 +1,36 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.appengine.helloworld; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START example] +@SuppressWarnings("serial") +public class HelloServlet extends HttpServlet { + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + PrintWriter out = resp.getWriter(); + out.println("Hello, world"); + } +} +// [END example] diff --git a/appengine/helloworld-mvm/src/main/java/com/example/managedvms/helloworld/HelloServlet.java b/appengine/helloworld-mvm/src/main/java/com/example/managedvms/helloworld/HelloServlet.java new file mode 100644 index 00000000000..78b2dc9b91d --- /dev/null +++ b/appengine/helloworld-mvm/src/main/java/com/example/managedvms/helloworld/HelloServlet.java @@ -0,0 +1,38 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.helloworld; + +import java.io.IOException; +import java.io.PrintWriter; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START example] +@SuppressWarnings("serial") +@WebServlet(name = "helloworld", value = "/*") +public class HelloServlet extends HttpServlet { + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + PrintWriter out = resp.getWriter(); + out.println("Hello, world"); + } +} +// [END example] diff --git a/appengine/helloworld-mvm/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/helloworld-mvm/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..dba606c1666 --- /dev/null +++ b/appengine/helloworld-mvm/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,9 @@ + + + true + true + + + + + diff --git a/appengine/helloworld-mvm/src/main/webapp/WEB-INF/web.xml b/appengine/helloworld-mvm/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..1a1704104a2 --- /dev/null +++ b/appengine/helloworld-mvm/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,14 @@ + + + + hello + com.example.appengine.helloworld.HelloServlet + + + hello + / + + diff --git a/appengine/mailgun/README.md b/appengine/mailgun/README.md new file mode 100644 index 00000000000..fd3b6c97681 --- /dev/null +++ b/appengine/mailgun/README.md @@ -0,0 +1,14 @@ +# Java Mailgun email sample for Google App Engine Managed VMs +This sample demonstrates how to use [Mailgun](https://www.mailgun.com) on [Google App Engine Managed VMs](https://cloud.google.com/appengine). +For more information about Mailgun, see their [documentation](https://documentation.mailgun.com/). +## Setup +Before you can run or deploy the sample, you will need to do the following: +1. [Create a Mailgun Account](http://www.mailgun.com/google). As of September 2015, Google users start with 30,000 free emails per month. +2. Configure your Mailgun settings in the environment variables section in ``app.yaml``. +## Running locally +Refer to the [top-level README](../README.md) for instructions on running and deploying. +You can run the application locally and send emails from your local machine. You +will need to set environment variables before starting your application: + $ export MAILGUN_API_KEY=[your-mailgun-api-key] + $ export MAILGUN_DOMAIN_NAME=[your-mailgun-domain-name] + $ mvn clean jetty:run diff --git a/appengine/mailgun/pom.xml b/appengine/mailgun/pom.xml new file mode 100644 index 00000000000..1ff464c3814 --- /dev/null +++ b/appengine/mailgun/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.managedvms + mailgun + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + + com.sun.jersey + jersey-core + 1.19 + + + com.sun.jersey + jersey-client + 1.19 + + + com.sun.jersey.contribs + jersey-multipart + 1.19 + + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + false + + + + org.apache.maven.plugins + 3.3 + maven-compiler-plugin + + 1.7 + 1.7 + + + + com.google.appengine + gcloud-maven-plugin + 2.0.9.89.v20151202 + + + + diff --git a/appengine/mailgun/src/main/java/com/example/managedvms/mailgun/MailgunServlet.java b/appengine/mailgun/src/main/java/com/example/managedvms/mailgun/MailgunServlet.java new file mode 100644 index 00000000000..caddf4e05d2 --- /dev/null +++ b/appengine/mailgun/src/main/java/com/example/managedvms/mailgun/MailgunServlet.java @@ -0,0 +1,67 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.mailgun; + +import com.sun.jersey.api.client.Client; +import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; +import com.sun.jersey.multipart.FormDataMultiPart; +import com.sun.jersey.multipart.file.FileDataBodyPart; + +import java.io.File; +import java.io.IOException; + +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.core.MediaType; + +// [START example] +@SuppressWarnings("serial") +@WebServlet(name = "mailgun", value = "/send/email") +public class MailgunServlet extends HttpServlet { + + private static final String MAILGUN_DOMAIN_NAME = System.getenv("MAILGUN_DOMAIN_NAME"); + private static final String MAILGUN_API_KEY= System.getenv("MAILGUN_API_KEY"); + + @Override + public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { + String recipient = req.getParameter("to"); + Client client = Client.create(); + client.addFilter(new HTTPBasicAuthFilter("api", MAILGUN_API_KEY)); + WebResource webResource = + client.resource("https://api.mailgun.net/v3/" + MAILGUN_DOMAIN_NAME + "/messages"); + FormDataMultiPart formData = new FormDataMultiPart(); + formData.field("from", "Mailgun User "); + formData.field("to", recipient); + formData.field("subject", "Complex Mailgun Example"); + formData.field("html", "HTML content"); + ClassLoader classLoader = getClass().getClassLoader(); + File txtFile = new File(classLoader.getResource("example-attachment.txt").getFile()); + formData.bodyPart(new FileDataBodyPart("attachment", txtFile, MediaType.TEXT_PLAIN_TYPE)); + ClientResponse clientResponse = + webResource.type(MediaType.MULTIPART_FORM_DATA_TYPE).post(ClientResponse.class, formData); + if (clientResponse.getStatus() == 200) { + resp.getWriter().print("Email sent."); + } else { + resp.getWriter().print("An error was encountered"); + } + } +} +// [END example] diff --git a/appengine/mailgun/src/main/resources/example-attachment.txt b/appengine/mailgun/src/main/resources/example-attachment.txt new file mode 100644 index 00000000000..e0da678a932 --- /dev/null +++ b/appengine/mailgun/src/main/resources/example-attachment.txt @@ -0,0 +1 @@ +This is a sample attachment. \ No newline at end of file diff --git a/appengine/mailgun/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/mailgun/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..f05d489f646 --- /dev/null +++ b/appengine/mailgun/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,13 @@ + + + true + true + + + + + + + + + diff --git a/appengine/mailgun/src/main/webapp/index.html b/appengine/mailgun/src/main/webapp/index.html new file mode 100644 index 00000000000..d85e8ac6192 --- /dev/null +++ b/appengine/mailgun/src/main/webapp/index.html @@ -0,0 +1,14 @@ + + + + Mailgun on Google App Engine Managed VMs + + + +
+ + +
+ + + diff --git a/appengine/memcache/pom.xml b/appengine/memcache/pom.xml new file mode 100644 index 00000000000..36b402688c3 --- /dev/null +++ b/appengine/memcache/pom.xml @@ -0,0 +1,51 @@ + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.managedvms + memcache + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + com.googlecode.xmemcached + xmemcached + 2.0.0 + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + false + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.7 + 1.7 + + + + com.google.appengine + gcloud-maven-plugin + 2.0.9.89.v20151202 + + + + diff --git a/appengine/memcache/src/main/java/com/example/managedvms/memcache/MemcacheServlet.java b/appengine/memcache/src/main/java/com/example/managedvms/memcache/MemcacheServlet.java new file mode 100644 index 00000000000..c2f7444f9a8 --- /dev/null +++ b/appengine/memcache/src/main/java/com/example/managedvms/memcache/MemcacheServlet.java @@ -0,0 +1,62 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.memcache; + +import net.rubyeye.xmemcached.MemcachedClient; +import net.rubyeye.xmemcached.MemcachedClientBuilder; +import net.rubyeye.xmemcached.XMemcachedClientBuilder; +import net.rubyeye.xmemcached.exception.MemcachedException; +import net.rubyeye.xmemcached.utils.AddrUtil; + +import java.io.IOException; +import java.util.concurrent.TimeoutException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START example] +@SuppressWarnings("serial") +@WebServlet(name = "memcache", value = "/*") +public class MemcacheServlet extends HttpServlet { + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, + ServletException { + String addr = + System.getenv().containsKey("MEMCACHE_PORT_11211_TCP_ADDR") + ? System.getenv("MEMCACHE_PORT_11211_TCP_ADDR") : "localhost"; + String port = + System.getenv().containsKey("MEMCACHE_PORT_11211_TCP_ADDR") + ? System.getenv("MEMCACHE_PORT_11211_TCP_PORT") : "11211"; + String key = "count"; + MemcachedClientBuilder builder = new XMemcachedClientBuilder( + AddrUtil.getAddresses(addr + ":" + port)); + MemcachedClient client = builder.build(); + long count = 0L; + try { + count = client.incr(key, 1L, 0L); + } catch (TimeoutException | InterruptedException | MemcachedException e) { + throw new ServletException("Memcache error", e); + } + resp.setContentType("text/plain"); + resp.getWriter().print("Value is " + count + "\n"); + } +} +// [END example] diff --git a/appengine/memcache/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/memcache/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..110b55c8db3 --- /dev/null +++ b/appengine/memcache/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,10 @@ + + + true + true + + + + + + diff --git a/appengine/sendgrid/README.md b/appengine/sendgrid/README.md new file mode 100644 index 00000000000..4a76dd9fd2b --- /dev/null +++ b/appengine/sendgrid/README.md @@ -0,0 +1,13 @@ +# Java SendGrid email sample for Google Managed VMs +This sample demonstrates how to use [SendGrid](https://www.sendgrid.com) on Google Managed VMs +For more information about SendGrid, see their [documentation](https://sendgrid.com/docs/User_Guide/index.html). +## Setup +Before you can run or deploy the sample, you will need to do the following: +1. [Create a SendGrid Account](http://sendgrid.com/partner/google). As of September 2015, Google users start with 25,000 free emails per month. +1. Configure your SendGrid settings in the environment variables section in ``src/main/appengine/app.yaml``. +## Running locally +You can run the application locally and send emails from your local machine. You +will need to set environment variables before starting your application: + $ export SENDGRID_API_KEY=[your-sendgrid-api-key] + $ export SENDGRID_SENDER=[your-sendgrid-sender-email-address] + $ mvn clean jetty:run diff --git a/appengine/sendgrid/pom.xml b/appengine/sendgrid/pom.xml new file mode 100644 index 00000000000..1b5a29e4932 --- /dev/null +++ b/appengine/sendgrid/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.managedvms + sendgrid + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + + com.sendgrid + sendgrid-java + 2.2.2 + + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + false + + + + org.apache.maven.plugins + 3.3 + maven-compiler-plugin + + 1.7 + 1.7 + + + + com.google.appengine + gcloud-maven-plugin + 2.0.9.89.v20151202 + + + + diff --git a/appengine/sendgrid/src/main/java/com/example/managedvms/sendgrid/SendEmailServlet.java b/appengine/sendgrid/src/main/java/com/example/managedvms/sendgrid/SendEmailServlet.java new file mode 100644 index 00000000000..31b71bfdec0 --- /dev/null +++ b/appengine/sendgrid/src/main/java/com/example/managedvms/sendgrid/SendEmailServlet.java @@ -0,0 +1,67 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.sendgrid; + +import com.sendgrid.SendGrid; +import com.sendgrid.SendGridException; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START example] +@SuppressWarnings("serial") +@WebServlet(name = "sendemail", value = "/send/email") +public class SendEmailServlet extends HttpServlet { + + @Override + public void service(HttpServletRequest req, HttpServletResponse resp) throws IOException, + ServletException { + final String SENDGRID_API_KEY = System.getenv("SENDGRID_API_KEY"); + final String SENDGRID_SENDER = System.getenv("SENDGRID_SENDER"); + final String TO_EMAIL = (String) req.getParameter("to"); + if (TO_EMAIL == null) { + resp.getWriter().print("Please provide an email address in the \"to\" query string" + + " parameter."); + return; + } + + SendGrid sendgrid = new SendGrid(SENDGRID_API_KEY); + SendGrid.Email email = new SendGrid.Email(); + email.addTo(TO_EMAIL); + email.setFrom(SENDGRID_SENDER); + email.setSubject("This is a test email"); + email.setText("Example text body."); + + try { + SendGrid.Response response = sendgrid.send(email); + if (response.getCode() != 200) { + resp.getWriter().print(String.format("An error occured: %s", response.getMessage())); + return; + } + resp.getWriter().print("Email sent."); + } + catch (SendGridException e) { + throw new ServletException("SendGrid error", e); + } + } +} +// [END example] diff --git a/appengine/sendgrid/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/sendgrid/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..00c515b1b87 --- /dev/null +++ b/appengine/sendgrid/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,13 @@ + + + true + true + + + + + + + + + diff --git a/appengine/static-files/pom.xml b/appengine/static-files/pom.xml new file mode 100644 index 00000000000..24d0f6a68b6 --- /dev/null +++ b/appengine/static-files/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.managedvms + staticfiles + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + false + + + + org.apache.maven.plugins + 3.3 + maven-compiler-plugin + + 1.7 + 1.7 + + + + com.google.appengine + gcloud-maven-plugin + 2.0.9.89.v20151202 + + + + diff --git a/appengine/static-files/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/static-files/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..dba606c1666 --- /dev/null +++ b/appengine/static-files/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,9 @@ + + + true + true + + + + + diff --git a/appengine/static-files/src/main/webapp/index.html b/appengine/static-files/src/main/webapp/index.html new file mode 100644 index 00000000000..d1643e9a6b1 --- /dev/null +++ b/appengine/static-files/src/main/webapp/index.html @@ -0,0 +1,10 @@ + + + +Static Files + + + +

This is a static file serving example.

+ + diff --git a/appengine/static-files/src/main/webapp/stylesheets/styles.css b/appengine/static-files/src/main/webapp/stylesheets/styles.css new file mode 100644 index 00000000000..573f441093f --- /dev/null +++ b/appengine/static-files/src/main/webapp/stylesheets/styles.css @@ -0,0 +1,4 @@ +body { + font-family: Verdana, Helvetica, sans-serif; + background-color: #CCCCFF; +} diff --git a/appengine/twilio/README.md b/appengine/twilio/README.md new file mode 100644 index 00000000000..d9da6335902 --- /dev/null +++ b/appengine/twilio/README.md @@ -0,0 +1,17 @@ +# Java Twilio voice and SMS sample for Google Managed VMs +This sample demonstrates how to use [Twilio](https://www.twilio.com) on Google Managed VMs +For more information about Twilio, see their [Java quickstart tutorials](https://www.twilio.com/docs/quickstart/java). +## Setup +Before you can run or deploy the sample, you will need to do the following: +1. [Create a Twilio Account](http://ahoy.twilio.com/googlecloudplatform). Google App Engine +customers receive a complimentary credit for SMS messages and inbound messages. +1. Create a number on twilio, and configure the voice request URL to be ``https://your-app-id.appspot.com/call/receive`` +and the SMS request URL to be ``https://your-app-id.appspot.com/sms/receive``. +1. Configure your Twilio settings in the environment variables section in ``src/main/appengine/app.yaml``. +## Running locally +You can run the application locally to test the callbacks and SMS sending. You +will need to set environment variables before starting your application: + $ export TWILIO_ACCOUNT_SID=[your-twilio-accoun-sid] + $ export TWILIO_AUTH_TOKEN=[your-twilio-auth-token] + $ export TWILIO_NUMBER=[your-twilio-number] + $ mvn clean jetty:run diff --git a/appengine/twilio/pom.xml b/appengine/twilio/pom.xml new file mode 100644 index 00000000000..5d1d530fb3d --- /dev/null +++ b/appengine/twilio/pom.xml @@ -0,0 +1,54 @@ + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.managedvms + twilio + + + + com.twilio.sdk + twilio-java-sdk + 5.8.0 + compile + + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + false + + + + org.apache.maven.plugins + 3.3 + maven-compiler-plugin + + 1.7 + 1.7 + + + + com.google.appengine + gcloud-maven-plugin + 2.0.9.89.v20151202 + + + + diff --git a/appengine/twilio/src/main/java/com/example/managedvms/twilio/ReceiveCallServlet.java b/appengine/twilio/src/main/java/com/example/managedvms/twilio/ReceiveCallServlet.java new file mode 100644 index 00000000000..5d2c2b0d207 --- /dev/null +++ b/appengine/twilio/src/main/java/com/example/managedvms/twilio/ReceiveCallServlet.java @@ -0,0 +1,51 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.twilio; + +import com.twilio.sdk.verbs.Say; +import com.twilio.sdk.verbs.TwiMLException; +import com.twilio.sdk.verbs.TwiMLResponse; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START example] +@SuppressWarnings("serial") +@WebServlet(name = "receivecall", value = "/call/receive") +public class ReceiveCallServlet extends HttpServlet { + + @Override + public void service(HttpServletRequest req, HttpServletResponse resp) throws IOException, + ServletException { + TwiMLResponse twiml = new TwiMLResponse(); + Say say = new Say("Hello from Twilio!"); + try { + twiml.append(say); + } catch (TwiMLException e) { + throw new ServletException("Twilio error", e); + } + + resp.setContentType("application/xml"); + resp.getWriter().print(twiml.toXML()); + } +} +// [END example] diff --git a/appengine/twilio/src/main/java/com/example/managedvms/twilio/ReceiveSmsServlet.java b/appengine/twilio/src/main/java/com/example/managedvms/twilio/ReceiveSmsServlet.java new file mode 100644 index 00000000000..a4796bac9d2 --- /dev/null +++ b/appengine/twilio/src/main/java/com/example/managedvms/twilio/ReceiveSmsServlet.java @@ -0,0 +1,55 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.twilio; + +import com.twilio.sdk.verbs.Message; +import com.twilio.sdk.verbs.TwiMLException; +import com.twilio.sdk.verbs.TwiMLResponse; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START example] +@SuppressWarnings("serial") +@WebServlet(name = "receivesms", value = "/sms/receive") +public class ReceiveSmsServlet extends HttpServlet { + + @Override + public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, + ServletException { + String fromNumber = request.getParameter("From"); + String body = request.getParameter("Body"); + String message = String.format("Hello, %s, you said %s", fromNumber, body); + + TwiMLResponse twiml = new TwiMLResponse(); + Message sms = new Message(message); + try { + twiml.append(sms); + } catch (TwiMLException e) { + throw new ServletException("Twilio error", e); + } + + response.setContentType("application/xml"); + response.getWriter().print(twiml.toXML()); + } +} +// [END example] diff --git a/appengine/twilio/src/main/java/com/example/managedvms/twilio/SendSmsServlet.java b/appengine/twilio/src/main/java/com/example/managedvms/twilio/SendSmsServlet.java new file mode 100644 index 00000000000..3e727f1a3e8 --- /dev/null +++ b/appengine/twilio/src/main/java/com/example/managedvms/twilio/SendSmsServlet.java @@ -0,0 +1,71 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.twilio; + +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicNameValuePair; + +import com.twilio.sdk.TwilioRestClient; +import com.twilio.sdk.TwilioRestException; +import com.twilio.sdk.resource.factory.MessageFactory; +import com.twilio.sdk.resource.instance.Account; +import com.twilio.sdk.resource.instance.Message; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +// [START example] +@SuppressWarnings("serial") +@WebServlet(name = "sendsms", value = "/sms/send") +public class SendSmsServlet extends HttpServlet { + + @Override + public void service(HttpServletRequest req, HttpServletResponse resp) throws IOException, + ServletException { + final String TWILIO_ACCOUNT_SID = System.getenv("TWILIO_ACCOUNT_SID"); + final String TWILIO_AUTH_TOKEN = System.getenv("TWILIO_AUTH_TOKEN"); + final String TWILIO_NUMBER = System.getenv("TWILIO_NUMBER"); + final String TO_NUMBER = (String) req.getParameter("to"); + if (TO_NUMBER == null) { + resp.getWriter().print("Please provide the number to message in the \"to\" query string" + + " parameter."); + return; + } + TwilioRestClient client = new TwilioRestClient(TWILIO_ACCOUNT_SID, + TWILIO_AUTH_TOKEN); + Account account = client.getAccount(); + MessageFactory messageFactory = account.getMessageFactory(); + List params = new ArrayList(); + params.add(new BasicNameValuePair("To", TO_NUMBER)); + params.add(new BasicNameValuePair("From", TWILIO_NUMBER)); + params.add(new BasicNameValuePair("Body", "Hello from Twilio!")); + try { + Message sms = messageFactory.create(params); + resp.getWriter().print(sms.getBody()); + } catch (TwilioRestException e) { + throw new ServletException("Twilio error", e); + } + } +} +// [END example] diff --git a/appengine/twilio/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/twilio/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..b3eae3585d5 --- /dev/null +++ b/appengine/twilio/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,14 @@ + + + true + true + + + + + + + + + + diff --git a/appengine/websockets/README.md b/appengine/websockets/README.md new file mode 100644 index 00000000000..79e308727b9 --- /dev/null +++ b/appengine/websockets/README.md @@ -0,0 +1,8 @@ +# Java websockets sample for Google Managed VMs +This sample demonstrates how to use websockets on Google Managed VMs +## Setup +Before you can run or deploy the sample, you will need to create a new firewall rule to allow traffic on port 65080. This port will be used for websocket connections. You can do this with the [Google Cloud SDK](https://cloud.google.com/sdk) with the following command: + $ gcloud compute firewall-rules create default-allow-websockets \ + --allow tcp:65080 \ + --target-tags websocket \ + --description "Allow websocket traffic on port 65080" diff --git a/appengine/websockets/pom.xml b/appengine/websockets/pom.xml new file mode 100644 index 00000000000..c9b1a22f5a6 --- /dev/null +++ b/appengine/websockets/pom.xml @@ -0,0 +1,76 @@ + + + 4.0.0 + war + 1.0-SNAPSHOT + com.example.managedvms + websockets + + + javax.servlet + javax.servlet-api + 3.1.0 + jar + provided + + + javax.websocket + javax.websocket-api + 1.1 + + + org.glassfish.tyrus + tyrus-server + 1.12 + + + org.glassfish.tyrus + tyrus-container-grizzly-server + 1.12 + + + jstl + jstl + 1.2 + + + taglibs + standard + 1.1.2 + + + com.google.guava + guava + 18.0 + + + + + ${project.build.directory}/${project.build.finalName}/WEB-INF/classes + + + org.apache.maven.plugins + maven-war-plugin + 2.6 + + false + + + + org.apache.maven.plugins + 3.3 + maven-compiler-plugin + + 1.7 + 1.7 + + + + com.google.appengine + gcloud-maven-plugin + 2.0.9.89.v20151202 + + + + diff --git a/appengine/websockets/src/main/java/com/example/managedvms/websockets/EchoEndpoint.java b/appengine/websockets/src/main/java/com/example/managedvms/websockets/EchoEndpoint.java new file mode 100644 index 00000000000..44744e0e3f7 --- /dev/null +++ b/appengine/websockets/src/main/java/com/example/managedvms/websockets/EchoEndpoint.java @@ -0,0 +1,32 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.websockets; + +import javax.websocket.OnMessage; +import javax.websocket.Session; +import javax.websocket.server.ServerEndpoint; + +// [START example] +@ServerEndpoint(value = "/echo") +public class EchoEndpoint { + + @OnMessage + public String echo(String text, Session session) { + return text; + } +} +// [END example] diff --git a/appengine/websockets/src/main/java/com/example/managedvms/websockets/WebsocketServlet.java b/appengine/websockets/src/main/java/com/example/managedvms/websockets/WebsocketServlet.java new file mode 100644 index 00000000000..3bfde7ac350 --- /dev/null +++ b/appengine/websockets/src/main/java/com/example/managedvms/websockets/WebsocketServlet.java @@ -0,0 +1,74 @@ +/** + * Copyright 2015 Google Inc. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.managedvms.websockets; + +import com.google.common.io.CharStreams; + +import org.glassfish.tyrus.server.Server; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.websocket.DeploymentException; + +// [START example] +@SuppressWarnings("serial") +public class WebsocketServlet extends HttpServlet { + + private static String METADATA_NETWORK_INTERFACE_URL = + "http://metadata/computeMetadata/v1/instance/network-interfaces/0/access-configs/0/external-ip"; + private static String EXTERNAL_IP = "localhost"; + + @Override + public void init() throws ServletException { + EXTERNAL_IP = getExternalIp(); + Server server = new Server(EXTERNAL_IP, 65080, "/", null, EchoEndpoint.class); + try { + server.start(); + } catch (DeploymentException e) { + throw new ServletException("Deployment error", e); + } + } + + @Override + public void service(HttpServletRequest req, HttpServletResponse resp) throws IOException, + ServletException { + req.getSession().getServletContext().setAttribute("external_ip", EXTERNAL_IP); + req.getRequestDispatcher("/index.jsp").forward(req, resp); + } + + public static String getExternalIp() { + try { + URL url = new URL(METADATA_NETWORK_INTERFACE_URL); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + con.setRequestProperty("Metadata-Flavor", "Google"); + try (InputStreamReader in = new InputStreamReader(con.getInputStream(), "UTF-8")) { + return CharStreams.toString(in); + } + } catch (IOException e) { + return "localhost"; + } + } +} +// [END example] diff --git a/appengine/websockets/src/main/webapp/WEB-INF/appengine-web.xml b/appengine/websockets/src/main/webapp/WEB-INF/appengine-web.xml new file mode 100644 index 00000000000..27ed6b4e59c --- /dev/null +++ b/appengine/websockets/src/main/webapp/WEB-INF/appengine-web.xml @@ -0,0 +1,14 @@ + + + true + true + true + + + + + + 65080 + websocket + + diff --git a/appengine/websockets/src/main/webapp/WEB-INF/web.xml b/appengine/websockets/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 00000000000..b8a448b7e1b --- /dev/null +++ b/appengine/websockets/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,10 @@ + + + websockets + com.example.managedvms.websockets.WebsocketServlet + + + websockets + / + + diff --git a/appengine/websockets/src/main/webapp/index.jsp b/appengine/websockets/src/main/webapp/index.jsp new file mode 100644 index 00000000000..52962632660 --- /dev/null +++ b/appengine/websockets/src/main/webapp/index.jsp @@ -0,0 +1,65 @@ +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> + + + + Google Managed VMs - Java Websockets Echo + + + + +

Echo demo

+
+ + +
+
+

Response:

+

+  
+
+

Status:

+

+  
+ + + + +