package org.zbus.client.service;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.zbus.client.Broker;
import org.zbus.client.broker.SingleBroker;
import org.zbus.client.broker.SingleBrokerConfig;
import org.zbus.client.service.Scanner.Listener;
import org.zbus.client.service.Scanner.ScanInfo;
import org.zbus.common.Helper;
import org.zbus.common.logging.Logger;
import org.zbus.common.logging.LoggerFactory;
public class ServiceLoader {
private static final Logger log = LoggerFactory
.getLogger(ServiceLoader.class);
private Broker broker;
private ExecutorService executor = new ThreadPoolExecutor(4, 16, 120,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
public ServiceLoader(Broker broker) {
this.broker = broker;
}
public void loadServicesFromBasePath(String basePath) {
this.loadService(basePath);
List<File> dirs = getDirs(basePath);
for (File f : dirs) {
this.loadService(f.getAbsolutePath());
}
}
public void loadService(final ServiceProvider sp) {
executor.execute(new Runnable() {
@Override
public void run() {
ServiceConfig config = sp.getConfig();
if (config.getBroker() == null) {
config.setBroker(broker);
}
Service service = new Service(config);
service.start();
}
});
}
public void loadService(String servicePath) {
Scanner scanner = new ClassScanner();
scanner.addJarpath(servicePath);
log.info("load service from: " + servicePath);
final List<URL> urls = new ArrayList<URL>();
try {
urls.add(new URL("file:" + servicePath));
} catch (MalformedURLException e) {
log.error(e.getMessage(), e);
}
scanner.scanJar(new Listener() {
@Override
public void onScanned(ScanInfo info) {
try {
log.info(info.toString());
URL url = new URL("file:" + info.jarpath);
urls.add(url);
} catch (MalformedURLException e) {
log.error(e.getMessage(), e);
}
}
});
final ContainerClassLoader classLoader = new ContainerClassLoader(
urls.toArray(new URL[0]));
scanner.scanClass(new Listener() {
@Override
public void onScanned(ScanInfo info) {
try {
Class<?> clazz = classLoader.loadClass(info.className);
boolean isServiceProvider = false;
for (Class<?> inf : clazz.getInterfaces()) {
if (inf == ServiceProvider.class) {
isServiceProvider = true;
break;
}
}
if (!isServiceProvider)
return;
log.info("service class found: " + clazz);
final ServiceProvider sp = (ServiceProvider) clazz
.newInstance();
loadService(sp);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
});
}
public static List<File> getDirs(String basePath) {
List<File> dirs = new ArrayList<File>();
try {
File base = new File(basePath);
if (base.isDirectory() && base.exists()) {
for (File dir : base.listFiles()) {
if (dir.isDirectory() && dir.exists()) {
dirs.add(dir);
}
}
}
} catch (Throwable e) {
log.error(e.getMessage(), e);
}
return dirs;
}
public static void load(String serviceBase, String brokerAddress)
throws Exception {
if (serviceBase == null) {
log.warn("mssing serviceBase directory");
return;
}
File file = new File(serviceBase);
if (file.exists()) {
if (file.isDirectory()) {
log.info(">>>ServiceBase: " + file.getAbsolutePath());
SingleBrokerConfig config = new SingleBrokerConfig();
config.setBrokerAddress(brokerAddress);
Broker broker = new SingleBroker(config);
ServiceLoader serviceLoader = new ServiceLoader(broker);
serviceLoader.loadServicesFromBasePath(serviceBase);
}
} else {
log.warn("!!!ServiceBase not exist: " + file.getAbsolutePath());
}
}
public static void main(String[] args) throws Exception {
String serviceBase = Helper.option(args, "-serviceBase", null);
String brokerAddress = Helper
.option(args, "-broker", "127.0.0.1:15555");
load(serviceBase, brokerAddress);
}
}