/**
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.airavata.api.server.util;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.thrift.TServiceClient;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ThriftClientPool<T extends TServiceClient> implements
AutoCloseable {
private static final Logger LOGGER = LoggerFactory
.getLogger(ThriftClientPool.class);
private final GenericObjectPool internalPool;
public ThriftClientPool(ClientFactory<T> clientFactory,
GenericObjectPool.Config poolConfig, String host, int port) {
this(clientFactory, new BinaryOverSocketProtocolFactory(host, port),
poolConfig);
}
public ThriftClientPool(ClientFactory<T> clientFactory,
ProtocolFactory protocolFactory, GenericObjectPool.Config poolConfig) {
this.internalPool = new GenericObjectPool(new ThriftClientFactory(
clientFactory, protocolFactory), poolConfig);
}
class ThriftClientFactory extends BasePoolableObjectFactory {
private ClientFactory<T> clientFactory;
private ProtocolFactory protocolFactory;
public ThriftClientFactory(ClientFactory<T> clientFactory,
ProtocolFactory protocolFactory) {
this.clientFactory = clientFactory;
this.protocolFactory = protocolFactory;
}
@Override
public T makeObject() throws Exception {
try {
TProtocol protocol = protocolFactory.make();
return clientFactory.make(protocol);
} catch (Exception e) {
LOGGER.warn(e.getMessage(), e);
throw new ThriftClientException(
"Can not make a new object for pool", e);
}
}
public void destroyObject(T obj) throws Exception {
if (obj.getOutputProtocol().getTransport().isOpen()) {
obj.getOutputProtocol().getTransport().close();
}
if (obj.getInputProtocol().getTransport().isOpen()) {
obj.getInputProtocol().getTransport().close();
}
}
}
public static interface ClientFactory<T> {
T make(TProtocol tProtocol);
}
public static interface ProtocolFactory {
TProtocol make();
}
public static class BinaryOverSocketProtocolFactory implements
ProtocolFactory {
private String host;
private int port;
public BinaryOverSocketProtocolFactory(String host, int port) {
this.host = host;
this.port = port;
}
public TProtocol make() {
TTransport transport = new TSocket(host, port);
try {
transport.open();
} catch (TTransportException e) {
LOGGER.warn(e.getMessage(), e);
throw new ThriftClientException("Can not make protocol", e);
}
return new TBinaryProtocol(transport);
}
}
public static class ThriftClientException extends RuntimeException {
// Fucking Eclipse
private static final long serialVersionUID = -2275296727467192665L;
public ThriftClientException(String message, Exception e) {
super(message, e);
}
}
public T getResource() {
try {
return (T) internalPool.borrowObject();
} catch (Exception e) {
throw new ThriftClientException(
"Could not get a resource from the pool", e);
}
}
public void returnResourceObject(T resource) {
try {
internalPool.returnObject(resource);
} catch (Exception e) {
throw new ThriftClientException(
"Could not return the resource to the pool", e);
}
}
public void returnBrokenResource(T resource) {
returnBrokenResourceObject(resource);
}
public void returnResource(T resource) {
returnResourceObject(resource);
}
protected void returnBrokenResourceObject(T resource) {
try {
internalPool.invalidateObject(resource);
} catch (Exception e) {
throw new ThriftClientException(
"Could not return the resource to the pool", e);
}
}
public void destroy() {
close();
}
public void close() {
try {
internalPool.close();
} catch (Exception e) {
throw new ThriftClientException("Could not destroy the pool", e);
}
}
}