You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by wo...@apache.org on 2011/10/12 22:10:42 UTC

svn commit: r1182565 [5/9] - in /shindig/trunk: config/ content/samplecontainer/examples/commoncontainer/ content/samplecontainer/examples/oauth2/ features/src/main/javascript/features/core.io/ features/src/main/javascript/features/shindig.xhrwrapper/ ...

Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/JSONOAuth2Persister.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/JSONOAuth2Persister.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/JSONOAuth2Persister.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/JSONOAuth2Persister.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,346 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you 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 org.apache.shindig.gadgets.oauth2.persistence.sample;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.shindig.common.Nullable;
+import org.apache.shindig.common.servlet.Authority;
+import org.apache.shindig.common.util.ResourceLoader;
+import org.apache.shindig.gadgets.oauth2.OAuth2Accessor;
+import org.apache.shindig.gadgets.oauth2.OAuth2Message;
+import org.apache.shindig.gadgets.oauth2.OAuth2Token;
+import org.apache.shindig.gadgets.oauth2.OAuth2Token.Type;
+import org.apache.shindig.gadgets.oauth2.logger.FilteredLogger;
+import org.apache.shindig.gadgets.oauth2.persistence.OAuth2Client;
+import org.apache.shindig.gadgets.oauth2.persistence.OAuth2Encrypter;
+import org.apache.shindig.gadgets.oauth2.persistence.OAuth2EncryptionException;
+import org.apache.shindig.gadgets.oauth2.persistence.OAuth2PersistenceException;
+import org.apache.shindig.gadgets.oauth2.persistence.OAuth2Persister;
+import org.apache.shindig.gadgets.oauth2.persistence.OAuth2TokenPersistence;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import com.google.caja.util.Maps;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+
+/**
+ * Persistence implementation that reads <code>config/oauth2.json</code> on
+ * startup
+ * 
+ */
+@Singleton
+public class JSONOAuth2Persister implements OAuth2Persister {
+  private static final String ALLOW_MODULE_OVERRIDE = "allowModuleOverride";
+  private static final String AUTHORIZATION_HEADER = "usesAuthorizationHeader";
+  private static final String AUTHORIZATION_URL = "authorizationUrl";
+  private static final String CLIENT_AUTHENTICATION = "client_authentication";
+  private static final String CLIENT_NAME = "clientName";
+  private static final String CLIENTS = "clients";
+  private static final String ENDPOINTS = "endpoints";
+  private static final String GADGET_BINDGINGS = "gadgetBindings";
+  private static final String NO_CLIENT_AUTHENTICATION = "NONE";
+  private static final String OAUTH2_CONFIG = "config/oauth2.json";
+  private static final String PROVIDER_NAME = "providerName";
+  private static final String PROVIDERS = "providers";
+  private static final String TOKEN_URL = "tokenUrl";
+  private static final String TYPE = "type";
+  private static final String URL_PARAMETER = "usesUrlParameter";
+
+  private final JSONObject configFile;
+  private final String contextRoot;
+  private final OAuth2Encrypter encrypter;
+  private final String globalRedirectUri;
+
+  private final Authority authority;
+
+  private final static String LOG_CLASS = JSONOAuth2Persister.class.getName();
+  private static final FilteredLogger LOG = FilteredLogger
+      .getFilteredLogger(JSONOAuth2Persister.LOG_CLASS);
+
+  @Inject
+  public JSONOAuth2Persister(final OAuth2Encrypter encrypter, final Authority authority,
+      final String globalRedirectUri,
+      @Nullable @Named("shindig.contextroot") final String contextRoot)
+      throws OAuth2PersistenceException {
+    this.encrypter = encrypter;
+    this.authority = authority;
+    this.globalRedirectUri = globalRedirectUri;
+    this.contextRoot = contextRoot;
+    try {
+      this.configFile = new JSONObject(
+          JSONOAuth2Persister.getJSONString(JSONOAuth2Persister.OAUTH2_CONFIG));
+    } catch (final Exception e) {
+      if (JSONOAuth2Persister.LOG.isLoggable()) {
+        JSONOAuth2Persister.LOG.log("OAuth2PersistenceException", e);
+      }
+      throw new OAuth2PersistenceException(e);
+    }
+  }
+
+  public JSONOAuth2Persister(final OAuth2Encrypter encrypter, final Authority authority,
+      final String globalRedirectUri,
+      @Nullable @Named("shindig.contextroot") final String contextRoot, final JSONObject configFile) {
+    this.encrypter = encrypter;
+    this.authority = authority;
+    this.globalRedirectUri = globalRedirectUri;
+    this.contextRoot = contextRoot;
+    this.configFile = configFile;
+  }
+
+  public OAuth2Token createToken() {
+    return new OAuth2TokenPersistence(this.encrypter);
+  }
+
+  public static OAuth2Client findClient(@SuppressWarnings("unused") final Integer index) {
+    return null;
+  }
+
+  public OAuth2Client findClient(final String providerName, final String gadgetUri)
+      throws OAuth2PersistenceException {
+    return null;
+  }
+
+  public static OAuth2Provider findProvider(@SuppressWarnings("unused") final Integer index) {
+    return null;
+  }
+
+  public static OAuth2Provider findProvider(@SuppressWarnings("unused") final String providerName) {
+    return null;
+  }
+
+  public static OAuth2Token findToken(@SuppressWarnings("unused") final Integer index) {
+    return null;
+  }
+
+  public OAuth2Token findToken(final String providerName, final String gadgetUri,
+      final String user, final String scope, final Type type) throws OAuth2PersistenceException {
+    return null;
+  }
+
+  public void insertToken(final OAuth2Token token) {
+    // does nothing
+  }
+
+  public Set<OAuth2Client> loadClients() throws OAuth2PersistenceException {
+    final Map<String, OAuth2GadgetBinding> gadgetBindings = this.loadGadgetBindings();
+    final Map<String, OAuth2Provider> providers = this.loadProviders();
+
+    final Map<String, OAuth2Client> internalMap = Maps.newHashMap();
+
+    try {
+      final JSONObject clients = this.configFile.getJSONObject(JSONOAuth2Persister.CLIENTS);
+      for (final Iterator<?> j = clients.keys(); j.hasNext();) {
+        final String clientName = (String) j.next();
+        final JSONObject settings = clients.getJSONObject(clientName);
+
+        final OAuth2Client client = new OAuth2Client(this.encrypter);
+
+        final String providerName = settings.getString(JSONOAuth2Persister.PROVIDER_NAME);
+        final OAuth2Provider provider = providers.get(providerName);
+        client.setAuthorizationUrl(provider.getAuthorizationUrl());
+        client.setClientAuthenticationType(provider.getClientAuthenticationType());
+        client.setAuthorizationHeader(provider.isAuthorizationHeader());
+        client.setUrlParameter(provider.isUrlParameter());
+        client.setTokenUrl(provider.getTokenUrl());
+
+        String redirectUri = settings.optString(OAuth2Message.REDIRECT_URI, null);
+        if (redirectUri == null) {
+          redirectUri = this.globalRedirectUri;
+        }
+        final String secret = settings.optString(OAuth2Message.CLIENT_SECRET);
+        final String clientId = settings.getString(OAuth2Message.CLIENT_ID);
+        final String typeS = settings.optString(JSONOAuth2Persister.TYPE, null);
+        String grantType = settings.optString(OAuth2Message.GRANT_TYPE, null);
+
+        try {
+          client.setEncryptedSecret(secret.getBytes("UTF-8"));
+        } catch (final OAuth2EncryptionException e) {
+          throw new OAuth2PersistenceException(e);
+        }
+
+        client.setClientId(clientId);
+
+        if (this.authority != null) {
+          redirectUri = redirectUri.replace("%authority%", this.authority.getAuthority());
+          redirectUri = redirectUri.replace("%contextRoot%", this.contextRoot);
+          redirectUri = redirectUri.replace("%origin%", this.authority.getOrigin());
+
+        }
+        client.setRedirectUri(redirectUri);
+
+        if ((grantType == null) || (grantType.length() == 0)) {
+          grantType = OAuth2Message.AUTHORIZATION;
+        }
+
+        client.setGrantType(grantType);
+
+        OAuth2Accessor.Type type = OAuth2Accessor.Type.UNKNOWN;
+        if (OAuth2Message.CONFIDENTIAL_CLIENT_TYPE.equals(typeS)) {
+          type = OAuth2Accessor.Type.CONFIDENTIAL;
+        } else if (OAuth2Message.PUBLIC_CLIENT_TYPE.equals(typeS)) {
+          type = OAuth2Accessor.Type.PUBLIC;
+        }
+        client.setType(type);
+
+        internalMap.put(clientName, client);
+      }
+    } catch (final Exception e) {
+      if (JSONOAuth2Persister.LOG.isLoggable()) {
+        JSONOAuth2Persister.LOG.log("OAuth2PersistenceException", e);
+      }
+      throw new OAuth2PersistenceException(e);
+    }
+
+    final Set<OAuth2Client> ret = new HashSet<OAuth2Client>(gadgetBindings.size());
+    for (final OAuth2GadgetBinding binding : gadgetBindings.values()) {
+      final String clientName = binding.getClientName();
+      final OAuth2Client client = internalMap.get(clientName);
+      client.setGadgetUri(binding.getGadgetUri());
+      client.setServiceName(binding.getGadgetServiceName());
+      client.setAllowModuleOverride(binding.isAllowOverride());
+      ret.add(client);
+    }
+
+    return ret;
+  }
+
+  private Map<String, OAuth2GadgetBinding> loadGadgetBindings() throws OAuth2PersistenceException {
+    final Map<String, OAuth2GadgetBinding> ret = Maps.newHashMap();
+
+    try {
+      final JSONObject bindings = this.configFile
+          .getJSONObject(JSONOAuth2Persister.GADGET_BINDGINGS);
+      for (final Iterator<?> i = bindings.keys(); i.hasNext();) {
+        final String gadgetUriS = (String) i.next();
+        String gadgetUri = null;
+        if (this.authority != null) {
+          gadgetUri = gadgetUriS.replace("%authority%", this.authority.getAuthority());
+          gadgetUri = gadgetUri.replace("%contextRoot%", this.contextRoot);
+          gadgetUri = gadgetUri.replace("%origin%", this.authority.getOrigin());
+        }
+
+        final JSONObject binding = bindings.getJSONObject(gadgetUriS);
+        for (final Iterator<?> j = binding.keys(); j.hasNext();) {
+          final String gadgetServiceName = (String) j.next();
+          final JSONObject settings = binding.getJSONObject(gadgetServiceName);
+          final String clientName = settings.getString(JSONOAuth2Persister.CLIENT_NAME);
+          final boolean allowOverride = settings
+              .getBoolean(JSONOAuth2Persister.ALLOW_MODULE_OVERRIDE);
+          final OAuth2GadgetBinding gadgetBinding = new OAuth2GadgetBinding(gadgetUri,
+              gadgetServiceName, clientName, allowOverride);
+
+          ret.put(gadgetBinding.getGadgetUri() + ":" + gadgetBinding.getGadgetServiceName(),
+              gadgetBinding);
+        }
+      }
+
+    } catch (final JSONException e) {
+      if (JSONOAuth2Persister.LOG.isLoggable()) {
+        JSONOAuth2Persister.LOG.log("OAuth2PersistenceException", e);
+      }
+      throw new OAuth2PersistenceException(e);
+    }
+
+    return ret;
+  }
+
+  private Map<String, OAuth2Provider> loadProviders() throws OAuth2PersistenceException {
+    final Map<String, OAuth2Provider> ret = Maps.newHashMap();
+
+    try {
+      final JSONObject providers = this.configFile.getJSONObject(JSONOAuth2Persister.PROVIDERS);
+      for (final Iterator<?> i = providers.keys(); i.hasNext();) {
+        final String providerName = (String) i.next();
+        final JSONObject provider = providers.getJSONObject(providerName);
+        final JSONObject endpoints = provider.getJSONObject(JSONOAuth2Persister.ENDPOINTS);
+
+        final String clientAuthenticationType = provider
+            .optString(JSONOAuth2Persister.CLIENT_AUTHENTICATION,
+                JSONOAuth2Persister.NO_CLIENT_AUTHENTICATION);
+
+        final boolean authorizationHeader = provider.optBoolean(
+            JSONOAuth2Persister.AUTHORIZATION_HEADER, false);
+
+        final boolean urlParameter = provider.optBoolean(JSONOAuth2Persister.URL_PARAMETER, false);
+
+        String authorizationUrl = endpoints.optString(JSONOAuth2Persister.AUTHORIZATION_URL, null);
+
+        if ((this.authority != null) && (authorizationUrl != null)) {
+          authorizationUrl = authorizationUrl.replace("%authority%", this.authority.getAuthority());
+          authorizationUrl = authorizationUrl.replace("%contextRoot%", this.contextRoot);
+          authorizationUrl = authorizationUrl.replace("%origin%", this.authority.getOrigin());
+
+        }
+
+        String tokenUrl = endpoints.optString(JSONOAuth2Persister.TOKEN_URL, null);
+        if ((this.authority != null) && (tokenUrl != null)) {
+          tokenUrl = tokenUrl.replace("%authority%", this.authority.getAuthority());
+          tokenUrl = tokenUrl.replace("%contextRoot%", this.contextRoot);
+          tokenUrl = tokenUrl.replace("%origin%", this.authority.getOrigin());
+        }
+
+        final OAuth2Provider oauth2Provider = new OAuth2Provider();
+
+        oauth2Provider.setName(providerName);
+        oauth2Provider.setAuthorizationUrl(authorizationUrl);
+        oauth2Provider.setTokenUrl(tokenUrl);
+        oauth2Provider.setClientAuthenticationType(clientAuthenticationType);
+        oauth2Provider.setAuthorizationHeader(authorizationHeader);
+        oauth2Provider.setUrlParameter(urlParameter);
+
+        ret.put(oauth2Provider.getName(), oauth2Provider);
+      }
+    } catch (final JSONException e) {
+      if (JSONOAuth2Persister.LOG.isLoggable()) {
+        JSONOAuth2Persister.LOG.log("OAuth2PersistenceException", e);
+      }
+      throw new OAuth2PersistenceException(e);
+    }
+
+    return ret;
+  }
+
+  public Set<OAuth2Token> loadTokens() throws OAuth2PersistenceException {
+    return Collections.emptySet();
+  }
+
+  public static boolean removeToken(@SuppressWarnings("unused") final Integer index) {
+    // does nothing
+    return false;
+  }
+
+  public boolean removeToken(final String providerName, final String gadgetUri, final String user,
+      final String scope, final Type type) {
+    return false;
+  }
+
+  public void updateToken(final OAuth2Token token) {
+    // does nothing
+  }
+
+  private static String getJSONString(final String location) throws IOException {
+    return ResourceLoader.getContent(location);
+  }
+}

Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/NoOpEncrypter.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/NoOpEncrypter.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/NoOpEncrypter.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/NoOpEncrypter.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you 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 org.apache.shindig.gadgets.oauth2.persistence.sample;
+
+import org.apache.shindig.gadgets.oauth2.persistence.OAuth2Encrypter;
+import org.apache.shindig.gadgets.oauth2.persistence.OAuth2EncryptionException;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+/**
+ * Sample of {@link OAuth2Encrypter} inteface that does nothing.
+ * 
+ */
+@Singleton
+public class NoOpEncrypter implements OAuth2Encrypter {
+  @Inject
+  public NoOpEncrypter() {
+
+  }
+
+  public byte[] decrypt(final byte[] encryptedSecret) throws OAuth2EncryptionException {
+    return encryptedSecret;
+  }
+
+  public byte[] encrypt(final byte[] plainSecret) throws OAuth2EncryptionException {
+    return plainSecret;
+  }
+}

Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/OAuth2GadgetBinding.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/OAuth2GadgetBinding.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/OAuth2GadgetBinding.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/OAuth2GadgetBinding.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you 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 org.apache.shindig.gadgets.oauth2.persistence.sample;
+
+/**
+ * Binds a gadget to a client.
+ * 
+ */
+public class OAuth2GadgetBinding {
+  private final boolean allowOverride;
+  private final String clientName;
+  private final String gadgetServiceName;
+  private final String gadgetUri;
+
+  public OAuth2GadgetBinding(final String gadgetUri, final String gadgetServiceName,
+      final String clientName, final boolean allowOverride) {
+    this.gadgetUri = gadgetUri;
+    this.gadgetServiceName = gadgetServiceName;
+    this.clientName = clientName;
+    this.allowOverride = allowOverride;
+  }
+
+  @Override
+  public boolean equals(final Object obj) {
+    if (obj == this) {
+      return true;
+    }
+    if (!(obj instanceof OAuth2GadgetBinding)) {
+      return false;
+    }
+    final OAuth2GadgetBinding other = (OAuth2GadgetBinding) obj;
+    if (this.gadgetUri == null) {
+      if (other.gadgetUri != null) {
+        return false;
+      }
+    } else if (!this.gadgetUri.equals(other.gadgetUri)) {
+      return false;
+    }
+    if (this.gadgetServiceName == null) {
+      if (other.gadgetServiceName != null) {
+        return false;
+      }
+    } else if (!this.gadgetServiceName.equals(other.gadgetServiceName)) {
+      return false;
+    }
+    return true;
+  }
+
+  public String getClientName() {
+    return this.clientName;
+  }
+
+  public String getGadgetServiceName() {
+    return this.gadgetServiceName;
+  }
+
+  public String getGadgetUri() {
+    return this.gadgetUri;
+  }
+
+  @Override
+  public int hashCode() {
+    if ((this.gadgetUri != null) && (this.gadgetServiceName != null)) {
+      return (this.gadgetUri + ":" + this.gadgetServiceName).hashCode();
+    }
+
+    return 0;
+  }
+
+  public boolean isAllowOverride() {
+    return this.allowOverride;
+  }
+
+  @Override
+  public String toString() {
+    return "org.apache.shindig.gadgets.oauth2.persistence.sample.OAuth2GadgetBinding: gadgetUri = "
+        + this.gadgetUri + " , gadgetServiceName = " + this.gadgetServiceName
+        + " , allowOverride = " + this.allowOverride;
+  }
+}

Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/OAuth2PersistenceModule.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/OAuth2PersistenceModule.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/OAuth2PersistenceModule.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/OAuth2PersistenceModule.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you 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 org.apache.shindig.gadgets.oauth2.persistence.sample;
+
+import org.apache.shindig.gadgets.oauth2.persistence.OAuth2Cache;
+import org.apache.shindig.gadgets.oauth2.persistence.OAuth2Encrypter;
+import org.apache.shindig.gadgets.oauth2.persistence.OAuth2Persister;
+
+import com.google.inject.AbstractModule;
+
+/**
+ * Binds default persistence classes for shindig.
+ * 
+ */
+public class OAuth2PersistenceModule extends AbstractModule {
+
+  @Override
+  protected void configure() {
+    this.bind(OAuth2Persister.class).to(JSONOAuth2Persister.class);
+    this.bind(OAuth2Cache.class).to(InMemoryCache.class);
+    this.bind(OAuth2Encrypter.class).to(NoOpEncrypter.class);
+  }
+}
\ No newline at end of file

Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/OAuth2Provider.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/OAuth2Provider.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/OAuth2Provider.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/oauth2/persistence/sample/OAuth2Provider.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you 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 org.apache.shindig.gadgets.oauth2.persistence.sample;
+
+import java.io.Serializable;
+
+/**
+ * Representation of OAuth2 endpoints and other relevant endpoint data.
+ * 
+ */
+public class OAuth2Provider implements Serializable {
+  private static final long serialVersionUID = -6539761759797255778L;
+
+  private boolean authorizationHeader = true;
+  private String authorizationUrl;
+  private String clientAuthenticationType;
+  private String name;
+  private String tokenUrl;
+  private boolean urlParameter = false;
+
+  @Override
+  public boolean equals(final Object obj) {
+    if (obj == this) {
+      return true;
+    }
+    if (!(obj instanceof OAuth2Provider)) {
+      return false;
+    }
+    final OAuth2Provider other = (OAuth2Provider) obj;
+    if (this.name == null) {
+      if (other.name != null) {
+        return false;
+      }
+    } else if (!this.name.equals(other.name)) {
+      return false;
+    }
+
+    return true;
+  }
+
+  public String getAuthorizationUrl() {
+    return this.authorizationUrl;
+  }
+
+  public String getClientAuthenticationType() {
+    return this.clientAuthenticationType;
+  }
+
+  public String getName() {
+    return this.name;
+  }
+
+  public String getTokenUrl() {
+    return this.tokenUrl;
+  }
+
+  @Override
+  public int hashCode() {
+    if (this.name != null) {
+      return this.name.hashCode();
+    }
+
+    return 0;
+  }
+
+  public boolean isAuthorizationHeader() {
+    return this.authorizationHeader;
+  }
+
+  public boolean isUrlParameter() {
+    return this.urlParameter;
+  }
+
+  public void setAuthorizationHeader(boolean authorizationHeader) {
+    this.authorizationHeader = authorizationHeader;
+  }
+
+  public void setAuthorizationUrl(final String authorizationUrl) {
+    this.authorizationUrl = authorizationUrl;
+  }
+
+  public void setClientAuthenticationType(final String clientAuthenticationType) {
+    this.clientAuthenticationType = clientAuthenticationType;
+  }
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  public void setTokenUrl(final String tokenUrl) {
+    this.tokenUrl = tokenUrl;
+  }
+
+  public void setUrlParameter(boolean urlParameter) {
+    this.urlParameter = urlParameter;
+  }
+
+  @Override
+  public String toString() {
+    return "org.apache.shindig.gadgets.oauth2.persistence.sample.OAuth2Provider: name = "
+        + this.name + " , authorizationUrl = " + this.authorizationUrl + " , tokenUrl = "
+        + this.tokenUrl + " , clientAuthenticationType = " + this.clientAuthenticationType;
+  }
+}

Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/preload/HttpPreloader.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/preload/HttpPreloader.java?rev=1182565&r1=1182564&r2=1182565&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/preload/HttpPreloader.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/preload/HttpPreloader.java Wed Oct 12 20:10:39 2011
@@ -26,6 +26,7 @@ import org.apache.shindig.gadgets.http.H
 import org.apache.shindig.gadgets.http.HttpResponse;
 import org.apache.shindig.gadgets.http.RequestPipeline;
 import org.apache.shindig.gadgets.oauth.OAuthArguments;
+import org.apache.shindig.gadgets.oauth2.OAuth2Arguments;
 import org.apache.shindig.gadgets.spec.Preload;
 import org.apache.shindig.gadgets.spec.RequestAuthenticationInfo;
 
@@ -73,6 +74,7 @@ public class HttpPreloader implements Pr
     return new HttpRequest(authenticationInfo.getHref())
         .setSecurityToken(context.getToken())
         .setOAuthArguments(new OAuthArguments(authenticationInfo))
+        .setOAuth2Arguments(new OAuth2Arguments(authenticationInfo))
         .setAuthType(authenticationInfo.getAuthType())
         .setContainer(context.getContainer())
         .setGadget(context.getUrl())

Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/ProxyRenderer.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/ProxyRenderer.java?rev=1182565&r1=1182564&r2=1182565&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/ProxyRenderer.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/ProxyRenderer.java Wed Oct 12 20:10:39 2011
@@ -30,6 +30,7 @@ import org.apache.shindig.gadgets.http.H
 import org.apache.shindig.gadgets.http.HttpResponse;
 import org.apache.shindig.gadgets.http.RequestPipeline;
 import org.apache.shindig.gadgets.oauth.OAuthArguments;
+import org.apache.shindig.gadgets.oauth2.OAuth2Arguments;
 import org.apache.shindig.gadgets.preload.PipelineExecutor;
 import org.apache.shindig.gadgets.spec.PipelinedData;
 import org.apache.shindig.gadgets.spec.View;
@@ -89,11 +90,13 @@ public class ProxyRenderer {
     uri.addQueryParameter("country", context.getLocale().getCountry());
 
     OAuthArguments oauthArgs = new OAuthArguments(view);
+    OAuth2Arguments oauth2Args = new OAuth2Arguments(view);
     oauthArgs.setProxiedContentRequest(true);
 
     HttpRequest request = new HttpRequest(uri.toUri())
         .setIgnoreCache(context.getIgnoreCache())
         .setOAuthArguments(oauthArgs)
+        .setOAuth2Arguments(oauth2Args)
         .setAuthType(view.getAuthType())
         .setSecurityToken(context.getToken())
         .setContainer(context.getContainer())

Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HttpRequestHandler.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HttpRequestHandler.java?rev=1182565&r1=1182564&r2=1182565&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HttpRequestHandler.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/HttpRequestHandler.java Wed Oct 12 20:10:39 2011
@@ -29,6 +29,7 @@ import org.apache.shindig.gadgets.http.H
 import org.apache.shindig.gadgets.http.HttpResponse;
 import org.apache.shindig.gadgets.http.RequestPipeline;
 import org.apache.shindig.gadgets.oauth.OAuthArguments;
+import org.apache.shindig.gadgets.oauth2.OAuth2Arguments;
 import org.apache.shindig.gadgets.rewrite.ResponseRewriterList.RewriteFlow;
 import org.apache.shindig.gadgets.rewrite.ResponseRewriterRegistry;
 import org.apache.shindig.gadgets.rewrite.RewriterRegistry;
@@ -203,15 +204,25 @@ public class HttpRequestHandler {
         req.setAuthType(AuthType.parse(httpApiRequest.authz));
       }
 
-      if (req.getAuthType() != AuthType.NONE) {
-        req.setSecurityToken(requestItem.getToken());
-        
-        Map<String, String> authSettings = getAuthSettings(requestItem);
-        OAuthArguments oauthArgs = new OAuthArguments(req.getAuthType(), authSettings);
-        oauthArgs.setSignOwner(httpApiRequest.signOwner);
-        oauthArgs.setSignViewer(httpApiRequest.signViewer);
-        
-        req.setOAuthArguments(oauthArgs);
+      final AuthType authType = req.getAuthType();
+      if (authType != AuthType.NONE) {
+        if (authType == AuthType.OAUTH2) {
+          req.setSecurityToken(requestItem.getToken());
+
+          Map<String, String> authSettings = getAuthSettings(requestItem);
+          OAuth2Arguments oauth2Args = new OAuth2Arguments(req.getAuthType(), authSettings);
+
+          req.setOAuth2Arguments(oauth2Args);
+        } else {
+          req.setSecurityToken(requestItem.getToken());
+
+          Map<String, String> authSettings = getAuthSettings(requestItem);
+          OAuthArguments oauthArgs = new OAuthArguments(req.getAuthType(), authSettings);
+          oauthArgs.setSignOwner(httpApiRequest.signOwner);
+          oauthArgs.setSignViewer(httpApiRequest.signViewer);
+
+          req.setOAuthArguments(oauthArgs);
+        }
       }
 
       // TODO: Allow the rewriter to use an externally forced mime type. This is needed
@@ -246,8 +257,7 @@ public class HttpRequestHandler {
       }
       return httpApiResponse;
     } catch (GadgetException ge) {
-      throw new ProtocolException(ge.getHttpStatusCode(),
-          ge.getMessage(), ge);
+      throw new ProtocolException(ge.getHttpStatusCode(), ge.getMessage(), ge);
     } catch (RewritingException re) {
       throw new ProtocolException(re.getHttpStatusCode(),
           re.getMessage(), re);

Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestHandler.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestHandler.java?rev=1182565&r1=1182564&r2=1182565&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestHandler.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/MakeRequestHandler.java Wed Oct 12 20:10:39 2011
@@ -47,6 +47,7 @@ import org.apache.shindig.gadgets.http.H
 import org.apache.shindig.gadgets.http.HttpResponse;
 import org.apache.shindig.gadgets.http.RequestPipeline;
 import org.apache.shindig.gadgets.oauth.OAuthArguments;
+import org.apache.shindig.gadgets.oauth2.OAuth2Arguments;
 import org.apache.shindig.gadgets.process.ProcessingException;
 import org.apache.shindig.gadgets.process.Processor;
 import org.apache.shindig.gadgets.rewrite.ResponseRewriterList.RewriteFlow;
@@ -62,7 +63,7 @@ import com.google.inject.Singleton;
 
 /**
  * Handles gadgets.io.makeRequest requests.
- *
+ * 
  * Unlike ProxyHandler, this may perform operations such as OAuth or signed fetch.
  */
 @Singleton
@@ -87,13 +88,11 @@ public class MakeRequestHandler {
   private final LockedDomainService lockedDomainService;
 
   @Inject
-  public MakeRequestHandler(RequestPipeline requestPipeline,
-      @RewriterRegistry(rewriteFlow = RewriteFlow.DEFAULT)
-      ResponseRewriterRegistry contentRewriterRegistry,
-      Provider<FeedProcessor> feedProcessorProvider,
-      GadgetAdminStore gadgetAdminStore,
-      Processor processor,
-      LockedDomainService lockedDomainService) {
+  public MakeRequestHandler(
+          RequestPipeline requestPipeline,
+          @RewriterRegistry(rewriteFlow = RewriteFlow.DEFAULT) ResponseRewriterRegistry contentRewriterRegistry,
+          Provider<FeedProcessor> feedProcessorProvider, GadgetAdminStore gadgetAdminStore,
+          Processor processor, LockedDomainService lockedDomainService) {
 
     this.requestPipeline = requestPipeline;
     this.contentRewriterRegistry = contentRewriterRegistry;
@@ -107,14 +106,14 @@ public class MakeRequestHandler {
    * Executes a request, returning the response as JSON to be handled by makeRequest.
    */
   public void fetch(HttpServletRequest request, HttpServletResponse response)
-      throws GadgetException, IOException {
+          throws GadgetException, IOException {
     HttpRequest rcr = buildHttpRequest(request);
     String container = rcr.getContainer();
 
     final Uri gadgetUri = rcr.getGadget();
     if (gadgetUri == null) {
       throw new GadgetException(GadgetException.Code.MISSING_PARAMETER,
-          "Unable to find gadget in request", HttpResponse.SC_FORBIDDEN);
+              "Unable to find gadget in request", HttpResponse.SC_FORBIDDEN);
     }
 
     Gadget gadget = null;
@@ -122,6 +121,7 @@ public class MakeRequestHandler {
       public Uri getUrl() {
         return gadgetUri;
       }
+
       public boolean getIgnoreCache() {
         return getParameter("bypassSpecCache").equals("1");
       }
@@ -129,9 +129,8 @@ public class MakeRequestHandler {
     try {
       gadget = processor.process(context);
     } catch (ProcessingException e) {
-      throw new GadgetException(
-          GadgetException.Code.INTERNAL_SERVER_ERROR, "Error processing gadget",
-          e, HttpResponse.SC_BAD_REQUEST);
+      throw new GadgetException(GadgetException.Code.INTERNAL_SERVER_ERROR,
+              "Error processing gadget", e, HttpResponse.SC_BAD_REQUEST);
     }
 
     // Validate gadget is correct for the host.
@@ -139,12 +138,12 @@ public class MakeRequestHandler {
     // another gadget in a locked domain environment.
     if (!lockedDomainService.isGadgetValidForHost(context.getHost(), gadget, container)) {
       throw new GadgetException(GadgetException.Code.GADGET_HOST_MISMATCH,
-          "The gadget is incorrect for this request", HttpResponse.SC_FORBIDDEN);
+              "The gadget is incorrect for this request", HttpResponse.SC_FORBIDDEN);
     }
 
-    if(!gadgetAdminStore.isWhitelisted(container, gadgetUri.toString())) {
+    if (!gadgetAdminStore.isWhitelisted(container, gadgetUri.toString())) {
       throw new GadgetException(GadgetException.Code.NON_WHITELISTED_GADGET,
-          "The requested content is unavailable", HttpResponse.SC_FORBIDDEN);
+              "The requested content is unavailable", HttpResponse.SC_FORBIDDEN);
     }
 
     // Serialize the response
@@ -156,7 +155,7 @@ public class MakeRequestHandler {
         results = contentRewriterRegistry.rewriteHttpResponse(rcr, results);
       } catch (RewritingException e) {
         throw new GadgetException(GadgetException.Code.INTERNAL_SERVER_ERROR, e,
-            e.getHttpStatusCode());
+                e.getHttpStatusCode());
       }
     }
 
@@ -173,30 +172,29 @@ public class MakeRequestHandler {
   }
 
   /**
-   * Generate a remote content request based on the parameters
-   * sent from the client.
+   * Generate a remote content request based on the parameters sent from the client.
+   * 
    * @throws GadgetException
    */
   protected HttpRequest buildHttpRequest(HttpServletRequest request) throws GadgetException {
     String urlStr = request.getParameter(Param.URL.getKey());
     if (urlStr == null) {
-      throw new GadgetException(GadgetException.Code.INVALID_PARAMETER,
-          Param.URL.getKey() + " parameter is missing.", HttpResponse.SC_BAD_REQUEST);
+      throw new GadgetException(GadgetException.Code.INVALID_PARAMETER, Param.URL.getKey()
+              + " parameter is missing.", HttpResponse.SC_BAD_REQUEST);
     }
 
     Uri url = null;
     try {
       url = ServletUtil.validateUrl(Uri.parse(urlStr));
     } catch (IllegalArgumentException e) {
-      throw new GadgetException(GadgetException.Code.INVALID_PARAMETER,
-          "Invalid " + Param.URL.getKey() + " parameter", HttpResponse.SC_BAD_REQUEST);
+      throw new GadgetException(GadgetException.Code.INVALID_PARAMETER, "Invalid "
+              + Param.URL.getKey() + " parameter", HttpResponse.SC_BAD_REQUEST);
     }
 
-    HttpRequest req = new HttpRequest(url)
-        .setMethod(getParameter(request, METHOD_PARAM, "GET"))
-        .setContainer(getContainer(request));
+    HttpRequest req = new HttpRequest(url).setMethod(getParameter(request, METHOD_PARAM, "GET"))
+            .setContainer(getContainer(request));
 
-    setPostData(request,req);
+    setPostData(request, req);
 
     String headerData = getParameter(request, HEADERS_PARAM, "");
     if (headerData.length() > 0) {
@@ -205,7 +203,7 @@ public class MakeRequestHandler {
         String[] parts = StringUtils.splitPreserveAllTokens(header, '=');
         if (parts.length != 2) {
           throw new GadgetException(GadgetException.Code.INVALID_PARAMETER,
-              "Malformed header param specified:" + header, HttpResponse.SC_BAD_REQUEST);
+                  "Malformed header param specified:" + header, HttpResponse.SC_BAD_REQUEST);
         }
         String headerName = Utf8UrlCoder.decode(parts[0]);
         if (!HttpRequestHandler.BAD_HEADERS.contains(headerName.toUpperCase())) {
@@ -214,8 +212,8 @@ public class MakeRequestHandler {
       }
     }
 
-    // Set the default content type  for post requests when a content type is not specified
-    if ("POST".equals(req.getMethod()) && req.getHeader("Content-Type")==null) {
+    // Set the default content type for post requests when a content type is not specified
+    if ("POST".equals(req.getMethod()) && req.getHeader("Content-Type") == null) {
       req.addHeader("Content-Type", "application/x-www-form-urlencoded");
     }
 
@@ -244,8 +242,13 @@ public class MakeRequestHandler {
     AuthType auth = AuthType.parse(getParameter(request, AUTHZ_PARAM, null));
     req.setAuthType(auth);
     if (auth != AuthType.NONE) {
-      req.setSecurityToken(extractAndValidateToken(request));
-      req.setOAuthArguments(new OAuthArguments(auth, request));
+      if (auth == AuthType.OAUTH2) {
+        req.setSecurityToken(extractAndValidateToken(request));
+        req.setOAuth2Arguments(new OAuth2Arguments(request));
+      } else {
+        req.setSecurityToken(extractAndValidateToken(request));
+        req.setOAuthArguments(new OAuthArguments(auth, request));
+      }
     }
 
     ServletUtil.setXForwardedForHeader(request, req);
@@ -253,19 +256,16 @@ public class MakeRequestHandler {
   }
 
   /**
-   * Set http request post data according to servlet request.
-   * It uses header encoding if available, and defaulted to utf8
-   * Override the function if different behavior is needed.
+   * Set http request post data according to servlet request. It uses header encoding if available,
+   * and defaulted to utf8 Override the function if different behavior is needed.
    */
-  protected void setPostData(HttpServletRequest request, HttpRequest req)
-      throws GadgetException {
+  protected void setPostData(HttpServletRequest request, HttpRequest req) throws GadgetException {
     String encoding = request.getCharacterEncoding();
     if (encoding == null) {
       encoding = "UTF-8";
     }
     try {
-      req.setPostBody(getParameter(request, POST_DATA_PARAM, "")
-          .getBytes(encoding.toUpperCase()));
+      req.setPostBody(getParameter(request, POST_DATA_PARAM, "").getBytes(encoding.toUpperCase()));
     } catch (UnsupportedEncodingException e) {
       // We might consider enumerating at least a small list of encodings
       // that we must always honor. For now, we return SC_BAD_REQUEST since
@@ -275,13 +275,12 @@ public class MakeRequestHandler {
   }
 
   /**
-   * Format a response as JSON, including additional JSON inserted by
-   * chained content fetchers.
+   * Format a response as JSON, including additional JSON inserted by chained content fetchers.
    */
   protected String convertResponseToJson(SecurityToken authToken, HttpServletRequest request,
-      HttpResponse results) throws GadgetException {
-    boolean getFullHeaders =
-        Boolean.parseBoolean(getParameter(request, GET_FULL_HEADERS_PARAM, "false"));
+          HttpResponse results) throws GadgetException {
+    boolean getFullHeaders = Boolean.parseBoolean(getParameter(request, GET_FULL_HEADERS_PARAM,
+            "false"));
     String originalUrl = request.getParameter(Param.URL.getKey());
     String body = results.getResponseAsString();
     if (body.length() > 0) {
@@ -289,8 +288,8 @@ public class MakeRequestHandler {
         body = processFeed(originalUrl, request, body);
       }
     }
-    Map<String, Object> resp =
-        FetchResponseUtils.getResponseAsJson(results, null, body, getFullHeaders);
+    Map<String, Object> resp = FetchResponseUtils.getResponseAsJson(results, null, body,
+            getFullHeaders);
 
     if (authToken != null) {
       String updatedAuthToken = authToken.getUpdatedToken();
@@ -323,15 +322,14 @@ public class MakeRequestHandler {
   /**
    * Processes a feed (RSS or Atom) using FeedProcessor.
    */
-  private String processFeed(String url, HttpServletRequest req, String xml)
-      throws GadgetException {
+  private String processFeed(String url, HttpServletRequest req, String xml) throws GadgetException {
     boolean getSummaries = Boolean.parseBoolean(getParameter(req, GET_SUMMARIES_PARAM, "false"));
     int numEntries;
     try {
       numEntries = Integer.valueOf(getParameter(req, NUM_ENTRIES_PARAM, DEFAULT_NUM_ENTRIES));
     } catch (NumberFormatException e) {
       throw new GadgetException(GadgetException.Code.INVALID_PARAMETER,
-          "numEntries paramater is not a number", HttpResponse.SC_BAD_REQUEST);
+              "numEntries paramater is not a number", HttpResponse.SC_BAD_REQUEST);
     }
     return feedProcessorProvider.get().process(url, xml, getSummaries, numEntries).toString();
   }
@@ -361,19 +359,20 @@ public class MakeRequestHandler {
    */
   @SuppressWarnings("boxing")
   protected static void setResponseHeaders(HttpServletRequest request,
-      HttpServletResponse response, HttpResponse results) throws GadgetException {
+          HttpServletResponse response, HttpResponse results) throws GadgetException {
     int refreshInterval = 0;
-    if (results.isStrictNoCache() || "1".equals(request.getParameter(UriCommon.Param.NO_CACHE.getKey()))) {
+    if (results.isStrictNoCache()
+            || "1".equals(request.getParameter(UriCommon.Param.NO_CACHE.getKey()))) {
       refreshInterval = 0;
     } else if (request.getParameter(UriCommon.Param.REFRESH.getKey()) != null) {
       try {
-        refreshInterval =  Integer.valueOf(request.getParameter(UriCommon.Param.REFRESH.getKey()));
+        refreshInterval = Integer.valueOf(request.getParameter(UriCommon.Param.REFRESH.getKey()));
       } catch (NumberFormatException nfe) {
         throw new GadgetException(GadgetException.Code.INVALID_PARAMETER,
-            "refresh parameter is not a number", HttpResponse.SC_BAD_REQUEST);
+                "refresh parameter is not a number", HttpResponse.SC_BAD_REQUEST);
       }
     } else {
-      refreshInterval = Math.max(60 * 60, (int)(results.getCacheTtl() / 1000L));
+      refreshInterval = Math.max(60 * 60, (int) (results.getCacheTtl() / 1000L));
     }
     HttpUtil.setCachingHeaders(response, refreshInterval, false);
 

Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/OAuth2CallbackServlet.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/OAuth2CallbackServlet.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/OAuth2CallbackServlet.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/servlet/OAuth2CallbackServlet.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you 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 org.apache.shindig.gadgets.servlet;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.shindig.common.servlet.HttpUtil;
+import org.apache.shindig.common.servlet.InjectedServlet;
+import org.apache.shindig.gadgets.oauth2.OAuth2Accessor;
+import org.apache.shindig.gadgets.oauth2.OAuth2Error;
+import org.apache.shindig.gadgets.oauth2.OAuth2Message;
+import org.apache.shindig.gadgets.oauth2.OAuth2Store;
+import org.apache.shindig.gadgets.oauth2.handler.AuthorizationEndpointResponseHandler;
+import org.apache.shindig.gadgets.oauth2.handler.OAuth2HandlerError;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+public class OAuth2CallbackServlet extends InjectedServlet {
+  private static final long serialVersionUID = -8829844832872635091L;
+
+  private transient List<AuthorizationEndpointResponseHandler> authorizationEndpointResponseHandlers;
+  private transient OAuth2Store store;
+  private transient Provider<OAuth2Message> oauth2MessageProvider;
+
+  private static final int ONE_HOUR_IN_SECONDS = 3600;
+
+  // This bit of magic passes the entire callback URL into the opening gadget
+  // for later use.
+  // gadgets.io.makeRequest (or osapi.oauth) will then pick up the callback URL
+  // to complete the
+  // oauth dance.
+  private static final String RESP_BODY = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" "
+      + "\"http://www.w3.org/TR/html4/loose.dtd\">\n"
+      + "<html>\n"
+      + "<head>\n"
+      + "<title>Close this window</title>\n"
+      + "</head>\n"
+      + "<body>\n"
+      + "<script type='text/javascript'>\n"
+      + "try {\n"
+      + "  window.opener.gadgets.io.oauthReceivedCallbackUrl_ = document.location.href;\n"
+      + "} catch (e) {\n"
+      + "}\n"
+      + "window.close();\n"
+      + "</script>\n"
+      + "Close this window.\n"
+      + "</body>\n" + "</html>\n";
+
+  private static final String RESP_ERROR_BODY = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" "
+      + "\"http://www.w3.org/TR/html4/loose.dtd\">\n"
+      + "<html>\n"
+      + "<head>\n"
+      + "<title>OAuth2 Error</title>\n"
+      + "</head>\n"
+      + "<body>\n"
+      + "<p>error = %s</p>"
+      + "<p>error description = %s</p>"
+      + "<p>error uri = %s</p>"
+      + "Close this window.\n"
+      + "</body>\n" + "</html>\n";
+
+  @Override
+  protected void doGet(final HttpServletRequest request, final HttpServletResponse resp)
+      throws IOException {
+
+    OAuth2Accessor accessor = null;
+    try {
+      final OAuth2Message msg = this.oauth2MessageProvider.get();
+      msg.parseRequest(request);
+      final OAuth2Error error = msg.getError();
+      final String requestStateKey = msg.getState();
+      if (requestStateKey == null) {
+        if (error != null) {
+          OAuth2CallbackServlet.sendError(error, msg.getErrorDescription(), msg.getErrorUri(),
+              null, resp, null);
+        } else {
+          OAuth2CallbackServlet.sendError(OAuth2Error.CALLBACK_PROBLEM,
+              "OAuth2CallbackServlet requestStateKey is null.", "", null, resp, null);
+        }
+        return;
+      }
+
+      final Integer index = Integer.decode(requestStateKey);
+      accessor = this.store.getOAuth2Accessor(index);
+
+      if (error != null) {
+        OAuth2CallbackServlet.sendError(error, msg.getErrorDescription(), msg.getErrorUri(),
+            accessor, resp, null);
+        return;
+      }
+
+      if ((accessor == null) || (!accessor.isValid()) || (accessor.isErrorResponse())) {
+        if (accessor != null) {
+          OAuth2CallbackServlet.sendError(OAuth2Error.CALLBACK_PROBLEM,
+              "OAuth2CallbackServlet accessor is invalid " + accessor, "", accessor, resp,
+              accessor.getErrorException());
+        } else {
+          OAuth2CallbackServlet.sendError(OAuth2Error.CALLBACK_PROBLEM,
+              "OAuth2CallbackServlet accessor is null", "", null, resp, null);
+
+        }
+        return;
+      }
+
+      if (!accessor.isRedirecting()) {
+        // Somehow our accessor got lost. We should not proceed.
+        OAuth2CallbackServlet.sendError(OAuth2Error.CALLBACK_PROBLEM,
+            "OAuth2CallbackServlet accessor is not valid, isn't redirecting.", "", accessor, resp,
+            null);
+        return;
+      }
+
+      boolean foundHandler = false;
+      for (final AuthorizationEndpointResponseHandler authorizationEndpointResponseHandler : this.authorizationEndpointResponseHandlers) {
+        if (authorizationEndpointResponseHandler.handlesRequest(accessor, request)) {
+          final OAuth2HandlerError handlerError = authorizationEndpointResponseHandler
+              .handleRequest(accessor, request);
+          if (handlerError != null) {
+            OAuth2CallbackServlet.sendError(handlerError.getError(),
+                handlerError.getContextMessage(), null, accessor, resp, handlerError.getCause());
+            return;
+          }
+          foundHandler = true;
+          break;
+        }
+      }
+
+      if (!foundHandler) {
+        OAuth2CallbackServlet.sendError(OAuth2Error.NO_RESPONSE_HANDLER,
+            "OAuth2Callback servlet couldn't find a AuthorizationEndpointResponseHandler", "",
+            accessor, resp, null);
+        return;
+      }
+
+      HttpUtil.setCachingHeaders(resp, OAuth2CallbackServlet.ONE_HOUR_IN_SECONDS, true);
+      resp.setContentType("text/html; charset=UTF-8");
+      resp.getWriter().write(OAuth2CallbackServlet.RESP_BODY);
+    } catch (final Exception e) {
+      OAuth2CallbackServlet.sendError(OAuth2Error.CALLBACK_PROBLEM,
+          "Exception occurred processing redirect.", "", accessor, resp, e);
+      if (IOException.class.isInstance(e)) {
+        throw (IOException) e;
+      }
+      return;
+    } finally {
+      if (accessor != null) {
+        accessor.setRedirecting(false);
+      }
+    }
+  }
+
+  private static void sendError(final OAuth2Error error, final String description,
+      final String uri, final OAuth2Accessor accessor, final HttpServletResponse resp,
+      final Throwable t) throws IOException {
+
+    HttpUtil.setCachingHeaders(resp, OAuth2CallbackServlet.ONE_HOUR_IN_SECONDS, true);
+    resp.setContentType("text/html; charset=UTF-8");
+
+    if (accessor != null) {
+      accessor.setErrorResponse(t, error, description, uri);
+    } else {
+      // We don't have an accessor to report the error back to the client in the
+      // normal manner.
+      // Anything is better than nothing, hack something together....
+      final String errorResponse = String.format(OAuth2CallbackServlet.RESP_ERROR_BODY,
+          error.getErrorCode(), error.getErrorDescription(description), uri);
+      resp.getWriter().write(errorResponse);
+      return;
+    }
+
+    resp.getWriter().write(OAuth2CallbackServlet.RESP_BODY);
+    return;
+  }
+
+  @Inject
+  public void setAuthorizationResponseHandlers(
+      final List<AuthorizationEndpointResponseHandler> authorizationEndpointResponseHandlers) {
+    this.authorizationEndpointResponseHandlers = authorizationEndpointResponseHandlers;
+  }
+
+  @Inject
+  public void setOAuth2Store(final OAuth2Store store) {
+    this.store = store;
+  }
+
+  @Inject
+  public void setOauth2MessageProvider(Provider<OAuth2Message> oauth2MessageProvider) {
+    this.oauth2MessageProvider = oauth2MessageProvider;
+  }
+}
\ No newline at end of file

Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/BaseOAuthService.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/BaseOAuthService.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/BaseOAuthService.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/BaseOAuthService.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shindig.gadgets.spec;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Maps;
+
+import org.apache.shindig.common.uri.Uri;
+import org.apache.shindig.common.xml.XmlUtil;
+
+import org.w3c.dom.Element;
+
+import java.util.Map;
+
+/**
+ * Information about an OAuth service that a gadget wants to use.
+ * This class defines the information common to both OAuth1.0 based service and OAuth2.0 based service.
+ *
+ * Instances are immutable.
+ */
+public abstract class BaseOAuthService {
+
+  /**
+   * Constructor for testing only.
+   */
+  BaseOAuthService() { }
+
+  public BaseOAuthService(Element serviceElement, Uri base) throws SpecParserException{
+    
+  }
+ 
+
+
+  /**
+   * Represents /OAuth/Service@name
+   */
+  abstract public String getName() ;
+
+  /**
+   * Method to use for requests to an OAuth request token or access token URL.
+   */
+  public enum Method {
+    GET, POST;
+
+    private static final Map<String, Method> METHODS =
+            ImmutableMap.of(GET.toString(), GET, POST.toString(), POST, "", GET);
+
+    public static Method parse(String value) throws SpecParserException {
+      value = value.trim();
+      Method result = METHODS.get(value);
+      if (result == null) {
+        throw new SpecParserException("Unknown OAuth method: " + value);
+      }
+      return result;
+    }
+  }
+
+  /**
+   * Location for OAuth parameters in requests to an OAuth request token,
+   * access token, or resource URL.
+   */
+  public enum Location {
+    HEADER("auth-header"),
+    URL("uri-query"),
+    BODY("post-body");
+
+    private static final Map<String, Location> LOCATIONS;
+
+    static {
+      LOCATIONS = Maps.newHashMap();
+      for (Location l : Location.values()) {
+        LOCATIONS.put(l.locationString, l);
+      }
+      // Default value
+      LOCATIONS.put("", Location.HEADER);
+    }
+
+    private String locationString;
+    private Location(String locationString) {
+      this.locationString = locationString;
+    }
+
+    @Override
+    public String toString() {
+      return locationString;
+    }
+
+    public static Location parse(String value) throws SpecParserException {
+      value = value.trim();
+      Location result = LOCATIONS.get(value);
+      if (result == null) {
+        throw new SpecParserException("Unknown OAuth param_location: " + value);
+      }
+      return result;
+    }
+  }
+
+  private static final String URL_ATTR = "url";
+  private static final String PARAM_LOCATION_ATTR = "param_location";
+  private static final String METHOD_ATTR = "method";
+
+  /**
+   * Description of an OAuth request token or access token URL.
+   */
+  public static class EndPoint {
+    public final Uri url;
+    public Uri getUrl() {
+		return url;
+	}
+
+	public Method getMethod() {
+		return method;
+	}
+
+	public Location getLocation() {
+		return location;
+	}
+
+	public final Method method;
+    public final Location location;
+
+    public EndPoint(Uri url, Method method, Location location) {
+      this.url = url;
+      this.method = method;
+      this.location = location;
+    }
+
+    public String toString(String element) {
+      return '<' + element + " url='" + url.toString() + "' " +
+              "method='" + method + "' param_location='" + location + "'/>";
+    }
+  }
+
+  Uri parseAuthorizationUrl(Element child, Uri base) throws SpecParserException {
+    Uri url = XmlUtil.getHttpUriAttribute(child, URL_ATTR, base);
+    if (url == null) {
+      throw new SpecParserException("OAuth/Service/Authorization @url is not valid: " +
+          child.getAttribute(URL_ATTR));
+    }
+    return base.resolve(url);
+  }
+
+
+  EndPoint parseEndPoint(String where, Element child, Uri base) throws SpecParserException {
+    Uri url = XmlUtil.getHttpUriAttribute(child, URL_ATTR, base);
+    if (url == null) {
+      throw new SpecParserException("Not an HTTP url: " + child.getAttribute(URL_ATTR));
+    }
+
+    Location location = Location.parse(child.getAttribute(PARAM_LOCATION_ATTR));
+    Method method = Method.parse(child.getAttribute(METHOD_ATTR));
+    return new EndPoint(base.resolve(url), method, location);
+  }
+}

Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ModulePrefs.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ModulePrefs.java?rev=1182565&r1=1182564&r2=1182565&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ModulePrefs.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/ModulePrefs.java Wed Oct 12 20:10:39 2011
@@ -109,10 +109,12 @@ public class ModulePrefs {
 
     // Eventually use a list of classes
     MutableBoolean oauthMarker = new MutableBoolean(false);
+    
     Set<ElementVisitor> visitors = ImmutableSet.of(
         new FeatureVisitor(oauthMarker),
         new PreloadVisitor(),
         new OAuthVisitor(oauthMarker),
+        new OAuth2Visitor(oauthMarker),
         new IconVisitor(),
         new LocaleVisitor(),
         new LinkVisitor(),
@@ -143,6 +145,7 @@ public class ModulePrefs {
     allLocales = prefs.allLocales;
     locales = prefs.locales;
     oauth = prefs.oauth;
+    oauth2 = prefs.oauth2;
 
     List<Preload> preloads = Lists.newArrayList();
     for (Preload preload : prefs.preloads) {
@@ -459,6 +462,8 @@ public class ModulePrefs {
   private Map<String, LinkSpec> links;
   private OAuthSpec oauth;
   private Multimap<String,Node> extraElements;
+  private OAuth2Spec oauth2;
+
 
   /**
    * @return Returns a list of flattened attributes for:
@@ -538,6 +543,13 @@ public class ModulePrefs {
   public OAuthSpec getOAuthSpec() {
     return oauth;
   }
+  
+  /**
+   * @return an OAuth2Spec built from the ModuleSpec/OAuthSpec element
+   */
+  public OAuth2Spec getOAuth2Spec() {
+    return oauth2;
+  }
 
   /**
    * @return a Multimap of tagnames to child elements of the ModuleSpec element
@@ -748,6 +760,34 @@ public class ModulePrefs {
     }
 
   }
+  
+  /**
+   * Process ModulePrefs/OAuth2
+   */
+  private final class OAuth2Visitor implements ElementVisitor {
+    private OAuth2Spec oauth2Spec = null;
+    private final MutableBoolean oauth2Marker;
+    
+    private OAuth2Visitor(MutableBoolean oauth2Marker) {
+      this.oauth2Marker = oauth2Marker;
+    }
+
+    public boolean visit(String tag, Element element) throws SpecParserException {
+      if (!"OAuth2".equals(tag)) return false;
+
+      if (oauth2Spec != null) {
+        throw new SpecParserException("ModulePrefs/OAuth2 may only occur once.");
+      }
+      oauth2Spec = new OAuth2Spec(element, base);
+      oauth2Marker.setValue(true);
+      return true;
+    }
+
+    public void apply(ModulePrefs moduleprefs) {
+      moduleprefs.oauth2 = oauth2Spec;
+    }
+
+  }
 
   /**
    * Processes ModulePrefs/Require and ModulePrefs/Optional
@@ -797,7 +837,7 @@ public class ModulePrefs {
         globalFeatures.put(Feature.CORE_FEATURE.getName(), Feature.CORE_FEATURE);
       }
       if (oauthMarker.booleanValue()) {
-        // <OAuth> tag found: security token needed.
+        // <OAuth>/<OAuth2> tag found: security token needed.
         features.put(Feature.SECURITY_TOKEN_FEATURE.getName(), Feature.SECURITY_TOKEN_FEATURE);
       }
       moduleprefs.features = ImmutableMap.copyOf(features);

Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuth2Service.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuth2Service.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuth2Service.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuth2Service.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.apache.shindig.gadgets.spec;
+
+import org.apache.shindig.common.uri.Uri;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Information about an OAuth2 service that a gadget wants to use.
+ *
+ * Instances are immutable.
+ */
+public class OAuth2Service extends BaseOAuthService {
+  private EndPoint authorizationUrl;
+  private EndPoint tokenUrl;
+  private String name;
+  private String scope;
+
+  /**
+   * Constructor for testing only.
+   */
+  OAuth2Service() { }
+
+  public OAuth2Service(Element serviceElement, Uri base) throws SpecParserException {
+    name = serviceElement.getAttribute("name");
+    scope = serviceElement.getAttribute("scope");
+    NodeList children = serviceElement.getChildNodes();
+    for (int i=0; i < children.getLength(); ++i) {
+      Node child = children.item(i);
+      if (child.getNodeType() != Node.ELEMENT_NODE) {
+        continue;
+      }
+      String childName = child.getNodeName();
+      if ("Authorization".equals(childName)) {
+        if (authorizationUrl != null) {
+          throw new SpecParserException("Multiple OAuth2/Service/Authorization elements");
+        }
+        authorizationUrl = parseEndPoint("OAuth2/Service/Authorization", (Element)child, base);
+      } else if ("Token".equals(childName)) {
+        if (tokenUrl != null) {
+          throw new SpecParserException("Multiple OAuth2/Service/Token elements");
+        }
+        tokenUrl = parseEndPoint("OAuth2/Service/Token", (Element)child, base);
+      }
+    }
+  }
+
+  /**
+   * Represents /OAuth2/Service/Authorization elements.
+   */
+  public EndPoint getAuthorizationUrl() {
+    return authorizationUrl;
+  }
+
+  /**
+   * Represents /OAuth2/Service/Token elements.
+   */
+  public EndPoint getTokenUrl() {
+    return tokenUrl;
+  }
+
+
+  /**
+   * Represents /OAuth2/Service@scope
+   */
+  public String getScope() {
+    return scope;
+  }
+  
+  /**
+   * Represents /OAuth/Service@name
+   */
+  public String getName() {
+    return name;
+  }
+  
+
+
+}

Added: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuth2Spec.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuth2Spec.java?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuth2Spec.java (added)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuth2Spec.java Wed Oct 12 20:10:39 2011
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.shindig.gadgets.spec;
+
+import com.google.common.collect.Maps;
+
+import org.apache.shindig.common.uri.Uri;
+
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Wraps an &lt;OAuth2&gt; element from the gadget spec.
+ *
+ * Instances are immutable.
+ */
+public class OAuth2Spec {
+
+  /** Keys are service names, values are service descriptors */
+  private final Map<String, OAuth2Service> serviceMap;
+
+  /**
+   * @param element the OAuth2 spec element
+   * @param base  The uri that the spec is loaded from. messages is assumed
+   *     to be relative to this path.
+   * @throws SpecParserException 
+   */
+  public OAuth2Spec(Element element, Uri base) throws SpecParserException {
+    serviceMap = Maps.newHashMap();
+    NodeList services = element.getElementsByTagName("Service");
+    for (int i=0; i < services.getLength(); ++i) {
+      Node node = services.item(i);
+      if (node.getNodeType() == Node.ELEMENT_NODE) {
+        parseService((Element)node, base);
+      }
+    }
+  }
+
+  private void parseService(Element serviceElement, Uri base) throws SpecParserException {
+    OAuth2Service service = new OAuth2Service(serviceElement, base);
+    serviceMap.put(service.getName(), service);
+  }
+
+  public Map<String, OAuth2Service> getServices() {
+    return Collections.unmodifiableMap(serviceMap);
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder();
+    sb.append("<OAuth2>");
+    for (Map.Entry<String, OAuth2Service> entry : serviceMap.entrySet()) {
+      sb.append("<Service name='");
+      sb.append(entry.getKey());
+      sb.append("'>");
+      OAuth2Service service = entry.getValue();
+      if (service.getAuthorizationUrl() != null) {
+        sb.append(service.getAuthorizationUrl().toString("Authorization"));
+      }
+      if (service.getTokenUrl() != null) {
+        sb.append(service.getTokenUrl().toString("Token"));        
+      }
+      sb.append("</Service>");
+    }
+    sb.append("</OAuth2>");
+    return sb.toString();
+  }
+
+}

Modified: shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuthService.java
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuthService.java?rev=1182565&r1=1182564&r2=1182565&view=diff
==============================================================================
--- shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuthService.java (original)
+++ shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/spec/OAuthService.java Wed Oct 12 20:10:39 2011
@@ -18,24 +18,18 @@
  */
 package org.apache.shindig.gadgets.spec;
 
-import com.google.common.collect.Maps;
-import com.google.common.collect.ImmutableMap;
-
 import org.apache.shindig.common.uri.Uri;
-import org.apache.shindig.common.xml.XmlUtil;
 
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
 
-import java.util.Map;
-
 /**
  * Information about an OAuth service that a gadget wants to use.
- *
+ * 
  * Instances are immutable.
  */
-public class OAuthService {
+public class OAuthService extends BaseOAuthService {
   private EndPoint requestUrl;
   private EndPoint accessUrl;
   private Uri authorizationUrl;
@@ -44,12 +38,12 @@ public class OAuthService {
   /**
    * Constructor for testing only.
    */
-  OAuthService() { }
+  OAuthService() {}
 
   public OAuthService(Element serviceElement, Uri base) throws SpecParserException {
     name = serviceElement.getAttribute("name");
     NodeList children = serviceElement.getChildNodes();
-    for (int i=0; i < children.getLength(); ++i) {
+    for (int i = 0; i < children.getLength(); ++i) {
       Node child = children.item(i);
       if (child.getNodeType() != Node.ELEMENT_NODE) {
         continue;
@@ -59,17 +53,17 @@ public class OAuthService {
         if (requestUrl != null) {
           throw new SpecParserException("Multiple OAuth/Service/Request elements");
         }
-        requestUrl = parseEndPoint("OAuth/Service/Request", (Element)child, base);
+        requestUrl = parseEndPoint("OAuth/Service/Request", (Element) child, base);
       } else if ("Authorization".equals(childName)) {
         if (authorizationUrl != null) {
           throw new SpecParserException("Multiple OAuth/Service/Authorization elements");
         }
-        authorizationUrl = parseAuthorizationUrl((Element)child, base);
+        authorizationUrl = parseAuthorizationUrl((Element) child, base);
       } else if ("Access".equals(childName)) {
         if (accessUrl != null) {
           throw new SpecParserException("Multiple OAuth/Service/Access elements");
         }
-        accessUrl = parseEndPoint("OAuth/Service/Access", (Element)child, base);
+        accessUrl = parseEndPoint("OAuth/Service/Access", (Element) child, base);
       }
     }
     if (requestUrl == null) {
@@ -82,17 +76,14 @@ public class OAuthService {
       throw new SpecParserException("/OAuth/Service/Authorization is required");
     }
     if (requestUrl.location != accessUrl.location) {
-      throw new SpecParserException(
-          "Access@location must be identical to Request@location");
+      throw new SpecParserException("Access@location must be identical to Request@location");
     }
     if (requestUrl.method != accessUrl.method) {
-      throw new SpecParserException(
-          "Access@method must be identical to Request@method");
+      throw new SpecParserException("Access@method must be identical to Request@method");
     }
-    if (requestUrl.location == Location.BODY &&
-        requestUrl.method == Method.GET) {
-      throw new SpecParserException("Incompatible parameter location, cannot" +
-          "use post-body with GET requests");
+    if (requestUrl.location == Location.BODY && requestUrl.method == Method.GET) {
+      throw new SpecParserException("Incompatible parameter location, cannot"
+              + "use post-body with GET requests");
     }
   }
 
@@ -109,6 +100,7 @@ public class OAuthService {
   public EndPoint getAccessUrl() {
     return accessUrl;
   }
+
   /**
    * Represents /OAuth/Service/Authorization elements.
    */
@@ -123,119 +115,4 @@ public class OAuthService {
     return name;
   }
 
-  /**
-   * Method to use for requests to an OAuth request token or access token URL.
-   */
-  public enum Method {
-    GET, POST;
-
-    private static final Map<String, Method> METHODS =
-            ImmutableMap.of(GET.toString(), GET, POST.toString(), POST, "", GET);
-
-    public static Method parse(String value) throws SpecParserException {
-      value = value.trim();
-      Method result = METHODS.get(value);
-      if (result == null) {
-        throw new SpecParserException("Unknown OAuth method: " + value);
-      }
-      return result;
-    }
-  }
-
-  /**
-   * Location for OAuth parameters in requests to an OAuth request token,
-   * access token, or resource URL.
-   */
-  public enum Location {
-    HEADER("auth-header"),
-    URL("uri-query"),
-    BODY("post-body");
-
-    private static final Map<String, Location> LOCATIONS;
-
-    static {
-      LOCATIONS = Maps.newHashMap();
-      for (Location l : Location.values()) {
-        LOCATIONS.put(l.locationString, l);
-      }
-      // Default value
-      LOCATIONS.put("", Location.HEADER);
-    }
-
-    private String locationString;
-    private Location(String locationString) {
-      this.locationString = locationString;
-    }
-
-    @Override
-    public String toString() {
-      return locationString;
-    }
-
-    public static Location parse(String value) throws SpecParserException {
-      value = value.trim();
-      Location result = LOCATIONS.get(value);
-      if (result == null) {
-        throw new SpecParserException("Unknown OAuth param_location: " + value);
-      }
-      return result;
-    }
-  }
-
-  private static final String URL_ATTR = "url";
-  private static final String PARAM_LOCATION_ATTR = "param_location";
-  private static final String METHOD_ATTR = "method";
-
-  /**
-   * Description of an OAuth request token or access token URL.
-   */
-  public static class EndPoint {
-    public final Uri url;
-    public Uri getUrl() {
-		return url;
-	}
-
-	public Method getMethod() {
-		return method;
-	}
-
-	public Location getLocation() {
-		return location;
-	}
-
-	public final Method method;
-    public final Location location;
-
-    public EndPoint(Uri url, Method method, Location location) {
-      this.url = url;
-      this.method = method;
-      this.location = location;
-    }
-
-    public String toString(String element) {
-      return '<' + element + " url='" + url.toString() + "' " +
-              "method='" + method + "' param_location='" + location + "'/>";
-    }
-  }
-
-  Uri parseAuthorizationUrl(Element child, Uri base) throws SpecParserException {
-    Uri url = XmlUtil.getHttpUriAttribute(child, URL_ATTR, base);
-    if (url == null) {
-      throw new SpecParserException("OAuth/Service/Authorization @url is not valid: " +
-          child.getAttribute(URL_ATTR));
-    }
-    return base.resolve(url);
-  }
-
-
-  EndPoint parseEndPoint(String where, Element child, Uri base) throws SpecParserException {
-    Uri url = XmlUtil.getHttpUriAttribute(child, URL_ATTR, base);
-    if (url == null) {
-      throw new SpecParserException("Not an HTTP url: " + child.getAttribute(URL_ATTR));
-    }
-
-    Location location = Location.parse(child.getAttribute(PARAM_LOCATION_ATTR));
-    Method method = Method.parse(child.getAttribute(METHOD_ATTR));
-    return new EndPoint(base.resolve(url), method, location);
-  }
 }

Added: shindig/trunk/java/gadgets/src/main/resources/org/apache/shindig/gadgets/oauth2/resource.properties
URL: http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/resources/org/apache/shindig/gadgets/oauth2/resource.properties?rev=1182565&view=auto
==============================================================================
--- shindig/trunk/java/gadgets/src/main/resources/org/apache/shindig/gadgets/oauth2/resource.properties (added)
+++ shindig/trunk/java/gadgets/src/main/resources/org/apache/shindig/gadgets/oauth2/resource.properties Wed Oct 12 20:10:39 2011
@@ -0,0 +1,81 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.  
+message_header= {0} encountered a problem :  
+authorization_code_problem=exchanging authorization_code for access_token : {0}
+authorization_code_problem.explanation=An error occured exchanging the authorization code for access_token.
+authorize_problem=initiating authorization {0}
+authorize_problem.explanation=An error occured initiating authorization.
+callback_problem=processing the redirect_uri response : {0}
+callback_problem.explanation=Error processing the redirect response from the service provider.
+client_credentials_problem=getting access_token from client_credentials : {0}
+client_credentials_problem.explanation=Error in the client_credentials flow.
+fetch_init_problem=initializing OAuth2Request : {0}
+fetch_init_problem.explanation=A low-level error occured intializing the OAuth2 request fetch.
+fetch_problem=executing OAuth2Request.fetch() : {0}
+fetch_problem.explanation=An error occurred issuing the OAuth2 request.
+gadget_spec_problem=processing the gadget spec : {0}
+gadget_spec_problem.explanation=A gadget spec was not found.  Most like your administrator has not configured your gadget to work with OAuth2.
+get_oauth2_accessor_problem=getting an OAuth2Accessor for the OAuth2Request : {0}
+get_oauth2_accessor_problem.explanation=The most common cause of this error is that your administrator has not created an OAuth2Client binding for this gadget and service.
+lookup_spec_problem=looking up the gadget spec : {0}
+lookup_spec_problem.explanation=A gadget spec was not found.  Most like your administrator has not configured your gadget to work with OAuth2.
+missing_fetch_params=there are missing required fetch params : {0} 
+missing_fetch_params.explanation=fetch() method was called with bad parameters.
+missing_server_response=problem with the OAuth2 service provider resonse : {0}
+missing_server_response.explanation=The server was able to create what it thought was a valid OAuth 2 request but was unable to issue the request or get a valid response from the service provider.
+no_response_handler=no response handler processed the response : {0}
+no_response_handler.explanation=There is no AuthorizationEndpointResponseHandler or TokenEndpointResponseHandler registered for what you are trying to do.
+no_gadget_spec=cannot find a gadget spec for {0}
+no_gadget_spec.explanation=A gadget spec was not found.  Most like your administrator has not configured your gadget to work with OAuth2.
+refresh_token_problem=exchanging the refresh_token for a new access_token : {0}
+refresh_token_problem.explanation=The system tried to exchaning a seemingly valid refresh_token for an access_token and encountered an error.
+secret_encryption_problem=encrytping token secret for persistence : {0}
+secret_encryption_problem.explanation=Error storing OAuth2 secrets with the provided encryption module.
+access_denied=access denied
+access_denied.explanation=User denied or canceled the authorization with the service provider.
+invalid_client=invalid client  : {0}
+invalid_client.explanation= Client authentication failed (e.g. unknown client, no client authentication included, or unsupported authentication method).
+invalid_grant=invalid grant : {0}
+invalid_grant.explanation=The provided authorization grant (e.g. authorization code, resource owner credentials, client credentials) is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.
+invalid_request=invalid request : {0}
+invalid_request.explanation=The request is missing a required parameter, includes an unsupported parameter value, repeats a parameter, includes multiple credentials, utilizes more than one mechanism for authenticating the client, or is otherwise malformed.
+invalid_scope=invalid scope : {0}
+invalid_scope.explanation= The requested scope is invalid, unknown, malformed, or exceeds the scope granted by the resource owner.
+server_error=server error : {0}
+server_error.explanation=The authorization server encountered an unexpected condition which prevented it from fulfilling the request.
+server_rejected_request=server rejected request : statuscode = {0}
+server_rejected_request.explanation=The server was able to create what it thought was a valid OAuth 2 request but the OAuth 2 service provider rejected it.
+temporarily_unavailable=temporarily unavailable : {0}
+temporarily_unavailable.explanation=The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.
+token_response_problem=processing response from token endpoint : {0}
+token_response_problem.explanation=The token endpoint sent a response that the server could not process.
+unauthorized_client=unauthorized client : {0}
+unauthorized_client.explanation=The client is not authorized to request an access token using this method.
+unsupported_grant_type=unsupported grant type : {0}
+unsupported_grant_type.explanation=The authorization server does not support obtaining an access token using this method.
+unsupported_response_type=unsupported response type : {0}
+unsupported_response_type.explanation=The authorization server does not support obtaining an authorization code using this method.
+mac_token_problem=mac token request : {0}
+mac_token_problem.explanation=Could not add a mac token on the request to the resource server.
+bearer_token_problem=bearer token request : {0}
+bearer_token_problem.explanation=Could not add a bearer token on the request to the resource server.
+authentication_problem=adding client authentication : {0}
+authentication_problem.explanation=Could not add authentication headers to the request.
+unknown_problem=unknown problem : {0}
+unknown_problem.explanation=Please see your system administrator for help.
+code_grant_problem=getting access_token from authorization code : {0}
+code_grant_problem.explanation=Error in the authorization_code flow.
\ No newline at end of file