/***************************************************************************** * Copyright [2013] [Jules White] * * * * Licensed under the Apache License, Version 2.0 (the "License"); * * you may not use this file except in compliance with the License. * * You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, software * * distributed under the License is distributed on an "AS IS" BASIS, * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * * See the License for the specific language governing permissions and * * limitations under the License. * ****************************************************************************/ package org.magnum.soda.proxy; import java.lang.reflect.InvocationHandler; import java.util.Map; import org.magnum.soda.MsgBus; import org.magnum.soda.ObjRegistry; import org.magnum.soda.msg.LocalAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; public class ProxyFactory { private static final Logger Log = LoggerFactory .getLogger(ProxyFactory.class); private static Map<String, Boolean> byValueClasses_ = Maps .newHashMap(new ImmutableMap.Builder<String, Boolean>() .put(String.class.getName(), true) .put(Boolean.class.getName(), true) .put(Integer.class.getName(), true) .put(Long.class.getName(), true) .put(Double.class.getName(), true) .put(Float.class.getName(), true) .put(Byte.class.getName(), true) .put(ObjRef.class.getName(), true) .put(Class.class.getName(), true) .put(byte[].class.getName(), true).build()); private MsgBus msgBus_; private LocalAddress myAddress_; private ObjRegistry objRegistry_; private ProxyCreator creator_; private InvocationSettings invocationSettings_ = new DefaultInvocationSettings(); public ProxyFactory(ObjRegistry reg, ProxyCreator creator, LocalAddress myaddr, MsgBus msgBus) { super(); creator_ = creator; msgBus_ = msgBus; myAddress_ = myaddr; objRegistry_ = reg; } @SuppressWarnings("unchecked") public <T> T createProxy(Class<T> type, ObjRef objid) { return (T) createProxy(new Class[] { type }, objid); } public Object createProxy(Class<?>[] types, ObjRef objid) { Log.debug("Creating a proxy for ref [{}]", objid); Object proxy = creator_.createProxy(creator_.getProxyClassLoader(), types, new ObjProxy(this, invocationSettings_, msgBus_, objid)); return proxy; } public Object createProxy(ObjRef ref) throws ClassNotFoundException { Class<?>[] types = new Class[ref.getTypes().length]; for (int i = 0; i < types.length; i++) { types[i] = Class.forName(ref.getTypes()[i]); } return createProxy(types, ref); } public ObjRef createObjRef(Class<?>[] types) { ObjRef ref = myAddress_.createObjRef(types); return ref; } public Object[] convertToObjectRefsIfNeeded(Object[] v) { int len = (v != null) ? v.length : 0; Object[] args = new Object[len]; if (v != null) { for (int i = 0; i < v.length; i++) { args[i] = convertToObjectRefIfNeeded(v[i]); } } return args; } public Object convertToObjectRefIfNeeded(Object v) { if (v instanceof Object[]) { return convertToObjectRefsIfNeeded((Object[]) v); } else if (v != null && !v.getClass().isPrimitive()) { v = createObjRef(v); } return v; } public Object createProxiesFromRefsIfNeeded(Object o) throws Exception { if (o instanceof Object[]) { Object[] vals = (Object[]) o; for (int i = 0; i < vals.length; i++) { vals[i] = createProxiesFromRefsIfNeeded(vals[i]); } } else if (o instanceof ObjRef) { ObjRef ref = (ObjRef) o; Object ex = objRegistry_.get(ref); if (ex == null) { o = createProxy(ref); objRegistry_.insert(ref, o); } else { o = ex; } } return o; } private Object createObjRef(Object v) { InvocationHandler hdlr = creator_.getInvocationHandler(v); if (hdlr != null) { if (hdlr instanceof ObjProxy) { v = ((ObjProxy) hdlr).getObjectRef(); } } String cls = v.getClass().getName(); boolean byval = false; if (v.getClass().getAnnotation(SodaByValue.class) != null) { byval = true; } else { Boolean bv = byValueClasses_.get(cls); byval = (bv != null) ? bv : false; } if (!byval) { ObjRef ref = objRegistry_.publish(v); v = ref; } return v; } public InvocationSettings getInvocationSettings() { return invocationSettings_; } public void setInvocationSettings(InvocationSettings invocationSettings) { invocationSettings_ = invocationSettings; } public void passByValue(Class<?> type) { byValueClasses_.put(type.getName(), true); } }