/* * Copyright (c) 2012 Socialize Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package com.socialize; import android.app.Activity; import android.content.Context; import com.socialize.android.ioc.IOCContainer; import com.socialize.annotations.NoAuth; import com.socialize.annotations.Synchronous; import com.socialize.api.SocializeSession; import com.socialize.error.AuthCanceledException; import com.socialize.error.SocializeException; import com.socialize.listener.SocializeAuthListener; import com.socialize.listener.SocializeInitListener; import com.socialize.listener.SocializeListener; import com.socialize.log.SocializeLogger; import org.apache.http.MethodNotSupportedException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; /** * Proxies all requests to top level Socialize interfaces to ensure that clients are both initialized and authenticated. * @author Jason Polites */ public class SocializeActionProxy implements InvocationHandler { private String delegateBean; private boolean synchronous = false; public SocializeActionProxy(String delegateBean) { super(); this.delegateBean = delegateBean; } public SocializeActionProxy(String delegateBean, boolean synchronous) { this(delegateBean); this.synchronous = synchronous; } /* (non-Javadoc) * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[]) */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { if(synchronous || method.isAnnotationPresent(Synchronous.class) || !isVoidMethod(method)) { Context context = findContext(args); if(context != null) { synchronized (this) { SocializeService socialize = Socialize.getSocialize(); if(!socialize.isInitialized(context)) { socialize.init(context); if(!socialize.isAuthenticated() && !method.isAnnotationPresent(NoAuth.class)) { socialize.authenticateSynchronous(context); } } } } return method.invoke(getBean(), args); } else { Activity context = findActivity(args); if(context != null) { SocializeListener listener = findListener(args); // Always init to set the context invokeWithInit(context, listener, method, args); } else { throw new MethodNotSupportedException("No activity found in method arguments for method [" + method.getName() + "]"); } } // Always void return null; } catch (Throwable e) { SocializeLogger.e(e.getMessage(), e); throw e; } } protected boolean isVoidMethod(Method method) { Class<?> returnType = method.getReturnType(); return (returnType == null || returnType.equals(Void.TYPE)); } protected void invokeWithInit(final Activity context, final SocializeListener listener, final Method method, final Object[] args) throws Throwable { SocializeServiceImpl service = getSocialize(); if(service.isInitialized(context)) { service.setContext(context); invoke(context, listener, method, args); } else { service.initAsync(context, new SocializeInitListener() { @Override public void onError(SocializeException error) { if(listener != null) { listener.onError(error); } } @Override public void onInit(Context ctx, IOCContainer container) { // Recurse try { invoke(context, listener, method, args); } catch (Throwable e) { if(listener != null) { listener.onError(SocializeException.wrap(e)); } } } }); } } protected void invoke(Activity context, SocializeListener listener, Method method, Object[] args) throws Throwable { SocializeService service = getSocialize(); if(!service.isAuthenticated() && !method.isAnnotationPresent(NoAuth.class)) { doAuthAsync(context, listener, method, args); } else { method.invoke(getBean(), args); } } protected Object getBean() throws MethodNotSupportedException { Object bean = Socialize.getBean(delegateBean); if(bean != null) { return bean; } else { throw new MethodNotSupportedException("No bean with name [" + delegateBean + "] found"); } } protected Activity findActivity(Object[] args) { for (Object object : args) { if(object instanceof Activity) { return (Activity) object; } } return null; } protected Context findContext(Object[] args) { for (Object object : args) { if(object instanceof Context) { return (Context) object; } } return null; } protected SocializeListener findListener(Object[] args) { for (Object object : args) { if(object instanceof SocializeListener) { return (SocializeListener) object; } } return null; } protected synchronized <L extends SocializeListener> void doAuthAsync(final Activity context, final SocializeListener listener, final Method method, final Object[] args) throws Throwable { final SocializeService service = getSocialize(); if(!service.isAuthenticated()) { synchronized (this) { if(!service.isAuthenticated()) { context.runOnUiThread(new Runnable() { @Override public void run() { service.authenticate(context, new SocializeAuthListener() { @Override public void onError(SocializeException error) { if(listener != null) { listener.onError(error); } } @Override public void onCancel() { if(listener != null) { listener.onError(new AuthCanceledException("Authentication was canceled by the user")); } } @Override public void onAuthSuccess(SocializeSession session) { // Recurse try { invoke(context, listener, method, args); } catch (Throwable e) { if(listener != null) { listener.onError(SocializeException.wrap(e)); } } } @Override public void onAuthFail(SocializeException error) { if(listener != null) { listener.onError(error); } } }); } }); } else { // Recurse invoke(context, listener, method, args); } } } else { // Recurse invoke(context, listener, method, args); } } protected SocializeServiceImpl getSocialize() { return (SocializeServiceImpl) Socialize.getSocialize(); } }