/* * Copyright 2014 The Skfiy Open Association. * * 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.skfiy.typhon.spi.cglib; import java.lang.reflect.Method; import java.util.Collection; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import org.skfiy.typhon.domain.Changeable; import org.skfiy.typhon.domain.Indexable; import org.skfiy.typhon.packet.Packet; import org.skfiy.typhon.packet.PacketIndexPropertyChange; import org.skfiy.typhon.packet.PacketPropertyChange; import org.skfiy.typhon.session.Session; import org.skfiy.typhon.util.DomainUtils; /** * * @author Kevin Zou <kevinz@skfiy.org> */ public class DomainProxyCallback implements MethodInterceptor { public static DomainProxyCallback INSTANCE = new DomainProxyCallback(); private static final Map<Object, PropertyMapping> MAPPINGS = new ConcurrentHashMap<>(); private DomainProxyCallback() { } @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { Object rs = proxy.invokeSuper(obj, args); Changeable c = (Changeable) obj; if (c.getPlayer() == null) { return null; } PropertyMapping mapping = MAPPINGS.get(method); if (mapping == null) { synchronized (MAPPINGS) { mapping = newMapping(method); MAPPINGS.put(method, mapping); } } Session session = c.getPlayer().getSession(); if (obj instanceof Indexable) { Indexable ine = (Indexable) obj; PacketIndexPropertyChange pipc = new PacketIndexPropertyChange(); pipc.setNs(c.getNs()); pipc.setType(Packet.Type.st); pipc.setPn(mapping.propertyName); pipc.setPt(mapping.propertyType); pipc.setVal(args[0]); pipc.setIdx(ine.getIndex()); session.write(pipc); } else { PacketPropertyChange ppc = new PacketPropertyChange(); ppc.setNs(c.getNs()); ppc.setType(Packet.Type.st); ppc.setPn(mapping.propertyName); ppc.setPt(mapping.propertyType); ppc.setVal(args[0]); session.write(ppc); } return rs; } private PropertyMapping newMapping(Method method) { PropertyMapping mapping = new PropertyMapping(); mapping.propertyName = method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4); Class<?> propertyClass = method.getParameterTypes()[0]; if (Boolean.TYPE == propertyClass || Boolean.class == propertyClass) { mapping.propertyType = DomainUtils.BOOLEAN; } else if (Character.TYPE == propertyClass || Character.class == propertyClass) { mapping.propertyType = DomainUtils.CHAR; } else if (Byte.TYPE == propertyClass || Byte.class == propertyClass) { mapping.propertyType = DomainUtils.BYTE; } else if (Short.TYPE == propertyClass || Short.class == propertyClass) { mapping.propertyType = DomainUtils.SHORT; } else if (Integer.TYPE == propertyClass || Integer.class == propertyClass) { mapping.propertyType = DomainUtils.INT; } else if (Float.TYPE == propertyClass || Float.class == propertyClass) { mapping.propertyType = DomainUtils.FLOAT; } else if (Long.TYPE == propertyClass || Long.class == propertyClass) { mapping.propertyType = DomainUtils.LONG; } else if (Double.TYPE == propertyClass || Double.class == propertyClass) { mapping.propertyType = DomainUtils.DOUBLE; } else if (String.class == propertyClass || Appendable.class.isAssignableFrom(propertyClass)) { mapping.propertyType = DomainUtils.STRING; } else if (Collection.class.isAssignableFrom(propertyClass) || propertyClass.isArray()) { mapping.propertyType = DomainUtils.ARRAY; } else { mapping.propertyType = DomainUtils.OBJECT; } return mapping; } private class PropertyMapping { String propertyName; int propertyType; } }