Created
August 20, 2013 17:43
-
-
Save gjb2048/6284708 to your computer and use it in GitHub Desktop.
RMI on the Raspberry Pi
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Pi RMI. | |
* © G J Barnard 2013 - Attribution-NonCommercial-ShareAlike 3.0 Unported - http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB. | |
*/ | |
package pirmi; | |
import java.rmi.Remote; | |
import java.rmi.RemoteException; | |
/** | |
* This interface defines the methods you want your server to provide as a | |
* service to the client. | |
* | |
* The client will use it as it's RMI connection 'class' and the server | |
* will implement it. | |
* | |
* @author G J Barnard | |
*/ | |
public interface PiInfo extends Remote | |
{ | |
public static final String PIINFO_SERVICE = "PiInfoServer"; | |
public static final int RMIRegistryPort = 2024; | |
public static final int ServicePort = 2025; | |
public String getHostName(String client) throws RemoteException; | |
public String getJavaVersion(String client) throws RemoteException; | |
public PiTriInfo getOSDetails(String client) throws RemoteException; | |
public String getDataModel(String client) throws RemoteException; | |
public String getEndian(String client) throws RemoteException; | |
public PiTriInfo getUserDetails(String client) throws RemoteException; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Pi RMI. | |
* © G J Barnard 2013 - Attribution-NonCommercial-ShareAlike 3.0 Unported - http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB. | |
*/ | |
package pirmi; | |
import java.net.InetAddress; | |
import java.net.MalformedURLException; | |
import java.net.UnknownHostException; | |
import java.rmi.Naming; | |
import java.rmi.NotBoundException; | |
import java.rmi.RemoteException; | |
import java.rmi.UnmarshalException; | |
/** | |
* This is the client that connects to the server and service within using the | |
* details supplied. | |
* | |
* It does this by contacting the RMI Registry on the port it is running on | |
* with the name of the service it wishes to use. Therefore three items are | |
* required to be known beforehand: server name addressable name / IP address, | |
* RMI Registry port on the server and the name of the service. | |
* | |
* @author G J Barnard | |
*/ | |
public class PiInfoClient | |
{ | |
private PiInfo connection = null; | |
private static PiInfoClient instance = null; | |
private String client; | |
public static void main(String[] args) | |
{ | |
if (args.length == 1) | |
{ | |
PiInfoClient us = PiInfoClient.getInstance(); | |
us.reportPiInfo(args[0]); | |
} | |
else | |
{ | |
System.err.println("Usage: java -Djava.security.policy=\"./pirmi/Policy\" pirmi.PiInfoClient server name (or server IP)"); | |
} | |
} | |
private PiInfoClient() | |
{ | |
} | |
/** | |
* | |
*/ | |
private void reportPiInfo(String host) | |
{ | |
try | |
{ | |
connection = connectToServer(host); | |
String serverName = connection.getHostName(client); | |
System.out.println(serverName + "'s Java version is: " + connection.getJavaVersion(client)); | |
PiTriInfo osInfo = connection.getOSDetails(client); | |
System.out.println(serverName + "'s OS details are:"); | |
displayPiTriInfo(osInfo); | |
System.out.println(serverName + "'s data model is: " + connection.getDataModel(client)); | |
System.out.println(serverName + "'s endian is: " + connection.getEndian(client)); | |
PiTriInfo userInfo = connection.getUserDetails(client); | |
System.out.println(serverName + "'s User details are:"); | |
displayPiTriInfo(userInfo); | |
} | |
catch (Exception ex) | |
{ | |
ex.printStackTrace(System.err); | |
} | |
} | |
private void displayPiTriInfo(PiTriInfo info) | |
{ | |
PiPairInfo[] pair = new PiPairInfo[3]; | |
pair[0] = info.getOne(); | |
pair[1] = info.getTwo(); | |
pair[2] = info.getThree(); | |
for (byte i = 0; i <= 2; i++) | |
{ | |
System.out.println(" " + pair[i].getKey() + " is: " + pair[i].getValue()); | |
} | |
} | |
/** | |
* Gets us in the singleton pattern. | |
* | |
* @return Us | |
*/ | |
public static PiInfoClient getInstance() | |
{ | |
if (instance == null) | |
{ | |
instance = new PiInfoClient(); | |
} | |
return instance; | |
} | |
/** | |
* Attempt a connection to the server. | |
* | |
* @param connectionHost server addressable name or IP address. | |
* @return The connection. | |
* @throws UnknownHostException | |
* @throws NotBoundException | |
* @throws MalformedURLException | |
* @throws RemoteException | |
* @throws UnmarshalException | |
* @throws ClassNotFoundException | |
* @throws java.rmi.ConnectException | |
* @throws java.security.AccessControlException | |
*/ | |
private PiInfo connectToServer(String connectionHost) throws UnknownHostException, NotBoundException, MalformedURLException, RemoteException, UnmarshalException, ClassNotFoundException, java.rmi.ConnectException, java.security.AccessControlException | |
{ | |
try | |
{ | |
// Create and install a security manager. | |
if (System.getSecurityManager() == null) | |
{ | |
System.out.println("Creating new security manager"); | |
System.setSecurityManager(new SecurityManager()); | |
} | |
// Info. | |
client = InetAddress.getLocalHost().getHostName(); | |
System.out.println("Client is on " + client + " with Java version " + System.getProperty("java.version")); | |
/* | |
* This does the actual connection returning a reference to the | |
* server service if it suceeds. | |
*/ | |
connection = (PiInfo) Naming.lookup("rmi://" | |
+ connectionHost | |
+ ":" + PiInfo.RMIRegistryPort + "/" + PiInfo.PIINFO_SERVICE); | |
System.out.println("PiInfoClient:connectToServer - Connected to " + connectionHost + ":" + PiInfo.RMIRegistryPort + "/" + PiInfo.PIINFO_SERVICE); | |
} | |
catch (UnmarshalException ue) | |
{ | |
System.err.println("PiInfoClient:connectToServer() - UnmarshalException - Check that the server can access it's configuration / policy files"); | |
ue.printStackTrace(System.err); | |
throw ue; | |
} | |
return connection; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Pi RMI. | |
* © G J Barnard 2013 - Attribution-NonCommercial-ShareAlike 3.0 Unported - http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB. | |
*/ | |
package pirmi; | |
import java.rmi.RemoteException; | |
import java.rmi.registry.LocateRegistry; | |
import java.rmi.registry.Registry; | |
/** | |
* This is the server that creates / gets a registry for the client to ask | |
* where the service we will serve is. Some other examples have you running | |
* the registry on the command line, but this demonstrates a way of doing so | |
* within code, saving time. | |
* | |
* The registry needs to operate on one port and the service another. This is | |
* so that one registry can inform clients of lots of services running on their | |
* own ports. I have chosen to specify the port of the service, but you could | |
* let the virtual machine to do so. This is helpful if you are using a | |
* network packet sniffer like WireShark as you can then filter the capture by | |
* port. | |
* | |
* You could have the server implement the service too, but I have decided to | |
* separate it out for clarity. | |
* | |
* @author G J Barnard | |
*/ | |
public class PiInfoServer extends Thread | |
{ | |
private static PiInfoServer instance = null; | |
private PiInfoService piInfoServer = null; | |
/** | |
* Constructor. | |
* | |
* @throws RemoteException | |
*/ | |
private PiInfoServer() throws RemoteException | |
{ | |
super(); | |
} | |
/** | |
* @param args the command line arguments | |
*/ | |
public static void main(String[] args) | |
{ | |
PiInfoServer us = PiInfoServer.getInstance(); | |
us.createServer(); | |
} | |
/** | |
* Create the server. | |
*/ | |
public void createServer() | |
{ | |
// Create and install a security manager | |
if (System.getSecurityManager() == null) | |
{ | |
System.out.println("Creating new security manager"); | |
// http://download.oracle.com/javase/6/docs/api/java/rmi/RMISecurityManager.html | |
// states to use SecurityManager instead of RMISecurityManager. | |
System.setSecurityManager(new SecurityManager()); | |
} | |
try | |
{ | |
// Now we have the configuration loaded we can create the managers and use them. | |
piInfoServer = new PiInfoService(PiInfo.ServicePort); | |
// http://stackoverflow.com/questions/2142668/java-rmi-automating-in-an-ide | |
Registry r; | |
try | |
{ | |
r = LocateRegistry.createRegistry(PiInfo.RMIRegistryPort); | |
} | |
catch (java.rmi.server.ExportException ex) | |
{ | |
r = LocateRegistry.getRegistry(PiInfo.RMIRegistryPort); | |
} | |
System.out.println("Service attempts rebind of registry"); | |
r.rebind(PiInfo.PIINFO_SERVICE, piInfoServer); | |
System.out.println("Server bound in registry"); | |
System.out.println("Press Ctrl-C to exit."); | |
} | |
catch (java.rmi.server.ExportException ee) | |
{ | |
// Cannot get RMI port. | |
System.err.println("Server cannot use RMI port " + PiInfo.RMIRegistryPort + " as it is already in use, check that you are not running another instance of the server."); | |
ee.printStackTrace(System.err); | |
System.exit(-1); | |
} | |
catch (Exception e) | |
{ | |
System.err.println("Server err: " + e.getMessage()); | |
System.exit(-1); | |
} | |
} | |
/** | |
* Executed at shutdown in response to a Ctrl-C etc. | |
*/ | |
@Override | |
public void run() | |
{ | |
// Perform shutdown methods. | |
System.out.println("Server Shutting Down."); | |
} | |
/** | |
* Gets us in the singleton pattern. | |
* | |
* @return Us | |
*/ | |
public static PiInfoServer getInstance() | |
{ | |
if (instance == null) | |
{ | |
try | |
{ | |
instance = new PiInfoServer(); | |
// Prepare for shutdown... | |
Runtime.getRuntime().addShutdownHook(instance); | |
} | |
catch (RemoteException ex) | |
{ | |
System.err.println("PiInfoServer:getInstance() - " + ex.getMessage()); | |
} | |
} | |
return instance; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Pi RMI. | |
* © G J Barnard 2013 - Attribution-NonCommercial-ShareAlike 3.0 Unported - http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB. | |
*/ | |
package pirmi; | |
import java.net.InetAddress; | |
import java.net.UnknownHostException; | |
import java.rmi.RemoteException; | |
import java.rmi.server.UnicastRemoteObject; | |
/** | |
* This is the class that implements the service served by the server for the | |
* client. It extends UnicastRemoteObject - | |
* http://docs.oracle.com/javase/7/docs/api/java/rmi/server/UnicastRemoteObject.html | |
* - so that will serve RMI requests and therefore requires to be processed by | |
* the 'rmic' tool to create the 'stub'used by the client as the reference to | |
* the server - see: | |
* http://docs.oracle.com/javase/7/docs/technotes/tools/windows/rmic.html. | |
* | |
* @author G J Barnard | |
*/ | |
public class PiInfoService extends UnicastRemoteObject implements PiInfo | |
{ | |
public PiInfoService(int port) throws RemoteException | |
{ | |
super(port); | |
} | |
/* | |
* Methods to get the following: | |
* java.version | |
* os.arch | |
* os.name | |
* os.version | |
* sun.arch.data.model | |
* sun.cpu.endian | |
* user.name | |
* user.home | |
* user.dir | |
*/ | |
@Override | |
public PiTriInfo getOSDetails(String client) throws RemoteException | |
{ | |
System.out.println("PiInfoService:getOSDetails("+ client +") called."); | |
PiTriInfo info = new PiTriInfo( | |
new PiPairInfo("os.name", System.getProperty("os.name")), | |
new PiPairInfo("os.arch", System.getProperty("os.arch")), | |
new PiPairInfo("os.version", System.getProperty("os.version"))); | |
return info; | |
} | |
@Override | |
public String getDataModel(String client) throws RemoteException | |
{ | |
System.out.println("PiInfoService:getDataModel("+ client +") called."); | |
return System.getProperty("sun.arch.data.model"); | |
} | |
@Override | |
public String getJavaVersion(String client) throws RemoteException | |
{ | |
System.out.println("PiInfoService:getJavaVersion("+ client +") called."); | |
return System.getProperty("java.version"); | |
} | |
@Override | |
public String getEndian(String client) throws RemoteException | |
{ | |
return System.getProperty("sun.cpu.endian"); | |
} | |
@Override | |
public PiTriInfo getUserDetails(String client) throws RemoteException | |
{ | |
System.out.println("PiInfoService:getUserDetails("+ client +") called."); | |
PiTriInfo info = new PiTriInfo( | |
new PiPairInfo("user.name", System.getProperty("user.name")), | |
new PiPairInfo("user.home", System.getProperty("user.home")), | |
new PiPairInfo("user.dir", System.getProperty("user.dir"))); | |
return info; | |
} | |
@Override | |
public String getHostName(String client) throws RemoteException | |
{ | |
System.out.println("PiInfoService:getHostName("+ client +") called."); | |
try | |
{ | |
return InetAddress.getLocalHost().getHostName(); | |
} | |
catch (UnknownHostException ex) | |
{ | |
return "Unknown"; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Pi RMI. | |
* © G J Barnard 2013 - Attribution-NonCommercial-ShareAlike 3.0 Unported - http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB. | |
*/ | |
package pirmi; | |
import java.io.Serializable; | |
/** | |
* Wrapper class the key-value pairs found in system properties. Must be | |
* 'Serializable' so that it can be sent over a stream - i.e. RMI call. | |
* | |
* @author G J Barnard | |
*/ | |
public class PiPairInfo implements Serializable | |
{ | |
private String key, value; | |
public PiPairInfo(String key, String value) | |
{ | |
this.key = key; | |
this.value = value; | |
} | |
public String getKey() | |
{ | |
return key; | |
} | |
public String getValue() | |
{ | |
return value; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Pi RMI. | |
* © G J Barnard 2013 - Attribution-NonCommercial-ShareAlike 3.0 Unported - http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB. | |
*/ | |
package pirmi; | |
import java.io.Serializable; | |
/** | |
* Wrapper class for three PiPairInfo's. Must be 'Serializable' so that it can | |
* be sent over a stream - i.e. RMI call. | |
* | |
* @author G J Barnard | |
*/ | |
public class PiTriInfo implements Serializable | |
{ | |
private PiPairInfo one, two, three; | |
public PiTriInfo(PiPairInfo one, PiPairInfo two, PiPairInfo three) | |
{ | |
this.one = one; | |
this.two = two; | |
this.three = three; | |
} | |
public PiPairInfo getOne() | |
{ | |
return one; | |
} | |
public PiPairInfo getTwo() | |
{ | |
return two; | |
} | |
public PiPairInfo getThree() | |
{ | |
return three; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Pi RMI. | |
* © G J Barnard 2013 - Attribution-NonCommercial-ShareAlike 3.0 Unported - http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en_GB. | |
*/ | |
grant | |
{ | |
permission java.security.AllPermission; // AllPermission for simplicity here - see http://docs.oracle.com/javase/7/docs/technotes/guides/security/permissions.html. | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
java -Djava.security.policy="./pirmi/Policy" pirmi.PiInfoClient %1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
java -Djava.security.policy="./pirmi/Policy" pirmi.PiInfoClient $1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
java -Djava.rmi.server.hostname="Enter IP here" -Djava.security.policy="./pirmi/Policy" pirmi.PiInfoServer |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment