package org.limewire.http.webservice;
import java.io.File;
import java.util.HashMap;
import org.jruby.rack.rails.RailsServletContextListener;
import org.limewire.core.api.library.LibraryManager;
import org.limewire.core.api.search.SearchManager;
import org.limewire.core.settings.ConnectionSettings;
import org.limewire.inject.EagerSingleton;
import org.limewire.io.NetworkUtils;
import org.limewire.core.impl.download.CoreDownloadListManager;
import org.limewire.core.impl.download.DownloadListenerList;
import org.mortbay.cometd.AbstractBayeux;
import org.mortbay.cometd.continuation.ContinuationCometdServlet;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.servlet.Context;
import org.mortbay.jetty.servlet.DefaultServlet;
import org.mortbay.jetty.servlet.ServletHolder;
import org.mortbay.servlet.ProxyServlet;
import org.mortbay.thread.QueuedThreadPool;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;
import com.limegroup.gnutella.NetworkManager;
import com.limegroup.gnutella.UPnPManager;
@EagerSingleton
public
class WebServiceManagerImpl implements WebServiceManager {
private final Provider<UPnPManager> upnpManager;
private NetworkManager networkManager;
private int _port = 4422;
private String status = "stopped";
private Injector injector;
private SearchManager searchManager;
private CoreDownloadListManager downloadManager;
private DownloadListenerList downloadListenerList;
private LibraryManager libraryManager;
@Inject
public WebServiceManagerImpl(Provider<UPnPManager> upnpManager,
NetworkManager networkManager, Injector injector, SearchManager searchManager,
CoreDownloadListManager downloadManager, DownloadListenerList downloadListenerList,
LibraryManager libraryManager) {
this.upnpManager = upnpManager;
this.networkManager = networkManager;
this.injector = injector;
this.searchManager = searchManager;
this.downloadManager = downloadManager;
this.downloadListenerList = downloadListenerList;
this.libraryManager = libraryManager;
}
@Override
public String getServiceName() {
return org.limewire.i18n.I18nMarker.marktr("WebService Manager");
}
@Override
public void start() {
if(!this.isServerRunning()) {
System.out.println("Starting mongrel...");
setStatus("starting");
// Try to port forward incoming traffic to our server via UPnP
mapPort();
String railsRoot = findRailsPath();
if(railsRoot != null) {
loadWebService(railsRoot);
setStatus("started");
} else {
System.out.println("Could not find rails root");
}
}
}
private String findRailsPath() {
String usablePath = null;
String[] loadPaths = {
"../../../../..",
"./rails"
};
// Look through the paths to find one
for(String path : loadPaths) {
File file = new File(path);
if(file.exists()) {
usablePath = path;
}
};
return usablePath;
}
public void loadWebService(String railsRoot) {
System.out.println("Jetty starting.");
Server server = new Server(4422);
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMinThreads(1);
threadPool.setMaxThreads(10);
server.setThreadPool(threadPool);
SelectChannelConnector connector = new SelectChannelConnector();
connector.setPort(4422);
Context context = new Context(null, "/", Context.NO_SESSIONS);
context.addFilter("org.jruby.rack.RackFilter", "/*", Handler.DEFAULT);
context.setResourceBase(railsRoot);
context.addEventListener(new RailsServletContextListener());
ProxyServlet.Transparent proxyServlet = new ProxyServlet.Transparent("", "ayce-test.ath.cx", 80);
ServletHolder proxyServletHolder = setupProxyServletHolder(proxyServlet);
context.addServlet(proxyServletHolder, "/ayce/*");
ContinuationCometdServlet cometdServlet = new ContinuationCometdServlet();
ServletHolder cometdServletHolder = setupCometdServletHolder(cometdServlet);
context.addServlet(cometdServletHolder, "/comet/*");
PartialDownloadStreamServlet partialDownloadStreamServlet = new PartialDownloadStreamServlet(this.downloadManager, this.searchManager, this.libraryManager);
ServletHolder streamServletHolder = new ServletHolder(partialDownloadStreamServlet);
context.addServlet(streamServletHolder, "/stream/*");
HashMap<String, String> options = new HashMap<String, String>();
options.put("rails.root", ".");
options.put("public.root", "public");
options.put("environment", "development");
options.put("org.mortbay.jetty.servlet.Default.relativeResourceBase", "/public");
options.put("jruby.max.runtimes", "1");
context.setAttribute("injector", this.injector);
context.setInitParams(options);
context.addServlet(new ServletHolder(new DefaultServlet()), "/");
server.setHandler(context);
try {
server.start();
//server.join();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
AbstractBayeux bayeux = cometdServlet.getBayeux();
new CometMonitorService(bayeux);
new CometSearchService(bayeux, this.searchManager, this.libraryManager);
new CometDownloadService(bayeux, this.downloadManager, this.downloadListenerList);
}
private static ServletHolder setupCometdServletHolder(ContinuationCometdServlet cometdServlet) {
ServletHolder cometdHolder = new ServletHolder(cometdServlet);
cometdHolder.setInitParameter("timeout", "120000");
cometdHolder.setInitParameter("interval", "0");
cometdHolder.setInitParameter("maxInterval", "10000");
cometdHolder.setInitParameter("multiFrameInterval", "2000");
cometdHolder.setInitParameter("difectDeliver", "true");
cometdHolder.setInitParameter("logLevel", "10");
return cometdHolder;
}
private static ServletHolder setupProxyServletHolder(ProxyServlet proxyServlet) {
ServletHolder proxyHolder = new ServletHolder(proxyServlet);
proxyHolder.setInitParameter("timeout", "120000");
proxyHolder.setInitParameter("interval", "0");
proxyHolder.setInitParameter("maxInterval", "10000");
proxyHolder.setInitParameter("multiFrameInterval", "2000");
proxyHolder.setInitParameter("difectDeliver", "true");
proxyHolder.setInitParameter("logLevel", "10");
return proxyHolder;
}
public void mapPort() {
boolean natted = upnpManager.get().isNATPresent();
boolean validPort = NetworkUtils.isValidPort(_port);
boolean forcedIP = ConnectionSettings.FORCE_IP_ADDRESS.getValue() &&
!ConnectionSettings.UPNP_IN_USE.getValue();
if(natted && validPort && !forcedIP) {
byte[] externalAddress = networkManager.getExternalAddress();
System.out.println(_port);
System.out.println(externalAddress);
int usedPort = upnpManager.get().mapPort(_port, externalAddress);
System.out.println(usedPort);
}
}
public void stop() {
if(this.isServerRunning()) {
this.setStatus("stopping");
}
}
public void restart() {
if(this.isServerRunning()) {
this.stop();
}
this.start();
}
public Boolean isServerRunning() {
return this.getStatus() == "started" || this.getStatus() == "starting";
}
public synchronized String getStatus() {
return this.status;
}
public synchronized void setStatus(String status) {
System.out.println("setting status to " + status);
this.status = status;
}
@Override
public boolean isAsyncStop() {
return true;
}
}