package net.i2p.android.router.service;
import android.content.Context;
import net.i2p.BOB.BOB;
import net.i2p.I2PAppContext;
import net.i2p.addressbook.DaemonThread;
import net.i2p.android.apps.NewsFetcher;
import net.i2p.android.router.util.Notifications;
import net.i2p.android.router.util.Util;
import net.i2p.i2ptunnel.TunnelControllerGroup;
import net.i2p.router.Job;
import net.i2p.router.JobImpl;
import net.i2p.router.RouterContext;
import net.i2p.util.I2PAppThread;
import java.io.IOException;
/**
* Load the clients we want.
*
* We can't use LoadClientAppsJob (reading in clients.config) directly
* because Class.forName() needs a PathClassLoader argument -
* http://doandroids.com/blogs/2010/6/10/android-classloader-dynamic-loading-of/
* ClassLoader cl = new PathClassLoader(_apkPath, ClassLoader.getSystemClassLoader());
*
* We can't extend LoadClientAppsJob to specify a class loader,
* even if we use it only for Class.forName() and not for
* setContextClassLoader(), because I2PTunnel still
* can't find the existing static RouterContext due to the new class loader.
*
* Also, if we load them that way, we can't register a shutdown hook.
*
* So fire off the ones we want here, without a clients.config file and
* without using Class.forName().
*
*/
class LoadClientsJob extends JobImpl {
private Context mCtx;
private Notifications _notif;
private DaemonThread _addressbook;
private BOB _bob;
/** this is the delay to load (and start) the clients. */
private static final long LOAD_DELAY = 90*1000;
public LoadClientsJob(Context ctx, RouterContext rCtx, Notifications notif) {
super(rCtx);
mCtx = ctx;
_notif = notif;
getTiming().setStartAfter(getContext().clock().now() + LOAD_DELAY);
}
public String getName() { return "Start Clients"; }
public void runJob() {
Job j = new RunI2PTunnel(getContext());
getContext().jobQueue().addJob(j);
Thread t = new I2PAppThread(new StatSummarizer(), "StatSummarizer", true);
t.setPriority(Thread.NORM_PRIORITY - 1);
t.start();
NewsFetcher fetcher = NewsFetcher.getInstance(mCtx, getContext(), _notif);
t = new I2PAppThread(fetcher, "NewsFetcher", true);
t.start();
_addressbook = new DaemonThread(new String[] {"addressbook"});
_addressbook.setName("Addressbook");
_addressbook.setDaemon(true);
_addressbook.start();
// add other clients here
_bob = new BOB(I2PAppContext.getGlobalContext(), null, new String[0]);
try {
_bob.startup();
} catch (IOException ioe) {}
getContext().addShutdownTask(new ClientShutdownHook());
}
private class RunI2PTunnel extends JobImpl {
public RunI2PTunnel(RouterContext ctx) {
super(ctx);
}
public String getName() { return "Start I2P Tunnel"; }
public void runJob() {
Util.d("Starting i2ptunnel");
TunnelControllerGroup tcg = TunnelControllerGroup.getInstance();
try {
tcg.startup();
int sz = tcg.getControllers().size();
Util.d("i2ptunnel started " + sz + " clients");
} catch (IllegalArgumentException iae) {
Util.e("i2ptunnel failed to start", iae);
}
}
}
private class ClientShutdownHook implements Runnable {
public void run() {
Util.d("client shutdown hook");
// i2ptunnel registers its own hook
// StatSummarizer registers its own hook
// NewsFetcher registers its own hook
if (_bob != null)
_bob.shutdown(null);
if (_addressbook != null)
_addressbook.halt();
}
}
}