package io.myweb;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import java.util.Collections;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import io.myweb.http.Method;
public class Service extends LocalService<WebContext> implements WebContext {
static final String ASSETS_CLASS_NAME = "io.myweb.MyAssetInfo";
static final String SERVICES_CLASS_NAME = "io.myweb.MyServices";
public static final String TAG = Service.class.getName();
private static List<Endpoint.Info> endpointList = new ArrayList<Endpoint.Info>();
private static List<Filter> filterList = new ArrayList<Filter>();
static {
addEndpointInfo(new Endpoint.Info(Method.GET, AppInfoEndpoint.SERVICES_JSON, AppInfoEndpoint.class));
addEndpointInfo(new Endpoint.Info(Method.GET, "/", AssetEndpoint.class));
try {
// run static initializers for generated classes
Class.forName(SERVICES_CLASS_NAME);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
filterList = Collections.unmodifiableList(filterList);
endpointList = Collections.unmodifiableList(endpointList);
}
// package access
static void addEndpointInfo(Endpoint.Info info) {
endpointList.add(info);
}
static void addFilter(Filter filter) {
filterList.add(filter);
}
private AssetLengthInfo assetLengthInfo;
private ExecutorService executorService;
private RequestProcessor requestProcessor;
private LocalServer localServer;
@Override
public Context getContext() {
return this;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "Received intent from server");
// We have to start listening on local socket
if (executorService == null) {
executorService = new ThreadPoolExecutor(2, 16, 60, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>(), ThreadFactories.newWorkerThreadFactory());
}
if (localServer == null || localServer.isClosed()) {
localServer = new LocalServer(this, executorService);
executorService.submit(localServer);
}
return android.app.Service.START_NOT_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "Creating myweb service");
if (requestProcessor == null) {
requestProcessor = new RequestProcessor(createEndpoints(), getFilters());
}
}
@Override
public void onDestroy() {
Log.d(TAG, "Destroying myweb service");
TempServiceConnection.terminateAll();
if (localServer != null) {
localServer.shutdown();
localServer = null;
}
if (executorService != null) {
executorService.shutdown();
executorService = null;
}
}
public Object bindService(ComponentName name) {
TempServiceConnection connection = TempServiceConnection.get(name.getClassName());
if (connection == null) connection = new TempServiceConnection(this, name, executorService);
return connection.getServiceObject(); // awaits connection
}
public List<Endpoint.Info> getEndpointInfos() {
return endpointList;
}
public List<Filter> getFilters() {
return filterList;
}
public AssetLengthInfo getAssetInfo() {
if (assetLengthInfo == null) {
try {
assetLengthInfo = (AssetLengthInfo) Class.forName(ASSETS_CLASS_NAME).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
return assetLengthInfo;
}
private List<? extends Endpoint> createEndpoints() {
List<Endpoint> list = new LinkedList<Endpoint>();
for (Endpoint.Info info: endpointList) {
try {
Endpoint ep = (Endpoint) info.getImplementingClass().getConstructor(WebContext.class).newInstance(this);
System.out.println(ep.httpMethod().toString()+" "+ep.originalPath()+" instantiated!");
list.add(ep);
} catch (Exception e) {
e.printStackTrace();
}
}
return list;
}
public RequestProcessor getRequestProcessor() {
return requestProcessor;
}
}