Added Absolute singleton to work around multiple classloader symptoms.
This commit is contained in:
@ -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
|
||||
|
@ -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/
|
||||
|
@ -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
10
src/java/.classpath
Normal 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
17
src/java/.project
Normal 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>
|
134
src/java/net/i2p/i2pcontrol/Example.java
Normal file
134
src/java/net/i2p/i2pcontrol/Example.java
Normal 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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
129
src/java/net/i2p/i2pcontrol/I2PControlManager.java
Normal file
129
src/java/net/i2p/i2pcontrol/I2PControlManager.java
Normal 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();
|
||||
}
|
||||
}
|
180
src/java/net/i2p/i2pcontrol/JSONRPCServlet.java
Normal file
180
src/java/net/i2p/i2pcontrol/JSONRPCServlet.java
Normal 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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
30
src/java/net/i2p/i2pcontrol/ManagerInterface.java
Normal file
30
src/java/net/i2p/i2pcontrol/ManagerInterface.java
Normal 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();
|
||||
|
||||
}
|
24
src/java/net/i2p/i2pcontrol/PassThroughProxyHandler.java
Normal file
24
src/java/net/i2p/i2pcontrol/PassThroughProxyHandler.java
Normal 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);
|
||||
}
|
||||
}
|
85
src/java/net/i2p/i2pcontrol/SecurityManager.java
Normal file
85
src/java/net/i2p/i2pcontrol/SecurityManager.java
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
35
src/java/net/i2p/i2pcontrol/Settings.java
Normal file
35
src/java/net/i2p/i2pcontrol/Settings.java
Normal 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";
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -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>
|
||||
|
@ -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>
|
||||
|
Reference in New Issue
Block a user