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"); +%> + + + + + + + + + +<% +while (rs.next()) { + String guestName = rs.getString("guestName"); + String content = rs.getString("content"); + int id = rs.getInt("entryID"); + %> + + + + + + <% +} +conn.close(); +%> + + +
NameMessageID
<%= guestName %><%= content %><%= id %>
+
+No more messages! +

Sign the guestbook!

+
+
First Name:
+
Message: +
+
+
+ +
+ + +// [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 + 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] + +
" method="post" enctype="multipart/form-data"> + + +
+ +// [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 + + +
" method="post" enctype="multipart/form-data"> + + + +
+ + + + // 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 @@ + + + +