App Engine Java SDK version 1.9.8
[gae.git] / java / src / main / com / google / appengine / api / NamespaceManager.java
blob73c632bc07fdfcba5a0658e5090a2d6056ba6ad8
1 // Copyright 2009 Google Inc. All Rights Reserved.
3 package com.google.appengine.api;
5 import com.google.apphosting.api.ApiProxy;
6 import com.google.apphosting.api.ApiProxy.Environment;
8 import java.util.Map;
9 import java.util.regex.Pattern;
11 /**
12 * Provides functions for manipulating the current namespace used for
13 * App Engine APIs.
15 * <p>The "current namespace" is the string that is returned by
16 * {@link #get()} and used by a number of APIs including Datatore,
17 * Memcache and Task Queue.
19 * <p>When a namespace aware class (e.g.,
20 * {@link com.google.appengine.api.datastore.Key},
21 * {@link com.google.appengine.api.datastore.Query} and
22 * {@link com.google.appengine.api.memcache.MemcacheService}) is constructed, it
23 * determines which namespace will be used by calling
24 * {@link NamespaceManager#get()} if it is otherwise unspecified. If
25 * {@link NamespaceManager#get()} returns null, the current namespace is unset
26 * and these APIs will use the empty ("") namespace in its place.
28 * <p>Example: <code><pre>
29 * {@link NamespaceManager}.{@link #set}("a-namespace");
30 * MemcacheService memcache = MemcacheServiceFactory.getMemcacheService();
31 * // Store record in namespace "a-namespace"
32 * memcache.put("key1", "value1");
34 * {@link NamespaceManager}.{@link #set}("other-namespace");
35 * // Store record in namespace "other-namespace"
36 * memcache.put("key2", "value2");
38 * MemcacheService boundMemcache =
39 * MemcacheServiceFactory.getMemcacheService("specific-namespace");
40 * {@link NamespaceManager}.{@link #set}("whatever-namespace");
41 * // The record is still stored in namespace "specific-namespace".
42 * boundMemcache.put("key3", "value3");
43 * </pre></code>
45 * <p>MemcacheService {@code memcache} (in the above example) uses the current
46 * namespace and {@code key1} will be stored in namespace {@code "a-namespace"},
47 * while {@code key2} is stored in namespace {@code "other-namespace"}. It is
48 * possible to override the current namespace and store data in specific
49 * namespace. In the above example {@code key3} is stored in namespace
50 * {@code "specific-namespace"}.
52 * <p>The Task Queue {@link com.google.appengine.api.taskqueue.Queue#add}
53 * methods will forward the {@link NamespaceManager} settings into the task
54 * being added causing the added task to be executed with the same current
55 * namespace as the task creator. The exception is that an unset current
56 * namespace (i.e. {@link NamespaceManager#get()} returns null) will be
57 * forwarded as an empty ("") namespace to the created task's requests.
59 * @see <a
60 * href="http://code.google.com/appengine/docs/java/multitenancy/">
61 * Multitenancy and the Namespaces Java API. In <em>Google App Engine
62 * Developer's Guide</em></a>.
64 public final class NamespaceManager {
65 private final static int NAMESPACE_MAX_LENGTH = 100;
66 private final static String NAMESPACE_REGEX = "[0-9A-Za-z._-]{0," + NAMESPACE_MAX_LENGTH +"}";
67 private static final Pattern NAMESPACE_PATTERN = Pattern.compile(NAMESPACE_REGEX);
69 /**
70 * We store the current namespace as an environment attribute identified
71 * by this key.
73 private static final String CURRENT_NAMESPACE_KEY =
74 NamespaceManager.class.getName() + ".currentNamespace";
75 private static final String APPS_NAMESPACE_KEY =
76 NamespaceManager.class.getName() + ".appsNamespace";
78 /**
79 * Set the value used to initialize the namespace of namespace-aware services.
81 * @param newNamespace the new namespace.
82 * @throws IllegalArgumentException if namespace string is invalid.
84 public static void set(String newNamespace) {
85 if (newNamespace == null) {
86 ApiProxy.getCurrentEnvironment().getAttributes().remove(CURRENT_NAMESPACE_KEY);
87 } else {
88 validateNamespace(newNamespace);
89 Environment environment = ApiProxy.getCurrentEnvironment();
90 environment.getAttributes().put(CURRENT_NAMESPACE_KEY, newNamespace);
94 /**
95 * Returns the current namespace setting or {@code null} if not set.
97 * <p>If the current namespace is unset, callers should assume
98 * the use of the "" (empty) namespace in all namespace-aware services.
100 public static String get() {
101 Map<String, Object> attributes = ApiProxy.getCurrentEnvironment().getAttributes();
102 return (String) attributes.get(CURRENT_NAMESPACE_KEY);
106 * Returns the Google Apps domain referring this request or
107 * otherwise the empty string ("").
109 public static String getGoogleAppsNamespace() {
110 Map<String, Object> attributes = ApiProxy.getCurrentEnvironment().getAttributes();
111 String appsNamespace = (String) attributes.get(APPS_NAMESPACE_KEY);
112 return appsNamespace == null ? "" : appsNamespace;
116 * Validate the format of a namespace string.
117 * @throws IllegalArgumentException If the format of the namespace string
118 * is invalid.
120 public static void validateNamespace(String namespace) {
121 if (!NAMESPACE_PATTERN.matcher(namespace).matches()) {
122 throw new IllegalArgumentException(
123 "Namespace '" + namespace + "' does not match pattern '" + NAMESPACE_PATTERN + "'.");
127 private NamespaceManager() {