/* Copyright (c) 2008 Google Inc. * * 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 sample.appsforyourdomain.labs.provisioning; import com.google.gdata.client.appsforyourdomain.AppsPropertyService; import com.google.gdata.data.Link; import com.google.gdata.data.appsforyourdomain.AppsForYourDomainException; import com.google.gdata.data.appsforyourdomain.generic.GenericEntry; import com.google.gdata.data.appsforyourdomain.generic.GenericFeed; import com.google.gdata.util.AuthenticationException; import com.google.gdata.util.ServiceException; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; /** * Sample client that uses multi-domain feeds to create users, aliases in one of * the user's domains. * * * */ public class ProvisioningApiMultiDomainSampleClient { private AppsPropertyService service; private String domain = null; public enum UserProperty { USER_EMAIL, PASSWORD, FIRST_NAME, LAST_NAME, HASH_FUNCTION, ADMIN, SUSPENDED, CHANGE_PASSWORD_AT_NEXT_LOGIN, QUOTA, IP_WHITELIST } public static Logger LOGGER = Logger.getLogger(ProvisioningApiMultiDomainSampleClient.class.getName()); /** * Parameterized constructor for authentication. * * @param adminEmail Domain administrator's email address * @param password admin account password * @param domain the primary domain name * @param appName application identifier * @throws AuthenticationException If an authentication error occurs. */ public ProvisioningApiMultiDomainSampleClient(String adminEmail, String password, String domain, String appName) throws AuthenticationException { this(domain, appName); service.setUserCredentials(adminEmail, password); } /** * Constructor for credential-less services - OAuth. */ public ProvisioningApiMultiDomainSampleClient(String domain, String appName) { service = new AppsPropertyService(appName); this.domain = domain; } /** * Creates an alias email for the user identified by the given email address. * * @param aliasEmail The alias email to create for the given user. * @param userEmail User's primary email address. * @return the newly created alias GenericEntry instance. * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public GenericEntry createAlias(String aliasEmail, String userEmail) throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { GenericEntry entry = new GenericEntry(); entry.addProperty("userEmail", userEmail); entry.addProperty("aliasEmail", aliasEmail); return service.insert(new URL("https://apps-apis.google.com/a/feeds/alias/2.0/" + domain), entry); } /** * Retrieves the alias entry for the given email alias. * * @param aliasEmail the user email alias. * @return GenericEntry * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public GenericEntry retrieveAlias(String aliasEmail) throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { return service.getEntry(new URL("https://apps-apis.google.com/a/feeds/alias/2.0/" + domain + "/" + aliasEmail), GenericEntry.class); } /** * Utility method that follows the next link and retrieves all pages of a * feed. * * @param feedUrl Url of the feed. * @return a List of GenericEntries in the feed queried. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ private List<GenericEntry> retrieveAllPages(URL feedUrl) throws IOException, ServiceException { List<GenericEntry> allEntries = new ArrayList<GenericEntry>(); try { do { GenericFeed feed = service.getFeed(feedUrl, GenericFeed.class); allEntries.addAll(feed.getEntries()); feedUrl = (feed.getNextLink() == null) ? null : new URL(feed.getNextLink().getHref()); } while (feedUrl != null); } catch (ServiceException se) { AppsForYourDomainException ae = AppsForYourDomainException.narrow(se); throw (ae != null) ? ae : se; } return allEntries; } /** * Retrieves all email aliases created in the customer domain. If you have more than * a few hundred aliases, you must use <code>retrieveFirstPageOfAliases</code> and * <code>retrieveNextPage</code>. * * @return a List of GenericEntry objects. * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public List<GenericEntry> retrieveAllAliases() throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { return retrieveAllPages(new URL("https://apps-apis.google.com/a/feeds/alias/2.0/" + domain)); } /** * Retrieves first page of email aliases created in the customer domain. To * retrieve subsequent pages, use <code>retrieveNextPage</code> with * <code>GenericFeed.getNextLink()</code> * * @return a List of GenericEntry objects. * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public GenericFeed retrieveFirstPageOfAliases() throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { return service.getFeed(new URL("https://apps-apis.google.com/a/feeds/alias/2.0/" + domain), GenericFeed.class); } /** * Retrieves all aliases created for the user identified by the given email * address. * * @param userEmail * @return a List of GenericEntry objects * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public List<GenericEntry> retrieveAllUserAliases(String userEmail) throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { return retrieveAllPages(new URL( "https://apps-apis.google.com/a/feeds/alias/2.0/" + domain + "?userEmail=" + userEmail)); } /** * Deletes the given alias. * * @param aliasEmail * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public void deleteAlias(String aliasEmail) throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { service.delete(new URL("https://apps-apis.google.com/a/feeds/alias/2.0/" + domain + "/" + aliasEmail)); } /** * Creates a new user with the given email address in the customer domain. * * @param email User email of the new account. * @param password * @param firstName * @param lastName * @return a GenericEntry instance of the newly created user. * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public GenericEntry createUser(String email, String password, String firstName, String lastName) throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { GenericEntry entry = new GenericEntry(); entry.addProperty("userEmail", email); entry.addProperty("password", password); entry.addProperty("firstName", firstName); entry.addProperty("lastName", lastName); return service .insert(new URL("https://apps-apis.google.com/a/feeds/user/2.0/" + domain), entry); } /** * Creates a user with one or more optional attributes set. * * @param email * @param password * @param firstName * @param lastName * @param optionalAttributes a hashmap of user property * <code>UserProperty</code> and values. * @return a GenericEntry instance of the newly created user. * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public GenericEntry createUser(String email, String password, String firstName, String lastName, Map<UserProperty, String> optionalAttributes) throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { GenericEntry entry = new GenericEntry(); entry.addProperty("userEmail", email); entry.addProperty("password", password); entry.addProperty("firstName", firstName); entry.addProperty("lastName", lastName); for (Map.Entry<UserProperty, String> mapEntry : optionalAttributes.entrySet()) { String value = mapEntry.getValue(); if (value == null || value.length() == 0) { continue; } switch (mapEntry.getKey()) { case HASH_FUNCTION: entry.addProperty("name", value); break; case ADMIN: entry.addProperty("isAdmin", value); break; case SUSPENDED: entry.addProperty("isSuspended", value); break; case CHANGE_PASSWORD_AT_NEXT_LOGIN: entry.addProperty("isChangePasswordAtNextLogin", value); break; case QUOTA: entry.addProperty("quotaInGb", value); break; case IP_WHITELIST: entry.addProperty("ipWhitelisted", value); break; default: break; } } return service .insert(new URL("https://apps-apis.google.com/a/feeds/user/2.0/" + domain), entry); } /** * * @param email * @return a GenricEntry instance * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public GenericEntry retrieveUser(String email) throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { return service.getEntry(new URL("https://apps-apis.google.com/a/feeds/user/2.0/" + domain + "/" + email), GenericEntry.class); } /** * Retrieves a feed of all users in the customer domain. If you have more than * a few hundred users, you must use <code>retrieveFirstPageOfUsers</code> and * <code>retrieveNextPage</code>. * * @return a list of GenericEntry objects * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public List<GenericEntry> retrieveAllUsers() throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { return retrieveAllPages(new URL("https://apps-apis.google.com/a/feeds/user/2.0/" + domain)); } /** * Retrieves the first page of users. To retrieve subsequent pages, use * <code>retrieveNextPage</code> with <code>GenericFeed.getNextLink()</code> * * @return a page of user entries. * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public GenericFeed retrieveFirstPageOfUsers() throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { return service.getFeed(new URL("https://apps-apis.google.com/a/feeds/user/2.0/" + domain), GenericFeed.class); } /** * Retrieves a single page of entries given an atom:link. * * @param next the next atom:link which can be obtained from a feed * <code>GenericFeed.getNextLink()</code> * @return a GenericFeed with a single page of entries. * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public GenericFeed retrieveNextPage(Link next) throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { return service.getFeed(new URL(next.getHref()), GenericFeed.class); } /** * Updates the given user attributes. * * @param email * @param updatedAttributes a key-Value map of attributes to be updated * @return updated GenericEntry * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public GenericEntry updateUser(String email, Map<String, String> updatedAttributes) throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { GenericEntry entry = new GenericEntry(); entry.addProperties(updatedAttributes); return service.update(new URL("https://apps-apis.google.com/a/feeds/user/2.0/" + domain + "/" + email), entry); } /** * deletes the given user account from the customer domain. * * @param email * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public void deleteUser(String email) throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { service .delete(new URL("https://apps-apis.google.com/a/feeds/user/2.0/" + domain + "/" + email)); } /** * changes the primary email address of the user to the given email address * * @param oldEmailAddress * @param newEmailAddress * @return the updated GenericEntry * @throws AppsForYourDomainException If a Provisioning API specific error * occurs. * @throws ServiceException If a generic GData framework error occurs. * @throws IOException If an error occurs communicating with the GData * service. */ public GenericEntry updateEmailAddress(String oldEmailAddress, String newEmailAddress) throws AppsForYourDomainException, MalformedURLException, IOException, ServiceException { GenericEntry entry = new GenericEntry(); entry.addProperty("userEmail", oldEmailAddress); entry.addProperty("newEmail", newEmailAddress); return service.update(new URL("https://apps-apis.google.com/a/feeds/user/userEmail/2.0/" + domain + "/" + oldEmailAddress), entry); } /** * The main driver for the sample. * * @param args java ProvisioningApiMultiDomainSampleClient [admin@example.com] * [adminpassword] [primarydomain] [secondarydomain] */ public static void main(String[] args) { if (args.length != 4) { System.out .println("Usage: java ProvisioningApiMultiDomainSampleClient <admin@example.com> " + "<adminpassword> <primarydomain> <secondarydomain>"); System.exit(1); } String adminEmail = args[0]; String adminPassword = args[1]; String primaryDomain = args[2]; String secondaryDomain = args[3]; try { ProvisioningApiMultiDomainSampleClient client = new ProvisioningApiMultiDomainSampleClient(adminEmail, adminPassword, primaryDomain, "multidomain-api-sample-" + primaryDomain); long time = System.currentTimeMillis(); String userEmail = "test-" + time + "@" + secondaryDomain; GenericEntry entry = client.createUser(userEmail, "p@ssw0rd", "firstName", "lastName"); LOGGER.log(Level.INFO, "Created user - " + entry.getProperty("userEmail")); entry = client.retrieveUser(userEmail); LOGGER.log(Level.INFO, "Retrieved user - " + entry.getProperty("userEmail")); // create user with optional attributes Map<UserProperty, String> optionalAttributes = new HashMap<UserProperty, String>(); optionalAttributes.put(UserProperty.ADMIN, String.valueOf(true)); optionalAttributes.put(UserProperty.SUSPENDED, String.valueOf(false)); optionalAttributes.put(UserProperty.HASH_FUNCTION, "MD5"); entry = client.createUser("test2-" + time + "@" + secondaryDomain, "0f359740bd1cda994f8b55330c86d845", "firstName", "lastName", optionalAttributes); LOGGER.log(Level.INFO, "Created user with optional attributes- " + entry.getProperty("userEmail")); Map<String, String> updatedAttributes = new HashMap<String, String>(); updatedAttributes.put("lastName", "Smith"); updatedAttributes.put("isSuspended", "true"); entry = client.updateUser(userEmail, updatedAttributes); LOGGER.log(Level.INFO, "Updated user - " + entry.getProperty("lastName")); List<GenericEntry> users = client.retrieveAllUsers(); LOGGER.log(Level.INFO, "Retrieved all users - " + users.size()); // Alias operations String aliasEmail = "alias-" + time + "@" + secondaryDomain; entry = client.createAlias(aliasEmail, userEmail); LOGGER.log(Level.INFO, "Created alias - " + entry.getProperty("aliasEmail")); entry = client.retrieveAlias(aliasEmail); LOGGER.log(Level.INFO, "Retrieved alias - " + entry.getProperty("aliasEmail")); List<GenericEntry> aliases = client.retrieveAllAliases(); LOGGER.log(Level.INFO, "Retrieved all aliases - " + users.size()); // cleanup client.deleteAlias(aliasEmail); LOGGER.log(Level.INFO, "Deleted - " + aliasEmail); client.deleteUser(userEmail); LOGGER.log(Level.INFO, "Deleted - " + userEmail); client.deleteUser("test2-" + time + "@" + secondaryDomain); } catch (AuthenticationException e) { e.printStackTrace(); } catch (AppsForYourDomainException e) { e.printStackTrace(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ServiceException e) { e.printStackTrace(); } } }