├── .gitignore ├── README.md ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── justdebugit │ │ └── thrift │ │ ├── bytecode │ │ ├── ClassGenerator.java │ │ ├── Mixin.java │ │ ├── NoSuchMethodException.java │ │ ├── NoSuchPropertyException.java │ │ ├── Proxy.java │ │ └── Wrapper.java │ │ ├── client │ │ ├── DefaultThrfitClientFactory.java │ │ ├── ThriftClientFactory.java │ │ └── ThriftStatefulPoolFactory.java │ │ ├── common │ │ ├── AbstractLifeCycle.java │ │ ├── LifeCycle.java │ │ ├── ServiceConfig.java │ │ ├── ThriftInitException.java │ │ └── ThriftRpcException.java │ │ ├── constants │ │ └── Constants.java │ │ ├── consumer │ │ ├── RpcConsumer.java │ │ └── RpcConsumerFactory.java │ │ ├── generated │ │ ├── BlackService.java │ │ ├── Category.java │ │ ├── DifferentSourceDetectedException.java │ │ ├── Friend.java │ │ ├── UserInfo.java │ │ ├── UserManagerService.java │ │ ├── UserRepoService.java │ │ ├── UserSource.java │ │ └── userManagerConstants.java │ │ ├── pool │ │ ├── AbstractObjectFactory.java │ │ ├── AbstractStatefulPool.java │ │ ├── AjustingLifeCycleMap.java │ │ ├── DelegatableStatefulPool.java │ │ ├── IllegalPoolStateException.java │ │ ├── LifeCycleMap.java │ │ ├── MultiPool.java │ │ ├── NodeKeyMapManager.java │ │ ├── NotifiableLifeCycleMap.java │ │ ├── State.java │ │ ├── StatefulPool.java │ │ ├── StatefulPoolFactory.java │ │ └── StatefulPoolMapManager.java │ │ ├── provider │ │ └── RpcProvider.java │ │ ├── proxy │ │ ├── PooledProxyFactory.java │ │ └── PooledTargetInvocationHandler.java │ │ ├── registry │ │ ├── ChangeListener.java │ │ ├── CuratorFactory.java │ │ ├── DefaultCuratorFactory.java │ │ ├── NodeEvent.java │ │ ├── Registry.java │ │ ├── ZkCuratorRegistry.java │ │ ├── ZkPathConstants.java │ │ └── ZkRegistryUtils.java │ │ ├── server │ │ ├── DefaultTServerFactory.java │ │ ├── Server.java │ │ └── TServerFactory.java │ │ └── utils │ │ ├── ClassHelper.java │ │ ├── NetUtils.java │ │ ├── ReflectUtils.java │ │ ├── StringUtils.java │ │ └── ZkRegistryUtils.java ├── resources │ └── logback.xml └── thrift │ ├── user.thrift │ └── userManager.thrift └── test └── java └── com └── justdebugit └── thrift └── example ├── raw ├── BlackServiceImpl.java ├── BlackServiceStub.java ├── RawThriftClientExample.java ├── RawThriftServerExample.java ├── UserManagerServiceImpl.java └── UserManagerServiceStub.java └── thriftrpc ├── RpcConsumerMain.java ├── RpcProviderMain.java └── Test.java /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .DS_Store? 3 | ._* 4 | .Spotlight-V100 5 | .Trashes 6 | ehthumbs.db 7 | Thumbs.db 8 | *.project 9 | *.classpath 10 | *.settings 11 | target 12 | bin 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # thrift-rpc 2 | 基于Thrift的rpc框架---自动发现服务(借助zookeeper),动态代理(减少代码编写),高性能(client连接池使用fastpool) 3 | # example 4 | 5 | provider 6 | ```java 7 | Map processorMap = ImmutableMap 8 | . of( 9 | "blackService", 10 | new BlackService.Processor( 11 | new BlackServiceImpl()), 12 | "userService", 13 | new UserManagerService.Processor( 14 | new UserManagerServiceImpl())); 15 | final RpcProvider rpcProvider = RpcProvider.builder() 16 | .connectStringForzk("127.0.0.1:2181") 17 | .processorMap(processorMap).serverPort(8080).build(); 18 | rpcProvider.start(); 19 | ``` 20 | 21 | consumer 22 | ```java 23 | ServiceConfig blacklistService = new ServiceConfig(); 24 | blacklistService.setServiceName("blackService") 25 | .setServiceClass(BlackService.class).setMinPoolSize(10); 26 | 27 | ServiceConfig userService = new ServiceConfig(); 28 | userService.setServiceName("userService").setServiceClass( 29 | UserManagerService.class); 30 | 31 | final RpcConsumer rpcConsumer = RpcConsumerFactory.newRpcConsumer( 32 | "127.0.0.1:2181", 33 | Lists.newArrayList(blacklistService, userService)); 34 | rpcConsumer.start(); 35 | 36 | final BlackService.Iface client = rpcConsumer 37 | .getService("blackService"); 38 | System.out.println(client.isBlack(11)); 39 | 40 | final UserManagerService.Iface userCliIface = rpcConsumer 41 | .getService("userService"); 42 | System.out.println(userCliIface.get(1)); 43 | ``` 44 | 45 | #性能测试 46 | 经测试,TPS 达到 2.08w/s 47 | 48 | ##TODO: 49 | 50 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | 5 | com.justdebugit.thrift 6 | thrift-rpc 7 | 0.0.1-SNAPSHOT 8 | jar 9 | 10 | thrift-rpc 11 | http://maven.apache.org 12 | 13 | 14 | UTF-8 15 | 16 | 17 | 18 | 19 | junit 20 | junit 21 | 3.8.1 22 | test 23 | 24 | 25 | org.apache.thrift 26 | libthrift 27 | 0.9.2 28 | 29 | 30 | com.google.guava 31 | guava 32 | 18.0 33 | 34 | 35 | org.slf4j 36 | slf4j-api 37 | 1.7.6 38 | 39 | 40 | ch.qos.logback 41 | logback-core 42 | 1.1.2 43 | 44 | 45 | ch.qos.logback 46 | logback-classic 47 | 1.1.2 48 | 49 | 50 | org.apache.zookeeper 51 | zookeeper 52 | 3.5.0-alpha 53 | 54 | 55 | org.slf4j 56 | slf4j-api 57 | 58 | 59 | org.slf4j 60 | slf4j-log4j12 61 | 62 | 63 | 64 | 65 | org.apache.curator 66 | curator-framework 67 | 2.8.0 68 | 69 | 70 | org.apache.curator 71 | curator-recipes 72 | 2.8.0 73 | 74 | 75 | com.google.guava 76 | guava 77 | 18.0 78 | 79 | 80 | org.apache.commons 81 | commons-lang3 82 | 3.3.2 83 | 84 | 85 | com.justdebugit 86 | fastpool 87 | 1.0-SNAPSHOT 88 | 89 | 90 | org.javassist 91 | javassist 92 | 3.18.2-GA 93 | 94 | 95 | 96 | 97 | 98 | 99 | org.apache.maven.plugins 100 | maven-compiler-plugin 101 | 102 | 1.7 103 | 1.7 104 | 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/bytecode/ClassGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2011 Alibaba Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.justdebugit.thrift.bytecode; 17 | 18 | import java.lang.reflect.Constructor; 19 | import java.lang.reflect.Method; 20 | import java.lang.reflect.Modifier; 21 | import java.security.ProtectionDomain; 22 | import java.util.ArrayList; 23 | import java.util.HashSet; 24 | import java.util.LinkedList; 25 | import java.util.List; 26 | import java.util.Map; 27 | import java.util.Set; 28 | import java.util.concurrent.ConcurrentHashMap; 29 | import java.util.concurrent.atomic.AtomicLong; 30 | 31 | import javassist.CannotCompileException; 32 | import javassist.ClassPool; 33 | import javassist.CtClass; 34 | import javassist.CtConstructor; 35 | import javassist.CtField; 36 | import javassist.CtMethod; 37 | import javassist.CtNewConstructor; 38 | import javassist.CtNewMethod; 39 | import javassist.LoaderClassPath; 40 | import javassist.NotFoundException; 41 | 42 | import com.justdebugit.thrift.utils.ReflectUtils; 43 | 44 | /** 45 | * ClassGenerator 46 | * 47 | * @author qian.lei 48 | */ 49 | 50 | public final class ClassGenerator 51 | { 52 | public static interface DC{} // dynamic class tag interface. 53 | 54 | private static final AtomicLong CLASS_NAME_COUNTER = new AtomicLong(0); 55 | 56 | private static final String SIMPLE_NAME_TAG = ""; 57 | 58 | private static final Map POOL_MAP = new ConcurrentHashMap(); //ClassLoader - ClassPool 59 | 60 | public static ClassGenerator newInstance() 61 | { 62 | return new ClassGenerator(getClassPool(Thread.currentThread().getContextClassLoader())); 63 | } 64 | 65 | public static ClassGenerator newInstance(ClassLoader loader) 66 | { 67 | return new ClassGenerator(getClassPool(loader)); 68 | } 69 | 70 | public static boolean isDynamicClass(Class cl) 71 | { 72 | return ClassGenerator.DC.class.isAssignableFrom(cl); 73 | } 74 | 75 | public static ClassPool getClassPool(ClassLoader loader) 76 | { 77 | if( loader == null ) 78 | return ClassPool.getDefault(); 79 | 80 | ClassPool pool = POOL_MAP.get(loader); 81 | if( pool == null ) 82 | { 83 | pool = new ClassPool(true); 84 | pool.appendClassPath(new LoaderClassPath(loader)); 85 | POOL_MAP.put(loader, pool); 86 | } 87 | return pool; 88 | } 89 | 90 | private ClassPool mPool; 91 | 92 | private CtClass mCtc; 93 | 94 | private String mClassName, mSuperClass; 95 | 96 | private Set mInterfaces; 97 | 98 | private List mFields, mConstructors, mMethods; 99 | 100 | private Map mCopyMethods; // 101 | 102 | private Map> mCopyConstructors; // 103 | 104 | private boolean mDefaultConstructor = false; 105 | 106 | private ClassGenerator(){} 107 | 108 | private ClassGenerator(ClassPool pool) 109 | { 110 | mPool = pool; 111 | } 112 | 113 | public String getClassName() 114 | { 115 | return mClassName; 116 | } 117 | 118 | public ClassGenerator setClassName(String name) 119 | { 120 | mClassName = name; 121 | return this; 122 | } 123 | 124 | public ClassGenerator addInterface(String cn) 125 | { 126 | if( mInterfaces == null ) 127 | mInterfaces = new HashSet(); 128 | mInterfaces.add(cn); 129 | return this; 130 | } 131 | 132 | public ClassGenerator addInterface(Class cl) 133 | { 134 | return addInterface(cl.getName()); 135 | } 136 | 137 | public ClassGenerator setSuperClass(String cn) 138 | { 139 | mSuperClass = cn; 140 | return this; 141 | } 142 | 143 | public ClassGenerator setSuperClass(Class cl) 144 | { 145 | mSuperClass = cl.getName(); 146 | return this; 147 | } 148 | 149 | public ClassGenerator addField(String code) 150 | { 151 | if( mFields == null ) 152 | mFields = new ArrayList(); 153 | mFields.add(code); 154 | return this; 155 | } 156 | 157 | public ClassGenerator addField(String name, int mod, Class type) 158 | { 159 | return addField(name, mod, type, null); 160 | } 161 | 162 | public ClassGenerator addField(String name, int mod, Class type, String def) 163 | { 164 | StringBuilder sb = new StringBuilder(); 165 | sb.append(modifier(mod)).append(' ').append(ReflectUtils.getName(type)).append(' '); 166 | sb.append(name); 167 | if( def != null && def.length() > 0 ) 168 | { 169 | sb.append('='); 170 | sb.append(def); 171 | } 172 | sb.append(';'); 173 | return addField(sb.toString()); 174 | } 175 | 176 | public ClassGenerator addMethod(String code) 177 | { 178 | if( mMethods == null ) 179 | mMethods = new ArrayList(); 180 | mMethods.add(code); 181 | return this; 182 | } 183 | 184 | public ClassGenerator addMethod(String name, int mod, Class rt, Class[] pts, String body) 185 | { 186 | return addMethod(name, mod, rt, pts, null, body); 187 | } 188 | 189 | public ClassGenerator addMethod(String name, int mod, Class rt, Class[] pts, Class[] ets, String body) 190 | { 191 | StringBuilder sb = new StringBuilder(); 192 | sb.append(modifier(mod)).append(' ').append(ReflectUtils.getName(rt)).append(' ').append(name); 193 | sb.append('('); 194 | for(int i=0;i 0 ) 197 | sb.append(','); 198 | sb.append(ReflectUtils.getName(pts[i])); 199 | sb.append(" arg").append(i); 200 | } 201 | sb.append(')'); 202 | if( ets != null && ets.length > 0 ) 203 | { 204 | sb.append(" throws "); 205 | for(int i=0;i 0 ) 208 | sb.append(','); 209 | sb.append(ReflectUtils.getName(ets[i])); 210 | } 211 | } 212 | sb.append('{').append(body).append('}'); 213 | return addMethod(sb.toString()); 214 | } 215 | 216 | public ClassGenerator addMethod(Method m) 217 | { 218 | addMethod(m.getName(), m); 219 | return this; 220 | } 221 | 222 | public ClassGenerator addMethod(String name, Method m) 223 | { 224 | String desc = name + ReflectUtils.getDescWithoutMethodName(m); 225 | addMethod(':' + desc); 226 | if( mCopyMethods == null ) 227 | mCopyMethods = new ConcurrentHashMap(8); 228 | mCopyMethods.put(desc, m); 229 | return this; 230 | } 231 | 232 | public ClassGenerator addConstructor(String code) 233 | { 234 | if( mConstructors == null ) 235 | mConstructors = new LinkedList(); 236 | mConstructors.add(code); 237 | return this; 238 | } 239 | 240 | public ClassGenerator addConstructor(int mod, Class[] pts, String body) 241 | { 242 | return addConstructor(mod, pts, null, body); 243 | } 244 | 245 | public ClassGenerator addConstructor(int mod, Class[] pts, Class[] ets, String body) 246 | { 247 | StringBuilder sb = new StringBuilder(); 248 | sb.append(modifier(mod)).append(' ').append(SIMPLE_NAME_TAG); 249 | sb.append('('); 250 | for(int i=0;i 0 ) 253 | sb.append(','); 254 | sb.append(ReflectUtils.getName(pts[i])); 255 | sb.append(" arg").append(i); 256 | } 257 | sb.append(')'); 258 | if( ets != null && ets.length > 0 ) 259 | { 260 | sb.append(" throws "); 261 | for(int i=0;i 0 ) 264 | sb.append(','); 265 | sb.append(ReflectUtils.getName(ets[i])); 266 | } 267 | } 268 | sb.append('{').append(body).append('}'); 269 | return addConstructor(sb.toString()); 270 | } 271 | 272 | public ClassGenerator addConstructor(Constructor c) 273 | { 274 | String desc = ReflectUtils.getDesc(c); 275 | addConstructor(":"+desc); 276 | if( mCopyConstructors == null ) 277 | mCopyConstructors = new ConcurrentHashMap>(4); 278 | mCopyConstructors.put(desc, c); 279 | return this; 280 | } 281 | 282 | public ClassGenerator addDefaultConstructor() 283 | { 284 | mDefaultConstructor = true; 285 | return this; 286 | } 287 | 288 | public ClassPool getClassPool() { 289 | return mPool; 290 | } 291 | 292 | public Class toClass(){ 293 | return toClass(getClass().getClassLoader(), getClass().getProtectionDomain()); 294 | } 295 | 296 | public Class toClass(ClassLoader loader, ProtectionDomain pd) 297 | { 298 | if( mCtc != null ) 299 | mCtc.detach(); 300 | long id = CLASS_NAME_COUNTER.getAndIncrement(); 301 | try 302 | { 303 | CtClass ctcs = mSuperClass == null ? null : mPool.get(mSuperClass); 304 | if( mClassName == null ) 305 | mClassName = ( mSuperClass == null || javassist.Modifier.isPublic(ctcs.getModifiers()) 306 | ? ClassGenerator.class.getName() : mSuperClass + "$sc" ) + id; 307 | mCtc = mPool.makeClass(mClassName); 308 | if( mSuperClass != null ) 309 | mCtc.setSuperclass(ctcs); 310 | mCtc.addInterface(mPool.get(DC.class.getName())); // add dynamic class tag. 311 | if( mInterfaces != null ) 312 | for( String cl : mInterfaces ) mCtc.addInterface(mPool.get(cl)); 313 | if( mFields != null ) 314 | for( String code : mFields ) mCtc.addField(CtField.make(code, mCtc)); 315 | if( mMethods != null ) 316 | { 317 | for( String code : mMethods ) 318 | { 319 | if( code.charAt(0) == ':' ) 320 | mCtc.addMethod(CtNewMethod.copy(getCtMethod(mCopyMethods.get(code.substring(1))), code.substring(1, code.indexOf('(')), mCtc, null)); 321 | else 322 | mCtc.addMethod(CtNewMethod.make(code, mCtc)); 323 | } 324 | } 325 | if( mDefaultConstructor ) 326 | mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc)); 327 | if( mConstructors != null ) 328 | { 329 | for( String code : mConstructors ) 330 | { 331 | if( code.charAt(0) == ':' ) 332 | { 333 | mCtc.addConstructor(CtNewConstructor.copy(getCtConstructor(mCopyConstructors.get(code.substring(1))), mCtc, null)); 334 | } 335 | else 336 | { 337 | String[] sn = mCtc.getSimpleName().split("\\$+"); // inner class name include $. 338 | mCtc.addConstructor(CtNewConstructor.make(code.replaceFirst(SIMPLE_NAME_TAG, sn[sn.length-1]), mCtc)); 339 | } 340 | } 341 | } 342 | return mCtc.toClass(loader, pd); 343 | } 344 | catch(RuntimeException e) 345 | { 346 | throw e; 347 | } 348 | catch(NotFoundException e) 349 | { 350 | throw new RuntimeException(e.getMessage(), e); 351 | } 352 | catch(CannotCompileException e) 353 | { 354 | throw new RuntimeException(e.getMessage(), e); 355 | } 356 | } 357 | 358 | public void release() 359 | { 360 | if( mCtc != null ) mCtc.detach(); 361 | if( mInterfaces != null ) mInterfaces.clear(); 362 | if( mFields != null ) mFields.clear(); 363 | if( mMethods != null ) mMethods.clear(); 364 | if( mConstructors != null ) mConstructors.clear(); 365 | if( mCopyMethods != null ) mCopyMethods.clear(); 366 | if( mCopyConstructors != null ) mCopyConstructors.clear(); 367 | } 368 | 369 | private CtClass getCtClass(Class c) throws NotFoundException 370 | { 371 | return mPool.get(c.getName()); 372 | } 373 | 374 | private CtMethod getCtMethod(Method m) throws NotFoundException 375 | { 376 | return getCtClass(m.getDeclaringClass()).getMethod(m.getName(),ReflectUtils.getDescWithoutMethodName(m)); 377 | } 378 | 379 | private CtConstructor getCtConstructor(Constructor c) throws NotFoundException 380 | { 381 | return getCtClass(c.getDeclaringClass()).getConstructor(ReflectUtils.getDesc(c)); 382 | } 383 | 384 | private static String modifier(int mod) 385 | { 386 | if( Modifier.isPublic(mod) ) return "public"; 387 | if( Modifier.isProtected(mod) ) return "protected"; 388 | if( Modifier.isPrivate(mod) ) return "private"; 389 | return ""; 390 | } 391 | } -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/bytecode/Mixin.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2011 Alibaba Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.justdebugit.thrift.bytecode; 17 | 18 | import java.lang.reflect.Method; 19 | import java.lang.reflect.Modifier; 20 | import java.util.HashSet; 21 | import java.util.Set; 22 | import java.util.concurrent.atomic.AtomicLong; 23 | 24 | import com.justdebugit.thrift.utils.ClassHelper; 25 | import com.justdebugit.thrift.utils.ReflectUtils; 26 | 27 | /** 28 | * Mixin 29 | * 30 | * @author qian.lei 31 | */ 32 | 33 | public abstract class Mixin 34 | { 35 | private static AtomicLong MIXIN_CLASS_COUNTER = new AtomicLong(0); 36 | 37 | private static final String PACKAGE_NAME = Mixin.class.getPackage().getName(); 38 | 39 | public static interface MixinAware{ void setMixinInstance(Object instance); } 40 | 41 | /** 42 | * mixin interface and delegates. 43 | * all class must be public. 44 | * 45 | * @param ics interface class array. 46 | * @param dc delegate class. 47 | * @return Mixin instance. 48 | */ 49 | public static Mixin mixin(Class[] ics, Class dc) 50 | { 51 | return mixin(ics, new Class[]{dc}); 52 | } 53 | 54 | /** 55 | * mixin interface and delegates. 56 | * all class must be public. 57 | * 58 | * @param ics interface class array. 59 | * @param dc delegate class. 60 | * @param cl class loader. 61 | * @return Mixin instance. 62 | */ 63 | public static Mixin mixin(Class[] ics, Class dc, ClassLoader cl) 64 | { 65 | return mixin(ics, new Class[]{dc}, cl); 66 | } 67 | 68 | /** 69 | * mixin interface and delegates. 70 | * all class must be public. 71 | * 72 | * @param ics interface class array. 73 | * @param dcs delegate class array. 74 | * @return Mixin instance. 75 | */ 76 | public static Mixin mixin(Class[] ics, Class[] dcs) 77 | { 78 | return mixin(ics, dcs, ClassHelper.getCallerClassLoader(Mixin.class)); 79 | } 80 | 81 | /** 82 | * mixin interface and delegates. 83 | * all class must be public. 84 | * 85 | * @param ics interface class array. 86 | * @param dcs delegate class array. 87 | * @param cl class loader. 88 | * @return Mixin instance. 89 | */ 90 | public static Mixin mixin(Class[] ics, Class[] dcs, ClassLoader cl) 91 | { 92 | assertInterfaceArray(ics); 93 | 94 | long id = MIXIN_CLASS_COUNTER.getAndIncrement(); 95 | String pkg = null; 96 | ClassGenerator ccp = null, ccm = null; 97 | try 98 | { 99 | ccp = ClassGenerator.newInstance(cl); 100 | 101 | // impl constructor 102 | StringBuilder code = new StringBuilder(); 103 | for(int i=0;i[]{ Object[].class }, code.toString()); 126 | 127 | // impl methods. 128 | Set worked = new HashSet(); 129 | for(int i=0;i rt = method.getReturnType(); 162 | String mn = method.getName(); 163 | if( Void.TYPE.equals(rt) ) 164 | ccp.addMethod(mn, method.getModifiers(), rt, method.getParameterTypes(), method.getExceptionTypes(), 165 | "d" + ix + "." + mn + "($$);"); 166 | else 167 | ccp.addMethod(mn, method.getModifiers(), rt, method.getParameterTypes(), method.getExceptionTypes(), 168 | "return ($r)d" + ix + "." + mn + "($$);"); 169 | } 170 | } 171 | 172 | if( pkg == null ) 173 | pkg = PACKAGE_NAME; 174 | 175 | // create MixinInstance class. 176 | String micn = pkg + ".mixin" + id; 177 | ccp.setClassName(micn); 178 | ccp.toClass(); 179 | 180 | // create Mixin class. 181 | String fcn = Mixin.class.getName() + id; 182 | ccm = ClassGenerator.newInstance(cl); 183 | ccm.setClassName(fcn); 184 | ccm.addDefaultConstructor(); 185 | ccm.setSuperClass(Mixin.class.getName()); 186 | ccm.addMethod("public Object newInstance(Object[] delegates){ return new " + micn + "($1); }"); 187 | Class mixin = ccm.toClass(); 188 | return (Mixin)mixin.newInstance(); 189 | } 190 | catch(RuntimeException e) 191 | { 192 | throw e; 193 | } 194 | catch(Exception e) 195 | { 196 | throw new RuntimeException(e.getMessage(), e); 197 | } 198 | finally 199 | { 200 | // release ClassGenerator 201 | if( ccp != null ) 202 | ccp.release(); 203 | if( ccm != null ) 204 | ccm.release(); 205 | } 206 | } 207 | 208 | /** 209 | * new Mixin instance. 210 | * 211 | * @param ds delegates instance. 212 | * @return instance. 213 | */ 214 | abstract public Object newInstance(Object[] ds); 215 | 216 | protected Mixin(){} 217 | 218 | private static int findMethod(Class[] dcs, String desc) 219 | { 220 | Class cl; 221 | Method[] methods; 222 | for(int i=0;i[] ics) 236 | { 237 | for(int i=0;i> ProxyCacheMap = new WeakHashMap>(); 56 | 57 | private static final Object PendingGenerationMarker = new Object(); 58 | 59 | /** 60 | * Get proxy. 61 | * 62 | * @param ics interface class array. 63 | * @return Proxy instance. 64 | */ 65 | public static Proxy getProxy(Class... ics) 66 | { 67 | return getProxy(ClassHelper.getCallerClassLoader(Proxy.class), ics); 68 | } 69 | 70 | /** 71 | * Get proxy. 72 | * @param cl class loader. 73 | * @param ics interface class array. 74 | * 75 | * @return Proxy instance. 76 | */ 77 | public static Proxy getProxy(ClassLoader cl, Class... ics) 78 | { 79 | if( ics.length > 65535 ) 80 | throw new IllegalArgumentException("interface limit exceeded"); 81 | 82 | StringBuilder sb = new StringBuilder(); 83 | for(int i=0;i tmp = null; 90 | try 91 | { 92 | tmp = Class.forName(itf, false, cl); 93 | } 94 | catch(ClassNotFoundException e) 95 | {} 96 | 97 | if( tmp != ics[i] ) 98 | throw new IllegalArgumentException(ics[i] + " is not visible from class loader"); 99 | 100 | sb.append(itf).append(';'); 101 | } 102 | 103 | // use interface class name list as key. 104 | String key = sb.toString(); 105 | 106 | // get cache by class loader. 107 | Map cache; 108 | synchronized( ProxyCacheMap ) 109 | { 110 | cache = ProxyCacheMap.get(cl); 111 | if( cache == null ) 112 | { 113 | cache = new HashMap(); 114 | ProxyCacheMap.put(cl, cache); 115 | } 116 | } 117 | 118 | Proxy proxy = null; 119 | synchronized( cache ) 120 | { 121 | do 122 | { 123 | Object value = cache.get(key); 124 | if( value instanceof Reference ) 125 | { 126 | proxy = (Proxy)((Reference)value).get(); 127 | if( proxy != null ) 128 | return proxy; 129 | } 130 | 131 | if( value == PendingGenerationMarker ) 132 | { 133 | try{ cache.wait(); }catch(InterruptedException e){} 134 | } 135 | else 136 | { 137 | cache.put(key, PendingGenerationMarker); 138 | break; 139 | } 140 | } 141 | while( true ); 142 | } 143 | 144 | long id = PROXY_CLASS_COUNTER.getAndIncrement(); 145 | String pkg = null; 146 | ClassGenerator ccp = null, ccm = null; 147 | try 148 | { 149 | ccp = ClassGenerator.newInstance(cl); 150 | 151 | Set worked = new HashSet(); 152 | List methods = new ArrayList(); 153 | 154 | for(int i=0;i rt = method.getReturnType(); 180 | Class[] pts = method.getParameterTypes(); 181 | 182 | StringBuilder code = new StringBuilder("Object[] args = new Object[").append(pts.length).append("];"); 183 | for(int j=0;j[]{ InvocationHandler.class }, new Class[0], "handler=$1;"); 203 | ccp.addDefaultConstructor(); 204 | Class clazz = ccp.toClass(); 205 | clazz.getField("methods").set(null, methods.toArray(new Method[0])); 206 | 207 | // create Proxy class. 208 | String fcn = Proxy.class.getName() + id; 209 | ccm = ClassGenerator.newInstance(cl); 210 | ccm.setClassName(fcn); 211 | ccm.addDefaultConstructor(); 212 | ccm.setSuperClass(Proxy.class); 213 | ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }"); 214 | Class pc = ccm.toClass(); 215 | proxy = (Proxy)pc.newInstance(); 216 | } 217 | catch(RuntimeException e) 218 | { 219 | throw e; 220 | } 221 | catch(Exception e) 222 | { 223 | throw new RuntimeException(e.getMessage(), e); 224 | } 225 | finally 226 | { 227 | // release ClassGenerator 228 | if( ccp != null ) 229 | ccp.release(); 230 | if( ccm != null ) 231 | ccm.release(); 232 | synchronized( cache ) 233 | { 234 | if( proxy == null ) 235 | cache.remove(key); 236 | else 237 | cache.put(key, new WeakReference(proxy)); 238 | cache.notifyAll(); 239 | } 240 | } 241 | return proxy; 242 | } 243 | 244 | /** 245 | * get instance with default handler. 246 | * 247 | * @return instance. 248 | */ 249 | public Object newInstance() 250 | { 251 | return newInstance(THROW_UNSUPPORTED_INVOKER); 252 | } 253 | 254 | /** 255 | * get instance with special handler. 256 | * 257 | * @return instance. 258 | */ 259 | abstract public Object newInstance(InvocationHandler handler); 260 | 261 | protected Proxy(){} 262 | 263 | private static String asArgument(Class cl, String name) 264 | { 265 | if( cl.isPrimitive() ) 266 | { 267 | if( Boolean.TYPE == cl ) 268 | return name + "==null?false:((Boolean)" + name + ").booleanValue()"; 269 | if( Byte.TYPE == cl ) 270 | return name + "==null?(byte)0:((Byte)" + name + ").byteValue()"; 271 | if( Character.TYPE == cl ) 272 | return name + "==null?(char)0:((Character)" + name + ").charValue()"; 273 | if( Double.TYPE == cl ) 274 | return name + "==null?(double)0:((Double)" + name + ").doubleValue()"; 275 | if( Float.TYPE == cl ) 276 | return name + "==null?(float)0:((Float)" + name + ").floatValue()"; 277 | if( Integer.TYPE == cl ) 278 | return name + "==null?(int)0:((Integer)" + name + ").intValue()"; 279 | if( Long.TYPE == cl ) 280 | return name + "==null?(long)0:((Long)" + name + ").longValue()"; 281 | if( Short.TYPE == cl ) 282 | return name + "==null?(short)0:((Short)" + name + ").shortValue()"; 283 | throw new RuntimeException(name+" is unknown primitive type."); 284 | } 285 | return "(" + ReflectUtils.getName(cl) + ")"+name; 286 | } 287 | } -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/bytecode/Wrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2011 Alibaba Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.justdebugit.thrift.bytecode; 17 | 18 | import java.lang.reflect.Field; 19 | import java.lang.reflect.InvocationTargetException; 20 | import java.lang.reflect.Method; 21 | import java.lang.reflect.Modifier; 22 | import java.util.ArrayList; 23 | import java.util.HashMap; 24 | import java.util.LinkedHashMap; 25 | import java.util.List; 26 | import java.util.Map; 27 | import java.util.concurrent.ConcurrentHashMap; 28 | import java.util.concurrent.atomic.AtomicLong; 29 | import java.util.regex.Matcher; 30 | 31 | import com.justdebugit.thrift.utils.ClassHelper; 32 | import com.justdebugit.thrift.utils.ReflectUtils; 33 | 34 | /** 35 | * Wrapper. 36 | * 37 | * @author qian.lei 38 | */ 39 | 40 | public abstract class Wrapper 41 | { 42 | private static AtomicLong WRAPPER_CLASS_COUNTER = new AtomicLong(0); 43 | 44 | private static final Map, Wrapper> WRAPPER_MAP = new ConcurrentHashMap, Wrapper>(); //class wrapper map 45 | 46 | private static final String[] EMPTY_STRING_ARRAY = new String[0]; 47 | 48 | private static final String[] OBJECT_METHODS = new String[]{"getClass", "hashCode", "toString", "equals"}; 49 | 50 | private static final Wrapper OBJECT_WRAPPER = new Wrapper(){ 51 | public String[] getMethodNames(){ return OBJECT_METHODS; } 52 | public String[] getDeclaredMethodNames(){ return OBJECT_METHODS; } 53 | public String[] getPropertyNames(){ return EMPTY_STRING_ARRAY; } 54 | public Class getPropertyType(String pn){ return null; } 55 | public Object getPropertyValue(Object instance, String pn) throws NoSuchPropertyException{ throw new NoSuchPropertyException("Property [" + pn + "] not found."); } 56 | public void setPropertyValue(Object instance, String pn, Object pv) throws NoSuchPropertyException{ throw new NoSuchPropertyException("Property [" + pn + "] not found."); } 57 | public boolean hasProperty(String name){ return false; } 58 | public Object invokeMethod(Object instance, String mn, Class[] types, Object[] args) throws NoSuchMethodException 59 | { 60 | if( "getClass".equals(mn) ) return instance.getClass(); 61 | if( "hashCode".equals(mn) ) return instance.hashCode(); 62 | if( "toString".equals(mn) ) return instance.toString(); 63 | if( "equals".equals(mn) ) 64 | { 65 | if( args.length == 1 ) return instance.equals(args[0]); 66 | throw new IllegalArgumentException("Invoke method [" + mn + "] argument number error."); 67 | } 68 | throw new NoSuchMethodException("Method [" + mn + "] not found."); 69 | } 70 | }; 71 | 72 | /** 73 | * get wrapper. 74 | * 75 | * @param c Class instance. 76 | * @return Wrapper instance(not null). 77 | */ 78 | public static Wrapper getWrapper(Class c) 79 | { 80 | while( ClassGenerator.isDynamicClass(c) ) // can not wrapper on dynamic class. 81 | c = c.getSuperclass(); 82 | 83 | if( c == Object.class ) 84 | return OBJECT_WRAPPER; 85 | 86 | Wrapper ret = WRAPPER_MAP.get(c); 87 | if( ret == null ) 88 | { 89 | ret = makeWrapper(c); 90 | WRAPPER_MAP.put(c,ret); 91 | } 92 | return ret; 93 | } 94 | /** 95 | * get property name array. 96 | * 97 | * @return property name array. 98 | */ 99 | abstract public String[] getPropertyNames(); 100 | 101 | /** 102 | * get property type. 103 | * 104 | * @param pn property name. 105 | * @return Property type or nul. 106 | */ 107 | abstract public Class getPropertyType(String pn); 108 | 109 | /** 110 | * has property. 111 | * 112 | * @param name property name. 113 | * @return has or has not. 114 | */ 115 | abstract public boolean hasProperty(String name); 116 | 117 | /** 118 | * get property value. 119 | * 120 | * @param instance instance. 121 | * @param pn property name. 122 | * @return value. 123 | */ 124 | abstract public Object getPropertyValue(Object instance, String pn) throws NoSuchPropertyException, IllegalArgumentException; 125 | 126 | /** 127 | * set property value. 128 | * 129 | * @param instance instance. 130 | * @param pn property name. 131 | * @param pv property value. 132 | */ 133 | abstract public void setPropertyValue(Object instance, String pn, Object pv) throws NoSuchPropertyException, IllegalArgumentException; 134 | 135 | /** 136 | * get property value. 137 | * 138 | * @param instance instance. 139 | * @param pns property name array. 140 | * @return value array. 141 | */ 142 | public Object[] getPropertyValues(Object instance, String[] pns) throws NoSuchPropertyException, IllegalArgumentException 143 | { 144 | Object[] ret = new Object[pns.length]; 145 | for(int i=0;i[] types, Object[] args) throws NoSuchMethodException, InvocationTargetException; 203 | 204 | private static Wrapper makeWrapper(Class c) 205 | { 206 | if( c.isPrimitive() ) 207 | throw new IllegalArgumentException("Can not create wrapper for primitive type: " + c); 208 | 209 | String name = c.getName(); 210 | ClassLoader cl = ClassHelper.getClassLoader(c); 211 | 212 | StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ "); 213 | StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ "); 214 | StringBuilder c3 = new StringBuilder("public Object invokeMethod(Object o, String n, Class[] p, Object[] v) throws " + InvocationTargetException.class.getName() + "{ "); 215 | 216 | c1.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); 217 | c2.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); 218 | c3.append(name).append(" w; try{ w = ((").append(name).append(")$1); }catch(Throwable e){ throw new IllegalArgumentException(e); }"); 219 | 220 | Map> pts = new HashMap>(); // 221 | Map ms = new LinkedHashMap(); // 222 | List mns = new ArrayList(); // method names. 223 | List dmns = new ArrayList(); // declaring method names. 224 | 225 | // get all public field. 226 | for( Field f : c.getFields() ) 227 | { 228 | String fn = f.getName(); 229 | Class ft = f.getType(); 230 | if( Modifier.isStatic(f.getModifiers()) || Modifier.isTransient(f.getModifiers()) ) 231 | continue; 232 | 233 | c1.append(" if( $2.equals(\"").append(fn).append("\") ){ w.").append(fn).append("=").append(arg(ft, "$3")).append("; return; }"); 234 | c2.append(" if( $2.equals(\"").append(fn).append("\") ){ return ($w)w.").append(fn).append("; }"); 235 | pts.put(fn, ft); 236 | } 237 | 238 | Method[] methods = c.getMethods(); 239 | // get all public method. 240 | boolean hasMethod = hasMethods(methods); 241 | if( hasMethod ){ 242 | c3.append(" try{"); 243 | } 244 | for( Method m : methods ) 245 | { 246 | if( m.getDeclaringClass() == Object.class ) //ignore Object's method. 247 | continue; 248 | 249 | String mn = m.getName(); 250 | c3.append(" if( \"").append(mn).append("\".equals( $2 ) "); 251 | int len = m.getParameterTypes().length; 252 | c3.append(" && ").append(" $3.length == ").append(len); 253 | 254 | boolean override = false; 255 | for( Method m2 : methods ) { 256 | if (m != m2 && m.getName().equals(m2.getName())) { 257 | override = true; 258 | break; 259 | } 260 | } 261 | if (override) { 262 | if (len > 0) { 263 | for (int l = 0; l < len; l ++) { 264 | c3.append(" && ").append(" $3[").append(l).append("].getName().equals(\"") 265 | .append(m.getParameterTypes()[l].getName()).append("\")"); 266 | } 267 | } 268 | } 269 | 270 | c3.append(" ) { "); 271 | 272 | if( m.getReturnType() == Void.TYPE ) 273 | c3.append(" w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");").append(" return null;"); 274 | else 275 | c3.append(" return ($w)w.").append(mn).append('(').append(args(m.getParameterTypes(), "$4")).append(");"); 276 | 277 | c3.append(" }"); 278 | 279 | mns.add(mn); 280 | if( m.getDeclaringClass() == c ) 281 | dmns.add(mn); 282 | ms.put(ReflectUtils.getDesc(m), m); 283 | } 284 | if( hasMethod ){ 285 | c3.append(" } catch(Throwable e) { " ); 286 | c3.append(" throw new java.lang.reflect.InvocationTargetException(e); " ); 287 | c3.append(" }"); 288 | } 289 | 290 | c3.append(" throw new " + NoSuchMethodException.class.getName() + "(\"Not found method \\\"\"+$2+\"\\\" in class " + c.getName() + ".\"); }"); 291 | 292 | // deal with get/set method. 293 | Matcher matcher; 294 | for( Map.Entry entry : ms.entrySet() ) 295 | { 296 | String md = entry.getKey(); 297 | Method method = (Method)entry.getValue(); 298 | if( ( matcher = ReflectUtils.GETTER_METHOD_DESC_PATTERN.matcher(md) ).matches() ) 299 | { 300 | String pn = propertyName(matcher.group(1)); 301 | c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }"); 302 | pts.put(pn, method.getReturnType()); 303 | } 304 | else if( ( matcher = ReflectUtils.IS_HAS_CAN_METHOD_DESC_PATTERN.matcher(md) ).matches() ) 305 | { 306 | String pn = propertyName(matcher.group(1)); 307 | c2.append(" if( $2.equals(\"").append(pn).append("\") ){ return ($w)w.").append(method.getName()).append("(); }"); 308 | pts.put(pn, method.getReturnType()); 309 | } 310 | else if( ( matcher = ReflectUtils.SETTER_METHOD_DESC_PATTERN.matcher(md) ).matches() ) 311 | { 312 | Class pt = method.getParameterTypes()[0]; 313 | String pn = propertyName(matcher.group(1)); 314 | c1.append(" if( $2.equals(\"").append(pn).append("\") ){ w.").append(method.getName()).append("(").append(arg(pt,"$3")).append("); return; }"); 315 | pts.put(pn, pt); 316 | } 317 | } 318 | c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }"); 319 | c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" filed or setter method in class " + c.getName() + ".\"); }"); 320 | 321 | // make class 322 | long id = WRAPPER_CLASS_COUNTER.getAndIncrement(); 323 | ClassGenerator cc = ClassGenerator.newInstance(cl); 324 | cc.setClassName( ( Modifier.isPublic(c.getModifiers()) ? Wrapper.class.getName() : c.getName() + "$sw" ) + id ); 325 | cc.setSuperClass(Wrapper.class); 326 | 327 | cc.addDefaultConstructor(); 328 | cc.addField("public static String[] pns;"); // property name array. 329 | cc.addField("public static " + Map.class.getName() + " pts;"); // property type map. 330 | cc.addField("public static String[] mns;"); // all method name array. 331 | cc.addField("public static String[] dmns;"); // declared method name array. 332 | for(int i=0,len=ms.size();i wc = cc.toClass(); 347 | // setup static field. 348 | wc.getField("pts").set(null, pts); 349 | wc.getField("pns").set(null, pts.keySet().toArray(new String[0])); 350 | wc.getField("mns").set(null, mns.toArray(new String[0])); 351 | wc.getField("dmns").set(null, dmns.toArray(new String[0])); 352 | int ix = 0; 353 | for( Method m : ms.values() ) 354 | wc.getField("mts" + ix++).set(null, m.getParameterTypes()); 355 | return (Wrapper)wc.newInstance(); 356 | } 357 | catch(RuntimeException e) 358 | { 359 | throw e; 360 | } 361 | catch(Throwable e) 362 | { 363 | throw new RuntimeException(e.getMessage(), e); 364 | } 365 | finally 366 | { 367 | cc.release(); 368 | ms.clear(); 369 | mns.clear(); 370 | dmns.clear(); 371 | } 372 | } 373 | 374 | private static String arg(Class cl, String name) 375 | { 376 | if( cl.isPrimitive() ) 377 | { 378 | if( cl == Boolean.TYPE ) 379 | return "((Boolean)" + name + ").booleanValue()"; 380 | if( cl == Byte.TYPE ) 381 | return "((Byte)" + name + ").byteValue()"; 382 | if( cl == Character.TYPE ) 383 | return "((Character)" + name + ").charValue()"; 384 | if( cl == Double.TYPE ) 385 | return "((Number)" + name + ").doubleValue()"; 386 | if( cl == Float.TYPE ) 387 | return "((Number)" + name + ").floatValue()"; 388 | if( cl == Integer.TYPE ) 389 | return "((Number)" + name + ").intValue()"; 390 | if( cl == Long.TYPE ) 391 | return "((Number)" + name + ").longValue()"; 392 | if( cl == Short.TYPE ) 393 | return "((Number)" + name + ").shortValue()"; 394 | throw new RuntimeException("Unknown primitive type: " + cl.getName()); 395 | } 396 | return "(" + ReflectUtils.getName(cl) + ")" + name; 397 | } 398 | 399 | private static String args(Class[] cs,String name) 400 | { 401 | int len = cs.length; 402 | if( len == 0 ) return ""; 403 | StringBuilder sb = new StringBuilder(); 404 | for(int i=0;i 0 ) 407 | sb.append(','); 408 | sb.append(arg(cs[i],name+"["+i+"]")); 409 | } 410 | return sb.toString(); 411 | } 412 | 413 | private static String propertyName(String pn) 414 | { 415 | return pn.length() == 1 || Character.isLowerCase(pn.charAt(1)) ? Character.toLowerCase(pn.charAt(0)) + pn.substring(1) : pn; 416 | } 417 | 418 | private static boolean hasMethods(Method[] methods){ 419 | if(methods == null || methods.length == 0){ 420 | return false; 421 | } 422 | for(Method m : methods){ 423 | if(m.getDeclaringClass() != Object.class){ 424 | return true; 425 | } 426 | } 427 | return false; 428 | } 429 | } -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/client/DefaultThrfitClientFactory.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.client; 2 | 3 | import java.io.Closeable; 4 | import java.io.IOException; 5 | import java.lang.reflect.Constructor; 6 | import java.net.InetSocketAddress; 7 | import java.util.concurrent.ConcurrentMap; 8 | 9 | import org.apache.thrift.TException; 10 | import org.apache.thrift.protocol.TCompactProtocol; 11 | import org.apache.thrift.protocol.TMultiplexedProtocol; 12 | import org.apache.thrift.protocol.TProtocol; 13 | import org.apache.thrift.transport.TFramedTransport; 14 | import org.apache.thrift.transport.TSocket; 15 | import org.apache.thrift.transport.TTransportException; 16 | import org.slf4j.Logger; 17 | import org.slf4j.LoggerFactory; 18 | 19 | import com.google.common.collect.Maps; 20 | import com.justdebugit.thrift.utils.ReflectUtils; 21 | 22 | public class DefaultThrfitClientFactory implements ThriftClientFactory{ 23 | private static final Logger LOGGER = LoggerFactory.getLogger(DefaultThrfitClientFactory.class); 24 | 25 | private ConcurrentMap clientMap = Maps.newConcurrentMap(); 26 | 27 | @SuppressWarnings("unchecked") 28 | @Override 29 | public T createClient(String serviceName,Class clazz, InetSocketAddress address) { 30 | Constructor constructor =null; 31 | try { 32 | constructor = ReflectUtils.findConstructor(clazz, TProtocol.class); 33 | } catch (NoSuchMethodException e) { 34 | LOGGER.error(e.getMessage(),e); 35 | throw new IllegalStateException("There is proper constructor "+e); 36 | } 37 | TFramedTransport transport = new TFramedTransport(new TSocket(address.getHostName(), 38 | address.getPort())); 39 | try { 40 | transport.open(); 41 | } catch (TTransportException e) { 42 | LOGGER.error(e.getMessage(),e); 43 | transport.close(); 44 | throw new IllegalStateException("Can not connect to remote host "+e); 45 | } 46 | T client = null; 47 | try { 48 | client = (T)constructor.newInstance(new TMultiplexedProtocol(new TCompactProtocol(transport), serviceName)); 49 | clientMap.putIfAbsent(client, transport); 50 | } catch (Exception e) { 51 | transport.close(); 52 | throw new IllegalStateException("Can not create instance clazz "+e); 53 | } 54 | return client; 55 | 56 | } 57 | 58 | 59 | 60 | @Override 61 | public void destroyClient(T client) throws TException { 62 | Closeable transport = clientMap.get(client); 63 | try { 64 | transport.close(); 65 | } catch (IOException e) { 66 | throw new TException(e.getMessage(),e); 67 | } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/client/ThriftClientFactory.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.client; 2 | 3 | import java.net.InetSocketAddress; 4 | 5 | import org.apache.thrift.TException; 6 | 7 | public interface ThriftClientFactory { 8 | 9 | T createClient(String serviceName,Class type,InetSocketAddress address); 10 | 11 | void destroyClient(T client) throws TException; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/client/ThriftStatefulPoolFactory.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.client; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.util.List; 5 | 6 | import org.apache.commons.lang3.StringUtils; 7 | 8 | import com.google.common.base.Preconditions; 9 | import com.google.common.base.Splitter; 10 | import com.google.common.collect.Lists; 11 | import com.justdebugit.fastpool.ObjectFactory; 12 | import com.justdebugit.fastpool.Pool; 13 | import com.justdebugit.fastpool.ScalableFastPool; 14 | import com.justdebugit.thrift.common.ServiceConfig; 15 | import com.justdebugit.thrift.pool.DelegatableStatefulPool; 16 | import com.justdebugit.thrift.pool.State; 17 | import com.justdebugit.thrift.pool.StatefulPool; 18 | import com.justdebugit.thrift.pool.StatefulPoolFactory; 19 | 20 | public class ThriftStatefulPoolFactory implements StatefulPoolFactory { 21 | private Class type; 22 | private ThriftClientFactory thriftFactory; 23 | private ServiceConfig rpcService; 24 | private String serviceName; 25 | 26 | 27 | public ThriftStatefulPoolFactory() {} 28 | 29 | @SuppressWarnings("unchecked") 30 | public ThriftStatefulPoolFactory(ServiceConfig rpcService) { 31 | Preconditions.checkNotNull(rpcService.getServiceName()); 32 | this.rpcService = rpcService; 33 | this.serviceName = rpcService.getServiceName(); 34 | this.type = (Class)rpcService.getClientClass(); 35 | this.thriftFactory = rpcService.getClientFactory(); 36 | } 37 | 38 | public ThriftStatefulPoolFactory(Class type,ThriftClientFactory thriftFactory) { 39 | this.type = type; 40 | this.thriftFactory = thriftFactory; 41 | } 42 | 43 | @Override 44 | public StatefulPool getPool(String host_port) { 45 | Preconditions.checkNotNull(type); 46 | Iterable iterable = Splitter.on(":").split(host_port); 47 | List list = Lists.newArrayList(iterable); 48 | final String host = StringUtils.substringAfterLast(list.get(0), "/"); 49 | final int port = Integer.valueOf(list.get(1)); 50 | 51 | final InetSocketAddress remoteAddress = new InetSocketAddress(host, port); 52 | ObjectFactory objectFactory = new ObjectFactory() { 53 | 54 | @Override 55 | public T makeObject() { 56 | return thriftFactory.createClient(serviceName,type, remoteAddress); 57 | } 58 | 59 | @Override 60 | public void destroyObject(T client) throws Exception { 61 | thriftFactory.destroyClient(client); 62 | } 63 | }; 64 | Pool scalableFastPool = null; 65 | if (rpcService!=null && rpcService.getMaxPoolSize()>0 && rpcService.getMinPoolSize() >0) { 66 | scalableFastPool = new ScalableFastPool(rpcService.getMinPoolSize(),rpcService.getMaxPoolSize(),objectFactory); 67 | }else { 68 | scalableFastPool = new ScalableFastPool(objectFactory); 69 | } 70 | StatefulPool statefulPool = new DelegatableStatefulPool(scalableFastPool); 71 | statefulPool.state().set(State.INITIALIZED); 72 | statefulPool.getRefCnt().set(0); 73 | return statefulPool; 74 | } 75 | 76 | 77 | 78 | @Override 79 | public Class getType() { 80 | return type; 81 | } 82 | 83 | 84 | @Override 85 | public void setType(Class type) { 86 | this.type = type; 87 | 88 | } 89 | 90 | 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/common/AbstractLifeCycle.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.common; 2 | 3 | import java.util.concurrent.atomic.AtomicBoolean; 4 | 5 | public abstract class AbstractLifeCycle implements LifeCycle{ 6 | protected AtomicBoolean state = new AtomicBoolean(false); 7 | 8 | public boolean isStarted(){ 9 | return state.get(); 10 | }; 11 | 12 | public void start(){ 13 | if (state.compareAndSet(false, true)) { 14 | doStart(); 15 | } 16 | } 17 | 18 | public void stop(){ 19 | if (state.compareAndSet(true, false)) { 20 | doStop(); 21 | } 22 | } 23 | 24 | protected abstract void doStart(); 25 | 26 | protected abstract void doStop(); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/common/LifeCycle.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.common; 2 | 3 | public interface LifeCycle { 4 | void start(); 5 | void stop(); 6 | boolean isStarted(); 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/common/ServiceConfig.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.common; 2 | 3 | import com.justdebugit.thrift.client.ThriftClientFactory; 4 | 5 | public class ServiceConfig { 6 | 7 | private Class serviceClass; 8 | 9 | private Class interfaceClass; 10 | 11 | private Class clientClass; 12 | 13 | private int minPoolSize; 14 | 15 | private int maxPoolSize; 16 | 17 | private ThriftClientFactory clientFactory; 18 | 19 | private String serviceName; 20 | 21 | // private ThriftStatefulPoolFactory thriftStatefulPoolFactory; 22 | 23 | 24 | 25 | 26 | public Class getInterfaceClass() { 27 | return interfaceClass; 28 | } 29 | 30 | public ServiceConfig setInterfaceClass(Class interfaceClass) { 31 | this.interfaceClass = interfaceClass; 32 | return this; 33 | } 34 | 35 | public ThriftClientFactory getClientFactory() { 36 | return clientFactory; 37 | } 38 | 39 | public ServiceConfig setClientFactory(ThriftClientFactory clientFactory) { 40 | this.clientFactory = clientFactory; 41 | return this; 42 | } 43 | 44 | public int getMinPoolSize() { 45 | return minPoolSize; 46 | } 47 | 48 | public ServiceConfig setMinPoolSize(int minPoolSize) { 49 | this.minPoolSize = minPoolSize; 50 | return this; 51 | } 52 | 53 | public int getMaxPoolSize() { 54 | return maxPoolSize; 55 | } 56 | 57 | public ServiceConfig setMaxPoolSize(int maxPoolSize) { 58 | this.maxPoolSize = maxPoolSize; 59 | return this; 60 | } 61 | 62 | public Class getClientClass() { 63 | return clientClass; 64 | } 65 | 66 | public ServiceConfig setClientClass(Class clientClass) { 67 | this.clientClass = clientClass; 68 | return this; 69 | } 70 | 71 | public String getServiceName() { 72 | return serviceName; 73 | } 74 | 75 | public ServiceConfig setServiceName(String serviceName) { 76 | this.serviceName = serviceName; 77 | return this; 78 | } 79 | 80 | public Class getServiceClass() { 81 | return serviceClass; 82 | } 83 | 84 | public ServiceConfig setServiceClass(Class serviceClass) { 85 | this.serviceClass = serviceClass; 86 | if (interfaceClass==null) { 87 | try { 88 | Class clazz = Class.forName(serviceClass.getName()+"$Iface"); 89 | interfaceClass = clazz; 90 | Class clientClazz = Class.forName(serviceClass.getName()+"$Client"); 91 | clientClass = clientClazz; 92 | } catch (ClassNotFoundException e) { 93 | throw new ThriftInitException(" can not find class of "+serviceClass+"$Iface.class or "+serviceClass+ "$Client; " +e.getMessage(), e); 94 | } 95 | } 96 | return this; 97 | } 98 | 99 | @Override 100 | public String toString() { 101 | return "ServiceConfig [interfaceClass=" 102 | + interfaceClass + ", minPoolSize=" + minPoolSize 103 | + ", maxPoolSize=" + maxPoolSize + ", clientFactory=" 104 | + clientFactory + "]"; 105 | } 106 | 107 | 108 | 109 | 110 | 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/common/ThriftInitException.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.common; 2 | 3 | public class ThriftInitException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 4603401356618901407L; 6 | 7 | public ThriftInitException(String message, Throwable cause) { 8 | super(message, cause); 9 | } 10 | 11 | public ThriftInitException(String message) { 12 | super(message); 13 | } 14 | 15 | public ThriftInitException(Throwable cause) { 16 | super(cause); 17 | } 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/common/ThriftRpcException.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.common; 2 | 3 | public class ThriftRpcException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 4603401356618901407L; 6 | 7 | public ThriftRpcException(String message, Throwable cause) { 8 | super(message, cause); 9 | } 10 | 11 | public ThriftRpcException(String message) { 12 | super(message); 13 | } 14 | 15 | public ThriftRpcException(Throwable cause) { 16 | super(cause); 17 | } 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/constants/Constants.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.constants; 2 | 3 | import java.util.regex.Pattern; 4 | 5 | public class Constants { 6 | 7 | public static final Pattern COMMA_SPLIT_PATTERN = Pattern 8 | .compile("\\s*[,]+\\s*"); 9 | 10 | public static final Integer DEFAULT_CONNECT_TIMEOUT = 6000; 11 | public static final Integer DEFAULT_SESSION_TIMEOUT = 12000; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/consumer/RpcConsumer.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.consumer; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.concurrent.ConcurrentMap; 6 | 7 | import com.google.common.base.Preconditions; 8 | import com.google.common.collect.Maps; 9 | import com.justdebugit.thrift.client.ThriftClientFactory; 10 | import com.justdebugit.thrift.client.ThriftStatefulPoolFactory; 11 | import com.justdebugit.thrift.common.AbstractLifeCycle; 12 | import com.justdebugit.thrift.common.ServiceConfig; 13 | import com.justdebugit.thrift.consumer.RpcConsumerFactory.Builder; 14 | import com.justdebugit.thrift.pool.MultiPool; 15 | import com.justdebugit.thrift.pool.StatefulPoolFactory; 16 | import com.justdebugit.thrift.pool.StatefulPoolMapManager; 17 | import com.justdebugit.thrift.proxy.PooledProxyFactory; 18 | import com.justdebugit.thrift.registry.CuratorFactory; 19 | import com.justdebugit.thrift.registry.DefaultCuratorFactory; 20 | import com.justdebugit.thrift.registry.Registry; 21 | import com.justdebugit.thrift.registry.ZkCuratorRegistry; 22 | 23 | public class RpcConsumer extends AbstractLifeCycle{ 24 | 25 | private List services; 26 | 27 | private String connectStringForZk; 28 | 29 | private int sessionTimeOutForZk; 30 | 31 | private int connectTimeOutForZk; 32 | 33 | private final ConcurrentMap proxyMap = Maps.newConcurrentMap(); 34 | private final Map> poolMap = Maps.newHashMap(); 35 | 36 | 37 | private final Registry registry; 38 | private final ThriftClientFactory thriftClientFactory; 39 | 40 | public RpcConsumer(Builder builder) { 41 | connectStringForZk = builder.getConnectString(); 42 | sessionTimeOutForZk = builder.getSessionTimeout(); 43 | connectTimeOutForZk = builder.getConnectTimeout(); 44 | CuratorFactory curatorFactory = new DefaultCuratorFactory(connectStringForZk,connectTimeOutForZk,sessionTimeOutForZk); 45 | this.registry = new ZkCuratorRegistry(curatorFactory); 46 | this.thriftClientFactory = builder.getDefaultThriftClientFactory(); 47 | services = builder.getRpcServices(); 48 | for (ServiceConfig rpcService : services) { 49 | Preconditions.checkNotNull(rpcService.getInterfaceClass()); 50 | if (rpcService.getClientFactory()==null) { 51 | rpcService.setClientFactory(thriftClientFactory); 52 | } 53 | String serviceName = rpcService.getServiceName()==null?rpcService.getInterfaceClass().getName():rpcService.getServiceName(); 54 | Preconditions.checkNotNull(serviceName, "Servicename must not be null"); 55 | rpcService.setServiceName(serviceName); 56 | proxyMap.put(serviceName, buildServiceProxy(rpcService)); 57 | } 58 | } 59 | 60 | 61 | public void addService(ServiceConfig rpcService){ 62 | Preconditions.checkNotNull(rpcService.getInterfaceClass()); 63 | if (rpcService.getClientFactory()==null) { 64 | rpcService.setClientFactory(thriftClientFactory); 65 | } 66 | proxyMap.put(rpcService.getServiceName(), buildServiceProxy(rpcService)); 67 | 68 | } 69 | 70 | 71 | @SuppressWarnings("unchecked") 72 | private T buildServiceProxy(ServiceConfig rpcService){ 73 | MultiPool pool = buildMultiPool(rpcService); 74 | poolMap.put(rpcService, pool); 75 | return PooledProxyFactory.getProxy((Class)rpcService.getInterfaceClass(),(Class)rpcService.getClientClass(),pool); 76 | 77 | } 78 | 79 | private MultiPool buildMultiPool(ServiceConfig rpcService) { 80 | StatefulPoolFactory statefulPoolFactory = new ThriftStatefulPoolFactory(rpcService); 81 | StatefulPoolMapManager statefulPoolMapManager = new StatefulPoolMapManager(rpcService.getServiceName(), registry, statefulPoolFactory); 82 | MultiPool pool = new MultiPool(statefulPoolMapManager); 83 | return pool; 84 | } 85 | 86 | 87 | 88 | public List getServices() { 89 | return services; 90 | } 91 | 92 | public void setServices(List services) { 93 | this.services = services; 94 | } 95 | 96 | public String getConnectStringForZk() { 97 | return connectStringForZk; 98 | } 99 | 100 | public void setConnectStringForZk(String connectStringForZk) { 101 | this.connectStringForZk = connectStringForZk; 102 | } 103 | 104 | public int getSessionTimeOutForZk() { 105 | return sessionTimeOutForZk; 106 | } 107 | 108 | public void setSessionTimeOutForZk(int sessionTimeOutForZk) { 109 | this.sessionTimeOutForZk = sessionTimeOutForZk; 110 | } 111 | 112 | public int getConnectTimeOutForZk() { 113 | return connectTimeOutForZk; 114 | } 115 | 116 | public void setConnectTimeOutForZk(int connectTimeOutForZk) { 117 | this.connectTimeOutForZk = connectTimeOutForZk; 118 | } 119 | 120 | 121 | @SuppressWarnings("unchecked") 122 | public T getService(String serviceName){ 123 | return (T)proxyMap.get(serviceName); 124 | } 125 | 126 | 127 | @Override 128 | protected void doStart() { 129 | for (Map.Entry> entry : poolMap.entrySet()) { 130 | MultiPool multiPool = entry.getValue(); 131 | multiPool.start(); 132 | } 133 | 134 | } 135 | 136 | 137 | @Override 138 | protected void doStop() { 139 | for (Map.Entry> entry : poolMap.entrySet()) { 140 | MultiPool multiPool = entry.getValue(); 141 | multiPool.stop(); 142 | } 143 | 144 | } 145 | 146 | 147 | 148 | } 149 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/consumer/RpcConsumerFactory.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.consumer; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | 6 | import com.google.common.collect.Lists; 7 | import com.justdebugit.thrift.client.DefaultThrfitClientFactory; 8 | import com.justdebugit.thrift.client.ThriftClientFactory; 9 | import com.justdebugit.thrift.common.ServiceConfig; 10 | import com.justdebugit.thrift.constants.Constants; 11 | 12 | 13 | 14 | public class RpcConsumerFactory { 15 | 16 | public static Builder builder(){ 17 | return new Builder() { 18 | }; 19 | } 20 | 21 | public static RpcConsumer newRpcConsumer(String zkConnectString,List list) { 22 | return builder().connectStringForZk(zkConnectString).addAllRpcServices(list) 23 | .connectTimeoutForZk(6000) 24 | .sessionTimeoutForZk(2000).build(); 25 | } 26 | 27 | public static RpcConsumer newRpcConsumer(String connectString, int sessionTimeout, 28 | int connectTimeout,List list) { 29 | return builder().connectStringForZk(connectString).addAllRpcServices(list) 30 | .sessionTimeoutForZk(sessionTimeout).connectTimeoutForZk(connectTimeout) 31 | .build(); 32 | } 33 | 34 | public static class Builder{ 35 | private String connectString; 36 | private int sessionTimeout = Constants.DEFAULT_SESSION_TIMEOUT; 37 | private int connectTimeout = Constants.DEFAULT_CONNECT_TIMEOUT; 38 | private ThriftClientFactory defaultThriftClientFactory = new DefaultThrfitClientFactory(); 39 | private List list = Lists.newArrayList(); 40 | 41 | 42 | 43 | 44 | public static Builder builder(){ 45 | return new Builder(); 46 | } 47 | 48 | public RpcConsumer build(){ 49 | return new RpcConsumer(this); 50 | } 51 | 52 | public Builder addAllRpcServices(Collection rpcServices){ 53 | list.addAll(rpcServices); 54 | return this; 55 | } 56 | 57 | public Builder addRpcService(ServiceConfig rpcService){ 58 | list.add(rpcService); 59 | return this; 60 | } 61 | 62 | public Builder connectStringForZk(String connectString){ 63 | this.connectString = connectString; 64 | return this; 65 | } 66 | 67 | public Builder sessionTimeoutForZk(int sessionTimeout){ 68 | this.sessionTimeout = sessionTimeout; 69 | return this; 70 | } 71 | 72 | public Builder connectTimeoutForZk(int connectTimeout){ 73 | this.connectTimeout = connectTimeout; 74 | return this; 75 | } 76 | 77 | public String getConnectString() { 78 | return connectString; 79 | } 80 | 81 | public int getSessionTimeout() { 82 | return sessionTimeout; 83 | } 84 | 85 | public int getConnectTimeout() { 86 | return connectTimeout; 87 | } 88 | 89 | public ThriftClientFactory getDefaultThriftClientFactory() { 90 | return defaultThriftClientFactory; 91 | } 92 | 93 | public List getRpcServices(){ 94 | return list; 95 | } 96 | 97 | public Builder defaultThriftClientFactory( 98 | ThriftClientFactory defaultThriftClientFactory) { 99 | this.defaultThriftClientFactory = defaultThriftClientFactory; 100 | return this; 101 | } 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/generated/Category.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.2) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | package com.justdebugit.thrift.generated; 8 | 9 | 10 | import java.util.Map; 11 | import java.util.HashMap; 12 | import org.apache.thrift.TEnum; 13 | 14 | public enum Category implements org.apache.thrift.TEnum { 15 | COLLEAGUE(1), 16 | CLASSMATE(2), 17 | FAMILY(3); 18 | 19 | private final int value; 20 | 21 | private Category(int value) { 22 | this.value = value; 23 | } 24 | 25 | /** 26 | * Get the integer value of this enum value, as defined in the Thrift IDL. 27 | */ 28 | public int getValue() { 29 | return value; 30 | } 31 | 32 | /** 33 | * Find a the enum type by its integer value, as defined in the Thrift IDL. 34 | * @return null if the value is not found. 35 | */ 36 | public static Category findByValue(int value) { 37 | switch (value) { 38 | case 1: 39 | return COLLEAGUE; 40 | case 2: 41 | return CLASSMATE; 42 | case 3: 43 | return FAMILY; 44 | default: 45 | return null; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/generated/DifferentSourceDetectedException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.2) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | package com.justdebugit.thrift.generated; 8 | 9 | import org.apache.thrift.scheme.IScheme; 10 | import org.apache.thrift.scheme.SchemeFactory; 11 | import org.apache.thrift.scheme.StandardScheme; 12 | 13 | import org.apache.thrift.scheme.TupleScheme; 14 | import org.apache.thrift.protocol.TTupleProtocol; 15 | import org.apache.thrift.protocol.TProtocolException; 16 | import org.apache.thrift.EncodingUtils; 17 | import org.apache.thrift.TException; 18 | import org.apache.thrift.async.AsyncMethodCallback; 19 | import org.apache.thrift.server.AbstractNonblockingServer.*; 20 | import java.util.List; 21 | import java.util.ArrayList; 22 | import java.util.Map; 23 | import java.util.HashMap; 24 | import java.util.EnumMap; 25 | import java.util.Set; 26 | import java.util.HashSet; 27 | import java.util.EnumSet; 28 | import java.util.Collections; 29 | import java.util.BitSet; 30 | import java.nio.ByteBuffer; 31 | import java.util.Arrays; 32 | import javax.annotation.Generated; 33 | import org.slf4j.Logger; 34 | import org.slf4j.LoggerFactory; 35 | 36 | @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"}) 37 | @Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2015-7-12") 38 | public class DifferentSourceDetectedException extends TException implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable { 39 | private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("DifferentSourceDetectedException"); 40 | 41 | private static final org.apache.thrift.protocol.TField UID1_FIELD_DESC = new org.apache.thrift.protocol.TField("uid1", org.apache.thrift.protocol.TType.I32, (short)1); 42 | private static final org.apache.thrift.protocol.TField UID2_FIELD_DESC = new org.apache.thrift.protocol.TField("uid2", org.apache.thrift.protocol.TType.I32, (short)2); 43 | private static final org.apache.thrift.protocol.TField MSG_FIELD_DESC = new org.apache.thrift.protocol.TField("msg", org.apache.thrift.protocol.TType.STRING, (short)3); 44 | 45 | private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); 46 | static { 47 | schemes.put(StandardScheme.class, new DifferentSourceDetectedExceptionStandardSchemeFactory()); 48 | schemes.put(TupleScheme.class, new DifferentSourceDetectedExceptionTupleSchemeFactory()); 49 | } 50 | 51 | public int uid1; // required 52 | public int uid2; // required 53 | public String msg; // required 54 | 55 | /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ 56 | public enum _Fields implements org.apache.thrift.TFieldIdEnum { 57 | UID1((short)1, "uid1"), 58 | UID2((short)2, "uid2"), 59 | MSG((short)3, "msg"); 60 | 61 | private static final Map byName = new HashMap(); 62 | 63 | static { 64 | for (_Fields field : EnumSet.allOf(_Fields.class)) { 65 | byName.put(field.getFieldName(), field); 66 | } 67 | } 68 | 69 | /** 70 | * Find the _Fields constant that matches fieldId, or null if its not found. 71 | */ 72 | public static _Fields findByThriftId(int fieldId) { 73 | switch(fieldId) { 74 | case 1: // UID1 75 | return UID1; 76 | case 2: // UID2 77 | return UID2; 78 | case 3: // MSG 79 | return MSG; 80 | default: 81 | return null; 82 | } 83 | } 84 | 85 | /** 86 | * Find the _Fields constant that matches fieldId, throwing an exception 87 | * if it is not found. 88 | */ 89 | public static _Fields findByThriftIdOrThrow(int fieldId) { 90 | _Fields fields = findByThriftId(fieldId); 91 | if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); 92 | return fields; 93 | } 94 | 95 | /** 96 | * Find the _Fields constant that matches name, or null if its not found. 97 | */ 98 | public static _Fields findByName(String name) { 99 | return byName.get(name); 100 | } 101 | 102 | private final short _thriftId; 103 | private final String _fieldName; 104 | 105 | _Fields(short thriftId, String fieldName) { 106 | _thriftId = thriftId; 107 | _fieldName = fieldName; 108 | } 109 | 110 | public short getThriftFieldId() { 111 | return _thriftId; 112 | } 113 | 114 | public String getFieldName() { 115 | return _fieldName; 116 | } 117 | } 118 | 119 | // isset id assignments 120 | private static final int __UID1_ISSET_ID = 0; 121 | private static final int __UID2_ISSET_ID = 1; 122 | private byte __isset_bitfield = 0; 123 | public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; 124 | static { 125 | Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); 126 | tmpMap.put(_Fields.UID1, new org.apache.thrift.meta_data.FieldMetaData("uid1", org.apache.thrift.TFieldRequirementType.DEFAULT, 127 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32))); 128 | tmpMap.put(_Fields.UID2, new org.apache.thrift.meta_data.FieldMetaData("uid2", org.apache.thrift.TFieldRequirementType.DEFAULT, 129 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32))); 130 | tmpMap.put(_Fields.MSG, new org.apache.thrift.meta_data.FieldMetaData("msg", org.apache.thrift.TFieldRequirementType.DEFAULT, 131 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); 132 | metaDataMap = Collections.unmodifiableMap(tmpMap); 133 | org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(DifferentSourceDetectedException.class, metaDataMap); 134 | } 135 | 136 | public DifferentSourceDetectedException() { 137 | } 138 | 139 | public DifferentSourceDetectedException( 140 | int uid1, 141 | int uid2, 142 | String msg) 143 | { 144 | this(); 145 | this.uid1 = uid1; 146 | setUid1IsSet(true); 147 | this.uid2 = uid2; 148 | setUid2IsSet(true); 149 | this.msg = msg; 150 | } 151 | 152 | /** 153 | * Performs a deep copy on other. 154 | */ 155 | public DifferentSourceDetectedException(DifferentSourceDetectedException other) { 156 | __isset_bitfield = other.__isset_bitfield; 157 | this.uid1 = other.uid1; 158 | this.uid2 = other.uid2; 159 | if (other.isSetMsg()) { 160 | this.msg = other.msg; 161 | } 162 | } 163 | 164 | public DifferentSourceDetectedException deepCopy() { 165 | return new DifferentSourceDetectedException(this); 166 | } 167 | 168 | @Override 169 | public void clear() { 170 | setUid1IsSet(false); 171 | this.uid1 = 0; 172 | setUid2IsSet(false); 173 | this.uid2 = 0; 174 | this.msg = null; 175 | } 176 | 177 | public int getUid1() { 178 | return this.uid1; 179 | } 180 | 181 | public DifferentSourceDetectedException setUid1(int uid1) { 182 | this.uid1 = uid1; 183 | setUid1IsSet(true); 184 | return this; 185 | } 186 | 187 | public void unsetUid1() { 188 | __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __UID1_ISSET_ID); 189 | } 190 | 191 | /** Returns true if field uid1 is set (has been assigned a value) and false otherwise */ 192 | public boolean isSetUid1() { 193 | return EncodingUtils.testBit(__isset_bitfield, __UID1_ISSET_ID); 194 | } 195 | 196 | public void setUid1IsSet(boolean value) { 197 | __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __UID1_ISSET_ID, value); 198 | } 199 | 200 | public int getUid2() { 201 | return this.uid2; 202 | } 203 | 204 | public DifferentSourceDetectedException setUid2(int uid2) { 205 | this.uid2 = uid2; 206 | setUid2IsSet(true); 207 | return this; 208 | } 209 | 210 | public void unsetUid2() { 211 | __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __UID2_ISSET_ID); 212 | } 213 | 214 | /** Returns true if field uid2 is set (has been assigned a value) and false otherwise */ 215 | public boolean isSetUid2() { 216 | return EncodingUtils.testBit(__isset_bitfield, __UID2_ISSET_ID); 217 | } 218 | 219 | public void setUid2IsSet(boolean value) { 220 | __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __UID2_ISSET_ID, value); 221 | } 222 | 223 | public String getMsg() { 224 | return this.msg; 225 | } 226 | 227 | public DifferentSourceDetectedException setMsg(String msg) { 228 | this.msg = msg; 229 | return this; 230 | } 231 | 232 | public void unsetMsg() { 233 | this.msg = null; 234 | } 235 | 236 | /** Returns true if field msg is set (has been assigned a value) and false otherwise */ 237 | public boolean isSetMsg() { 238 | return this.msg != null; 239 | } 240 | 241 | public void setMsgIsSet(boolean value) { 242 | if (!value) { 243 | this.msg = null; 244 | } 245 | } 246 | 247 | public void setFieldValue(_Fields field, Object value) { 248 | switch (field) { 249 | case UID1: 250 | if (value == null) { 251 | unsetUid1(); 252 | } else { 253 | setUid1((Integer)value); 254 | } 255 | break; 256 | 257 | case UID2: 258 | if (value == null) { 259 | unsetUid2(); 260 | } else { 261 | setUid2((Integer)value); 262 | } 263 | break; 264 | 265 | case MSG: 266 | if (value == null) { 267 | unsetMsg(); 268 | } else { 269 | setMsg((String)value); 270 | } 271 | break; 272 | 273 | } 274 | } 275 | 276 | public Object getFieldValue(_Fields field) { 277 | switch (field) { 278 | case UID1: 279 | return Integer.valueOf(getUid1()); 280 | 281 | case UID2: 282 | return Integer.valueOf(getUid2()); 283 | 284 | case MSG: 285 | return getMsg(); 286 | 287 | } 288 | throw new IllegalStateException(); 289 | } 290 | 291 | /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ 292 | public boolean isSet(_Fields field) { 293 | if (field == null) { 294 | throw new IllegalArgumentException(); 295 | } 296 | 297 | switch (field) { 298 | case UID1: 299 | return isSetUid1(); 300 | case UID2: 301 | return isSetUid2(); 302 | case MSG: 303 | return isSetMsg(); 304 | } 305 | throw new IllegalStateException(); 306 | } 307 | 308 | @Override 309 | public boolean equals(Object that) { 310 | if (that == null) 311 | return false; 312 | if (that instanceof DifferentSourceDetectedException) 313 | return this.equals((DifferentSourceDetectedException)that); 314 | return false; 315 | } 316 | 317 | public boolean equals(DifferentSourceDetectedException that) { 318 | if (that == null) 319 | return false; 320 | 321 | boolean this_present_uid1 = true; 322 | boolean that_present_uid1 = true; 323 | if (this_present_uid1 || that_present_uid1) { 324 | if (!(this_present_uid1 && that_present_uid1)) 325 | return false; 326 | if (this.uid1 != that.uid1) 327 | return false; 328 | } 329 | 330 | boolean this_present_uid2 = true; 331 | boolean that_present_uid2 = true; 332 | if (this_present_uid2 || that_present_uid2) { 333 | if (!(this_present_uid2 && that_present_uid2)) 334 | return false; 335 | if (this.uid2 != that.uid2) 336 | return false; 337 | } 338 | 339 | boolean this_present_msg = true && this.isSetMsg(); 340 | boolean that_present_msg = true && that.isSetMsg(); 341 | if (this_present_msg || that_present_msg) { 342 | if (!(this_present_msg && that_present_msg)) 343 | return false; 344 | if (!this.msg.equals(that.msg)) 345 | return false; 346 | } 347 | 348 | return true; 349 | } 350 | 351 | @Override 352 | public int hashCode() { 353 | List list = new ArrayList(); 354 | 355 | boolean present_uid1 = true; 356 | list.add(present_uid1); 357 | if (present_uid1) 358 | list.add(uid1); 359 | 360 | boolean present_uid2 = true; 361 | list.add(present_uid2); 362 | if (present_uid2) 363 | list.add(uid2); 364 | 365 | boolean present_msg = true && (isSetMsg()); 366 | list.add(present_msg); 367 | if (present_msg) 368 | list.add(msg); 369 | 370 | return list.hashCode(); 371 | } 372 | 373 | @Override 374 | public int compareTo(DifferentSourceDetectedException other) { 375 | if (!getClass().equals(other.getClass())) { 376 | return getClass().getName().compareTo(other.getClass().getName()); 377 | } 378 | 379 | int lastComparison = 0; 380 | 381 | lastComparison = Boolean.valueOf(isSetUid1()).compareTo(other.isSetUid1()); 382 | if (lastComparison != 0) { 383 | return lastComparison; 384 | } 385 | if (isSetUid1()) { 386 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.uid1, other.uid1); 387 | if (lastComparison != 0) { 388 | return lastComparison; 389 | } 390 | } 391 | lastComparison = Boolean.valueOf(isSetUid2()).compareTo(other.isSetUid2()); 392 | if (lastComparison != 0) { 393 | return lastComparison; 394 | } 395 | if (isSetUid2()) { 396 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.uid2, other.uid2); 397 | if (lastComparison != 0) { 398 | return lastComparison; 399 | } 400 | } 401 | lastComparison = Boolean.valueOf(isSetMsg()).compareTo(other.isSetMsg()); 402 | if (lastComparison != 0) { 403 | return lastComparison; 404 | } 405 | if (isSetMsg()) { 406 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.msg, other.msg); 407 | if (lastComparison != 0) { 408 | return lastComparison; 409 | } 410 | } 411 | return 0; 412 | } 413 | 414 | public _Fields fieldForId(int fieldId) { 415 | return _Fields.findByThriftId(fieldId); 416 | } 417 | 418 | public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { 419 | schemes.get(iprot.getScheme()).getScheme().read(iprot, this); 420 | } 421 | 422 | public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { 423 | schemes.get(oprot.getScheme()).getScheme().write(oprot, this); 424 | } 425 | 426 | @Override 427 | public String toString() { 428 | StringBuilder sb = new StringBuilder("DifferentSourceDetectedException("); 429 | boolean first = true; 430 | 431 | sb.append("uid1:"); 432 | sb.append(this.uid1); 433 | first = false; 434 | if (!first) sb.append(", "); 435 | sb.append("uid2:"); 436 | sb.append(this.uid2); 437 | first = false; 438 | if (!first) sb.append(", "); 439 | sb.append("msg:"); 440 | if (this.msg == null) { 441 | sb.append("null"); 442 | } else { 443 | sb.append(this.msg); 444 | } 445 | first = false; 446 | sb.append(")"); 447 | return sb.toString(); 448 | } 449 | 450 | public void validate() throws org.apache.thrift.TException { 451 | // check for required fields 452 | // check for sub-struct validity 453 | } 454 | 455 | private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { 456 | try { 457 | write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out))); 458 | } catch (org.apache.thrift.TException te) { 459 | throw new java.io.IOException(te); 460 | } 461 | } 462 | 463 | private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { 464 | try { 465 | // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. 466 | __isset_bitfield = 0; 467 | read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in))); 468 | } catch (org.apache.thrift.TException te) { 469 | throw new java.io.IOException(te); 470 | } 471 | } 472 | 473 | private static class DifferentSourceDetectedExceptionStandardSchemeFactory implements SchemeFactory { 474 | public DifferentSourceDetectedExceptionStandardScheme getScheme() { 475 | return new DifferentSourceDetectedExceptionStandardScheme(); 476 | } 477 | } 478 | 479 | private static class DifferentSourceDetectedExceptionStandardScheme extends StandardScheme { 480 | 481 | public void read(org.apache.thrift.protocol.TProtocol iprot, DifferentSourceDetectedException struct) throws org.apache.thrift.TException { 482 | org.apache.thrift.protocol.TField schemeField; 483 | iprot.readStructBegin(); 484 | while (true) 485 | { 486 | schemeField = iprot.readFieldBegin(); 487 | if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 488 | break; 489 | } 490 | switch (schemeField.id) { 491 | case 1: // UID1 492 | if (schemeField.type == org.apache.thrift.protocol.TType.I32) { 493 | struct.uid1 = iprot.readI32(); 494 | struct.setUid1IsSet(true); 495 | } else { 496 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); 497 | } 498 | break; 499 | case 2: // UID2 500 | if (schemeField.type == org.apache.thrift.protocol.TType.I32) { 501 | struct.uid2 = iprot.readI32(); 502 | struct.setUid2IsSet(true); 503 | } else { 504 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); 505 | } 506 | break; 507 | case 3: // MSG 508 | if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { 509 | struct.msg = iprot.readString(); 510 | struct.setMsgIsSet(true); 511 | } else { 512 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); 513 | } 514 | break; 515 | default: 516 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); 517 | } 518 | iprot.readFieldEnd(); 519 | } 520 | iprot.readStructEnd(); 521 | 522 | // check for required fields of primitive type, which can't be checked in the validate method 523 | struct.validate(); 524 | } 525 | 526 | public void write(org.apache.thrift.protocol.TProtocol oprot, DifferentSourceDetectedException struct) throws org.apache.thrift.TException { 527 | struct.validate(); 528 | 529 | oprot.writeStructBegin(STRUCT_DESC); 530 | oprot.writeFieldBegin(UID1_FIELD_DESC); 531 | oprot.writeI32(struct.uid1); 532 | oprot.writeFieldEnd(); 533 | oprot.writeFieldBegin(UID2_FIELD_DESC); 534 | oprot.writeI32(struct.uid2); 535 | oprot.writeFieldEnd(); 536 | if (struct.msg != null) { 537 | oprot.writeFieldBegin(MSG_FIELD_DESC); 538 | oprot.writeString(struct.msg); 539 | oprot.writeFieldEnd(); 540 | } 541 | oprot.writeFieldStop(); 542 | oprot.writeStructEnd(); 543 | } 544 | 545 | } 546 | 547 | private static class DifferentSourceDetectedExceptionTupleSchemeFactory implements SchemeFactory { 548 | public DifferentSourceDetectedExceptionTupleScheme getScheme() { 549 | return new DifferentSourceDetectedExceptionTupleScheme(); 550 | } 551 | } 552 | 553 | private static class DifferentSourceDetectedExceptionTupleScheme extends TupleScheme { 554 | 555 | @Override 556 | public void write(org.apache.thrift.protocol.TProtocol prot, DifferentSourceDetectedException struct) throws org.apache.thrift.TException { 557 | TTupleProtocol oprot = (TTupleProtocol) prot; 558 | BitSet optionals = new BitSet(); 559 | if (struct.isSetUid1()) { 560 | optionals.set(0); 561 | } 562 | if (struct.isSetUid2()) { 563 | optionals.set(1); 564 | } 565 | if (struct.isSetMsg()) { 566 | optionals.set(2); 567 | } 568 | oprot.writeBitSet(optionals, 3); 569 | if (struct.isSetUid1()) { 570 | oprot.writeI32(struct.uid1); 571 | } 572 | if (struct.isSetUid2()) { 573 | oprot.writeI32(struct.uid2); 574 | } 575 | if (struct.isSetMsg()) { 576 | oprot.writeString(struct.msg); 577 | } 578 | } 579 | 580 | @Override 581 | public void read(org.apache.thrift.protocol.TProtocol prot, DifferentSourceDetectedException struct) throws org.apache.thrift.TException { 582 | TTupleProtocol iprot = (TTupleProtocol) prot; 583 | BitSet incoming = iprot.readBitSet(3); 584 | if (incoming.get(0)) { 585 | struct.uid1 = iprot.readI32(); 586 | struct.setUid1IsSet(true); 587 | } 588 | if (incoming.get(1)) { 589 | struct.uid2 = iprot.readI32(); 590 | struct.setUid2IsSet(true); 591 | } 592 | if (incoming.get(2)) { 593 | struct.msg = iprot.readString(); 594 | struct.setMsgIsSet(true); 595 | } 596 | } 597 | } 598 | 599 | } 600 | 601 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/generated/UserInfo.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.2) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | package com.justdebugit.thrift.generated; 8 | 9 | import org.apache.thrift.scheme.IScheme; 10 | import org.apache.thrift.scheme.SchemeFactory; 11 | import org.apache.thrift.scheme.StandardScheme; 12 | 13 | import org.apache.thrift.scheme.TupleScheme; 14 | import org.apache.thrift.protocol.TTupleProtocol; 15 | import org.apache.thrift.protocol.TProtocolException; 16 | import org.apache.thrift.EncodingUtils; 17 | import org.apache.thrift.TException; 18 | import org.apache.thrift.async.AsyncMethodCallback; 19 | import org.apache.thrift.server.AbstractNonblockingServer.*; 20 | import java.util.List; 21 | import java.util.ArrayList; 22 | import java.util.Map; 23 | import java.util.HashMap; 24 | import java.util.EnumMap; 25 | import java.util.Set; 26 | import java.util.HashSet; 27 | import java.util.EnumSet; 28 | import java.util.Collections; 29 | import java.util.BitSet; 30 | import java.nio.ByteBuffer; 31 | import java.util.Arrays; 32 | import javax.annotation.Generated; 33 | import org.slf4j.Logger; 34 | import org.slf4j.LoggerFactory; 35 | 36 | @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"}) 37 | @Generated(value = "Autogenerated by Thrift Compiler (0.9.2)", date = "2015-7-12") 38 | public class UserInfo implements org.apache.thrift.TBase, java.io.Serializable, Cloneable, Comparable { 39 | private static final org.apache.thrift.protocol.TStruct STRUCT_DESC = new org.apache.thrift.protocol.TStruct("UserInfo"); 40 | 41 | private static final org.apache.thrift.protocol.TField UID_FIELD_DESC = new org.apache.thrift.protocol.TField("uid", org.apache.thrift.protocol.TType.I32, (short)1); 42 | private static final org.apache.thrift.protocol.TField NAME_FIELD_DESC = new org.apache.thrift.protocol.TField("name", org.apache.thrift.protocol.TType.STRING, (short)2); 43 | private static final org.apache.thrift.protocol.TField SCORE_FIELD_DESC = new org.apache.thrift.protocol.TField("score", org.apache.thrift.protocol.TType.DOUBLE, (short)3); 44 | private static final org.apache.thrift.protocol.TField SOURCE_FIELD_DESC = new org.apache.thrift.protocol.TField("source", org.apache.thrift.protocol.TType.I32, (short)4); 45 | 46 | private static final Map, SchemeFactory> schemes = new HashMap, SchemeFactory>(); 47 | static { 48 | schemes.put(StandardScheme.class, new UserInfoStandardSchemeFactory()); 49 | schemes.put(TupleScheme.class, new UserInfoTupleSchemeFactory()); 50 | } 51 | 52 | public int uid; // required 53 | public String name; // optional 54 | public double score; // optional 55 | /** 56 | * 57 | * @see UserSource 58 | */ 59 | public UserSource source; // optional 60 | 61 | /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */ 62 | public enum _Fields implements org.apache.thrift.TFieldIdEnum { 63 | UID((short)1, "uid"), 64 | NAME((short)2, "name"), 65 | SCORE((short)3, "score"), 66 | /** 67 | * 68 | * @see UserSource 69 | */ 70 | SOURCE((short)4, "source"); 71 | 72 | private static final Map byName = new HashMap(); 73 | 74 | static { 75 | for (_Fields field : EnumSet.allOf(_Fields.class)) { 76 | byName.put(field.getFieldName(), field); 77 | } 78 | } 79 | 80 | /** 81 | * Find the _Fields constant that matches fieldId, or null if its not found. 82 | */ 83 | public static _Fields findByThriftId(int fieldId) { 84 | switch(fieldId) { 85 | case 1: // UID 86 | return UID; 87 | case 2: // NAME 88 | return NAME; 89 | case 3: // SCORE 90 | return SCORE; 91 | case 4: // SOURCE 92 | return SOURCE; 93 | default: 94 | return null; 95 | } 96 | } 97 | 98 | /** 99 | * Find the _Fields constant that matches fieldId, throwing an exception 100 | * if it is not found. 101 | */ 102 | public static _Fields findByThriftIdOrThrow(int fieldId) { 103 | _Fields fields = findByThriftId(fieldId); 104 | if (fields == null) throw new IllegalArgumentException("Field " + fieldId + " doesn't exist!"); 105 | return fields; 106 | } 107 | 108 | /** 109 | * Find the _Fields constant that matches name, or null if its not found. 110 | */ 111 | public static _Fields findByName(String name) { 112 | return byName.get(name); 113 | } 114 | 115 | private final short _thriftId; 116 | private final String _fieldName; 117 | 118 | _Fields(short thriftId, String fieldName) { 119 | _thriftId = thriftId; 120 | _fieldName = fieldName; 121 | } 122 | 123 | public short getThriftFieldId() { 124 | return _thriftId; 125 | } 126 | 127 | public String getFieldName() { 128 | return _fieldName; 129 | } 130 | } 131 | 132 | // isset id assignments 133 | private static final int __UID_ISSET_ID = 0; 134 | private static final int __SCORE_ISSET_ID = 1; 135 | private byte __isset_bitfield = 0; 136 | private static final _Fields optionals[] = {_Fields.NAME,_Fields.SCORE,_Fields.SOURCE}; 137 | public static final Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> metaDataMap; 138 | static { 139 | Map<_Fields, org.apache.thrift.meta_data.FieldMetaData> tmpMap = new EnumMap<_Fields, org.apache.thrift.meta_data.FieldMetaData>(_Fields.class); 140 | tmpMap.put(_Fields.UID, new org.apache.thrift.meta_data.FieldMetaData("uid", org.apache.thrift.TFieldRequirementType.DEFAULT, 141 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.I32))); 142 | tmpMap.put(_Fields.NAME, new org.apache.thrift.meta_data.FieldMetaData("name", org.apache.thrift.TFieldRequirementType.OPTIONAL, 143 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.STRING))); 144 | tmpMap.put(_Fields.SCORE, new org.apache.thrift.meta_data.FieldMetaData("score", org.apache.thrift.TFieldRequirementType.OPTIONAL, 145 | new org.apache.thrift.meta_data.FieldValueMetaData(org.apache.thrift.protocol.TType.DOUBLE))); 146 | tmpMap.put(_Fields.SOURCE, new org.apache.thrift.meta_data.FieldMetaData("source", org.apache.thrift.TFieldRequirementType.OPTIONAL, 147 | new org.apache.thrift.meta_data.EnumMetaData(org.apache.thrift.protocol.TType.ENUM, UserSource.class))); 148 | metaDataMap = Collections.unmodifiableMap(tmpMap); 149 | org.apache.thrift.meta_data.FieldMetaData.addStructMetaDataMap(UserInfo.class, metaDataMap); 150 | } 151 | 152 | public UserInfo() { 153 | } 154 | 155 | public UserInfo( 156 | int uid) 157 | { 158 | this(); 159 | this.uid = uid; 160 | setUidIsSet(true); 161 | } 162 | 163 | /** 164 | * Performs a deep copy on other. 165 | */ 166 | public UserInfo(UserInfo other) { 167 | __isset_bitfield = other.__isset_bitfield; 168 | this.uid = other.uid; 169 | if (other.isSetName()) { 170 | this.name = other.name; 171 | } 172 | this.score = other.score; 173 | if (other.isSetSource()) { 174 | this.source = other.source; 175 | } 176 | } 177 | 178 | public UserInfo deepCopy() { 179 | return new UserInfo(this); 180 | } 181 | 182 | @Override 183 | public void clear() { 184 | setUidIsSet(false); 185 | this.uid = 0; 186 | this.name = null; 187 | setScoreIsSet(false); 188 | this.score = 0.0; 189 | this.source = null; 190 | } 191 | 192 | public int getUid() { 193 | return this.uid; 194 | } 195 | 196 | public UserInfo setUid(int uid) { 197 | this.uid = uid; 198 | setUidIsSet(true); 199 | return this; 200 | } 201 | 202 | public void unsetUid() { 203 | __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __UID_ISSET_ID); 204 | } 205 | 206 | /** Returns true if field uid is set (has been assigned a value) and false otherwise */ 207 | public boolean isSetUid() { 208 | return EncodingUtils.testBit(__isset_bitfield, __UID_ISSET_ID); 209 | } 210 | 211 | public void setUidIsSet(boolean value) { 212 | __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __UID_ISSET_ID, value); 213 | } 214 | 215 | public String getName() { 216 | return this.name; 217 | } 218 | 219 | public UserInfo setName(String name) { 220 | this.name = name; 221 | return this; 222 | } 223 | 224 | public void unsetName() { 225 | this.name = null; 226 | } 227 | 228 | /** Returns true if field name is set (has been assigned a value) and false otherwise */ 229 | public boolean isSetName() { 230 | return this.name != null; 231 | } 232 | 233 | public void setNameIsSet(boolean value) { 234 | if (!value) { 235 | this.name = null; 236 | } 237 | } 238 | 239 | public double getScore() { 240 | return this.score; 241 | } 242 | 243 | public UserInfo setScore(double score) { 244 | this.score = score; 245 | setScoreIsSet(true); 246 | return this; 247 | } 248 | 249 | public void unsetScore() { 250 | __isset_bitfield = EncodingUtils.clearBit(__isset_bitfield, __SCORE_ISSET_ID); 251 | } 252 | 253 | /** Returns true if field score is set (has been assigned a value) and false otherwise */ 254 | public boolean isSetScore() { 255 | return EncodingUtils.testBit(__isset_bitfield, __SCORE_ISSET_ID); 256 | } 257 | 258 | public void setScoreIsSet(boolean value) { 259 | __isset_bitfield = EncodingUtils.setBit(__isset_bitfield, __SCORE_ISSET_ID, value); 260 | } 261 | 262 | /** 263 | * 264 | * @see UserSource 265 | */ 266 | public UserSource getSource() { 267 | return this.source; 268 | } 269 | 270 | /** 271 | * 272 | * @see UserSource 273 | */ 274 | public UserInfo setSource(UserSource source) { 275 | this.source = source; 276 | return this; 277 | } 278 | 279 | public void unsetSource() { 280 | this.source = null; 281 | } 282 | 283 | /** Returns true if field source is set (has been assigned a value) and false otherwise */ 284 | public boolean isSetSource() { 285 | return this.source != null; 286 | } 287 | 288 | public void setSourceIsSet(boolean value) { 289 | if (!value) { 290 | this.source = null; 291 | } 292 | } 293 | 294 | public void setFieldValue(_Fields field, Object value) { 295 | switch (field) { 296 | case UID: 297 | if (value == null) { 298 | unsetUid(); 299 | } else { 300 | setUid((Integer)value); 301 | } 302 | break; 303 | 304 | case NAME: 305 | if (value == null) { 306 | unsetName(); 307 | } else { 308 | setName((String)value); 309 | } 310 | break; 311 | 312 | case SCORE: 313 | if (value == null) { 314 | unsetScore(); 315 | } else { 316 | setScore((Double)value); 317 | } 318 | break; 319 | 320 | case SOURCE: 321 | if (value == null) { 322 | unsetSource(); 323 | } else { 324 | setSource((UserSource)value); 325 | } 326 | break; 327 | 328 | } 329 | } 330 | 331 | public Object getFieldValue(_Fields field) { 332 | switch (field) { 333 | case UID: 334 | return Integer.valueOf(getUid()); 335 | 336 | case NAME: 337 | return getName(); 338 | 339 | case SCORE: 340 | return Double.valueOf(getScore()); 341 | 342 | case SOURCE: 343 | return getSource(); 344 | 345 | } 346 | throw new IllegalStateException(); 347 | } 348 | 349 | /** Returns true if field corresponding to fieldID is set (has been assigned a value) and false otherwise */ 350 | public boolean isSet(_Fields field) { 351 | if (field == null) { 352 | throw new IllegalArgumentException(); 353 | } 354 | 355 | switch (field) { 356 | case UID: 357 | return isSetUid(); 358 | case NAME: 359 | return isSetName(); 360 | case SCORE: 361 | return isSetScore(); 362 | case SOURCE: 363 | return isSetSource(); 364 | } 365 | throw new IllegalStateException(); 366 | } 367 | 368 | @Override 369 | public boolean equals(Object that) { 370 | if (that == null) 371 | return false; 372 | if (that instanceof UserInfo) 373 | return this.equals((UserInfo)that); 374 | return false; 375 | } 376 | 377 | public boolean equals(UserInfo that) { 378 | if (that == null) 379 | return false; 380 | 381 | boolean this_present_uid = true; 382 | boolean that_present_uid = true; 383 | if (this_present_uid || that_present_uid) { 384 | if (!(this_present_uid && that_present_uid)) 385 | return false; 386 | if (this.uid != that.uid) 387 | return false; 388 | } 389 | 390 | boolean this_present_name = true && this.isSetName(); 391 | boolean that_present_name = true && that.isSetName(); 392 | if (this_present_name || that_present_name) { 393 | if (!(this_present_name && that_present_name)) 394 | return false; 395 | if (!this.name.equals(that.name)) 396 | return false; 397 | } 398 | 399 | boolean this_present_score = true && this.isSetScore(); 400 | boolean that_present_score = true && that.isSetScore(); 401 | if (this_present_score || that_present_score) { 402 | if (!(this_present_score && that_present_score)) 403 | return false; 404 | if (this.score != that.score) 405 | return false; 406 | } 407 | 408 | boolean this_present_source = true && this.isSetSource(); 409 | boolean that_present_source = true && that.isSetSource(); 410 | if (this_present_source || that_present_source) { 411 | if (!(this_present_source && that_present_source)) 412 | return false; 413 | if (!this.source.equals(that.source)) 414 | return false; 415 | } 416 | 417 | return true; 418 | } 419 | 420 | @Override 421 | public int hashCode() { 422 | List list = new ArrayList(); 423 | 424 | boolean present_uid = true; 425 | list.add(present_uid); 426 | if (present_uid) 427 | list.add(uid); 428 | 429 | boolean present_name = true && (isSetName()); 430 | list.add(present_name); 431 | if (present_name) 432 | list.add(name); 433 | 434 | boolean present_score = true && (isSetScore()); 435 | list.add(present_score); 436 | if (present_score) 437 | list.add(score); 438 | 439 | boolean present_source = true && (isSetSource()); 440 | list.add(present_source); 441 | if (present_source) 442 | list.add(source.getValue()); 443 | 444 | return list.hashCode(); 445 | } 446 | 447 | @Override 448 | public int compareTo(UserInfo other) { 449 | if (!getClass().equals(other.getClass())) { 450 | return getClass().getName().compareTo(other.getClass().getName()); 451 | } 452 | 453 | int lastComparison = 0; 454 | 455 | lastComparison = Boolean.valueOf(isSetUid()).compareTo(other.isSetUid()); 456 | if (lastComparison != 0) { 457 | return lastComparison; 458 | } 459 | if (isSetUid()) { 460 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.uid, other.uid); 461 | if (lastComparison != 0) { 462 | return lastComparison; 463 | } 464 | } 465 | lastComparison = Boolean.valueOf(isSetName()).compareTo(other.isSetName()); 466 | if (lastComparison != 0) { 467 | return lastComparison; 468 | } 469 | if (isSetName()) { 470 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.name, other.name); 471 | if (lastComparison != 0) { 472 | return lastComparison; 473 | } 474 | } 475 | lastComparison = Boolean.valueOf(isSetScore()).compareTo(other.isSetScore()); 476 | if (lastComparison != 0) { 477 | return lastComparison; 478 | } 479 | if (isSetScore()) { 480 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.score, other.score); 481 | if (lastComparison != 0) { 482 | return lastComparison; 483 | } 484 | } 485 | lastComparison = Boolean.valueOf(isSetSource()).compareTo(other.isSetSource()); 486 | if (lastComparison != 0) { 487 | return lastComparison; 488 | } 489 | if (isSetSource()) { 490 | lastComparison = org.apache.thrift.TBaseHelper.compareTo(this.source, other.source); 491 | if (lastComparison != 0) { 492 | return lastComparison; 493 | } 494 | } 495 | return 0; 496 | } 497 | 498 | public _Fields fieldForId(int fieldId) { 499 | return _Fields.findByThriftId(fieldId); 500 | } 501 | 502 | public void read(org.apache.thrift.protocol.TProtocol iprot) throws org.apache.thrift.TException { 503 | schemes.get(iprot.getScheme()).getScheme().read(iprot, this); 504 | } 505 | 506 | public void write(org.apache.thrift.protocol.TProtocol oprot) throws org.apache.thrift.TException { 507 | schemes.get(oprot.getScheme()).getScheme().write(oprot, this); 508 | } 509 | 510 | @Override 511 | public String toString() { 512 | StringBuilder sb = new StringBuilder("UserInfo("); 513 | boolean first = true; 514 | 515 | sb.append("uid:"); 516 | sb.append(this.uid); 517 | first = false; 518 | if (isSetName()) { 519 | if (!first) sb.append(", "); 520 | sb.append("name:"); 521 | if (this.name == null) { 522 | sb.append("null"); 523 | } else { 524 | sb.append(this.name); 525 | } 526 | first = false; 527 | } 528 | if (isSetScore()) { 529 | if (!first) sb.append(", "); 530 | sb.append("score:"); 531 | sb.append(this.score); 532 | first = false; 533 | } 534 | if (isSetSource()) { 535 | if (!first) sb.append(", "); 536 | sb.append("source:"); 537 | if (this.source == null) { 538 | sb.append("null"); 539 | } else { 540 | sb.append(this.source); 541 | } 542 | first = false; 543 | } 544 | sb.append(")"); 545 | return sb.toString(); 546 | } 547 | 548 | public void validate() throws org.apache.thrift.TException { 549 | // check for required fields 550 | // check for sub-struct validity 551 | } 552 | 553 | private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException { 554 | try { 555 | write(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(out))); 556 | } catch (org.apache.thrift.TException te) { 557 | throw new java.io.IOException(te); 558 | } 559 | } 560 | 561 | private void readObject(java.io.ObjectInputStream in) throws java.io.IOException, ClassNotFoundException { 562 | try { 563 | // it doesn't seem like you should have to do this, but java serialization is wacky, and doesn't call the default constructor. 564 | __isset_bitfield = 0; 565 | read(new org.apache.thrift.protocol.TCompactProtocol(new org.apache.thrift.transport.TIOStreamTransport(in))); 566 | } catch (org.apache.thrift.TException te) { 567 | throw new java.io.IOException(te); 568 | } 569 | } 570 | 571 | private static class UserInfoStandardSchemeFactory implements SchemeFactory { 572 | public UserInfoStandardScheme getScheme() { 573 | return new UserInfoStandardScheme(); 574 | } 575 | } 576 | 577 | private static class UserInfoStandardScheme extends StandardScheme { 578 | 579 | public void read(org.apache.thrift.protocol.TProtocol iprot, UserInfo struct) throws org.apache.thrift.TException { 580 | org.apache.thrift.protocol.TField schemeField; 581 | iprot.readStructBegin(); 582 | while (true) 583 | { 584 | schemeField = iprot.readFieldBegin(); 585 | if (schemeField.type == org.apache.thrift.protocol.TType.STOP) { 586 | break; 587 | } 588 | switch (schemeField.id) { 589 | case 1: // UID 590 | if (schemeField.type == org.apache.thrift.protocol.TType.I32) { 591 | struct.uid = iprot.readI32(); 592 | struct.setUidIsSet(true); 593 | } else { 594 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); 595 | } 596 | break; 597 | case 2: // NAME 598 | if (schemeField.type == org.apache.thrift.protocol.TType.STRING) { 599 | struct.name = iprot.readString(); 600 | struct.setNameIsSet(true); 601 | } else { 602 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); 603 | } 604 | break; 605 | case 3: // SCORE 606 | if (schemeField.type == org.apache.thrift.protocol.TType.DOUBLE) { 607 | struct.score = iprot.readDouble(); 608 | struct.setScoreIsSet(true); 609 | } else { 610 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); 611 | } 612 | break; 613 | case 4: // SOURCE 614 | if (schemeField.type == org.apache.thrift.protocol.TType.I32) { 615 | struct.source = com.justdebugit.thrift.generated.UserSource.findByValue(iprot.readI32()); 616 | struct.setSourceIsSet(true); 617 | } else { 618 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); 619 | } 620 | break; 621 | default: 622 | org.apache.thrift.protocol.TProtocolUtil.skip(iprot, schemeField.type); 623 | } 624 | iprot.readFieldEnd(); 625 | } 626 | iprot.readStructEnd(); 627 | 628 | // check for required fields of primitive type, which can't be checked in the validate method 629 | struct.validate(); 630 | } 631 | 632 | public void write(org.apache.thrift.protocol.TProtocol oprot, UserInfo struct) throws org.apache.thrift.TException { 633 | struct.validate(); 634 | 635 | oprot.writeStructBegin(STRUCT_DESC); 636 | oprot.writeFieldBegin(UID_FIELD_DESC); 637 | oprot.writeI32(struct.uid); 638 | oprot.writeFieldEnd(); 639 | if (struct.name != null) { 640 | if (struct.isSetName()) { 641 | oprot.writeFieldBegin(NAME_FIELD_DESC); 642 | oprot.writeString(struct.name); 643 | oprot.writeFieldEnd(); 644 | } 645 | } 646 | if (struct.isSetScore()) { 647 | oprot.writeFieldBegin(SCORE_FIELD_DESC); 648 | oprot.writeDouble(struct.score); 649 | oprot.writeFieldEnd(); 650 | } 651 | if (struct.source != null) { 652 | if (struct.isSetSource()) { 653 | oprot.writeFieldBegin(SOURCE_FIELD_DESC); 654 | oprot.writeI32(struct.source.getValue()); 655 | oprot.writeFieldEnd(); 656 | } 657 | } 658 | oprot.writeFieldStop(); 659 | oprot.writeStructEnd(); 660 | } 661 | 662 | } 663 | 664 | private static class UserInfoTupleSchemeFactory implements SchemeFactory { 665 | public UserInfoTupleScheme getScheme() { 666 | return new UserInfoTupleScheme(); 667 | } 668 | } 669 | 670 | private static class UserInfoTupleScheme extends TupleScheme { 671 | 672 | @Override 673 | public void write(org.apache.thrift.protocol.TProtocol prot, UserInfo struct) throws org.apache.thrift.TException { 674 | TTupleProtocol oprot = (TTupleProtocol) prot; 675 | BitSet optionals = new BitSet(); 676 | if (struct.isSetUid()) { 677 | optionals.set(0); 678 | } 679 | if (struct.isSetName()) { 680 | optionals.set(1); 681 | } 682 | if (struct.isSetScore()) { 683 | optionals.set(2); 684 | } 685 | if (struct.isSetSource()) { 686 | optionals.set(3); 687 | } 688 | oprot.writeBitSet(optionals, 4); 689 | if (struct.isSetUid()) { 690 | oprot.writeI32(struct.uid); 691 | } 692 | if (struct.isSetName()) { 693 | oprot.writeString(struct.name); 694 | } 695 | if (struct.isSetScore()) { 696 | oprot.writeDouble(struct.score); 697 | } 698 | if (struct.isSetSource()) { 699 | oprot.writeI32(struct.source.getValue()); 700 | } 701 | } 702 | 703 | @Override 704 | public void read(org.apache.thrift.protocol.TProtocol prot, UserInfo struct) throws org.apache.thrift.TException { 705 | TTupleProtocol iprot = (TTupleProtocol) prot; 706 | BitSet incoming = iprot.readBitSet(4); 707 | if (incoming.get(0)) { 708 | struct.uid = iprot.readI32(); 709 | struct.setUidIsSet(true); 710 | } 711 | if (incoming.get(1)) { 712 | struct.name = iprot.readString(); 713 | struct.setNameIsSet(true); 714 | } 715 | if (incoming.get(2)) { 716 | struct.score = iprot.readDouble(); 717 | struct.setScoreIsSet(true); 718 | } 719 | if (incoming.get(3)) { 720 | struct.source = com.justdebugit.thrift.generated.UserSource.findByValue(iprot.readI32()); 721 | struct.setSourceIsSet(true); 722 | } 723 | } 724 | } 725 | 726 | } 727 | 728 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/generated/UserSource.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.2) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | package com.justdebugit.thrift.generated; 8 | 9 | 10 | import java.util.Map; 11 | import java.util.HashMap; 12 | import org.apache.thrift.TEnum; 13 | 14 | public enum UserSource implements org.apache.thrift.TEnum { 15 | WEIBO(1), 16 | QQ(2), 17 | WEIXIN(3), 18 | RENREN(4); 19 | 20 | private final int value; 21 | 22 | private UserSource(int value) { 23 | this.value = value; 24 | } 25 | 26 | /** 27 | * Get the integer value of this enum value, as defined in the Thrift IDL. 28 | */ 29 | public int getValue() { 30 | return value; 31 | } 32 | 33 | /** 34 | * Find a the enum type by its integer value, as defined in the Thrift IDL. 35 | * @return null if the value is not found. 36 | */ 37 | public static UserSource findByValue(int value) { 38 | switch (value) { 39 | case 1: 40 | return WEIBO; 41 | case 2: 42 | return QQ; 43 | case 3: 44 | return WEIXIN; 45 | case 4: 46 | return RENREN; 47 | default: 48 | return null; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/generated/userManagerConstants.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.2) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | package com.justdebugit.thrift.generated; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | @SuppressWarnings({"cast", "rawtypes", "serial", "unchecked"}) 13 | public class userManagerConstants { 14 | 15 | public static final int INT32CONSTANT = 9853; 16 | 17 | public static final List BLACKLIST = new ArrayList(); 18 | static { 19 | BLACKLIST.add(10); 20 | BLACKLIST.add(11); 21 | BLACKLIST.add(12); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/pool/AbstractObjectFactory.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.pool; 2 | 3 | import com.justdebugit.fastpool.ObjectFactory; 4 | 5 | /** 6 | * abstract objectFactory for connection 7 | * @author justdebugit@gmail.com 8 | * 9 | * @param 10 | */ 11 | public abstract class AbstractObjectFactory implements ObjectFactory{ 12 | private String host; 13 | private int port; 14 | 15 | public AbstractObjectFactory(String host,int port) { 16 | this.host = host; 17 | this.port = port; 18 | } 19 | 20 | public String getHost() { 21 | return host; 22 | } 23 | 24 | public void setHost(String host) { 25 | this.host = host; 26 | } 27 | 28 | public int getPort() { 29 | return port; 30 | } 31 | 32 | public void setPort(int port) { 33 | this.port = port; 34 | } 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/pool/AbstractStatefulPool.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.pool; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | import java.util.concurrent.atomic.AtomicReference; 5 | 6 | public abstract class AbstractStatefulPool implements StatefulPool { 7 | private final AtomicReference state = new AtomicReference(State.UNINITIALIZED); 8 | 9 | private final AtomicInteger refCnt = new AtomicInteger(); 10 | 11 | @Override 12 | public AtomicReference state() { 13 | return state; 14 | } 15 | 16 | @Override 17 | public AtomicInteger getRefCnt() { 18 | return refCnt; 19 | } 20 | 21 | protected boolean isInitialized(){ 22 | return state.get()==State.INITIALIZED; 23 | } 24 | 25 | protected boolean hasRef(){ 26 | return refCnt.get()>0; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/pool/AjustingLifeCycleMap.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.pool; 2 | 3 | import java.util.Map; 4 | 5 | import org.apache.commons.lang3.tuple.ImmutablePair; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import com.justdebugit.thrift.registry.ChangeListener; 10 | import com.justdebugit.thrift.registry.NodeEvent; 11 | import com.justdebugit.thrift.registry.Registry; 12 | 13 | public class AjustingLifeCycleMap extends NotifiableLifeCycleMap{ 14 | private static final long serialVersionUID = -6764469565224658815L; 15 | private static final Logger LOGGER = LoggerFactory.getLogger(AjustingLifeCycleMap.class); 16 | 17 | 18 | private final Registry registry ; 19 | private final String path; 20 | 21 | private volatile ChangeListener changeListener = null; 22 | 23 | 24 | public AjustingLifeCycleMap(String path,Registry registry) { 25 | this.registry = registry; 26 | this.path = path; 27 | start(); 28 | } 29 | 30 | 31 | @Override 32 | protected void doStart() { 33 | changeListener = new ChangeListener() { 34 | 35 | @Override 36 | public void onChange(NodeEvent event) { 37 | ImmutablePair data = event.getData(); 38 | switch (event.getType()) { 39 | case CHILD_ADDED: 40 | putIfAbsent(data.getKey(),data.getValue()); 41 | break; 42 | case CHILD_REMOVED: 43 | remove(data.getKey()); 44 | break; 45 | case CHILD_UPDATED: 46 | put(data.getKey(),data.getValue()); 47 | break; 48 | default: 49 | break; 50 | } 51 | getEventBus().post(event); 52 | } 53 | }; 54 | registry.subscribe(path, changeListener); 55 | Map map = registry.getChildren(path); 56 | if (map!=null) { 57 | putAll(map); 58 | }else { 59 | LOGGER.warn("path not exists"); 60 | registry.register(path); 61 | } 62 | } 63 | 64 | @Override 65 | protected void doStop() { 66 | if (changeListener==null) { 67 | registry.unsubscribe(path, changeListener); 68 | } 69 | 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/pool/DelegatableStatefulPool.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.pool; 2 | 3 | import java.io.IOException; 4 | import java.util.concurrent.TimeUnit; 5 | import java.util.concurrent.TimeoutException; 6 | 7 | import com.justdebugit.fastpool.Pool; 8 | 9 | public class DelegatableStatefulPool extends AbstractStatefulPool{ 10 | 11 | private Pool pool; 12 | 13 | public DelegatableStatefulPool(Pool pool) { 14 | this.pool = pool; 15 | } 16 | 17 | @Override 18 | public T get() throws InterruptedException, IllegalPoolStateException { 19 | if (!isInitialized()) { 20 | throw new IllegalPoolStateException("pool is either uninitialized or destroyed"); 21 | } 22 | return pool.get(); 23 | } 24 | 25 | @Override 26 | public T get(long timeout, TimeUnit timeUnit) throws InterruptedException, 27 | TimeoutException, IllegalPoolStateException { 28 | if (!isInitialized()) { 29 | throw new IllegalPoolStateException("pool is either uninitialized or destroyed"); 30 | } 31 | return pool.get(); 32 | } 33 | 34 | @Override 35 | public void release(T t, boolean broken) { 36 | pool.release(t, broken); 37 | } 38 | 39 | @Override 40 | public void release(T t) { 41 | pool.release(t); 42 | 43 | } 44 | 45 | @Override 46 | public int size() { 47 | return pool.size(); 48 | } 49 | 50 | @Override 51 | public void scale(int size) throws IllegalPoolStateException{ 52 | if (!isInitialized()) { 53 | throw new IllegalPoolStateException("pool is either uninitialized or destroyed"); 54 | } 55 | pool.scale(size); 56 | } 57 | 58 | @Override 59 | public void close() throws IOException { 60 | pool.close(); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/pool/IllegalPoolStateException.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.pool; 2 | 3 | public final class IllegalPoolStateException extends RuntimeException { 4 | 5 | private static final long serialVersionUID = 1571857199149792306L; 6 | 7 | public IllegalPoolStateException() { 8 | super(); 9 | } 10 | 11 | 12 | public IllegalPoolStateException(String message) { 13 | super(message); 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/pool/LifeCycleMap.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.pool; 2 | 3 | import java.util.concurrent.ConcurrentHashMap; 4 | import java.util.concurrent.atomic.AtomicBoolean; 5 | 6 | import com.justdebugit.thrift.common.LifeCycle; 7 | 8 | 9 | public abstract class LifeCycleMap extends ConcurrentHashMap implements LifeCycle{ 10 | 11 | private static final long serialVersionUID = -4277180793264814684L; 12 | 13 | protected AtomicBoolean state = new AtomicBoolean(false); 14 | 15 | public boolean isStarted(){ 16 | return state.get(); 17 | }; 18 | 19 | public void start(){ 20 | if (state.compareAndSet(false, true)) { 21 | doStart(); 22 | } 23 | } 24 | 25 | public void stop(){ 26 | if (state.compareAndSet(true, false)) { 27 | doStop(); 28 | } 29 | } 30 | 31 | protected abstract void doStart(); 32 | 33 | protected abstract void doStop(); 34 | } -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/pool/MultiPool.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.pool; 2 | 3 | import java.io.IOException; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Random; 7 | import java.util.concurrent.TimeUnit; 8 | import java.util.concurrent.TimeoutException; 9 | import java.util.concurrent.atomic.AtomicBoolean; 10 | 11 | import org.apache.commons.lang3.tuple.ImmutablePair; 12 | 13 | import com.google.common.cache.Cache; 14 | import com.google.common.cache.CacheBuilder; 15 | import com.google.common.collect.Lists; 16 | import com.justdebugit.fastpool.Pool; 17 | import com.justdebugit.thrift.common.LifeCycle; 18 | 19 | public class MultiPool implements Pool,LifeCycle { 20 | 21 | 22 | private static final LoadBalance DEFAULT_LOAD_BALANCE = new RandomPolicy(); 23 | private AtomicBoolean state = new AtomicBoolean(false); 24 | private final StatefulPoolMapManager path2pool; 25 | private final Cache> cache = CacheBuilder.newBuilder().weakKeys().build(); 26 | private LoadBalance loadBalance; 27 | 28 | 29 | public MultiPool(StatefulPoolMapManager path2pool,LoadBalance loadBalance) { 30 | this.path2pool = path2pool; 31 | this.loadBalance = loadBalance; 32 | start(); 33 | } 34 | 35 | public MultiPool(StatefulPoolMapManager path2pool) { 36 | this(path2pool, DEFAULT_LOAD_BALANCE); 37 | } 38 | 39 | 40 | 41 | @Override 42 | public T get() throws InterruptedException { 43 | ImmutablePair> pair = getPool(); 44 | if (pair==null) { 45 | throw new IllegalPoolStateException("there is no pool available"); 46 | } 47 | T entry = null; 48 | StatefulPool pool = pair.getValue(); 49 | cache.put(entry=pool.get(), pool); 50 | pool.getRefCnt().incrementAndGet(); 51 | return entry; 52 | } 53 | 54 | @Override 55 | public T get(long timeout, TimeUnit timeUnit) throws InterruptedException, 56 | TimeoutException { 57 | T entry = null; 58 | ImmutablePair> pair = getPool(); 59 | if (pair==null) { 60 | throw new IllegalPoolStateException("there is no pool available"); 61 | } 62 | StatefulPool pool = pair.getValue(); 63 | cache.put(entry=pool.get(timeout,timeUnit), pool); 64 | pool.getRefCnt().incrementAndGet(); 65 | return entry; 66 | } 67 | 68 | 69 | 70 | 71 | @Override 72 | public void release(T entry, boolean broken) { 73 | StatefulPool statefulPool = cache.getIfPresent(entry); 74 | if (statefulPool!=null) { 75 | try { 76 | statefulPool.release(entry,broken); 77 | } finally{ 78 | statefulPool.getRefCnt().decrementAndGet(); 79 | } 80 | } 81 | } 82 | 83 | @Override 84 | public void release(T entry) { 85 | StatefulPool statefulPool = cache.getIfPresent(entry); 86 | if (statefulPool!=null) { 87 | try { 88 | statefulPool.release(entry); 89 | } finally{ 90 | statefulPool.getRefCnt().decrementAndGet(); 91 | } 92 | } 93 | } 94 | 95 | @Override 96 | public int size() { 97 | return path2pool.size(); 98 | } 99 | 100 | @Override 101 | public void scale(int size) { 102 | throw new UnsupportedOperationException(); 103 | } 104 | 105 | 106 | 107 | private ImmutablePair> getPool() { 108 | Map> objectMap = path2pool.getObjectMap(); 109 | StatefulPool foundPool = null; 110 | for (int i = 0; i < objectMap.size(); i++) { 111 | String key = loadBalance.select(Lists.newArrayList(objectMap 112 | .keySet())); 113 | foundPool = path2pool.get(key); 114 | if (foundPool == null 115 | || foundPool.state().get() != State.INITIALIZED) { 116 | continue; 117 | } else { 118 | return ImmutablePair.of(key, foundPool); 119 | } 120 | } 121 | throw new IllegalPoolStateException( 122 | " thers is no useful pool in the container"); 123 | } 124 | 125 | 126 | public static class RandomPolicy implements LoadBalance{ 127 | Random random = new Random(); 128 | @Override 129 | public String select(List list) { 130 | if (list.size()<1) { 131 | throw new IllegalPoolStateException(" pool size must greater than one"); 132 | } 133 | return list.get(random.nextInt(list.size())); 134 | } 135 | 136 | } 137 | 138 | public interface LoadBalance { 139 | String select(List list); 140 | } 141 | 142 | @Override 143 | public void start() { 144 | if (state.compareAndSet(false, true)) { 145 | path2pool.start(); 146 | } 147 | } 148 | 149 | @Override 150 | public void stop() { 151 | if (state.compareAndSet(true, false)) { 152 | path2pool.stop(); 153 | try { 154 | close(); 155 | } catch (IOException e) { 156 | 157 | } 158 | }; 159 | } 160 | 161 | @Override 162 | public boolean isStarted() { 163 | return state.get(); 164 | } 165 | 166 | @Override 167 | public void close() throws IOException { 168 | // TODO Auto-generated method stub 169 | 170 | } 171 | 172 | 173 | } 174 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/pool/NodeKeyMapManager.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.pool; 2 | 3 | import java.util.concurrent.ConcurrentMap; 4 | import java.util.concurrent.atomic.AtomicBoolean; 5 | 6 | import org.jboss.netty.util.internal.ConcurrentHashMap; 7 | 8 | import com.google.common.eventbus.Subscribe; 9 | import com.justdebugit.thrift.common.LifeCycle; 10 | import com.justdebugit.thrift.registry.NodeEvent; 11 | import com.justdebugit.thrift.registry.Registry; 12 | import com.justdebugit.thrift.registry.ZkPathConstants; 13 | 14 | 15 | abstract class NodeKeyMapManager implements LifeCycle{ 16 | private final AtomicBoolean state = new AtomicBoolean(); 17 | private final ConcurrentMap objectMap = new ConcurrentHashMap(); //nodePath -->对象 映射 18 | 19 | protected NotifiableLifeCycleMap configMap = null;//nodePath -> 节点数据 映射 20 | protected String serviceName; 21 | 22 | public NodeKeyMapManager(String serviceName,Registry registry){ 23 | String path = "/"+serviceName + ZkPathConstants.PROVIDER_SUFFIX_PATH; 24 | this.configMap = new AjustingLifeCycleMap(path, registry); 25 | } 26 | 27 | @Override 28 | public void start() { 29 | if (state.compareAndSet(false, true)) { 30 | configMap.start(); 31 | configMap.getEventBus().register(this); 32 | for (String node : configMap.keySet()) { 33 | objectMap.putIfAbsent(node, createObject(node)); 34 | } 35 | } 36 | } 37 | 38 | @Override 39 | public void stop() { 40 | if (state.compareAndSet(true, false)) { 41 | configMap.stop(); 42 | configMap.getEventBus().unregister(this); 43 | } 44 | } 45 | 46 | @Override 47 | public boolean isStarted() { 48 | return state.get(); 49 | } 50 | 51 | public V get(String key){ 52 | return objectMap.get(key); 53 | } 54 | 55 | protected ConcurrentMap getObjectMap(){ 56 | return objectMap; 57 | } 58 | 59 | 60 | 61 | @Subscribe 62 | protected void onChange(NodeEvent event){ 63 | String key = event.getData().getKey(); 64 | switch (event.getType()) { 65 | case CHILD_ADDED: 66 | onAdd(key); 67 | break; 68 | case CHILD_REMOVED: 69 | onRemove(key); 70 | default: 71 | break; 72 | } 73 | 74 | }; 75 | 76 | protected abstract void onAdd(String key); 77 | 78 | protected abstract void onRemove(String key); 79 | 80 | protected abstract V createObject(String key); 81 | 82 | protected abstract int size(); 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/pool/NotifiableLifeCycleMap.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.pool; 2 | 3 | import com.google.common.eventbus.EventBus; 4 | 5 | public abstract class NotifiableLifeCycleMap extends LifeCycleMap{ 6 | private static final long serialVersionUID = -4004240708096262886L; 7 | private final EventBus eventBus = new EventBus("MAP-CHANGED"); 8 | 9 | public EventBus getEventBus(){ 10 | return eventBus; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/pool/State.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.pool; 2 | 3 | public enum State { 4 | UNINITIALIZED,INITIALIZED,DESTROYED 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/pool/StatefulPool.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.pool; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | import java.util.concurrent.atomic.AtomicReference; 5 | 6 | import com.justdebugit.fastpool.Pool; 7 | /** 8 | * 有状态的pool,支持计算器、状态变更 9 | * @author justdebugit@gmail.com 10 | * 11 | * @param 12 | */ 13 | public interface StatefulPool extends Pool { 14 | 15 | 16 | AtomicReference state(); 17 | 18 | 19 | AtomicInteger getRefCnt(); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/pool/StatefulPoolFactory.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.pool; 2 | 3 | /** 4 | * 创建statefulPool工厂类 5 | * @author justdebugit@gmail.com 6 | * 7 | * @param 8 | */ 9 | public interface StatefulPoolFactory { 10 | 11 | StatefulPool getPool(String info); 12 | 13 | 14 | Class getType(); 15 | 16 | void setType(Class type); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/pool/StatefulPoolMapManager.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.pool; 2 | 3 | import java.io.IOException; 4 | import java.util.Map; 5 | import java.util.concurrent.ConcurrentMap; 6 | 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | 10 | import com.justdebugit.thrift.registry.Registry; 11 | 12 | public class StatefulPoolMapManager extends NodeKeyMapManager>{ 13 | 14 | private static final Logger LOGGER = LoggerFactory.getLogger(StatefulPoolFactory.class); 15 | 16 | private StatefulPoolFactory poolFactory; 17 | 18 | public StatefulPoolMapManager(String serviceName, Registry registry,StatefulPoolFactory poolFactory) { 19 | super(serviceName, registry); 20 | this.poolFactory = poolFactory; 21 | } 22 | 23 | 24 | @Override 25 | protected void onAdd(String key) { 26 | getObjectMap().put(key, createObject(key)); 27 | } 28 | 29 | @Override 30 | protected void onRemove(String key) { 31 | StatefulPool statefulPool = getObjectMap().get(key); 32 | statefulPool.state().set(State.DESTROYED); 33 | } 34 | 35 | 36 | public StatefulPool get(String key){ 37 | StatefulPool statefulPool = getObjectMap().get(key); 38 | if (statefulPool.state().get()==State.DESTROYED && statefulPool.getRefCnt().get()<=0) { 39 | try { 40 | statefulPool.close(); 41 | } catch (IOException e) { 42 | LOGGER.error(e.getMessage(),e); 43 | } 44 | getObjectMap().remove(key); 45 | return null; 46 | } 47 | return statefulPool; 48 | } 49 | 50 | @Override 51 | protected StatefulPool createObject(String key) { 52 | return poolFactory.getPool(key); 53 | } 54 | 55 | 56 | @Override 57 | protected int size() { 58 | int sum = 0; 59 | ConcurrentMap> map = getObjectMap(); 60 | for (Map.Entry> entry : map.entrySet()) { 61 | sum += entry.getValue().size(); 62 | } 63 | return sum; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/provider/RpcProvider.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.provider; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.util.Map; 5 | import java.util.Set; 6 | 7 | import org.apache.thrift.TProcessor; 8 | import org.apache.thrift.server.TServer; 9 | 10 | import com.google.common.base.Preconditions; 11 | import com.google.common.collect.Maps; 12 | import com.google.common.collect.Sets; 13 | import com.justdebugit.thrift.common.AbstractLifeCycle; 14 | import com.justdebugit.thrift.constants.Constants; 15 | import com.justdebugit.thrift.registry.CuratorFactory; 16 | import com.justdebugit.thrift.registry.DefaultCuratorFactory; 17 | import com.justdebugit.thrift.registry.Registry; 18 | import com.justdebugit.thrift.registry.ZkCuratorRegistry; 19 | import com.justdebugit.thrift.registry.ZkPathConstants; 20 | import com.justdebugit.thrift.server.DefaultTServerFactory; 21 | import com.justdebugit.thrift.server.TServerFactory; 22 | import com.justdebugit.thrift.utils.NetUtils; 23 | import com.justdebugit.thrift.utils.ZkRegistryUtils; 24 | 25 | public class RpcProvider extends AbstractLifeCycle{ 26 | private String host; 27 | private int port; 28 | private TServer server ; 29 | private Registry registry; 30 | private Map processorMap = Maps.newConcurrentMap(); 31 | private Set pathSet = Sets.newCopyOnWriteArraySet(); 32 | 33 | 34 | public RpcProvider(ProviderBuilder builder){ 35 | registry = makeRegistry(builder); 36 | port = builder.getPort(); 37 | host = builder.getHost()==null?NetUtils.ANYHOST:builder.getHost(); 38 | server = makeTserver(builder); 39 | processorMap.putAll(builder.getProcessorMap()); 40 | 41 | } 42 | 43 | private TServer makeTserver(ProviderBuilder builder){ 44 | server = builder.gettServer(); 45 | if (server ==null) { 46 | TServerFactory tServerFactory = null; 47 | if ((tServerFactory=builder.gettServerFactory())!=null) { 48 | server = tServerFactory.createTServer(); 49 | }else { 50 | Preconditions.checkArgument(!builder.getProcessorMap().isEmpty(), "processor map can not be null "); 51 | Preconditions.checkArgument(builder.getPort()!=0, "port must be greater than zero"); 52 | InetSocketAddress address = null; 53 | if (builder.getHost()!=null) { 54 | address = new InetSocketAddress(builder.getHost(), port); 55 | }else { 56 | address = new InetSocketAddress(port); 57 | } 58 | 59 | TServerFactory _tServerFactory = new DefaultTServerFactory(builder.getProcessorMap(), address); 60 | server = _tServerFactory.createTServer(); 61 | } 62 | } 63 | return server; 64 | 65 | } 66 | 67 | private Registry makeRegistry(ProviderBuilder builder) { 68 | registry = builder.getRegistry(); 69 | if (registry==null) { 70 | CuratorFactory curatorFactory = new DefaultCuratorFactory( 71 | builder.getConnectStringForzk(), 72 | builder.getConectTimeoutForZk(), 73 | builder.getSessionTimeoutForZk()); 74 | registry = new ZkCuratorRegistry(curatorFactory); 75 | } 76 | return registry; 77 | } 78 | 79 | 80 | public void doStart() { 81 | for (Map.Entry entry : processorMap.entrySet()) { 82 | StringBuilder pathBuilder = new StringBuilder("/"+entry.getKey()+ZkPathConstants.PROVIDER_SUFFIX_PATH); 83 | pathBuilder.append("/"+host+":"+port); 84 | String path = pathBuilder.toString(); 85 | pathSet.add(path); 86 | ZkRegistryUtils.registerWithGuaranteed(registry, path, String.valueOf(System.currentTimeMillis()).getBytes()); 87 | } 88 | server.serve(); 89 | } 90 | 91 | public void doStop() { 92 | server.stop(); 93 | for (String path : pathSet) { 94 | registry.unregister(path); 95 | pathSet.remove(path); 96 | } 97 | } 98 | 99 | public static ProviderBuilder builder(){ 100 | return new ProviderBuilder(); 101 | } 102 | 103 | public static class ProviderBuilder{ 104 | private String host; 105 | private int port; 106 | private String connectStringForzk ; 107 | private int sessionTimeoutForZk = Constants.DEFAULT_SESSION_TIMEOUT; 108 | private int conectTimeoutForZk = Constants.DEFAULT_CONNECT_TIMEOUT; 109 | 110 | private Registry registry; 111 | private TServerFactory tServerFactory; 112 | private TServer tServer; 113 | 114 | private Map processorMap = Maps.newConcurrentMap(); 115 | 116 | public RpcProvider build(){ 117 | return new RpcProvider(this); 118 | } 119 | 120 | public ProviderBuilder processorMap(Map map){ 121 | processorMap.putAll(map); 122 | return this; 123 | } 124 | 125 | public ProviderBuilder connectStringForzk(String connectString){ 126 | this.connectStringForzk = connectString; 127 | return this; 128 | } 129 | 130 | public ProviderBuilder sessionTimeoutForZk(int sessionTimeoutForZk){ 131 | this.sessionTimeoutForZk = sessionTimeoutForZk; 132 | return this; 133 | } 134 | 135 | public ProviderBuilder connectTimeoutForZk(int connectTimeoutForZk){ 136 | this.conectTimeoutForZk = connectTimeoutForZk; 137 | return this; 138 | } 139 | 140 | public ProviderBuilder serverPort(int port){ 141 | this.port = port; 142 | return this; 143 | } 144 | 145 | public ProviderBuilder serverHost(String hostname){ 146 | this.host= hostname; 147 | return this; 148 | } 149 | 150 | public ProviderBuilder tServerFactory(TServerFactory tServerFactory){ 151 | this.tServerFactory = tServerFactory; 152 | return this; 153 | } 154 | 155 | public ProviderBuilder tServer(TServer tServer){ 156 | this.tServer = tServer; 157 | return this; 158 | } 159 | 160 | public ProviderBuilder registry(Registry registry){ 161 | this.registry = registry; 162 | return this; 163 | } 164 | 165 | public String getHost() { 166 | return host; 167 | } 168 | 169 | public int getPort() { 170 | return port; 171 | } 172 | 173 | public String getConnectStringForzk() { 174 | return connectStringForzk; 175 | } 176 | 177 | public int getSessionTimeoutForZk() { 178 | return sessionTimeoutForZk; 179 | } 180 | 181 | public int getConectTimeoutForZk() { 182 | return conectTimeoutForZk; 183 | } 184 | 185 | public Registry getRegistry() { 186 | return registry; 187 | } 188 | 189 | public TServerFactory gettServerFactory() { 190 | return tServerFactory; 191 | } 192 | 193 | public TServer gettServer() { 194 | return tServer; 195 | } 196 | 197 | public Map getProcessorMap() { 198 | return processorMap; 199 | } 200 | } 201 | 202 | 203 | } 204 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/proxy/PooledProxyFactory.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.proxy; 2 | 3 | import com.justdebugit.fastpool.Pool; 4 | import com.justdebugit.thrift.bytecode.Proxy; 5 | 6 | /** 7 | * PooledProxyFactory 8 | 9 | * @author justdebugit 10 | */ 11 | public final class PooledProxyFactory { 12 | 13 | @SuppressWarnings("unchecked") 14 | public static T getProxy(Class interfaceClass,Class clientClass,Pool pool) { 15 | return (T) Proxy.getProxy(interfaceClass).newInstance(new PooledTargetInvocationHandler(clientClass,pool)); 16 | } 17 | 18 | } -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/proxy/PooledTargetInvocationHandler.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.proxy; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | 6 | import com.justdebugit.fastpool.Pool; 7 | import com.justdebugit.thrift.bytecode.Wrapper; 8 | 9 | /** 10 | * 11 | * @author justdebugit@gmail.com 12 | * 13 | * @param 14 | */ 15 | public class PooledTargetInvocationHandler implements InvocationHandler { 16 | 17 | private final Wrapper wrapper; 18 | 19 | private final Pool pool; 20 | 21 | public PooledTargetInvocationHandler(Class clientClass,Pool pool) { 22 | this.wrapper = Wrapper.getWrapper(clientClass); 23 | this.pool = pool; 24 | } 25 | 26 | 27 | @Override 28 | public Object invoke(Object proxy, Method method, Object[] args) 29 | throws Throwable { 30 | Object result = null; 31 | T target = pool.get(); 32 | try { 33 | result = wrapper.invokeMethod(target, method.getName(), method.getParameterTypes(), args); 34 | } 35 | finally{ 36 | pool.release(target); 37 | } 38 | return result; 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/registry/ChangeListener.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.registry; 2 | 3 | public interface ChangeListener { 4 | 5 | void onChange(NodeEvent event); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/registry/CuratorFactory.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.registry; 2 | 3 | import org.apache.curator.framework.CuratorFramework; 4 | import org.apache.curator.framework.recipes.cache.NodeCache; 5 | import org.apache.curator.framework.recipes.cache.PathChildrenCache; 6 | 7 | 8 | public interface CuratorFactory { 9 | /** 10 | * 新建一个curator client 11 | * @return 12 | */ 13 | CuratorFramework getCuratorClient(); 14 | /** 15 | * 创建一个nodeCache用于监听某阶段新建删除内容修改事件 16 | * @param client 17 | * @param path 18 | * @return 19 | */ 20 | NodeCache getNodeCache(CuratorFramework client,String path); 21 | /** 22 | * 创建一个pathChildrenCache用于监听子节点增删改事件 23 | * @param client 24 | * @param path 25 | * @return 26 | */ 27 | PathChildrenCache getPathChildrenCache(CuratorFramework client,String path); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/registry/DefaultCuratorFactory.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.registry; 2 | 3 | import org.apache.curator.framework.CuratorFramework; 4 | import org.apache.curator.framework.CuratorFrameworkFactory; 5 | import org.apache.curator.framework.CuratorFrameworkFactory.Builder; 6 | import org.apache.curator.framework.imps.CuratorFrameworkState; 7 | import org.apache.curator.framework.recipes.cache.NodeCache; 8 | import org.apache.curator.framework.recipes.cache.PathChildrenCache; 9 | import org.apache.curator.framework.recipes.cache.PathChildrenCache.StartMode; 10 | import org.apache.curator.retry.RetryNTimes; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | import com.google.common.base.Preconditions; 15 | import com.justdebugit.thrift.constants.Constants; 16 | 17 | public class DefaultCuratorFactory implements CuratorFactory{ 18 | private static final Logger LOGGER = LoggerFactory.getLogger(DefaultCuratorFactory.class); 19 | private String connectString;//192.16.10.1:2181,192.16.10.2:2181,192.16.10.3:2181这种格式 20 | private Integer connectTimeout; 21 | private Integer sessionTimeout; 22 | 23 | public DefaultCuratorFactory(String connString,Integer connectTimeout,Integer sessionTimeout) { 24 | this.connectString = connString; 25 | this.connectTimeout = connectTimeout; 26 | this.sessionTimeout = sessionTimeout; 27 | } 28 | 29 | 30 | public DefaultCuratorFactory(String connString) { 31 | this(connString, Constants.DEFAULT_CONNECT_TIMEOUT, Constants.DEFAULT_SESSION_TIMEOUT); 32 | } 33 | 34 | 35 | @Override 36 | public CuratorFramework getCuratorClient() { 37 | Preconditions.checkNotNull(connectString); 38 | Builder builder = CuratorFrameworkFactory.builder() 39 | .connectString(connectString).sessionTimeoutMs(sessionTimeout) 40 | .retryPolicy(new RetryNTimes(Integer.MAX_VALUE, 100)) 41 | .connectionTimeoutMs(connectTimeout); 42 | CuratorFramework client = builder.build(); 43 | client.start(); 44 | return client; 45 | } 46 | 47 | @Override 48 | public NodeCache getNodeCache(CuratorFramework client, String path) { 49 | Preconditions.checkArgument(client!=null && client.getState()==CuratorFrameworkState.STARTED,"client is not started"); 50 | NodeCache nodeCache = new NodeCache(client, path); 51 | try { 52 | nodeCache.start(true);////同步初始化,将zk节点数据写入pathCache 53 | } catch (Exception e) { 54 | LOGGER.error("starting nodeCache error "+e.getMessage()); 55 | throw new IllegalStateException(e.getMessage(), e); 56 | } 57 | return nodeCache; 58 | } 59 | 60 | @Override 61 | public PathChildrenCache getPathChildrenCache(CuratorFramework client, 62 | String path) { 63 | Preconditions.checkArgument(client!=null && client.getState()==CuratorFrameworkState.STARTED,"client is not started"); 64 | PathChildrenCache childrenCache = new PathChildrenCache(client, path,true); 65 | try { 66 | childrenCache.start(StartMode.BUILD_INITIAL_CACHE);//同步初始化,将zk节点数据写入childrenCache 67 | } catch (Exception e) { 68 | LOGGER.error("starting nodeCache error "+e.getMessage()); 69 | throw new IllegalStateException(e.getMessage(), e); 70 | } 71 | return childrenCache; 72 | } 73 | 74 | 75 | public void setConnectString(String connectString) { 76 | this.connectString = connectString; 77 | } 78 | 79 | public void setConnectTimeout(Integer connectTimeout) { 80 | this.connectTimeout = connectTimeout; 81 | } 82 | 83 | public void setSessionTimeout(Integer sessionTimeout) { 84 | this.sessionTimeout = sessionTimeout; 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/registry/NodeEvent.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.registry; 2 | 3 | import org.apache.commons.lang3.tuple.ImmutablePair; 4 | 5 | 6 | public class NodeEvent { 7 | 8 | public enum EventType { 9 | /** 10 | * CHILD_ADDED, 节点增加 11 | * CHILD_UPDATED, 子节点内容发生变化 12 | * CHILD_REMOVED, 子节点被删除 13 | * NODE_CHANAGED 节点发生变化 14 | */ 15 | CHILD_ADDED,CHILD_UPDATED,CHILD_REMOVED,NODE_CHANAGED 16 | } 17 | 18 | private final EventType type; 19 | private final ImmutablePair data; 20 | 21 | public NodeEvent(EventType type,ImmutablePair data ) { 22 | this.type = type; 23 | this.data = data; 24 | } 25 | 26 | public EventType getType() { 27 | return type; 28 | } 29 | public ImmutablePair getData() { 30 | return data; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/registry/Registry.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.registry; 2 | 3 | import java.util.Map; 4 | 5 | 6 | /** 7 | * 提供注册中心注册与订阅功能接口 8 | * @author justdebugit@gmail.com 9 | * 10 | */ 11 | public interface Registry { 12 | 13 | /** 14 | * 注册数据到path指定的节点上,没有就创建 15 | * @param path 路径 16 | * @param bytes 数据 17 | */ 18 | void register(String path,byte[] bytes); 19 | 20 | 21 | 22 | /** 23 | * 注册数据到path指定的节点上,数据使用默认 24 | * @param path 路径 25 | * @param bytes 数据 默认数据 26 | */ 27 | void register(String path); 28 | 29 | /** 30 | * 解除注册 31 | * @param path 路径 32 | */ 33 | void unregister(String path); 34 | 35 | 36 | /** 37 | * 订阅,绑定监听器 38 | * @param path 39 | * @param listener 40 | */ 41 | void subscribe(String path,ChangeListener listener); 42 | 43 | /** 44 | * 解除订阅,解除监听器 45 | * @param path 46 | * @param listener 47 | */ 48 | void unsubscribe(String path,ChangeListener listener); 49 | 50 | /** 51 | * 获取节点数据 52 | * @param path 节点路径 53 | * @return 54 | */ 55 | byte[] getData(String path); 56 | 57 | /** 58 | * 获取子节点数据 59 | * @param path 父节点路径 60 | * @return 61 | */ 62 | Map getChildren(String path); 63 | 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/registry/ZkCuratorRegistry.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.registry; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.Set; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | import java.util.concurrent.ConcurrentMap; 8 | 9 | import org.apache.commons.lang3.tuple.ImmutablePair; 10 | import org.apache.curator.framework.CuratorFramework; 11 | import org.apache.curator.framework.recipes.cache.ChildData; 12 | import org.apache.curator.framework.recipes.cache.NodeCache; 13 | import org.apache.curator.framework.recipes.cache.NodeCacheListener; 14 | import org.apache.curator.framework.recipes.cache.PathChildrenCache; 15 | import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent; 16 | import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent.Type; 17 | import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener; 18 | import org.apache.zookeeper.CreateMode; 19 | import org.apache.zookeeper.KeeperException.NoNodeException; 20 | import org.apache.zookeeper.KeeperException.NodeExistsException; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import com.google.common.base.Preconditions; 25 | import com.google.common.collect.ImmutableSet; 26 | import com.google.common.collect.Maps; 27 | import com.justdebugit.thrift.registry.NodeEvent.EventType; 28 | 29 | /** 30 | * 注册、监听、解除注册、解除监听 31 | * 32 | * @author justdebugit@gmail.com 33 | * 34 | */ 35 | public class ZkCuratorRegistry implements Registry { 36 | private static final Logger LOGGER = LoggerFactory 37 | .getLogger(ZkCuratorRegistry.class); 38 | 39 | private final CuratorFactory curatorFactory; 40 | private final CuratorFramework client; 41 | private final NodeCacheManager nodeCacheManager; 42 | private static final Set ignoreTypes = ImmutableSet.of( 43 | Type.CONNECTION_SUSPENDED, Type.CONNECTION_RECONNECTED, 44 | Type.CONNECTION_LOST, Type.INITIALIZED); 45 | 46 | public ZkCuratorRegistry(CuratorFactory curatorFactory) { 47 | Preconditions.checkNotNull(curatorFactory); 48 | this.curatorFactory = curatorFactory; 49 | this.client = curatorFactory.getCuratorClient(); 50 | nodeCacheManager = new NodeCacheManager(); 51 | } 52 | 53 | @Override 54 | public void register(String path, byte[] bytes) { 55 | try { 56 | client.create().creatingParentsIfNeeded() 57 | .withMode(CreateMode.EPHEMERAL).forPath(path, bytes); 58 | } catch (NodeExistsException e) { 59 | LOGGER.warn(e.getMessage(), e); 60 | } catch (Exception e) { 61 | throw new IllegalStateException(" can not create path " + path 62 | + " " + e.getMessage(), e); 63 | } 64 | } 65 | 66 | @Override 67 | public void register(String path) { 68 | try { 69 | client.create().creatingParentsIfNeeded() 70 | .withMode(CreateMode.EPHEMERAL).forPath(path); 71 | } catch (NodeExistsException e) { 72 | LOGGER.warn("node already Exists " + e.getMessage(), e); 73 | } catch (Exception e) { 74 | throw new IllegalStateException(" can not create path " + path 75 | + " " + e.getMessage(), e); 76 | } 77 | } 78 | 79 | @Override 80 | public void unregister(String path) { 81 | try { 82 | client.delete().guaranteed().forPath(path); 83 | } catch (NoNodeException e) { 84 | LOGGER.warn("no node exists " + e.getMessage(), e); 85 | } catch (Exception e) { 86 | throw new IllegalStateException(" can not delete path " + path 87 | + " " + e.getMessage(), e); 88 | } 89 | } 90 | 91 | @Override 92 | public void subscribe(String path, ChangeListener listener) { 93 | nodeCacheManager.addListener(path, listener); 94 | } 95 | 96 | @Override 97 | public void unsubscribe(String path, ChangeListener listener) { 98 | nodeCacheManager.removeListener(path, listener); 99 | } 100 | 101 | @Override 102 | public byte[] getData(String path) { 103 | NodeCache nodeCache = nodeCacheManager.nodeCacheMap.get(path); 104 | ChildData childData = null; 105 | if (nodeCache != null 106 | && (childData = nodeCache.getCurrentData()) != null) { 107 | return childData.getData(); 108 | } 109 | return null; 110 | } 111 | 112 | @Override 113 | public Map getChildren(String path) { 114 | PathChildrenCache pathChildrenCache = nodeCacheManager.childNodeCacheMap 115 | .get(path); 116 | List children = null; 117 | if (pathChildrenCache != null 118 | && (children = pathChildrenCache.getCurrentData()) != null) { 119 | Map retMap = Maps.newHashMap(); 120 | for (ChildData childData : children) { 121 | retMap.put(childData.getPath(), childData.getData()); 122 | } 123 | return retMap; 124 | } 125 | return null; 126 | } 127 | 128 | /** 129 | * 监听节点事件每个path存放一个nodeCache和childrenNodeCache, 130 | * 通过nodeCache和childrenNodeCache不用关心重连、session失效等问题 131 | * 132 | */ 133 | private class NodeCacheManager { 134 | final ConcurrentMap nodeCacheMap = new ConcurrentHashMap(); 135 | final ConcurrentMap childNodeCacheMap = Maps 136 | .newConcurrentMap(); 137 | final ConcurrentMap change2ChildListenerMap = Maps 138 | .newConcurrentMap(); 139 | final ConcurrentMap change2NodeListenerMap = Maps 140 | .newConcurrentMap(); 141 | 142 | void addListener(String path, final ChangeListener listener) { 143 | addToNodeCache(path, listener); 144 | addToChildNodeCache(path, listener); 145 | } 146 | 147 | void removeListener(String path, final ChangeListener listener) { 148 | NodeCache nodeCache = nodeCacheMap.get(path); 149 | if (nodeCache != null) { 150 | nodeCache.getListenable().removeListener( 151 | change2NodeListenerMap.get(path)); 152 | } 153 | PathChildrenCache pathChildrenCache = childNodeCacheMap.get(path); 154 | if (pathChildrenCache != null) { 155 | pathChildrenCache.getListenable().removeListener( 156 | change2ChildListenerMap.get(path)); 157 | } 158 | } 159 | 160 | private void addToChildNodeCache(String path, 161 | final ChangeListener listener) { 162 | PathChildrenCache childrenCache = childNodeCacheMap.get(path); 163 | if (childrenCache == null) { 164 | childNodeCacheMap.putIfAbsent(path, 165 | curatorFactory.getPathChildrenCache(client, path)); 166 | childrenCache = childNodeCacheMap.get(path); 167 | } 168 | PathChildrenCacheListener pathChildrenCacheListener = new PathChildrenCacheListener() { 169 | 170 | @Override 171 | public void childEvent(CuratorFramework client, 172 | PathChildrenCacheEvent event) throws Exception { 173 | if (ignoreTypes.contains(event.getType())) { 174 | return; 175 | } 176 | ImmutablePair pair = ImmutablePair 177 | . of(event.getData().getPath(), 178 | event.getData().getData()); 179 | switch (event.getType()) { 180 | case CHILD_ADDED: 181 | listener.onChange(new NodeEvent(EventType.CHILD_ADDED, 182 | pair)); 183 | break; 184 | case CHILD_UPDATED: 185 | listener.onChange(new NodeEvent( 186 | EventType.CHILD_UPDATED, pair)); 187 | break; 188 | case CHILD_REMOVED: 189 | listener.onChange(new NodeEvent( 190 | EventType.CHILD_REMOVED, pair)); 191 | break; 192 | default: 193 | break; 194 | } 195 | } 196 | }; 197 | change2ChildListenerMap.putIfAbsent(listener, 198 | pathChildrenCacheListener); 199 | childrenCache.getListenable().addListener( 200 | change2ChildListenerMap.get(listener)); 201 | } 202 | 203 | private void addToNodeCache(String path, final ChangeListener listener) { 204 | NodeCache nodeCache = nodeCacheMap.get(path); 205 | if (nodeCache == null) { 206 | nodeCacheMap.putIfAbsent(path, 207 | curatorFactory.getNodeCache(client, path)); 208 | nodeCache = nodeCacheMap.get(path); 209 | } 210 | final NodeCache tmpCache = nodeCache; 211 | NodeCacheListener nodeCacheListener = new NodeCacheListener() { 212 | 213 | @Override 214 | public void nodeChanged() throws Exception { 215 | ChildData childData = tmpCache.getCurrentData(); 216 | if (childData!=null) { 217 | ImmutablePair pair = ImmutablePair 218 | . of(childData.getPath(), 219 | childData.getData()); 220 | listener.onChange(new NodeEvent(EventType.NODE_CHANAGED, 221 | pair)); 222 | }else { 223 | listener.onChange(new NodeEvent(EventType.NODE_CHANAGED, 224 | null)); 225 | } 226 | } 227 | }; 228 | change2NodeListenerMap.putIfAbsent(listener, nodeCacheListener); 229 | nodeCache.getListenable().addListener( 230 | change2NodeListenerMap.get(listener)); 231 | } 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/registry/ZkPathConstants.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.registry; 2 | 3 | public class ZkPathConstants { 4 | /** 5 | * 格式约定:1 父节点/com.xxx.xxService/providers 6 | * 2 子节点 192.168.137.1:8989 7 | * 192.168.137.2:8989 8 | * 192.168.137.3:8989 9 | * 3 子节点代表提供服务的实例 10 | */ 11 | public static final String PROVIDER_SUFFIX_PATH = "/providers"; 12 | 13 | 14 | /** 15 | * 格式约定:1 父节点/com.xxx.xxService/consumers 16 | * 2 子节点 192.168.137.1 17 | * 192.168.137.2 18 | * 192.168.137.3 19 | * 3 子节点代表消费服务的实例 20 | * 4 暂未用到 21 | */ 22 | public static final String CONSUMER_SUFFIX_PATH = "/consumers"; 23 | 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/registry/ZkRegistryUtils.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.registry; 2 | 3 | /** 4 | * 提供registry工具类 5 | * @author justdebugit@gmail.com 6 | * 7 | */ 8 | public final class ZkRegistryUtils { 9 | private ZkRegistryUtils(){} 10 | 11 | /** 12 | * 即便session丢失,重连时会重新注册 13 | */ 14 | public static void registerWithGuaranteed(final Registry registry,final String path,final byte[] bytes){ 15 | registry.register(path,bytes); 16 | registry.subscribe(path, new ChangeListener() { 17 | 18 | @Override 19 | public void onChange(NodeEvent event) { 20 | switch (event.getType()) { 21 | case NODE_CHANAGED: 22 | registry.register(path, bytes); 23 | break; 24 | default: 25 | break; 26 | } 27 | } 28 | }); 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/server/DefaultTServerFactory.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.server; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.util.Map; 5 | import java.util.concurrent.Executors; 6 | 7 | import org.apache.thrift.TMultiplexedProcessor; 8 | import org.apache.thrift.TProcessor; 9 | import org.apache.thrift.protocol.TCompactProtocol; 10 | import org.apache.thrift.server.TServer; 11 | import org.apache.thrift.server.TThreadedSelectorServer; 12 | import org.apache.thrift.transport.TFramedTransport; 13 | import org.apache.thrift.transport.TNonblockingServerSocket; 14 | import org.apache.thrift.transport.TTransportException; 15 | 16 | import com.justdebugit.thrift.common.ThriftInitException; 17 | 18 | public class DefaultTServerFactory implements TServerFactory { 19 | private final Map map; 20 | private final InetSocketAddress address; 21 | 22 | public DefaultTServerFactory(Map processorMap,InetSocketAddress address) { 23 | this.map = processorMap; 24 | this.address = address; 25 | } 26 | 27 | @Override 28 | public TServer createTServer() { 29 | TMultiplexedProcessor tMultiplexedProcessor = new TMultiplexedProcessor(); 30 | for (Map.Entry entry : this.map.entrySet()) { 31 | tMultiplexedProcessor.registerProcessor(entry.getKey(), entry.getValue()); 32 | } 33 | TNonblockingServerSocket socket = null; 34 | try { 35 | socket = new TNonblockingServerSocket(address); 36 | } catch (TTransportException e) { 37 | throw new ThriftInitException(e.getMessage(), e); 38 | } 39 | 40 | TThreadedSelectorServer.Args args = new TThreadedSelectorServer.Args( 41 | socket); 42 | args.executorService(Executors.newFixedThreadPool(20)); 43 | args.protocolFactory(new TCompactProtocol.Factory()); 44 | args.processor(tMultiplexedProcessor); 45 | args.transportFactory(new TFramedTransport.Factory()); 46 | TThreadedSelectorServer server = new TThreadedSelectorServer(args); 47 | return server; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/server/Server.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.server; 2 | 3 | import java.io.IOException; 4 | 5 | public interface Server { 6 | public abstract void start() throws IOException; 7 | 8 | public abstract void stop(); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/server/TServerFactory.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.server; 2 | 3 | import org.apache.thrift.server.TServer; 4 | 5 | public interface TServerFactory { 6 | 7 | TServer createTServer(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/utils/ClassHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2011 Alibaba Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.justdebugit.thrift.utils; 17 | 18 | import java.lang.reflect.Array; 19 | import java.util.Arrays; 20 | import java.util.HashMap; 21 | import java.util.HashSet; 22 | import java.util.Iterator; 23 | import java.util.Map; 24 | import java.util.Set; 25 | 26 | public class ClassHelper { 27 | 28 | public static Class forNameWithThreadContextClassLoader(String name) 29 | throws ClassNotFoundException { 30 | return forName(name, Thread.currentThread().getContextClassLoader()); 31 | } 32 | 33 | public static Class forNameWithCallerClassLoader(String name, Class caller) 34 | throws ClassNotFoundException { 35 | return forName(name, caller.getClassLoader()); 36 | } 37 | 38 | public static ClassLoader getCallerClassLoader(Class caller) { 39 | return caller.getClassLoader(); 40 | } 41 | 42 | /** 43 | * get class loader 44 | * 45 | * @param cls 46 | * @return class loader 47 | */ 48 | public static ClassLoader getClassLoader(Class cls) { 49 | ClassLoader cl = null; 50 | try { 51 | cl = Thread.currentThread().getContextClassLoader(); 52 | } catch (Throwable ex) { 53 | // Cannot access thread context ClassLoader - falling back to system class loader... 54 | } 55 | if (cl == null) { 56 | // No thread context class loader -> use class loader of this class. 57 | cl = cls.getClassLoader(); 58 | } 59 | return cl; 60 | } 61 | 62 | /** 63 | * Return the default ClassLoader to use: typically the thread context 64 | * ClassLoader, if available; the ClassLoader that loaded the ClassUtils 65 | * class will be used as fallback. 66 | *

67 | * Call this method if you intend to use the thread context ClassLoader in a 68 | * scenario where you absolutely need a non-null ClassLoader reference: for 69 | * example, for class path resource loading (but not necessarily for 70 | * Class.forName, which accepts a null ClassLoader 71 | * reference as well). 72 | * 73 | * @return the default ClassLoader (never null) 74 | * @see java.lang.Thread#getContextClassLoader() 75 | */ 76 | public static ClassLoader getClassLoader() { 77 | return getClassLoader(ClassHelper.class); 78 | } 79 | 80 | /** 81 | * Same as Class.forName(), except that it works for primitive 82 | * types. 83 | */ 84 | public static Class forName(String name) throws ClassNotFoundException { 85 | return forName(name, getClassLoader()); 86 | } 87 | 88 | /** 89 | * Replacement for Class.forName() that also returns Class 90 | * instances for primitives (like "int") and array class names (like 91 | * "String[]"). 92 | * 93 | * @param name the name of the Class 94 | * @param classLoader the class loader to use (may be null, 95 | * which indicates the default class loader) 96 | * @return Class instance for the supplied name 97 | * @throws ClassNotFoundException if the class was not found 98 | * @throws LinkageError if the class file could not be loaded 99 | * @see Class#forName(String, boolean, ClassLoader) 100 | */ 101 | public static Class forName(String name, ClassLoader classLoader) 102 | throws ClassNotFoundException, LinkageError { 103 | 104 | Class clazz = resolvePrimitiveClassName(name); 105 | if (clazz != null) { 106 | return clazz; 107 | } 108 | 109 | // "java.lang.String[]" style arrays 110 | if (name.endsWith(ARRAY_SUFFIX)) { 111 | String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length()); 112 | Class elementClass = forName(elementClassName, classLoader); 113 | return Array.newInstance(elementClass, 0).getClass(); 114 | } 115 | 116 | // "[Ljava.lang.String;" style arrays 117 | int internalArrayMarker = name.indexOf(INTERNAL_ARRAY_PREFIX); 118 | if (internalArrayMarker != -1 && name.endsWith(";")) { 119 | String elementClassName = null; 120 | if (internalArrayMarker == 0) { 121 | elementClassName = name 122 | .substring(INTERNAL_ARRAY_PREFIX.length(), name.length() - 1); 123 | } else if (name.startsWith("[")) { 124 | elementClassName = name.substring(1); 125 | } 126 | Class elementClass = forName(elementClassName, classLoader); 127 | return Array.newInstance(elementClass, 0).getClass(); 128 | } 129 | 130 | ClassLoader classLoaderToUse = classLoader; 131 | if (classLoaderToUse == null) { 132 | classLoaderToUse = getClassLoader(); 133 | } 134 | return classLoaderToUse.loadClass(name); 135 | } 136 | 137 | /** 138 | * Resolve the given class name as primitive class, if appropriate, 139 | * according to the JVM's naming rules for primitive classes. 140 | *

141 | * Also supports the JVM's internal class names for primitive arrays. Does 142 | * not support the "[]" suffix notation for primitive arrays; this is 143 | * only supported by {@link #forName}. 144 | * 145 | * @param name the name of the potentially primitive class 146 | * @return the primitive class, or null if the name does not 147 | * denote a primitive class or primitive array class 148 | */ 149 | public static Class resolvePrimitiveClassName(String name) { 150 | Class result = null; 151 | // Most class names will be quite long, considering that they 152 | // SHOULD sit in a package, so a length check is worthwhile. 153 | if (name != null && name.length() <= 8) { 154 | // Could be a primitive - likely. 155 | result = (Class) primitiveTypeNameMap.get(name); 156 | } 157 | return result; 158 | } 159 | 160 | /** Suffix for array class names: "[]" */ 161 | public static final String ARRAY_SUFFIX = "[]"; 162 | /** Prefix for internal array class names: "[L" */ 163 | private static final String INTERNAL_ARRAY_PREFIX = "[L"; 164 | 165 | /** 166 | * Map with primitive type name as key and corresponding primitive type as 167 | * value, for example: "int" -> "int.class". 168 | */ 169 | private static final Map> primitiveTypeNameMap = new HashMap>(16); 170 | 171 | /** 172 | * Map with primitive wrapper type as key and corresponding primitive type 173 | * as value, for example: Integer.class -> int.class. 174 | */ 175 | private static final Map,Class> primitiveWrapperTypeMap = new HashMap, Class>(8); 176 | 177 | static { 178 | primitiveWrapperTypeMap.put(Boolean.class, boolean.class); 179 | primitiveWrapperTypeMap.put(Byte.class, byte.class); 180 | primitiveWrapperTypeMap.put(Character.class, char.class); 181 | primitiveWrapperTypeMap.put(Double.class, double.class); 182 | primitiveWrapperTypeMap.put(Float.class, float.class); 183 | primitiveWrapperTypeMap.put(Integer.class, int.class); 184 | primitiveWrapperTypeMap.put(Long.class, long.class); 185 | primitiveWrapperTypeMap.put(Short.class, short.class); 186 | 187 | Set> primitiveTypeNames = new HashSet>(16); 188 | primitiveTypeNames.addAll(primitiveWrapperTypeMap.values()); 189 | primitiveTypeNames.addAll(Arrays 190 | .asList(new Class[] { boolean[].class, byte[].class, char[].class, double[].class, 191 | float[].class, int[].class, long[].class, short[].class })); 192 | for (Iterator> it = primitiveTypeNames.iterator(); it.hasNext();) { 193 | Class primitiveClass = (Class) it.next(); 194 | primitiveTypeNameMap.put(primitiveClass.getName(), primitiveClass); 195 | } 196 | } 197 | 198 | public static String toShortString(Object obj){ 199 | if(obj == null){ 200 | return "null"; 201 | } 202 | return obj.getClass().getSimpleName() + "@" + System.identityHashCode(obj); 203 | 204 | } 205 | } -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/utils/NetUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2011 Alibaba Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.justdebugit.thrift.utils; 17 | 18 | import java.io.IOException; 19 | import java.net.InetAddress; 20 | import java.net.InetSocketAddress; 21 | import java.net.NetworkInterface; 22 | import java.net.ServerSocket; 23 | import java.net.UnknownHostException; 24 | import java.util.Enumeration; 25 | import java.util.Random; 26 | import java.util.regex.Pattern; 27 | 28 | import org.slf4j.Logger; 29 | import org.slf4j.LoggerFactory; 30 | 31 | 32 | /** 33 | * IP and Port Helper for RPC, 34 | * 35 | * @author shawn.qianx 36 | */ 37 | 38 | public class NetUtils { 39 | 40 | private static final Logger logger = LoggerFactory.getLogger(NetUtils.class); 41 | 42 | public static final String LOCALHOST = "127.0.0.1"; 43 | 44 | public static final String ANYHOST = "0.0.0.0"; 45 | 46 | private static final int RND_PORT_START = 30000; 47 | 48 | private static final int RND_PORT_RANGE = 10000; 49 | 50 | private static final Random RANDOM = new Random(System.currentTimeMillis()); 51 | 52 | public static int getRandomPort() { 53 | return RND_PORT_START + RANDOM.nextInt(RND_PORT_RANGE); 54 | } 55 | 56 | public static int getAvailablePort() { 57 | ServerSocket ss = null; 58 | try { 59 | ss = new ServerSocket(); 60 | ss.bind(null); 61 | return ss.getLocalPort(); 62 | } catch (IOException e) { 63 | return getRandomPort(); 64 | } finally { 65 | if (ss != null) { 66 | try { 67 | ss.close(); 68 | } catch (IOException e) { 69 | } 70 | } 71 | } 72 | } 73 | 74 | public static int getAvailablePort(int port) { 75 | if (port <= 0) { 76 | return getAvailablePort(); 77 | } 78 | for(int i = port; i < MAX_PORT; i ++) { 79 | ServerSocket ss = null; 80 | try { 81 | ss = new ServerSocket(i); 82 | return i; 83 | } catch (IOException e) { 84 | // continue 85 | } finally { 86 | if (ss != null) { 87 | try { 88 | ss.close(); 89 | } catch (IOException e) { 90 | } 91 | } 92 | } 93 | } 94 | return port; 95 | } 96 | 97 | private static final int MIN_PORT = 0; 98 | 99 | private static final int MAX_PORT = 65535; 100 | 101 | public static boolean isInvalidPort(int port){ 102 | return port > MIN_PORT || port <= MAX_PORT; 103 | } 104 | 105 | private static final Pattern ADDRESS_PATTERN = Pattern.compile("^\\d{1,3}(\\.\\d{1,3}){3}\\:\\d{1,5}$"); 106 | 107 | public static boolean isValidAddress(String address){ 108 | return ADDRESS_PATTERN.matcher(address).matches(); 109 | } 110 | 111 | private static final Pattern LOCAL_IP_PATTERN = Pattern.compile("127(\\.\\d{1,3}){3}$"); 112 | 113 | public static boolean isLocalHost(String host) { 114 | return host != null 115 | && (LOCAL_IP_PATTERN.matcher(host).matches() 116 | || host.equalsIgnoreCase("localhost")); 117 | } 118 | 119 | public static boolean isAnyHost(String host) { 120 | return "0.0.0.0".equals(host); 121 | } 122 | 123 | public static boolean isInvalidLocalHost(String host) { 124 | return host == null 125 | || host.length() == 0 126 | || host.equalsIgnoreCase("localhost") 127 | || host.equals("0.0.0.0") 128 | || (LOCAL_IP_PATTERN.matcher(host).matches()); 129 | } 130 | 131 | public static boolean isValidLocalHost(String host) { 132 | return ! isInvalidLocalHost(host); 133 | } 134 | 135 | public static InetSocketAddress getLocalSocketAddress(String host, int port) { 136 | return isInvalidLocalHost(host) ? 137 | new InetSocketAddress(port) : new InetSocketAddress(host, port); 138 | } 139 | 140 | private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$"); 141 | 142 | private static boolean isValidAddress(InetAddress address) { 143 | if (address == null || address.isLoopbackAddress()) 144 | return false; 145 | String name = address.getHostAddress(); 146 | return (name != null 147 | && ! ANYHOST.equals(name) 148 | && ! LOCALHOST.equals(name) 149 | && IP_PATTERN.matcher(name).matches()); 150 | } 151 | 152 | public static String getLocalHost(){ 153 | InetAddress address = getLocalAddress(); 154 | return address == null ? LOCALHOST : address.getHostAddress(); 155 | } 156 | 157 | private static volatile InetAddress LOCAL_ADDRESS = null; 158 | 159 | /** 160 | * 遍历本地网卡,返回第一个合理的IP。 161 | * 162 | * @return 本地网卡IP 163 | */ 164 | public static InetAddress getLocalAddress() { 165 | if (LOCAL_ADDRESS != null) 166 | return LOCAL_ADDRESS; 167 | InetAddress localAddress = getLocalAddress0(); 168 | LOCAL_ADDRESS = localAddress; 169 | return localAddress; 170 | } 171 | 172 | public static String getLogHost() { 173 | InetAddress address = LOCAL_ADDRESS; 174 | return address == null ? LOCALHOST : address.getHostAddress(); 175 | } 176 | 177 | private static InetAddress getLocalAddress0() { 178 | InetAddress localAddress = null; 179 | try { 180 | localAddress = InetAddress.getLocalHost(); 181 | if (isValidAddress(localAddress)) { 182 | return localAddress; 183 | } 184 | } catch (Throwable e) { 185 | logger.warn("Failed to retriving ip address, " + e.getMessage(), e); 186 | } 187 | try { 188 | Enumeration interfaces = NetworkInterface.getNetworkInterfaces(); 189 | if (interfaces != null) { 190 | while (interfaces.hasMoreElements()) { 191 | try { 192 | NetworkInterface network = interfaces.nextElement(); 193 | Enumeration addresses = network.getInetAddresses(); 194 | if (addresses != null) { 195 | while (addresses.hasMoreElements()) { 196 | try { 197 | InetAddress address = addresses.nextElement(); 198 | if (isValidAddress(address)) { 199 | return address; 200 | } 201 | } catch (Throwable e) { 202 | logger.warn("Failed to retriving ip address, " + e.getMessage(), e); 203 | } 204 | } 205 | } 206 | } catch (Throwable e) { 207 | logger.warn("Failed to retriving ip address, " + e.getMessage(), e); 208 | } 209 | } 210 | } 211 | } catch (Throwable e) { 212 | logger.warn("Failed to retriving ip address, " + e.getMessage(), e); 213 | } 214 | logger.error("Could not get local host ip address, will use 127.0.0.1 instead."); 215 | return localAddress; 216 | } 217 | 218 | 219 | /** 220 | * @param hostName 221 | * @return ip address or hostName if UnknownHostException 222 | */ 223 | public static String getIpByHost(String hostName) { 224 | try{ 225 | return InetAddress.getByName(hostName).getHostAddress(); 226 | }catch (UnknownHostException e) { 227 | return hostName; 228 | } 229 | } 230 | 231 | public static String toAddressString(InetSocketAddress address) { 232 | return address.getAddress().getHostAddress() + ":" + address.getPort(); 233 | } 234 | 235 | public static InetSocketAddress toAddress(String address) { 236 | int i = address.indexOf(':'); 237 | String host; 238 | int port; 239 | if (i > -1) { 240 | host = address.substring(0, i); 241 | port = Integer.parseInt(address.substring(i + 1)); 242 | } else { 243 | host = address; 244 | port = 0; 245 | } 246 | return new InetSocketAddress(host, port); 247 | } 248 | 249 | public static String toURL(String protocol, String host, int port, String path) { 250 | StringBuilder sb = new StringBuilder(); 251 | sb.append(protocol).append("://"); 252 | sb.append(host).append(':').append(port); 253 | if( path.charAt(0) != '/' ) 254 | sb.append('/'); 255 | sb.append(path); 256 | return sb.toString(); 257 | } 258 | 259 | } -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1999-2011 Alibaba Group. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.justdebugit.thrift.utils; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Collection; 20 | import java.util.HashMap; 21 | import java.util.List; 22 | import java.util.Map; 23 | import java.util.TreeMap; 24 | import java.util.regex.Matcher; 25 | import java.util.regex.Pattern; 26 | 27 | import org.slf4j.Logger; 28 | import org.slf4j.LoggerFactory; 29 | 30 | /** 31 | * StringUtils 32 | * 33 | * @author qian.lei 34 | */ 35 | 36 | public final class StringUtils { 37 | 38 | private static final Logger logger = LoggerFactory.getLogger(StringUtils.class); 39 | 40 | public static final String[] EMPTY_STRING_ARRAY = new String[0]; 41 | 42 | private static final Pattern KVP_PATTERN = Pattern.compile("([_.a-zA-Z0-9][-_.a-zA-Z0-9]*)[=](.*)"); //key value pair pattern. 43 | 44 | private static final Pattern INT_PATTERN = Pattern.compile("^\\d+$"); 45 | 46 | public static boolean isBlank(String str) 47 | { 48 | if( str == null || str.length() == 0 ) 49 | return true; 50 | return false; 51 | } 52 | 53 | /** 54 | * is empty string. 55 | * 56 | * @param str source string. 57 | * @return is empty. 58 | */ 59 | public static boolean isEmpty(String str) 60 | { 61 | if( str == null || str.length() == 0 ) 62 | return true; 63 | return false; 64 | } 65 | 66 | /** 67 | * is not empty string. 68 | * 69 | * @param str source string. 70 | * @return is not empty. 71 | */ 72 | public static boolean isNotEmpty(String str) 73 | { 74 | return str != null && str.length() > 0; 75 | } 76 | 77 | /** 78 | * 79 | * @param s1 80 | * @param s2 81 | * @return equals 82 | */ 83 | public static boolean isEquals(String s1, String s2) { 84 | if (s1 == null && s2 == null) 85 | return true; 86 | if (s1 == null || s2 == null) 87 | return false; 88 | return s1.equals(s2); 89 | } 90 | 91 | /** 92 | * is integer string. 93 | * 94 | * @param str 95 | * @return is integer 96 | */ 97 | public static boolean isInteger(String str) { 98 | if (str == null || str.length() == 0) 99 | return false; 100 | return INT_PATTERN.matcher(str).matches(); 101 | } 102 | 103 | public static int parseInteger(String str) { 104 | if (! isInteger(str)) 105 | return 0; 106 | return Integer.parseInt(str); 107 | } 108 | 109 | /** 110 | * Returns true if s is a legal Java identifier.

111 | * more info. 112 | */ 113 | public static boolean isJavaIdentifier(String s) { 114 | if (s.length() == 0 || !Character.isJavaIdentifierStart(s.charAt(0))) { 115 | return false; 116 | } 117 | for (int i=1; i 0 && values != null && values.length > 0) { 134 | for (String v : values) { 135 | if (value.equals(v)) { 136 | return true; 137 | } 138 | } 139 | } 140 | return false; 141 | } 142 | 143 | public static boolean isNumeric(String str) { 144 | if (str == null) { 145 | return false; 146 | } 147 | int sz = str.length(); 148 | for (int i = 0; i < sz; i++) { 149 | if (Character.isDigit(str.charAt(i)) == false) { 150 | return false; 151 | } 152 | } 153 | return true; 154 | } 155 | 156 | 157 | 158 | /** 159 | * translat. 160 | * 161 | * @param src source string. 162 | * @param from src char table. 163 | * @param to target char table. 164 | * @return String. 165 | */ 166 | public static String translat(String src, String from, String to) 167 | { 168 | if( isEmpty(src) ) return src; 169 | StringBuilder sb = null; 170 | int ix; 171 | char c; 172 | for(int i=0,len=src.length();i list = null; 204 | char c; 205 | int ix = 0,len=str.length(); 206 | for(int i=0;i(); 213 | list.add(str.substring(ix, i)); 214 | ix = i + 1; 215 | } 216 | } 217 | if( ix > 0 ) 218 | list.add(str.substring(ix)); 219 | return list == null ? EMPTY_STRING_ARRAY : (String[])list.toArray(EMPTY_STRING_ARRAY); 220 | } 221 | 222 | /** 223 | * join string. 224 | * 225 | * @param array String array. 226 | * @return String. 227 | */ 228 | public static String join(String[] array) 229 | { 230 | if( array.length == 0 ) return ""; 231 | StringBuilder sb = new StringBuilder(); 232 | for( String s : array ) 233 | sb.append(s); 234 | return sb.toString(); 235 | } 236 | 237 | /** 238 | * join string like javascript. 239 | * 240 | * @param array String array. 241 | * @param split split 242 | * @return String. 243 | */ 244 | public static String join(String[] array, char split) 245 | { 246 | if( array.length == 0 ) return ""; 247 | StringBuilder sb = new StringBuilder(); 248 | for(int i=0;i 0 ) 251 | sb.append(split); 252 | sb.append(array[i]); 253 | } 254 | return sb.toString(); 255 | } 256 | 257 | /** 258 | * join string like javascript. 259 | * 260 | * @param array String array. 261 | * @param split split 262 | * @return String. 263 | */ 264 | public static String join(String[] array, String split) 265 | { 266 | if( array.length == 0 ) return ""; 267 | StringBuilder sb = new StringBuilder(); 268 | for(int i=0;i 0 ) 271 | sb.append(split); 272 | sb.append(array[i]); 273 | } 274 | return sb.toString(); 275 | } 276 | 277 | public static String join(Collection coll, String split) { 278 | if(coll.isEmpty()) return ""; 279 | 280 | StringBuilder sb = new StringBuilder(); 281 | boolean isFirst = true; 282 | for(String s : coll) { 283 | if(isFirst) isFirst = false; else sb.append(split); 284 | sb.append(s); 285 | } 286 | return sb.toString(); 287 | } 288 | 289 | /** 290 | * parse key-value pair. 291 | * 292 | * @param str string. 293 | * @param itemSeparator item separator. 294 | * @return key-value map; 295 | */ 296 | private static Map parseKeyValuePair(String str, String itemSeparator) 297 | { 298 | String[] tmp = str.split(itemSeparator); 299 | Map map = new HashMap(tmp.length); 300 | for(int i=0;i ps) { 312 | StringBuilder buf = new StringBuilder(); 313 | if (ps != null && ps.size() > 0) { 314 | for (Map.Entry entry : new TreeMap(ps).entrySet()) { 315 | String key = entry.getKey(); 316 | String value = entry.getValue(); 317 | if (key != null && key.length() > 0 318 | && value != null && value.length() > 0) { 319 | if (buf.length() > 0) { 320 | buf.append("&"); 321 | } 322 | buf.append(key); 323 | buf.append("="); 324 | buf.append(value); 325 | } 326 | } 327 | } 328 | return buf.toString(); 329 | } 330 | 331 | public static String camelToSplitName(String camelName, String split) { 332 | if (camelName == null || camelName.length() == 0) { 333 | return camelName; 334 | } 335 | StringBuilder buf = null; 336 | for (int i = 0; i < camelName.length(); i ++) { 337 | char ch = camelName.charAt(i); 338 | if (ch >= 'A' && ch <= 'Z') { 339 | if (buf == null) { 340 | buf = new StringBuilder(); 341 | if (i > 0) { 342 | buf.append(camelName.substring(0, i)); 343 | } 344 | } 345 | if (i > 0) { 346 | buf.append(split); 347 | } 348 | buf.append(Character.toLowerCase(ch)); 349 | } else if (buf != null) { 350 | buf.append(ch); 351 | } 352 | } 353 | return buf == null ? camelName : buf.toString(); 354 | } 355 | 356 | 357 | private StringUtils(){} 358 | } -------------------------------------------------------------------------------- /src/main/java/com/justdebugit/thrift/utils/ZkRegistryUtils.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.utils; 2 | 3 | import com.justdebugit.thrift.registry.ChangeListener; 4 | import com.justdebugit.thrift.registry.NodeEvent; 5 | import com.justdebugit.thrift.registry.Registry; 6 | 7 | /** 8 | * 提供registry工具类 9 | * @author justdebugit@gmail.com 10 | * 11 | */ 12 | public final class ZkRegistryUtils { 13 | private ZkRegistryUtils(){} 14 | 15 | /** 16 | * 即便session丢失,重连时会重新注册 17 | */ 18 | public static void registerWithGuaranteed(final Registry registry,final String path,final byte[] bytes){ 19 | registry.register(path,bytes); 20 | registry.subscribe(path, new ChangeListener() { 21 | 22 | @Override 23 | public void onChange(NodeEvent event) { 24 | switch (event.getType()) { 25 | case NODE_CHANAGED: 26 | if (event.getData()==null) { 27 | registry.register(path, bytes); 28 | } 29 | break; 30 | default: 31 | break; 32 | } 33 | } 34 | }); 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/main/thrift/user.thrift: -------------------------------------------------------------------------------- 1 | namespace java com.justdebugit.thrift.generated 2 | 3 | 4 | enum UserSource { 5 | WEIBO = 1, 6 | QQ = 2, 7 | WEIXIN = 3, 8 | RENREN = 4 9 | } 10 | 11 | struct UserInfo { 12 | 1: i32 uid, 13 | 2: optional string name, 14 | 3: optional double score, 15 | 4: optional UserSource source 16 | } 17 | 18 | service UserRepoService { 19 | UserInfo get(1: i32 uid), 20 | //注册用户 21 | void put(1: i32 uid,2: UserInfo info) 22 | 23 | } -------------------------------------------------------------------------------- /src/main/thrift/userManager.thrift: -------------------------------------------------------------------------------- 1 | include "user.thrift" 2 | 3 | namespace java com.justdebugit.thrift.generated 4 | 5 | const i32 INT32CONSTANT = 9853 6 | const list BLACK_LIST = {10,11,12} 7 | 8 | enum Category { 9 | COLLEAGUE = 1, 10 | CLASSMATE = 2, 11 | FAMILY = 3 12 | } 13 | 14 | struct Friend { 15 | 1: i32 uid, 16 | 2: optional user.UserInfo userInfo, 17 | 3: optional Category cat = Category.CLASSMATE, 18 | 4: optional string beizhu 19 | } 20 | 21 | exception DifferentSourceDetectedException { 22 | 1: i32 uid1, 23 | 2: i32 uid2, 24 | 2: string msg 25 | } 26 | 27 | service UserManagerService extends user.UserRepoService { 28 | 29 | //获取我的好友列表 30 | list getMyFriends(1:i32 uid), 31 | 32 | //拉黑 33 | oneway void defriend(1:i32 uid,2:i32 uid), 34 | 35 | //添加好友 36 | bool addfriend(1:i32 uid, 2:i32 uid), 37 | 38 | //好友PK 39 | i32 compare(1:i32 uid, 2:i32 uid) throws (1:DifferentSourceDetectedException dsde) 40 | 41 | } 42 | 43 | -------------------------------------------------------------------------------- /src/test/java/com/justdebugit/thrift/example/raw/BlackServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.example.raw; 2 | import org.apache.thrift.TException; 3 | 4 | import com.justdebugit.thrift.generated.*; 5 | public class BlackServiceImpl implements BlackService.Iface { 6 | 7 | @Override 8 | public boolean isBlack(int uid) throws TException { 9 | return userManagerConstants.BLACKLIST.contains(uid); 10 | } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/com/justdebugit/thrift/example/raw/BlackServiceStub.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.example.raw; 2 | 3 | import java.io.IOException; 4 | 5 | import org.apache.thrift.TException; 6 | import org.apache.thrift.protocol.TCompactProtocol; 7 | import org.apache.thrift.protocol.TMultiplexedProtocol; 8 | import org.apache.thrift.transport.TFramedTransport; 9 | import org.apache.thrift.transport.TSocket; 10 | import org.apache.thrift.transport.TTransportException; 11 | 12 | import com.justdebugit.thrift.generated.BlackService; 13 | 14 | 15 | 16 | public class BlackServiceStub implements BlackService.Iface{ 17 | private final BlackService.Client client ; 18 | 19 | public BlackServiceStub(String host,int port) throws IOException, TTransportException{ 20 | TFramedTransport transport = new TFramedTransport(new TSocket(host, 21 | port)); 22 | transport.open(); 23 | client = new BlackService.Client(new TMultiplexedProtocol(new TCompactProtocol(transport), "blackService")); 24 | } 25 | 26 | @Override 27 | public boolean isBlack(int uid) throws TException { 28 | return client.isBlack(uid); 29 | } 30 | 31 | 32 | 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/justdebugit/thrift/example/raw/RawThriftClientExample.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.example.raw; 2 | 3 | import java.io.IOException; 4 | 5 | import org.apache.thrift.TException; 6 | 7 | /** 8 | * Hello world! 9 | * 10 | */ 11 | public class RawThriftClientExample 12 | { 13 | public static void main( String[] args ) throws IOException, TException, InterruptedException 14 | { 15 | final BlackServiceStub blackServiceStub = new BlackServiceStub("127.0.0.1",8080); 16 | System.out.println(blackServiceStub.isBlack(11)); 17 | final UserManagerServiceStub userManagerServiceStub = new UserManagerServiceStub("127.0.0.1", 8080); 18 | userManagerServiceStub.addfriend(2, 3); 19 | userManagerServiceStub.compare(1, 2); 20 | userManagerServiceStub.defriend(2, 1); 21 | System.out.println(userManagerServiceStub.get(2)); 22 | System.out.println(userManagerServiceStub.getMyFriends(2)); 23 | Thread.sleep(Integer.MAX_VALUE); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/com/justdebugit/thrift/example/raw/RawThriftServerExample.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.example.raw; 2 | 3 | import java.util.Map; 4 | import java.util.concurrent.Executors; 5 | 6 | import org.apache.thrift.TMultiplexedProcessor; 7 | import org.apache.thrift.TProcessor; 8 | import org.apache.thrift.protocol.TCompactProtocol; 9 | import org.apache.thrift.server.TThreadedSelectorServer; 10 | import org.apache.thrift.transport.TFramedTransport; 11 | import org.apache.thrift.transport.TNonblockingServerSocket; 12 | import org.apache.thrift.transport.TTransportException; 13 | 14 | import com.google.common.collect.ImmutableMap; 15 | import com.justdebugit.thrift.generated.BlackService; 16 | import com.justdebugit.thrift.generated.UserManagerService; 17 | 18 | public class RawThriftServerExample { 19 | public static void main(String[] argsa) throws TTransportException { 20 | final Map defaultMap = ImmutableMap 21 | . of("blackService", 22 | new BlackService.Processor( 23 | new BlackServiceImpl()), "userService", 24 | new UserManagerService.Processor( 25 | new UserManagerServiceImpl())); 26 | TMultiplexedProcessor tMultiplexedProcessor = new TMultiplexedProcessor(); 27 | TNonblockingServerSocket socket = new TNonblockingServerSocket(8080); 28 | TThreadedSelectorServer.Args args = new TThreadedSelectorServer.Args(socket); 29 | args.executorService(Executors.newFixedThreadPool(20)); 30 | args.protocolFactory(new TCompactProtocol.Factory()); 31 | args.processor(tMultiplexedProcessor); 32 | args.transportFactory(new TFramedTransport.Factory()); 33 | TThreadedSelectorServer server = new TThreadedSelectorServer(args); 34 | for (Map.Entry entry : defaultMap.entrySet()) { 35 | tMultiplexedProcessor.registerProcessor(entry.getKey(), entry.getValue()); 36 | } 37 | server.serve(); 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/com/justdebugit/thrift/example/raw/UserManagerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.example.raw; 2 | 3 | import java.util.Set; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | import java.util.concurrent.ConcurrentMap; 6 | 7 | import org.apache.thrift.TException; 8 | 9 | import com.google.common.base.Objects; 10 | import com.google.common.collect.Sets; 11 | import com.justdebugit.thrift.generated.DifferentSourceDetectedException; 12 | import com.justdebugit.thrift.generated.UserInfo; 13 | import com.justdebugit.thrift.generated.UserManagerService; 14 | 15 | public class UserManagerServiceImpl implements UserManagerService.Iface{ 16 | //所有注册用户 17 | static ConcurrentMap map = new ConcurrentHashMap(); 18 | static ConcurrentMap> friendsMap = new ConcurrentHashMap>(); 19 | static{ 20 | UserInfo userInfo = new UserInfo(1); 21 | userInfo.score = 10.2; 22 | StringBuilder stringBuilder = new StringBuilder(); 23 | for (int i = 0; i < 10000; i++) { 24 | stringBuilder.append("a"); 25 | } 26 | userInfo.name = stringBuilder.toString(); 27 | UserInfo userInfo2 = new UserInfo(userInfo); 28 | userInfo2.setName("test2"); 29 | userInfo2.setUid(2); 30 | UserInfo userInfo3 = new UserInfo(userInfo); 31 | userInfo3.setUid(3); 32 | userInfo3.setName("test3"); 33 | map.put(1, userInfo); 34 | map.put(2, userInfo2); 35 | map.put(3, userInfo3); 36 | friendsMap.put(1, Sets.newHashSet(userInfo2,userInfo3)); 37 | friendsMap.put(2, Sets.newHashSet(userInfo)); 38 | } 39 | 40 | @Override 41 | public UserInfo get(int uid) throws TException { 42 | return map.get(uid); 43 | } 44 | 45 | @Override 46 | public void put(int uid, UserInfo info) throws TException { 47 | map.put(uid, info); 48 | 49 | } 50 | 51 | @Override 52 | public Set getMyFriends(int uid) throws TException { 53 | return friendsMap.get(uid); 54 | } 55 | 56 | @Override 57 | public void defriend(int uid1, int uid2) throws TException { 58 | Set list = friendsMap.get(uid1); 59 | if (list!=null) { 60 | synchronized (list) { 61 | UserInfo info = map.get(uid2); 62 | if (info==null) { 63 | throw new TException("user "+uid2 +" is not exist"); 64 | } 65 | list.remove(info); 66 | } 67 | } 68 | } 69 | 70 | @Override 71 | public boolean addfriend(int uid1, int uid2) throws TException { 72 | Set list = friendsMap.get(uid1); 73 | if (list!=null) { 74 | synchronized (list) { 75 | UserInfo info = map.get(uid2); 76 | if (info==null) { 77 | throw new TException("user "+uid2 +" is not exist"); 78 | } 79 | list.add(info); 80 | } 81 | }else { 82 | friendsMap.putIfAbsent(uid1, Sets.newHashSet()); 83 | return false; 84 | } 85 | return true; 86 | } 87 | 88 | @Override 89 | public int compare(int uid1, int uid2) 90 | throws DifferentSourceDetectedException, TException { 91 | UserInfo userInfo1 = map.get(uid1); 92 | UserInfo userInfo2 = map.get(uid2); 93 | if (userInfo1==null||userInfo2==null) { 94 | throw new TException("user not found"); 95 | } 96 | if (!Objects.equal(userInfo1.getSource(), userInfo2.getSource())) { 97 | throw new DifferentSourceDetectedException(uid1, uid2, "not same source"); 98 | } 99 | return userInfo1.getScore() > userInfo2.getScore()?uid1:uid2; 100 | } 101 | 102 | 103 | } 104 | -------------------------------------------------------------------------------- /src/test/java/com/justdebugit/thrift/example/raw/UserManagerServiceStub.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.example.raw; 2 | 3 | import java.io.IOException; 4 | import java.util.Set; 5 | 6 | import org.apache.thrift.TException; 7 | import org.apache.thrift.protocol.TCompactProtocol; 8 | import org.apache.thrift.protocol.TMultiplexedProtocol; 9 | import org.apache.thrift.transport.TFramedTransport; 10 | import org.apache.thrift.transport.TSocket; 11 | import org.apache.thrift.transport.TTransportException; 12 | 13 | import com.justdebugit.thrift.generated.DifferentSourceDetectedException; 14 | import com.justdebugit.thrift.generated.UserInfo; 15 | import com.justdebugit.thrift.generated.UserManagerService; 16 | 17 | public class UserManagerServiceStub implements UserManagerService.Iface{ 18 | 19 | private final UserManagerService.Client client ; 20 | 21 | 22 | public UserManagerServiceStub(String host,int port) throws IOException, TTransportException { 23 | TFramedTransport transport = new TFramedTransport(new TSocket(host, 24 | port)); 25 | transport.open(); 26 | client = new UserManagerService.Client(new TMultiplexedProtocol(new TCompactProtocol(transport), "userService")); 27 | } 28 | 29 | @Override 30 | public UserInfo get(int uid) { 31 | try { 32 | return client.get(uid); 33 | } catch (TException e) { 34 | e.printStackTrace(); 35 | return null; 36 | } 37 | } 38 | 39 | @Override 40 | public void put(int uid, UserInfo info) throws TException { 41 | client.put(uid, info); 42 | } 43 | 44 | @Override 45 | public Set getMyFriends(int uid) throws TException { 46 | return client.getMyFriends(uid); 47 | } 48 | 49 | @Override 50 | public void defriend(int uid1, int uid2) throws TException { 51 | client.defriend(uid1, uid2); 52 | } 53 | 54 | @Override 55 | public boolean addfriend(int uid1, int uid2) throws TException { 56 | return client.addfriend(uid1, uid2); 57 | } 58 | 59 | @Override 60 | public int compare(int uid1, int uid2) 61 | throws DifferentSourceDetectedException, TException { 62 | return client.compare(uid1, uid2); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/com/justdebugit/thrift/example/thriftrpc/RpcConsumerMain.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.example.thriftrpc; 2 | 3 | import org.apache.thrift.TException; 4 | 5 | import com.google.common.collect.Lists; 6 | import com.justdebugit.thrift.common.ServiceConfig; 7 | import com.justdebugit.thrift.consumer.RpcConsumer; 8 | import com.justdebugit.thrift.consumer.RpcConsumerFactory; 9 | import com.justdebugit.thrift.generated.BlackService; 10 | import com.justdebugit.thrift.generated.UserManagerService; 11 | 12 | public class RpcConsumerMain { 13 | public static void main(String[] args) throws TException { 14 | ServiceConfig blacklistService = new ServiceConfig(); 15 | blacklistService.setServiceName("blackService") 16 | .setServiceClass(BlackService.class).setMinPoolSize(10); 17 | 18 | ServiceConfig userService = new ServiceConfig(); 19 | userService.setServiceName("userService").setServiceClass( 20 | UserManagerService.class); 21 | 22 | final RpcConsumer rpcConsumer = RpcConsumerFactory.newRpcConsumer( 23 | "127.0.0.1:2181", 24 | Lists.newArrayList(blacklistService, userService)); 25 | rpcConsumer.start(); 26 | 27 | final BlackService.Iface client = rpcConsumer 28 | .getService("blackService"); 29 | System.out.println(client.isBlack(11)); 30 | 31 | final UserManagerService.Iface userCliIface = rpcConsumer 32 | .getService("userService"); 33 | System.out.println(userCliIface.get(1)); 34 | 35 | Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 36 | 37 | @Override 38 | public void run() { 39 | rpcConsumer.stop(); 40 | } 41 | })); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/com/justdebugit/thrift/example/thriftrpc/RpcProviderMain.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.example.thriftrpc; 2 | 3 | import java.util.Map; 4 | 5 | import org.apache.thrift.TProcessor; 6 | 7 | import com.google.common.collect.ImmutableMap; 8 | import com.justdebugit.thrift.example.raw.BlackServiceImpl; 9 | import com.justdebugit.thrift.example.raw.UserManagerServiceImpl; 10 | import com.justdebugit.thrift.generated.BlackService; 11 | import com.justdebugit.thrift.generated.UserManagerService; 12 | import com.justdebugit.thrift.provider.RpcProvider; 13 | 14 | 15 | public class RpcProviderMain { 16 | public static void main(String[] args) { 17 | final Map processorMap = ImmutableMap 18 | . of( 19 | "blackService", 20 | new BlackService.Processor( 21 | new BlackServiceImpl()), 22 | "userService", 23 | new UserManagerService.Processor( 24 | new UserManagerServiceImpl())); 25 | final RpcProvider rpcProvider = RpcProvider.builder() 26 | .connectStringForzk("127.0.0.1:2181") 27 | .processorMap(processorMap).serverPort(8080).build(); 28 | Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { 29 | 30 | @Override 31 | public void run() { 32 | rpcProvider.stop(); 33 | 34 | } 35 | })); 36 | rpcProvider.start(); 37 | 38 | 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/com/justdebugit/thrift/example/thriftrpc/Test.java: -------------------------------------------------------------------------------- 1 | package com.justdebugit.thrift.example.thriftrpc; 2 | 3 | import com.justdebugit.thrift.generated.BlackService; 4 | 5 | 6 | public class Test { 7 | public static void main(String[] args) throws ClassNotFoundException { 8 | Class clazz = BlackService.class; 9 | Class.forName(clazz.getName()+"$"+"Client"); 10 | } 11 | 12 | } 13 | --------------------------------------------------------------------------------