diff --git a/dump/LogFilterImpl.java b/dump/LogFilterImpl.java
new file mode 100644
index 00000000000..bc90d3dedbe
--- /dev/null
+++ b/dump/LogFilterImpl.java
@@ -0,0 +1,35 @@
+package mysite.server;
+
+import java.io.IOException;
+import java.util.logging.Logger;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+public class LogFilterImpl implements Filter {
+
+ private FilterConfig filterConfig;
+ private static final Logger log = Logger.getLogger(LogFilterImpl.class.getName());
+
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
+ throws IOException, ServletException {
+ log.warning("Log filter processed a " + getFilterConfig().getInitParameter("logType")
+ + " request");
+
+ filterChain.doFilter(request, response);
+ }
+
+ public FilterConfig getFilterConfig() {
+ return filterConfig;
+ }
+
+ public void init(FilterConfig filterConfig) {
+ this.filterConfig = filterConfig;
+ }
+
+ public void destroy() {}
+
+}
diff --git a/dump/appconfig.xml b/dump/appconfig.xml
new file mode 100644
index 00000000000..22fc19790c9
--- /dev/null
+++ b/dump/appconfig.xml
@@ -0,0 +1,226 @@
+// [START pagespeed_example]
+
+ *.cdn.myapp.com
+ www.flickr.com
+ http://*/*.svg
+ http://secure.foo.com/*
+ CollapseWhitespace
+ CombineJs
+ ProxyImages
+
+
+// [END pagespeed_example]
+
+// [START custom_error_example]
+
+
+
+
+// [END custom_error_example]
+
+// [START expiration_example]
+
+
+
+// [END expiration_example]
+
+// [START expiration_example_yaml]
+static_files:
+- include: /**.png
+expiration: 4d 5h
+// [END expiration_example_yaml]
+
+// [START static_codesample_xml]
+
+
+
+ // [END static_codesample_xml]
+
+ // [START static_codesample_yaml]
+ static_files:
+ - include: /**.png
+ - exclude: /data/**.png
+ // [END static_codesample_yaml]
+
+ // [START resource_codesample_xml]
+
+
+
+ // [END resource_codesample_xml]
+
+ // [START resource_codesample_yaml]
+ resource_files:
+ - include: /**.xml
+ - exclude: /feeds/**.xml
+ // [END resource_codesample_yaml]
+
+ //[START header_codesample_xml]
+
+
+
+
+
+ //[END header_codesample_xml]
+
+ //[START header_codesample_yaml]
+ static_files:
+ - include: /static/*
+ http_headers:
+ Access-Control-Allow-Origin: http://example.org
+ //[END header_codesample_yaml]
+
+ //[START mapper_codesample_yaml]
+ handlers:
+ - url: /red/*
+ servlet: mysite.server.TeamServlet
+ init_params:
+ teamColor: red
+ bgColor: "#CC0000"
+ name: redteam
+ - url: /blue/*
+ servlet: mysite.server.TeamServlet
+ init_params:
+ teamColor: blue
+ bgColor: "#0000CC"
+ name: blueteam
+ - url: /register/*
+ jsp: /register/start.jsp
+ - url: /*.special
+ filter: mysite.server.LogFilterImpl
+ init_params:
+ logType: special
+ //[END mapper_codesample_yaml]
+
+ //[START environment_variables]
+
+
+
+
+
+
+
+
+
+ //[END environment_variables]
+
+ //[START environment_variables_yaml]
+ system_properties:
+ myapp.maximum-message-length: 140
+ myapp.notify-every-n-signups: 1000
+ myapp.notify-url: http://www.example.com/signupnotify
+ env_variables:
+ DEFAULT_ENCODING: UTF-8
+ context_params:
+ rack.env: production
+ //[END environment_variables_yaml]
+
+ //[START inbound_services]
+
+ mail
+ warmup
+
+ //[END inbound_services]
+
+ //[START admin_console_custom_pages]
+
+
+
+
+ //[END admin_console_custom_pages]
+
+ //[START about_app_yaml_example]
+ application: myapp
+ version: alpha-001
+ runtime: java
+ api_version: 1
+
+ handlers:
+ - url: /admin/*
+ login: admin
+ //[END about_app_yaml_example]
+
+ //[START minimal_appengine_web_xml]
+
+
+ _your_app_id_
+ alpha-001
+ true
+
+ //[END minimal_appengine_web_xml]
+
+ //[START secure_handler_yaml]
+ handlers:
+
+ - url: /youraccount/*
+ login: required
+ secure: always
+ //[END secure_handler_yaml]
+
+ //[START servlet_listeners]
+ listeners:
+ - com.example.MyListener
+ - com.example.MyOtherListener
+ //[END servlet_listeners]
+
+ //[START login_example_yaml]
+ handlers:
+
+ - url: /profile/*
+ login: required
+
+ - url: /admin/*
+ servlet: com.example.AdminServlet
+ login: admin
+ //[END login_example_yaml]
+
+ //[START welcome_files]
+ welcome_files:
+ - index.jsp
+ - index.html
+ //[END welcome_files]
+
+ //[START load_on_startup]
+
+ my-servlet
+ com.company.MyServlet
+ 1
+
+ //[END load_on_startup]
+
+ //[START ServletContextListener]
+
+ com.company.MyListener
+
+ //[END ServletContextListener]
+
+ //[START listener_filter]
+ public class MyListener implements ServletContextListener {
+ public void contextInitialized(ServletContextEvent event) {
+ // This will be invoked as part of a warmup request, or the first user
+ // request if no warmup request was invoked.
+ }
+ public void contextDestroyed(ServletContextEvent event) {
+ // App Engine does not currently invoke this method.
+ }
+ }
+ //[END listener_filter]
+
+ //[START custom_warmup_servlet]
+
+ _ah_warmup
+ com.company.MyWarmupServlet
+ //[END custom_warmup_servlet]
+
+ //[START warmup_yaml]
+ inbound_services:
+ - xmpp_message
+ - mail
+ //[END warmup_yaml]
+
+ //[START custom_xml_output]
+ web_xml: |
+
+ 500
+ /errors/servererror.jsp
+
+ //[END custom_xml_output]
diff --git a/dump/appidentity.java b/dump/appidentity.java
new file mode 100644
index 00000000000..37178ce21b9
--- /dev/null
+++ b/dump/appidentity.java
@@ -0,0 +1,56 @@
+// [START versioned_hostnames]
+public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ resp.setContentType("text/plain");
+ Environment env = ApiProxy.getCurrentEnvironment();
+ resp.getWriter().println("default_version_hostname: "
+ + env.getAttributes().get("com.google.appengine.runtime.default_version_hostname"));
+}
+// [END versioned_hostnames]
+
+// [START asserting_identity_to_Google_APIs]
+import com.google.appengine.api.appidentity.AppIdentityService;
+import com.google.appengine.api.appidentity.AppIdentityServiceFactory;
+import java.io.OutputStreamWriter;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+// Note that any JSON parser can be used; this one is used for illustrative purposes.
+import org.json.JSONObject;
+import org.json.JSONTokener;
+
+
+public String createShortUrl(String longUrl) throws Exception {
+ try {
+ ArrayList scopes = new ArrayList();
+ scopes.add("https://www.googleapis.com/auth/urlshortener");
+ AppIdentityService appIdentity = AppIdentityServiceFactory.getAppIdentityService();
+ AppIdentityService.GetAccessTokenResult accessToken = appIdentity.getAccessToken(scopes);
+ // The token asserts the identity reported by appIdentity.getServiceAccountName()
+ JSONObject request = new JSONObject();
+ request.put("longUrl", longUrl);
+
+ URL url = new URL("https://www.googleapis.com/urlshortener/v1/url?pp=1");
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setDoOutput(true);
+ connection.setRequestMethod("POST");
+ connection.addRequestProperty("Content-Type", "application/json");
+ connection.addRequestProperty("Authorization", "Bearer " + accessToken.getAccessToken());
+
+ OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
+ request.write(writer);
+ writer.close();
+
+ if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
+ // Note: Should check the content-encoding.
+ JSONTokener response_tokens = new JSONTokener(connection.getInputStream());
+ JSONObject response = new JSONObject(response_tokens);
+ return (String) response.get("id");
+ } else {
+ throw new Exception();
+ }
+ } catch (Exception e) {
+ // Error handling elided.
+ throw e;
+ }
+}
+// [END asserting_identity_to_Google_APIs]
diff --git a/dump/backends.java b/dump/backends.java
new file mode 100644
index 00000000000..33ced192756
--- /dev/null
+++ b/dump/backends.java
@@ -0,0 +1,48 @@
+// [START shutdown_1]
+LifecycleManager.getInstance().setShutdownHook(new ShutdownHook() {
+ public void shutdown() {
+ LifecycleManager.getInstance().interruptAllRequests();
+ }
+});
+// [END shutdown_1]
+
+// [START shutdown_2]
+while (haveMoreWork() &&
+ !LifecycleManager.getInstance().isShuttingDown()) {
+ doSomeWork();
+ saveState();
+ }
+// [END shutdown_2]
+
+// [START addressing_backends]
+import com.google.appengine.api.backends.BackendService;
+import com.google.appengine.api.backends.BackendServiceFactory;
+
+BackendService backendsApi = BackendServiceFactory.getBackendService();
+
+// Get the backend handling the current request.
+String currentBackendName = backendsApi.getCurrentBackend();
+// Get the backend instance handling the current request.
+int currentInstance = backendsApi.getCurrentInstance();
+// [END addressing_backends]
+
+// [START background_threads]
+import com.google.appengine.api.ThreadManager;
+import java.util.concurrent.AtomicLong;
+
+AtomicLong counter = new AtomicLong();
+
+Thread thread = ThreadManager.createBackgroundThread(new Runnable() {
+ public void run() {
+ try {
+ while (true) {
+ counter.incrementAndGet();
+ Thread.sleep(10);
+ }
+ } catch (InterruptedException ex) {
+ throw new RuntimeException("Interrupted in loop:", ex);
+ }
+ }
+});
+thread.start();
+// [END background_threads]
diff --git a/dump/backends.xml b/dump/backends.xml
new file mode 100644
index 00000000000..a53bcb4fd99
--- /dev/null
+++ b/dump/backends.xml
@@ -0,0 +1,29 @@
+
+
+
+ B8
+ 5
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+ B4
+
+
+
diff --git a/dump/capabilities.java b/dump/capabilities.java
new file mode 100644
index 00000000000..40978a27ade
--- /dev/null
+++ b/dump/capabilities.java
@@ -0,0 +1,20 @@
+// [START image_resize]
+import com.google.appengine.api.capabilities.*;
+
+CapabilitiesService service =
+CapabilitiesServiceFactory.getCapabilitiesService();
+CapabilityStatus status = service.getStatus(Capability.IMAGES).getStatus();
+
+if (status == CapabilityStatus.DISABLED) {
+ // Images API is not available.
+}
+// [END image_resize]
+
+// [START intro]
+CapabilityStatus status =
+service.getStatus(Capability.DATASTORE_WRITE).getStatus();
+
+if (status == CapabilityStatus.DISABLED) {
+ // Datastore is in read-only mode.
+}
+// [END intro]
diff --git a/dump/channel.java b/dump/channel.java
new file mode 100644
index 00000000000..5950d4b7176
--- /dev/null
+++ b/dump/channel.java
@@ -0,0 +1,80 @@
+// [START create_channel_1]
+public class TicTacToeServlet extends HttpServlet {
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ // Game creation, user sign-in, etc. omitted for brevity.
+ String userId = userService.getCurrentUser().getUserId();
+
+ ChannelService channelService = ChannelServiceFactory.getChannelService();
+
+ // The 'Game' object exposes a method which creates a unique string based on the game's key
+ // and the user's id.
+ String token = channelService.createChannel(game.getChannelKey(userId));
+
+ // Index is the contents of our index.html resource, details omitted for brevity.
+ index = index.replaceAll("\\{\\{ token \\}\\}", token);
+
+ resp.setContentType("text/html");
+ resp.getWriter().write(index);
+ }
+}
+// [END create_channel_1]
+
+// [START create_channel_2]
+
+
+
+// [END create_channel_2]
+
+// [START validate_message]
+public class Game {
+ // member variables, etc omitted for brevity.
+
+ public String getChannelKey(String user) {
+ return user + KeyFactory.keyToString(key);
+ }
+
+ private void sendUpdateToUser(String user) {
+ if (user != null) {
+ ChannelService channelService = ChannelServiceFactory.getChannelService();
+ String channelKey = getChannelKey(user);
+ channelService.sendMessage(new ChannelMessage(channelKey, getMessageString()));
+ }
+ }
+
+ public void sendUpdateToClients() {
+ sendUpdateToUser(userX);
+ sendUpdateToUser(userO);
+ }
+}
+
+public class MoveServlet extends HttpServlet {
+ @Override
+ public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ String gameId = req.getParameter("g");
+ Game game = pm.getObjectById(Game.class, KeyFactory.stringToKey(gameId));
+
+ // Code to retrieve user id, check rules and update game omitted for brevity
+ game.sendUpdateToClients();
+ }
+}
+// [END validate_message]
+
+// [START tracking_client_connections_and_disconnections]
+
+channel_presence
+
+// [END tracking_client_connections_and_disconnections]
+
+// [START channel_presence]
+// In the handler for _ah/channel/connected/
+ChannelService channelService = ChannelServiceFactory.getChannelService();
+ChannelPresence presence = channelService.parsePresence(req);
+// [END channel_presence]
diff --git a/dump/cloud-sql.java b/dump/cloud-sql.java
new file mode 100644
index 00000000000..da26816732a
--- /dev/null
+++ b/dump/cloud-sql.java
@@ -0,0 +1,201 @@
+// [START import]
+import java.io.*;
+import javax.servlet.http.*;
+import java.sql.*;
+// [END register_the_JDBC_driver]
+
+// [START connect_and_post_to_your_database_1]
+import java.io.*;
+import java.sql.*;
+import javax.servlet.http.*;
+import com.google.appengine.api.utils.SystemProperty;
+
+public class GuestbookServlet extends HttpServlet {
+ @Override
+ public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
+ String url = null;
+ try {
+ if (SystemProperty.environment.value() ==
+ SystemProperty.Environment.Value.Production) {
+ // Load the class that provides the new "jdbc:google:mysql://" prefix.
+ Class.forName("com.mysql.jdbc.GoogleDriver");
+ url = "jdbc:google:mysql://your-project-id:your-instance-name/guestbook?user=root";
+ } else {
+ // Local MySQL instance to use during development.
+ Class.forName("com.mysql.jdbc.Driver");
+ url = "jdbc:mysql://127.0.0.1:3306/guestbook?user=root";
+
+ // Alternatively, connect to a Google Cloud SQL instance using:
+ // jdbc:mysql://ip-address-of-google-cloud-sql-instance:3306/guestbook?user=root
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ return;
+ }
+
+ PrintWriter out = resp.getWriter();
+ try {
+ Connection conn = DriverManager.getConnection(url);
+ try {
+ String fname = req.getParameter("fname");
+ String content = req.getParameter("content");
+ if (fname == "" || content == "") {
+ out.println(
+ "You are missing either a message or a name! Try again! " +
+ "Redirecting in 3 seconds...");
+ } else {
+ String statement = "INSERT INTO entries (guestName, content) VALUES( ? , ? )";
+ PreparedStatement stmt = conn.prepareStatement(statement);
+ stmt.setString(1, fname);
+ stmt.setString(2, content);
+ int success = 2;
+ success = stmt.executeUpdate();
+ if (success == 1) {
+ out.println(
+ "Success! Redirecting in 3 seconds...");
+ } else if (success == 0) {
+ out.println(
+ "Failure! Please try again! " +
+ "Redirecting in 3 seconds...");
+ }
+ }
+ } finally {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ }
+ resp.setHeader("Refresh", "3; url=/guestbook.jsp");
+ }
+}
+// [END connect_and_post_to_your_database_1]
+
+// [START connect_and_post_to_your_database_2]
+Connection conn = DriverManager.getConnection(
+ "jdbc:google:mysql://your-project-id:your-instance-name/database",
+ "user", "password");
+// [END connect_and_post_to_your_database_2]
+
+// [START create_your_webform]
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ page import="java.util.List" %>
+<%@ page import="java.sql.*" %>
+<%@ page import="com.google.appengine.api.utils.SystemProperty" %>
+
+
+
+
+<%
+String url = null;
+if (SystemProperty.environment.value() ==
+ SystemProperty.Environment.Value.Production) {
+ // Load the class that provides the new "jdbc:google:mysql://" prefix.
+ Class.forName("com.mysql.jdbc.GoogleDriver");
+ url = "jdbc:google:mysql://your-project-id:your-instance-name/guestbook?user=root";
+} else {
+ // Local MySQL instance to use during development.
+ Class.forName("com.mysql.jdbc.Driver");
+ url = "jdbc:mysql://127.0.0.1:3306/guestbook?user=root";
+}
+
+Connection conn = DriverManager.getConnection(url);
+ResultSet rs = conn.createStatement().executeQuery(
+ "SELECT guestName, content, entryID FROM entries");
+%>
+
+
+
+
+Name |
+Message |
+ID |
+
+
+<%
+while (rs.next()) {
+ String guestName = rs.getString("guestName");
+ String content = rs.getString("content");
+ int id = rs.getInt("entryID");
+ %>
+
+ <%= guestName %> |
+ <%= content %> |
+ <%= id %> |
+
+ <%
+}
+conn.close();
+%>
+
+
+
+
+No more messages!
+Sign the guestbook!
+
+
+
+// [END create_your_webform]
+
+// [START map_your_servlet]
+
+
+
+sign
+guestbook.GuestbookServlet
+
+
+sign
+/sign
+
+
+guestbook.jsp
+
+
+// [END map_your_servlet]
+
+// [START enable_connector_j]
+
+
+...
+true
+
+// [END enable_connector_j]
+
+// [START persistence_pattern]
+import java.util.Map;
+import java.util.HashMap;
+import com.google.appengine.api.utils.SystemProperty;
+
+...
+// Set the persistence driver and url based on environment, production or local.
+Map properties = new HashMap();
+if (SystemProperty.environment.value() ==
+ SystemProperty.Environment.Value.Production) {
+ properties.put("javax.persistence.jdbc.driver",
+ "com.mysql.jdbc.GoogleDriver");
+ properties.put("javax.persistence.jdbc.url",
+ "jdbc:google:mysql://your-project-id:your-instance-name/demo");
+} else {
+ properties.put("javax.persistence.jdbc.driver",
+ "com.mysql.jdbc.Driver");
+ properties.put("javax.persistence.jdbc.url",
+ "jdbc:mysql://127.0.0.1:3306/demo");
+}
+
+// Create a EntityManager which will perform operations on the database.
+EntityManagerFactory emf = Persistence.createEntityManagerFactory(
+ "persistence-unit-name", propertiesMap);
+...
+// [END persistence_pattern]
diff --git a/dump/index.java b/dump/index.java
new file mode 100644
index 00000000000..3c0778adfba
--- /dev/null
+++ b/dump/index.java
@@ -0,0 +1,78 @@
+//[START requests_and_servlets]
+import java.io.IOException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class MyServlet extends HttpServlet {
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws IOException {
+ resp.setContentType("text/plain");
+ resp.getWriter().println("Hello, world");
+ }
+}
+// [END requests_and_servlets]
+
+// [START class_loader_JAR_ordering]
+
+
+
+// [END class_loader_JAR_ordering]
+
+//[START no_signed_JAR_files]
+ java.lang.SecurityException: SHA1 digest error for com/example/SomeClass.class
+ at com.google.appengine.runtime.Request.process-d36f818a24b8cf1d(Request.java)
+ at sun.security.util.ManifestEntryVerifier.verify(ManifestEntryVerifier.java:210)
+ at java.util.jar.JarVerifier.processEntry(JarVerifier.java:218)
+ at java.util.jar.JarVerifier.update(JarVerifier.java:205)
+ at java.util.jar.JarVerifier$VerifierStream.read(JarVerifier.java:428)
+ at sun.misc.Resource.getBytes(Resource.java:124)
+ at java.net.URLClassLoader.defineClass(URLClassLoader.java:273)
+ at sun.reflect.GeneratedMethodAccessor5.invoke(Unknown Source)
+ at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+ at java.lang.reflect.Method.invoke(Method.java:616)
+at java.lang.ClassLoader.loadClass(ClassLoader.java:266)
+//[END no_signed_JAR_files]
+
+//[START logging_1]
+ import java.util.logging.Logger;
+ ...
+
+ public class MyServlet extends HttpServlet {
+ private static final Logger log = Logger.getLogger(MyServlet.class.getName());
+
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse resp)
+ throws IOException {
+
+ log.info("An informational message.");
+
+ log.warning("A warning message.");
+
+ log.severe("An error message.");
+ }
+ }
+//[END logging_1]
+
+//[START logging_2]
+
+...
+
+
+
+
+
+
+//[END logging_2]
+
+//[START the_environment]
+if (SystemProperty.environment.value() ==
+ SystemProperty.Environment.Value.Production) {
+ The app is running on App Engine...
+ }
+//[END the_environment]
+
+//[START request_IDs]
+com.google.apphosting.api.ApiProxy.getCurrentEnvironment().getAttributes().get("com.google.appengine.runtime.request_log_id")
+//[END request_IDs]
diff --git a/samples/README.md b/samples/README.md
new file mode 100644
index 00000000000..93714092989
--- /dev/null
+++ b/samples/README.md
@@ -0,0 +1,4 @@
+appengine-skeleton
+=============================
+
+This is a generated application from the appengine-skeleton archetype.
diff --git a/samples/nbactions.xml b/samples/nbactions.xml
new file mode 100644
index 00000000000..cfa22117a74
--- /dev/null
+++ b/samples/nbactions.xml
@@ -0,0 +1,52 @@
+
+
+
+ CUSTOM-appengine:devserver
+ appengine:devserver
+
+ appengine:devserver
+
+
+
+ CUSTOM-appengine:update
+ appengine:update
+
+ appengine:update
+
+
+
+ CUSTOM-appengine:rollback
+ appengine:rollback
+
+ appengine:rollback
+
+
+
+ CUSTOM-appengine:update_cron
+ appengine:update_cron
+
+ appengine:update_cron
+
+
+
+ CUSTOM-appengine:update_dos
+ appengine:update_dos
+
+ appengine:update_dos
+
+
+
+ CUSTOM-appengine:update_indexes
+ appengine:update_indexes
+
+ appengine:update_indexes
+
+
+
+ CUSTOM-appengine:update_queues
+ appengine:update_queues
+
+ appengine:update_queues
+
+
+
diff --git a/samples/pom.xml b/samples/pom.xml
new file mode 100644
index 00000000000..4689a833523
--- /dev/null
+++ b/samples/pom.xml
@@ -0,0 +1,156 @@
+
+
+
+ 4.0.0
+ war
+ 1.0-SNAPSHOT
+
+ com.google.appengine.samples
+ samples
+
+
+ 1
+ UTF-8
+
+
+
+ 3.1.0
+
+
+
+
+
+ com.google.appengine
+ appengine-api-1.0-sdk
+ 1.9.18
+
+
+ javax.servlet
+ servlet-api
+ 2.5
+ provided
+
+
+ jstl
+ jstl
+ 1.2
+
+
+
+
+ com.google.appengine
+ appengine-testing
+ 1.9.18
+ test
+
+
+ com.google.appengine
+ appengine-api-stubs
+ 1.9.18
+ test
+
+
+
+
+
+ ${project.build.directory}/${project.build.finalName}/WEB-INF/classes
+
+
+ org.codehaus.mojo
+ versions-maven-plugin
+ 2.1
+
+
+ compile
+
+ display-dependency-updates
+ display-plugin-updates
+
+
+
+
+
+ org.apache.maven.plugins
+ 3.1
+ maven-compiler-plugin
+
+
+ 1.7
+
+
+
+ org.apache.maven.plugins
+ maven-war-plugin
+ 2.4
+
+ true
+
+
+
+ ${basedir}/src/main/webapp/WEB-INF
+ true
+ WEB-INF
+
+
+
+
+
+
+ com.google.appengine
+ appengine-maven-plugin
+ 1.9.18
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+ org.eclipse.m2e
+ lifecycle-mapping
+ 1.0.0
+
+
+
+
+
+
+ org.codehaus.mojo
+
+
+ versions-maven-plugin
+
+
+ [2.1,)
+
+
+
+ display-dependency-updates
+
+
+ display-plugin-updates
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/src/main/java/blobstore.java b/samples/src/main/java/blobstore.java
new file mode 100644
index 00000000000..5dce93c1ef6
--- /dev/null
+++ b/samples/src/main/java/blobstore.java
@@ -0,0 +1,192 @@
+//[START uploading_a_blob_1]
+
+
+
+// [END uploading_a_blob_1]
+
+// [START uploading_a_blob_2]
+Map> blobs = blobstoreService.getUploads(req);
+List blobKeys = blobs.get("myFile");
+
+if (blobKeys == null || blobKeys.isEmpty()) {
+ res.sendRedirect("/");
+} else {
+ res.sendRedirect("/serve?blob-key=" + blobKeys.get(0).getKeyString());
+}
+// [END uploading_a_blob_2]
+
+// [START serving_a_blob]
+public void doGet(HttpServletRequest req, HttpServletResponse res)
+ throws IOException {
+ BlobKey blobKey = new BlobKey(req.getParameter("blob-key"));
+ blobstoreService.serve(blobKey, res);
+ // [END serving_a_blob]
+
+ // [START complete_sample_application]
+ // file Upload.java
+
+ import java.io.IOException;
+ import java.util.List;
+ import java.util.Map;
+
+ import javax.servlet.ServletException;
+ import javax.servlet.http.HttpServlet;
+ import javax.servlet.http.HttpServletRequest;
+ import javax.servlet.http.HttpServletResponse;
+
+ import com.google.appengine.api.blobstore.BlobKey;
+ import com.google.appengine.api.blobstore.BlobstoreService;
+ import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
+
+ public class Upload extends HttpServlet {
+ private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
+
+ @Override
+ public void doPost(HttpServletRequest req, HttpServletResponse res)
+ throws ServletException, IOException {
+
+ Map> blobs = blobstoreService.getUploads(req);
+ List blobKeys = blobs.get("myFile");
+
+ if (blobKeys == null || blobKeys.isEmpty()) {
+ res.sendRedirect("/");
+ } else {
+ res.sendRedirect("/serve?blob-key=" + blobKeys.get(0).getKeyString());
+ }
+ }
+ }
+
+ // file Serve.java
+
+ import java.io.IOException;
+
+ import javax.servlet.http.HttpServlet;
+ import javax.servlet.http.HttpServletRequest;
+ import javax.servlet.http.HttpServletResponse;
+
+ import com.google.appengine.api.blobstore.BlobKey;
+ import com.google.appengine.api.blobstore.BlobstoreService;
+ import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
+
+ public class Serve extends HttpServlet {
+ private BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
+
+ @Override
+ public void doGet(HttpServletRequest req, HttpServletResponse res)
+ throws IOException {
+ BlobKey blobKey = new BlobKey(req.getParameter("blob-key"));
+ blobstoreService.serve(blobKey, res);
+ }
+ }
+
+
+ // file index.jsp
+
+ <%@ page import="com.google.appengine.api.blobstore.BlobstoreServiceFactory" %>
+ <%@ page import="com.google.appengine.api.blobstore.BlobstoreService" %>
+
+ <%
+ BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
+ %>
+
+
+
+
+ Upload Test
+
+
+
+
+
+
+ // web.xml
+
+
+
+
+
+ Upload
+ Upload
+
+
+
+ Serve
+ Serve
+
+
+
+ Upload
+ /upload
+
+
+
+ Serve
+ /serve
+
+
+
+ // [END complete_sample_application]
+
+ // [START writing_files_to_the_Blobstore]
+ // Get a file service
+ FileService fileService = FileServiceFactory.getFileService();
+
+ // Create a new Blob file with mime-type "text/plain"
+ AppEngineFile file = fileService.createNewBlobFile("text/plain");
+
+ // Open a channel to write to it
+ boolean lock = false;
+ FileWriteChannel writeChannel = fileService.openWriteChannel(file, lock);
+
+ // Different standard Java ways of writing to the channel
+ // are possible. Here we use a PrintWriter:
+ PrintWriter out = new PrintWriter(Channels.newWriter(writeChannel, "UTF8"));
+ out.println("The woods are lovely dark and deep.");
+ out.println("But I have promises to keep.");
+
+ // Close without finalizing and save the file path for writing later
+ out.close();
+ String path = file.getFullPath();
+
+ // Write more to the file in a separate request:
+ file = new AppEngineFile(path);
+
+ // This time lock because we intend to finalize
+ lock = true;
+ writeChannel = fileService.openWriteChannel(file, lock);
+
+ // This time we write to the channel directly
+ writeChannel.write(ByteBuffer.wrap
+ ("And miles to go before I sleep.".getBytes()));
+
+ // Now finalize
+ writeChannel.closeFinally();
+
+ // Later, read from the file using the Files API
+ lock = false; // Let other people read at the same time
+ FileReadChannel readChannel = fileService.openReadChannel(file, false);
+
+ // Again, different standard Java ways of reading from the channel.
+ BufferedReader reader =
+ new BufferedReader(Channels.newReader(readChannel, "UTF8"));
+ String line = reader.readLine();
+ // line = "The woods are lovely dark and deep."
+
+ readChannel.close();
+
+ // Now read from the file using the Blobstore API
+ BlobKey blobKey = fileService.getBlobKey(file);
+ BlobstoreService blobStoreService = BlobstoreServiceFactory.getBlobstoreService();
+ String segment = new String(blobStoreService.fetchData(blobKey, 30, 40));
+ // [END writing_files_to_the_Blobstore]
diff --git a/samples/src/main/webapp/WEB-INF/appengine-web.xml b/samples/src/main/webapp/WEB-INF/appengine-web.xml
new file mode 100644
index 00000000000..ed19fa8acb0
--- /dev/null
+++ b/samples/src/main/webapp/WEB-INF/appengine-web.xml
@@ -0,0 +1,10 @@
+
+
+ civil-authority-768
+ ${appengine.app.version}
+ true
+
+
+
+
+
diff --git a/samples/src/main/webapp/WEB-INF/logging.properties b/samples/src/main/webapp/WEB-INF/logging.properties
new file mode 100644
index 00000000000..a17206681f0
--- /dev/null
+++ b/samples/src/main/webapp/WEB-INF/logging.properties
@@ -0,0 +1,13 @@
+# A default java.util.logging configuration.
+# (All App Engine logging is through java.util.logging by default).
+#
+# To use this configuration, copy it into your application's WEB-INF
+# folder and add the following to your appengine-web.xml:
+#
+#
+#
+#
+#
+
+# Set the default logging level for all loggers to WARNING
+.level = WARNING
diff --git a/samples/src/main/webapp/WEB-INF/web.xml b/samples/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 00000000000..28bf558b8fa
--- /dev/null
+++ b/samples/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,4 @@
+
+
+
+