Added Absolute singleton to work around multiple classloader symptoms.

This commit is contained in:
dev
2011-06-16 08:59:41 +00:00
parent 571240e349
commit 435a667acb
15 changed files with 703 additions and 32 deletions

View File

@ -5,4 +5,4 @@ clientApp.0.stopargs=-d $PLUGIN stop
clientApp.0.delay=15
clientApp.0.startOnLoad=true
# we also use i2p.jar and i2ptunnel.jar, they are in the standard router classpath
clientApp.0.classpath=$PLUGIN/lib/I2PControl.jar,$I2P/lib/i2psnark.jar
clientApp.0.classpath=$PLUGIN/lib/I2PControl.jar

View File

@ -1,7 +1,7 @@
name=I2PControl
signer=dev@robertfoss.se
consoleLinkName=I2PControl
consoleLinkURL=http://127.0.0.1:7657/I2PControl/
consoleLinkURL=/I2PControl/
description=Remote Control Service
author=hottuna
websiteURL=http://XR1kDnLKSUO9lhZGmB9kq8a386yDXkgvqc~nCkfUMESL~XIUIYzXO6xkmbHHS6VANkAtapVPSb1x6iwA7S7BL1E9lnUwgBsK3Wzh9YpLVpYq2thFEWAI-mkUgrhcnSTn5VoetjR~Cv4sI7geDL4MsMEnmno5KKTwVJY6di3dJkzwKx4epjfs3KiCqizTqfLykc8KDitjQ~9-PvBUV9q79~reEsJ32AGSwGflV8a8S8OSv0Jw7V4AvljMLdIYD-FwVUCFHUHzqUcDSyEklmOQoYFxDc2fytx5v04H8YZH4Zp29tJq-O97lCx4TBZxyRaQnWcoE74D0ChTv8Y1~kRYwYloWbcya--XgvLgWbnGbOQZgFUpFc1OGhJFukgVHqTrj~S8DaC4Yv2~P7dcjItYZ12JBoq1wXbQN-ZP~BrOW9FJd7qP~AH4vT1MlstkOTxbIvhDVVY-fPvI7Wf~4IR5uwfeSO65luBpoMqlsNML4mTySv7TGkUVB51aVJkziEtDAAAA/

View File

@ -31,7 +31,7 @@
srcdir="./java"
debug="true" deprecation="on" source="1.5" target="1.5"
destdir="./build/obj"
classpath="${i2plib}/i2p.jar:${jettylib}/javax.servlet.jar" >
classpath="${i2plib}/i2p.jar:${jettylib}/javax.servlet.jar:${i2plib}/org.mortbay.jetty.jar" >
<compilerarg line="${javac.compilerargs}" />
</javac>
</target>

10
src/java/.classpath Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry exported="true" kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="/home/hottuna/Apps/i2p/lib/commons-logging.jar"/>
<classpathentry kind="lib" path="/home/hottuna/Apps/i2p/lib/i2p.jar"/>
<classpathentry kind="lib" path="/home/hottuna/Apps/i2p/lib/javax.servlet.jar"/>
<classpathentry kind="lib" path="/home/hottuna/Apps/i2p/lib/org.mortbay.jetty.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

17
src/java/.project Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>i2pcontrol</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,134 @@
package net.i2p.i2pcontrol;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
import java.text.*;
import java.util.*;
import javax.servlet.http.*;
/**
* Demonstration of the JSON-RPC 2.0 Server framework usage. The request
* handlers are implemented as static nested classes for convenience, but in
* real life applications may be defined as regular classes within their old
* source files.
*
* @author Vladimir Dzhuvinov
* @version 2011-03-05
*/
public class Example {
// Implements a handler for an "echo" JSON-RPC method
public static class EchoHandler implements RequestHandler {
// Reports the method names of the handled requests
public String[] handledRequests() {
return new String[]{"echo"};
}
// Processes the requests
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
if (req.getMethod().equals("echo")) {
// Echo first parameter
List params = (List)req.getParams();
Object input = params.get(0);
return new JSONRPC2Response(input, req.getID());
}
else {
// Method name not supported
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
}
}
}
// Implements a handler for "getDate" and "getTime" JSON-RPC methods
// that return the current date and time
public static class DateTimeHandler implements RequestHandler {
// Reports the method names of the handled requests
public String[] handledRequests() {
return new String[]{"getDate", "getTime"};
}
// Processes the requests
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
if (req.getMethod().equals("getDate")) {
DateFormat df = DateFormat.getDateInstance();
String date = df.format(new Date());
return new JSONRPC2Response(date, req.getID());
}
else if (req.getMethod().equals("getTime")) {
DateFormat df = DateFormat.getTimeInstance();
String time = df.format(new Date());
return new JSONRPC2Response(time, req.getID());
}
else {
// Method name not supported
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
}
}
}
public static void main(String[] args) {
// Create a new JSON-RPC 2.0 request dispatcher
Dispatcher dispatcher = new Dispatcher();
// Register the "echo", "getDate" and "getTime" handlers with it
dispatcher.register(new EchoHandler());
dispatcher.register(new DateTimeHandler());
// Simulate an "echo" JSON-RPC 2.0 request
List echoParam = new LinkedList();
echoParam.add("Hello world!");
JSONRPC2Request req = new JSONRPC2Request("echo", echoParam, "req-id-01");
System.out.println("Request: \n" + req);
JSONRPC2Response resp = dispatcher.dispatch(req, null);
System.out.println("Response: \n" + resp);
// Simulate a "getDate" JSON-RPC 2.0 request
req = new JSONRPC2Request("getDate", "req-id-02");
System.out.println("Request: \n" + req);
resp = dispatcher.dispatch(req, null);
System.out.println("Response: \n" + resp);
// Simulate a "getTime" JSON-RPC 2.0 request
req = new JSONRPC2Request("getTime", "req-id-03");
System.out.println("Request: \n" + req);
resp = dispatcher.dispatch(req, null);
System.out.println("Response: \n" + resp);
}
}

View File

@ -1,6 +1,6 @@
package net.i2p.i2pcontrol;
/*
* Copyright 2010 zzz (zzz@mail.i2p)
* Copyright 2010 hottuna (dev@robertfoss.se)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -16,23 +16,15 @@ package net.i2p.i2pcontrol;
*
*/
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.List;
import java.util.Properties;
import java.util.Date;
import net.i2p.I2PAppContext;
import net.i2p.data.Base32;
import net.i2p.data.DataHelper;
import net.i2p.data.Destination;
import net.i2p.data.PrivateKeyFile;
import net.i2p.util.FileUtil;
import net.i2p.util.I2PAppThread;
import net.i2p.util.Log;
import org.mortbay.http.handler.AbstractHttpHandler;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.servlet.ServletHttpContext;
/**
* This handles the starting and stopping of an eepsite tunnel and jetty
@ -41,20 +33,24 @@ import net.i2p.util.Log;
* This makes installation of a new eepsite a turnkey operation -
* the user is not required to configure a new tunnel in i2ptunnel manually.
*
* Usage: ZzzOTController -d $PLUGIN [start|stop]
* Usage: I2PControlController -d $PLUGIN [start|stop]
*
* @author zzz
* @author hottuna
*/
public class I2PControlController {
public class I2PControlController{
private static final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(I2PControlController.class);
private static Object _lock = new Object();
private static Server _server;
private static Settings _settings;
private static final int SERVER_PORT = 7658;
public static void main(String args[]) {
if (args.length != 3 || (!"-d".equals(args[0])))
throw new IllegalArgumentException("Usage: PluginController -d $PLUGIN [start|stop]");
if ("start".equals(args[2]))
if ("start".equals(args[2])){
start(args);
else if ("stop".equals(args[2]))
} else if ("stop".equals(args[2]))
stop();
else
throw new IllegalArgumentException("Usage: PluginController -d $PLUGIN [start|stop]");
@ -68,16 +64,45 @@ public class I2PControlController {
int ms = cal.get(Calendar.MILLISECOND);
return hour+":"+minute+":"+second+":"+ms;
}
private static void start(String args[]) {
File pluginDir = new File(args[1]);
/*File pluginDir = new File(args[1]);
if (!pluginDir.exists())
throw new IllegalArgumentException("Plugin directory " + pluginDir.getAbsolutePath() + " does not exist");
*/
_server = new Server();
try {
_server.addListener(Settings.getListenIP() +":" +Settings.getListenPort());
ServletHttpContext context = (ServletHttpContext) _server.getContext("/");
context.addServlet("/", "net.i2p.i2pcontrol.JSONRPCServlet");
//context.setClassLoader(Thread.currentThread().getContextClassLoader());
_server.start();
} catch (IOException e) {
_log.error("Unable to add listener " + Settings.getListenIP()+":"+Settings.getListenPort() + " - " + e.getMessage());
} catch (ClassNotFoundException e) {
_log.error("Unable to find class net.i2p.i2pcontrol.JSONRPCServlet: " + e.getMessage());
} catch (InstantiationException e) {
_log.error("Unable to instantiate class net.i2p.i2pcontrol.JSONRPCServlet: " + e.getMessage());
} catch (IllegalAccessException e) {
_log.error("Illegal access: " + e.getMessage());
} catch (Exception e) {
_log.error("Unable to start jetty server: " + e.getMessage());
}
}
private static void stop() {
// Maybe do things. Perhaps.
try {
if (_server != null)
_server.stop();
_server = null;
} catch (InterruptedException e) {
_log.error("Stopping server" + e);
}
}
}

View File

@ -0,0 +1,129 @@
package net.i2p.i2pcontrol;
/*
* Copyright 2010 hottuna (dev@robertfoss.se)
*
* Licensed 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.
*
*/
import java.lang.reflect.*;
/**
* There can be only one - ie. even if the class is loaded in several different classloaders,
* there will be only one instance of the object.
*/
public class I2PControlManager implements ManagerInterface{
private static StringBuilder _history;
/**
* This is effectively an instance of this class (although actually it may be instead a
* java.lang.reflect.Proxy wrapping an instance from the original classloader).
*/
public static ManagerInterface instance = null;
/**
* Retrieve an instance of AbsoluteSingleton from the original classloader. This is a true
* Singleton, in that there will only be one instance of this object in the virtual machine,
* even though there may be several copies of its class file loaded in different classloaders.
*/
public synchronized static ManagerInterface getInstance() {
ClassLoader myClassLoader = I2PControlManager.class.getClassLoader();
if (instance==null) {
// The root classloader is sun.misc.Launcher package. If we are not in a sun package,
// we need to get hold of the instance of ourself from the class in the root classloader.
if (! myClassLoader.toString().startsWith("sun.")) {
try {
// So we find our parent classloader
ClassLoader parentClassLoader = I2PControlManager.class.getClassLoader().getParent();
// And get the other version of our current class
Class otherClassInstance = parentClassLoader.loadClass(I2PControlManager.class.getName());
// And call its getInstance method - this gives the correct instance of ourself
Method getInstanceMethod = otherClassInstance.getDeclaredMethod("getInstance", new Class[] { });
Object otherAbsoluteSingleton = getInstanceMethod.invoke(null, new Object[] { } );
// But, we can't cast it to our own interface directly because classes loaded from
// different classloaders implement different versions of an interface.
// So instead, we use java.lang.reflect.Proxy to wrap it in an object that *does*
// support our interface, and the proxy will use reflection to pass through all calls
// to the object.
instance = (ManagerInterface) Proxy.newProxyInstance(myClassLoader,
new Class[] { ManagerInterface.class },
new PassThroughProxyHandler(otherAbsoluteSingleton));
// And catch the usual tedious set of reflection exceptions
// We're cheating here and just catching everything - don't do this in real code
} catch (Exception e) {
e.printStackTrace();
}
// We're in the root classloader, so the instance we have here is the correct one
} else {
instance = new I2PControlManager();
}
}
return instance;
}
private I2PControlManager() {
_history = new StringBuilder();
}
private String value = "";
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingleTonInterface#getValue()
*/
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingletonInterface#getValue()
*/
public String getValue() { return value; }
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingleTonInterface#setValue(java.lang.String)
*/
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingletonInterface#setValue(java.lang.String)
*/
public void setValue(String value) {
this.value = value;
}
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingleTonInterface#prependHistory(java.lang.String)
*/
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingletonInterface#prependHistory(java.lang.String)
*/
public void prependHistory(String str){
_history.insert(0,str + "<br>\n");
}
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingleTonInterface#appendHistory(java.lang.String)
*/
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingletonInterface#appendHistory(java.lang.String)
*/
public void appendHistory(String str){
_history.append("<br>\n" + str);
}
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingleTonInterface#getHistory()
*/
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingletonInterface#getHistory()
*/
public String getHistory(){
return _history.toString();
}
}

View File

@ -0,0 +1,180 @@
package net.i2p.i2pcontrol;
/*
* Copyright 2011 hottuna (dev@robertfoss.se)
*
* Licensed 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.
*
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import net.i2p.I2PAppContext;
import net.i2p.stat.RateStat;
import net.i2p.util.Log;
import com.thetransactioncompany.jsonrpc2.*;
import com.thetransactioncompany.jsonrpc2.server.*;
/**
* Provide an JSON-RPC 2.0 API for remote controlling of I2P
*/
public class JSONRPCServlet extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = -45075606818515212L;
private static final int BUFFER_LENGTH = 2048;
private static Dispatcher disp;
private static char[] readBuffer;
private static ManagerInterface _manager;
private static Log _log;
@Override
public void init(){
_log = I2PAppContext.getGlobalContext().logManager().getLog(JSONRPCServlet.class);
readBuffer = new char[BUFFER_LENGTH];
_manager = (ManagerInterface) I2PControlManager.getInstance();
disp = new Dispatcher();
disp.register(new EchoHandler());
disp.register(new StatHandler());
}
protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException
{
httpServletResponse.setContentType("text/html");
PrintWriter out = httpServletResponse.getWriter();
out.println("Nothing to see here");
}
protected void doPost(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException
{
String req = getRequest(httpServletRequest.getInputStream());
JSONRPC2Message msg = null;
JSONRPC2Response jsonResp = null;
try {
msg = JSONRPC2Message.parse(req);
if (msg instanceof JSONRPC2Request) {
jsonResp = disp.dispatch((JSONRPC2Request)msg, null);
_manager.prependHistory("Request: " + msg);
_manager.prependHistory("Response: " + jsonResp);
System.out.println("The message is a Request");
}
else if (msg instanceof JSONRPC2Notification) {
disp.dispatch((JSONRPC2Notification)msg, null);
_manager.prependHistory("Notification: " + msg);
System.out.println("The message is a Notification");
}
PrintWriter out = httpServletResponse.getWriter();
out.println("Response:"); // Delete me
out.println(jsonResp);
out.close();
} catch (JSONRPC2ParseException e) {
_log.error("Unable to parse JSONRPC2Message: " + e.getMessage());
}
}
private String getRequest(ServletInputStream sis) throws IOException{
Writer writer = new StringWriter();
BufferedReader reader = new BufferedReader(new InputStreamReader(sis,"UTF-8"));
int n;
while ((n = reader.read(readBuffer)) != -1) {
writer.write(readBuffer, 0, n);
}
return writer.toString();
}
// Implements a handler for an "echo" JSON-RPC method
public static class EchoHandler implements RequestHandler {
// Reports the method names of the handled requests
public String[] handledRequests() {
return new String[]{"echo"};
}
// Processes the requests
public JSONRPC2Response process(JSONRPC2Request req, MessageContext ctx) {
if (req.getMethod().equals("echo")) {
// Echo first parameter
List params = (List)req.getParams();
Object input = params.get(0);
return new JSONRPC2Response(input, req.getID());
}
else {
// Method name not supported
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
}
}
}
public static class StatHandler implements RequestHandler {
public String[] handledRequests() {
return new String[]{"getRate"};
}
@Override
public JSONRPC2Response process(JSONRPC2Request req,
MessageContext ctx) {
if (req.getMethod().equals("getRate")) {
List params = (List)req.getParams();
if (params.size()!=2)
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
String input;
long period;
try {
input = (String) params.get(0);
period = Long.parseLong((String) params.get(1));
} catch (NumberFormatException e){
return new JSONRPC2Response(JSONRPC2Error.PARSE_ERROR, req.getID());
}
RateStat rate = I2PAppContext.getGlobalContext().statManager().getRate(input);
// If RateStat or the requested period doesn't already exist, create them.s
if (rate == null || rate.getRate(period) == null){
long[] tempArr = new long[1];
tempArr[0] = period;
I2PAppContext.getGlobalContext().statManager().createRequiredRateStat(input, "I2PControl", "I2PControl", tempArr);
rate = I2PAppContext.getGlobalContext().statManager().getRate(input);
}
if (rate.getRate(period) == null)
return new JSONRPC2Response(JSONRPC2Error.INTERNAL_ERROR, req.getID());
return new JSONRPC2Response(rate.getRate(period).getAverageValue(), req.getID());
}
return new JSONRPC2Response(JSONRPC2Error.METHOD_NOT_FOUND, req.getID());
}
}
}

View File

@ -0,0 +1,30 @@
package net.i2p.i2pcontrol;
public interface ManagerInterface {
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingleTonInterface#getValue()
*/
public abstract String getValue();
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingleTonInterface#setValue(java.lang.String)
*/
public abstract void setValue(String value);
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingleTonInterface#prependHistory(java.lang.String)
*/
public abstract void prependHistory(String str);
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingleTonInterface#appendHistory(java.lang.String)
*/
public abstract void appendHistory(String str);
/* (non-Javadoc)
* @see net.i2p.i2pcontrol.SingleTonInterface#getHistory()
*/
public abstract String getHistory();
}

View File

@ -0,0 +1,24 @@
package net.i2p.i2pcontrol;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* An invocation handler that passes on any calls made to it directly to its delegate.
* This is useful to handle identical classes loaded in different classloaders - the
* VM treats them as different classes, but they have identical signatures.
*
* Note this is using class.getMethod, which will only work on public methods.
*/
class PassThroughProxyHandler implements InvocationHandler {
private final Object delegate;
public PassThroughProxyHandler(Object delegate) {
this.delegate = delegate;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Method delegateMethod = delegate.getClass().getMethod(method.getName(), method.getParameterTypes());
return delegateMethod.invoke(delegate, args);
}
}

View File

@ -0,0 +1,85 @@
package net.i2p.i2pcontrol;
/*
* Copyright 2011 hottuna (dev@robertfoss.se)
*
* Licensed 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.
*
*/
import java.io.File;
import net.i2p.I2PAppContext;
import net.i2p.crypto.HMAC256Generator;
import net.i2p.crypto.SHA256Generator;
import net.i2p.util.Log;
/**
* Manage the password storing for I2PControl.
*/
public class SecurityManager {
private final int HASH_ITERATIONS = 1000;
private static final String STORE_FILE = "security.store";
private static Log _log;
static {
_log = I2PAppContext.getGlobalContext().logManager().getLog(SecurityManager.class);
loadStore();
}
/**
* Load password store from default file.
*/
private static void loadStore(){
File store = new File(STORE_FILE);
if (!store.exists() && !store.canRead())
_log.debug("Security store, " + STORE_FILE + " doesn't exist or can't be read. Removing password.");
}
/**
* Save security store
*/
private void saveStore(){
}
/**
* Verifies password against what is stored
*/
public boolean verifyPassword(String pwd){
return false;
}
/**
* Overwrite old password with input
*/
public boolean overwritePassword(String pwd){
return false;
}
/**
* Hash input HASH_ITERATIONS times
* @return input hashed HASH_ITERATIONS times
*/
private String hashPassword(String pwd){
SHA256Generator hashGen = new SHA256Generator(I2PAppContext.getGlobalContext());
byte[] bytes = pwd.getBytes();
for (int i = 0; i < 1000; i++){
bytes = hashGen.calculateHash(bytes).toByteArray();
}
return new String(bytes);
}
}

View File

@ -0,0 +1,35 @@
package net.i2p.i2pcontrol;
/*
* Copyright 2011 hottuna (dev@robertfoss.se)
*
* Licensed 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.
*
*/
/**
* Manage settings for I2PControl
*/
public class Settings {
public static int getListenPort() {
// TODO Auto-generated method stub
return 7658;
}
public static String getListenIP() {
// TODO Auto-generated method stub
return "localhost";
}
}

View File

@ -2,7 +2,7 @@
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>I2PControl</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<!--<welcome-file>index.html</welcome-file>-->
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
@ -13,8 +13,7 @@
<servlet-mapping>
<servlet-name>index</servlet-name>
<url-pattern>/test</url-pattern>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

View File

@ -1,14 +1,17 @@
<%@page import="net.i2p.i2pcontrol.I2PControlController" %>
<%@page
import="net.i2p.i2pcontrol.*"
%>
<html>
<head>
<title>I2PControl</title>
</head><body style="background-color: #000; color: #c30; font-size: 400%;">
<h1>
</head><body style="background-color: #000; color: #c30; font-size: 250%;">
<h2>
I2PControl
</h1>
</h2>
<table cellspacing="8">
<tr><td>Status:<td align="right"><%=I2PControlController.getTestString()%>
<tr><td>Status again:<td align="right"><%=I2PControlController.getTestString()%>
<tr><td><h3>History:</h3><td align="right"><%
ManagerInterface _manager = I2PControlManager.getInstance();
out.print( _manager.getHistory() );
</table>
</body>
</html>