FTPClient connection with Java on AWS Virtual Machine - java

I'm trying to connect to my FTP server in Java SE 1.8. To do so I use this method :
private void connectFTP() {
String server = "ftp.XXXXXXXXXX.site";
int port = 21;
String user = "XXXX";
String pass = "XXXX";
if(!ftpConnexionSuccess.get())
{
client = new FTPClient();
client.configure(new FTPClientConfig(FTPClientConfig.SYST_UNIX));
try {
client.connect(server, port);
ftpConnexionSuccess.set(client.login(user, pass));
if (!ftpConnexionSuccess.get()) {
System.out.println("Could not login to the server");
return;
}
else
{
System.out.println("LOGGED IN SERVER");
client.changeWorkingDirectory("/crypto");
listenedFile = getListenedFile();
System.out.println(listenedFile.getName());
if(listenedFile != null)
{
baseFileTimeStamp.set(listenedFile.getTimestamp().getTimeInMillis());
}
System.out.println(baseFileTimeStamp);
}
} catch (Exception ex) {
System.err.println("FTP connection error : Sleeping for 5 seconds before trying again (" + ex.getMessage() + ")");
ex.printStackTrace();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {e.printStackTrace();}
try {
client.disconnect();
} catch (IOException e) {e.printStackTrace();}
connectFTP();
}
}
}
It works great when I'm on Eclipse and when I export the app on my Windows 10.
Nonetheless, when I try to launch the app on my AWS Webmachine I get a null pointer exception at "listenedFile". The method to listen to this file is the one below.
private FTPFile getListenedFile() {
FTPFile returnedFile = null;
try {
for(FTPFile file : client.listFiles())
{
if(file.getName().contains("filetolisten.txt"))
returnedFile = file;
}
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
try {
client.disconnect();
} catch (IOException e1) {e1.printStackTrace();}
connectFTP();
return getListenedFile();
}
return returnedFile;
}
I thought it was because of the line
client.configure(new FTPClientConfig(FTPClientConfig.SYST_UNIX));
I tried to delete the line, and to replace SYST_UNIX with SYST_NT, but nothing worked.
I tried to delete the line, and to replace SYST_UNIX with SYST_NT, but nothing worked. Also updated Java, updated the common-nets library. Nothing worked

Related

Java Card Connecting To a Simulator failed

I am trying to test a Java Card applet to establish a connection to a simulator such as cref:
try {
sckClient = new Socket("localhost", 9025);
InputStream is = sckClient.getInputStream();
OutputStream os = sckClient.getOutputStream();
cad = CadDevice.getCadClientInstance(CadDevice.PROTOCOL_T0, is, os);
} catch (Exception e) {
System.out.println("error");
return;
}
try {
cad.powerUp();
} catch (IOException e) {
e.printStackTrace();
} catch (CadTransportException e) {
System.out.println("error");
try {
sckClient.close();
} catch (IOException e1) {
e1.printStackTrace();
}
return;
}
My code get stuck in powerUp without any error or exception.
I am using the sample_device and sample_platform that comes with Java Card Development Kit 3.0.5u1

Jackcess DatabaseBuilder.open fails

I am using Jackcess API in my Eclipse plugin project. I added jackcess-2.1.0.jar file under resources/lib. I included the jar under my Binary build and in build.properties. I successfully make a connection using connection string but my DatabaseBuilder.open() call is not executing. My code is
public void run() {
try {
File tempTarget = File.createTempFile("eap-mirror", "eap");
try {
this.source = DriverManager.getConnection(EaDbStringParser.eaDbStringToJdbc(sourceString));
this.source.setReadOnly(true);
try {
FileUtils.copyFile(new File(templateFileString), tempTarget);
} catch (IOException e) {
e.printStackTrace();
}
// Changes
try {
this.target = DatabaseBuilder.open(tempTarget);
} catch (IOException e) {
e.printStackTrace();
}
Collection<String> tables = selectTables(source);
long time = System.currentTimeMillis();
for (String tableName : tables) {
long tTime = System.currentTimeMillis();
Table table = target.getTable(tableName);
System.out.print("Mirroring table " + tableName + "...");
table.setOverrideAutonumber(true);
copyTable(table, source, target);
System.out.println(" took "+ (System.currentTimeMillis() - tTime));
}
System.out.println("Done. Overall time: "+ (System.currentTimeMillis() - time));
System.out.println("done");
} catch (SQLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// More Code here
} catch (IOException e1) {
}
}
When I run the class in debug mode and I reach DatabaseBuilder.open call it fails.
Here is my project structure:
Can anyone tell me the possible reason for it ?
The .open method of DatabaseBuilder expects to open an existing well-formed Access database file. The .createTempFile method of java.io.File creates a 0-byte file. So, the code
File dbFile;
try {
dbFile = File.createTempFile("eap-mirror", "eap");
try (Database db = DatabaseBuilder.open(dbFile)) {
System.out.println(db.getFileFormat());
} catch (IOException ioe) {
ioe.printStackTrace(System.out);
}
} catch (Exception e) {
e.printStackTrace(System.out);
} finally {
System.out.println("Finally...");
}
will cause Jackcess to throw
java.io.IOException: Empty database file
when it tries to do DatabaseBuilder.open(dbFile).
Instead, you should DatabaseBuilder.create to convert the 0-byte file into a real Access database file like this
File dbFile;
try {
dbFile = File.createTempFile("eap-mirror", ".accdb");
dbFile.deleteOnExit();
try (Database db = DatabaseBuilder.create(Database.FileFormat.V2010, dbFile)) {
System.out.println(db.getFileFormat());
} catch (IOException ioe) {
ioe.printStackTrace(System.out);
}
} catch (Exception e) {
e.printStackTrace(System.out);
} finally {
System.out.println("Finally...");
}

error in connect to xmpp(openfire) server using java

I am new to XMPP. For a whole day I am stuck in connecting to my XMPP server (Openfire version 3.9.3) from Java. I am using the Smack (version 4.0.7) library. Here is simple code...
ConnectionConfiguration config =new ConnectionConfiguration("servername",5223);
XMPPTCPConnection connection = new XMPPTCPConnection(config);
// Connect to the server
try {
connection.connect();
connection.login("username", "password");
} catch (IOException e) {
e.printStackTrace();
} catch (XMPPException e) {
e.printStackTrace();
} catch (SmackException e) {
e.printStackTrace();
}
But when I run this code this error is showing ...
org.jivesoftware.smack.SmackException$NoResponseException
at org.jivesoftware.smack.XMPPConnection.throwConnectionExceptionOrNoResponse(XMPPConnection.java:548)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.throwConnectionExceptionOrNoResponse(XMPPTCPConnection.java:867)
at org.jivesoftware.smack.tcp.PacketReader.startup(PacketReader.java:113)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.initConnection(XMPPTCPConnection.java:482)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectUsingConfiguration(XMPPTCPConnection.java:440)
at org.jivesoftware.smack.tcp.XMPPTCPConnection.connectInternal(XMPPTCPConnection.java:811)
at org.jivesoftware.smack.XMPPConnection.connect(XMPPConnection.java:396)
at test.third.<init>(third.java:19)
at test.third.main(third.java:34)
There may be a silly mistake and easy solution. I googled but somehow I am not getting the right solution.
public void connectAndLogin( {
connect();
login();
}
private void connect() {
/**
* Set server configuration
*
* connect to server
*/
setConfiguration();
try {
getConnection().connect();
} catch (XMPPException e) {
e.printStackTrace();
setConnection(null);
}
}
private void setConfiguration() {
ConnectionConfiguration config = new ConnectionConfiguration(Constants.IP);
SmackConfiguration.setPacketReplyTimeout(Constants.PACKET_TIME_OUT);
System.out.println(SmackConfiguration.getVersion());
config.setRosterLoadedAtLogin(false);
// config.setCompressionEnabled(true);
config.setVerifyChainEnabled(false);
config.setReconnectionAllowed(true);
config.setSASLAuthenticationEnabled(false);
config.setSecurityMode(SecurityMode.disabled);
config.setDebuggerEnabled(false);
connection = new XMPPConnection(config);
}
private void login() {
if(getConnection()!=null){
String USER_NAME="";
String PASSWORD="";
try {
getConnection().login(USER_NAME,PASSWORD, Constants.RESOURCE);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Try using port 5222 instead of 5223. That's the old SSL way which isn't typically used anymore.

apache ftpclient retrievefile() downloading corrupted file

I am using org.apache.commons.net.ftp.FTPClient for downloading files from ftp server.
It downloads all the files from my ftp server except those files with names like test.xml test.txt west.xml etc., The files with these names are getting downloaded with no data inside the file. retrieveFile() method is returning boolean false for these files.
I tried to download the same file by renaming its name manually on ftp server. It worked well with other names.
Please let me know how to solve this problem.
EDIT- Adding sample code
public static boolean downloadFTPDir(String localDir, FTPClient ftpClient) {
OutputStream output = null;
try {
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
/*
* Use passive mode as default because most of us are behind
* firewalls these days.
*/
ftpClient.enterLocalPassiveMode();
FTPFile[] fileList = ftpClient.listFiles();
for (FTPFile ftpFile : fileList) {
if(ftpFile.isDirectory()){
String tempDir = localDir + File.separatorChar+ftpFile.getName();
try {
File temp = new File(tempDir);
temp.mkdirs();
} catch (Exception e) {
System.out.println("Could not create local directory "+tempDir);
return false;
}
if(ftpClient.changeWorkingDirectory(ftpFile.getName())) {
downloadFTPDir(tempDir, ftpClient);
} else {
System.out.println("Could change directory to "+ftpFile.getName()+" on FTP server");
return false;
}
} else {
output = new FileOutputStream(localDir + File.separatorChar + ftpFile.getName());
if (!ftpClient.retrieveFile(ftpFile.getName(), output)) {
System.out.println("Unable to download file from FTP server : " + ftpFile.getName());
File tmp = null;
try {
output.close();
/*tmp = new File(localDir + File.separatorChar + ftpFile.getName());
tmp.delete();
logger.info("Deleted corrupt downloaded file : " + tmp.getAbsolutePath());*/
} catch (FTPConnectionClosedException e) {
System.out.println("Connection to FTP server is closed ");
return false;
} catch (Exception e1) {
System.out.println("Unable to delete corrupt file from local directory : " + tmp.getAbsolutePath());
return false;
}
}
output.close();
System.out.println("FTP file download successful : " + ftpFile.getName());
}
}
} catch (FTPConnectionClosedException e) {
e.printStackTrace();
return false;
} catch (FileNotFoundException e1) {
e1.printStackTrace();
return false;
} catch (IOException e2) {
e2.printStackTrace();
return false;
} catch (Exception e3) {
try {
output.close();
} catch (Exception e4) {
e3.printStackTrace();
}
return false;
} finally{
try {
if(output!=null)
output.close();
} catch (Exception e5) {
e5.printStackTrace();
}
}
return true;
}
public static void main(String[] args) {
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect("FTP IP", 21);
System.out.println("connecting");
if(FTPReply.isPositiveCompletion(ftpClient.getReply())) {
System.out.println("connected");
if(!ftpClient.login("FTP username", "FTP Password")) {
System.out.println("could not login");
ftpClient.disconnect();
return;
}
System.out.println("logged in");
String remotePath = "FTP directory Path";
StringTokenizer st = new StringTokenizer(remotePath, "/");
String dir = null;
boolean status = false;
while (st.hasMoreTokens()) {
dir = st.nextToken();
status = ftpClient.changeWorkingDirectory(dir);
if (!status) {
System.out.println("FTP client is not able to change the current directory to " + dir);
return ;
}
}
System.out.println("connected");
downloadFTPDir("local path", ftpClient);
} else {
ftpClient.disconnect();
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

establishing communication between Java desktop app and Java browser applet via sockets

I'm new to network I/O programming, and I've run into a snag-- basically what I want to do is have a desktop app talk to the google maps javascript API. In order to facilitate this, I have built a java applet which will act as a bridge between the desktop app and the browser javascript app. When I run the desktop app and applet together in Eclipse they can communicate perfectly, and I am able to invoke applet functions by writing strings to a Socket bound to the same port the applet has established a ServerSocket connection with. For testing purposes in Eclipse, I send the string "sendJSAlertTest" to the socket's outputstream, then derive a Method instance using the java.lang.reflect API from the ServerSocket inputstream, and then finally invoke the resulting method in the applet. When the applet is running in a browser I write "sendJSAlert" to the socket instead since it leads to the actual invocation of javascript. The result in Eclipse using the appletviewer is that the desktop application context prints the output "awesome sendJSAlert" and the applet context prints the output from the sendJSAlertTest() method, "Hello Client, I'm a Server!". The result of passing "sendJSAlert" to the applet running in the browser is that the desktop application prints null, suggesting that for some reason the inputstream of the ServerSocket is empty, and the browser itself does nothing when it should generate a javascript alert box with the text "Hello Client, I'm a Server!". The browser I'm using is Google Chrome, and for the moment I am simply running everything on the local machine (e.g. no remote server involved yet)
Below is the relevant Java code and HTML:
SocketClient.java
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class SocketClient {
Socket socket = null;
PrintWriter out = null;
BufferedReader in = null;
private InetAddress myAddress;
private String remoteFunction;
public SocketClient(){
}
public void listenSocket(int portNum){
//Create socket connection
try{
System.out.println("#Client Trying to create socket bound to port " + portNum);
socket = new Socket(<my hostname here as a string>, portNum);
System.out.println("the attached socket port is " + socket.getLocalPort());
System.out.flush();
out = new PrintWriter(socket.getOutputStream(), true);
out.println("sendJSAlertTest");
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = in.readLine();
System.out.println("#CLient side Text received from server: " + line);
} catch (UnknownHostException e) {
System.out.println("Unknown host: <my hostname here as a string>.eng");
System.exit(1);
} catch (IOException e) {
System.out.println("No I/O");
e.printStackTrace();
System.exit(1);
}
}
public void setRemoteFunction(String funcName){
remoteFunction = funcName;
}
public String getRemoteFunction(){
return remoteFunction;
}
}
SocketServer.java
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.*;
class SocketServer {
ServerSocket server = null;
Socket client = null;
BufferedReader in = null;
PrintWriter out = null;
String line;
private NetComm hNet;
private Method serverMethod;
SocketServer(NetComm netmain){
hNet = netmain;
}
public void listenSocket(int portNum){
try{
System.out.println("#server Trying to create socket bound to port " + portNum);
server = new ServerSocket(portNum);
System.out.println("the attached socket port is " + server.getLocalPort());
} catch (IOException e) {
System.out.println("Could not listen on port " + portNum);
System.exit(-1);
}
try{
client = server.accept();
System.out.println("Connection accepted!");
} catch (IOException e) {
System.out.println("Accept failed: " + portNum);
System.exit(-1);
}
try{
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.out.println("Accept failed: " + portNum);
System.exit(-1);
}
while(true){
try{
System.out.println("trying to read from inputstream...");
line = in.readLine();
System.out.println(line);
//Now that we have a method name, invoke it
try {
serverMethod = hNet.getClass().getDeclaredMethod(line,
String.class);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
serverMethod.invoke(hNet, "Hello Client, I'm a Server!");
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Send data back to client
out.println("awesome " + line);
} catch (IOException e) {
System.out.println("Read failed");
System.out.flush();
System.exit(-1);
}
}
}
protected void finalize(){
//Clean up
try{
in.close();
out.close();
server.close();
} catch (IOException e) {
System.out.println("Could not close.");
System.exit(-1);
}
}
public int getBoundLocalPort(){
return server.getLocalPort();
}
}
NetComm.java
import cresco.ai.att.ccm.core.CCMMain;
import cresco.ai.att.ccm.gui.DataPanel;
import java.io.*;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.util.ArrayList;
import javax.servlet.*;
import javax.servlet.http.*;
import java.applet.*;
public class NetComm extends JApplet{//HttpServlet{
private CCMMain hMain;
private DataPanel dpLocal;
private SocketServer sockserver;
private Method serverMethod;
String testStr;
Integer testInt; /*integer */
Character testChar; /*character*/
//Testing this...
ServerSocket server = null;
Socket client = null;
BufferedReader in = null;
PrintWriter out = null;
String line;
#Override
public void init(){
sockserver = new SocketServer(this);
//For offline debug (should be disabled in a release to the webapp):
//initSocketServer is commented out in the release version and
//invoked in the Eclipse testbed version. In the webapp,
//initSocketServer is invoked from javascript (see below js sockPuppet())
//////initSocketServer(0);
String msg = "Hello from Java (using javascript alert)";
try {
getAppletContext().showDocument(new URL("javascript:doAlert(\"" +
msg +"\")"));
}
catch (MalformedURLException me) { }
}
public void sendJSAlertTest(String message){
System.out.println("sendJSAlert remotely invoked, with message: " +
message);
}
public void sendJSAlert(String message){
try {
getAppletContext().showDocument(new URL("javascript:doAlert(\"" +
message +"\")"));
}
catch (MalformedURLException me) { }
}
public void initSocketServer(int portNum){
sockserver.listenSocket(portNum);
}
public void finalizeSocketServer(){
sockserver.finalize();
}
public int socket2Me(int portNum){
try {
socks.add(new ServerSocket(portNum));
return 0; //socket opened successfully
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return -1; //socket failed to open
}
}
public int getSocketServerPort(){
return sockserver.getBoundLocalPort();
}
public void showRectTest(){
try {
getAppletContext().showDocument(new
URL("javascript:overlayRect()"));
}
catch (MalformedURLException me) { }
}
public void setGUI(DataPanel d){
dpLocal = d;
}
}
MapViz.html
<html>
<head>
<title>Welcome to Geographic Midpoint Map Vizualization!</title>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no">
<meta charset="UTF-8">
<link href="https://google-developers.appspot.com/maps/documentation/javascript
/examples/default.css"
rel="stylesheet" type="text/css">
...google maps stuff omitted...
<script type="text/javascript">
<script type="text/javascript">
function overlayRect(){
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.fillStyle="#FF0000";
ctx.fillRect(0,0,150,75);
}
function doAlert(s){
alert(s);
}
function testJava(){
document.ccmApplet.showRectTest();
}
function sockPuppet(){
var i = parseInt(document.getElementById("args").value,10);
alert("parsing the input args... got " + i);
if(i == NaN || i == null){
i = 0;
}
alert("passed NaN OR null block, i is " + i);
//i = 6672; //because $%*& you, that's why!
document.ccmApplet.initSocketServer(i);
//document.ccmApplet.listenSocket(i);
alert("inittializing socket server...");
//queryPort();
alert("querying port...");
document.ccmApplet.finalizeSocketServer();
//document.ccmApplet.finalize();
alert("finalizing socket server...");
}
function queryPort(){
var d = document.getElementById("debug");
var s1 = "Last port opened was: ";
//var s2 = document.ccmApplet.getLastBoundPort();
var s2 = document.ccmApplet.getSocketServerPort();
var sFinal = s1.concat(s2);
d.value = sFinal;
}
</script>
</head>
<body>
<applet width="500" height="50" name="ccmApplet" archive="CCM.jar"
code="cresco.ai.att.ccm.io.NetComm" MAYSCRIPT></applet>
<p></p>
<canvas id="myCanvas" width="200" height="100"></canvas>
<div id="map_canvas"></div>
<input id="args" type="textentry" value="" />
<button height="50" width="50" onClick="sockPuppet()">Test Socket
Creation</button>
<input id="debug" type="debugthingy" value="debug area..." />
<button height="50" width="50" onClick="testJava()">Test Java Callback</button>
</body>
</html>
In the webapp, I fill in the args input with a valid port number on the local machine and press the Test Socket Connection button which invokes the sockPuppet() javascript. This should create a ServerSocket and bind it to the specified port, which I then separately connect my desktop client app to via SocketClient.listenSocket. The result from Eclipse in the desktop app context is "awesome sendJSAlertTest" and in the appletviewer context is the output "sendJSAlert remotely invoked, with message: Hello Client, I'm a Server!". The webapp, invoking sendJSAlert(), should call the javascript alert function on the same message, creating a popup box with the message "sendJSAlert remotely invoked, with message: Hello Client, I'm a Server!" but instead nothing happens in the browser (nor the Chrome java or javascript debug consoles), and the desktop app output is null instead of "awesome sendJSAlert" as expected
So the question: What might be the cause of the different results? I know the browser's security sandbox could be an issue, but I've included a permissions file which should allow communication via sockets on any localhost port:
grant {
permission java.net.SocketPermission
"localhost:1024-",
"accept, connect, listen, resolve";
};
It's certainly possible though that I have not applied the permissions properly (I used the sun policytool gui); what exactly needs to be done in the applet code (if anything) to apply the permissions? Could a security problem result in the lack of response I'm seeing? I'd expect an exception to be reported in Chrome's java debug console, but there weren't any...
any help would be much appreciated, thanks!
-CCJ
UPDATE:
Okay, some new information: I ran the applet again in Chrome with the javascript console open (could have sworn I tried this before without effect, but evidently not) and received the following console output--
"Uncaught Error: java.security.AccessControlException: access denied
("java.net.SocketPermission" "<myipaddress>:4218" "accept,resolve") MapVizApp.html:154
sockPuppet MapVizApp.html:154 onclick MapVizApp.html:179 Uncaught Error: Error
calling method on NPObject. sockPuppet onclick "
So the question now is why am I tripping this security exception? The policy file with the permissions given above is in the same working directory as the html page and the jar file containing the applet, and I added the following to my system's JRE security policy file
//Grants my NetComm applet the ability to accept, connect, and listen on unpriv. ports
grant codeBase "file:${user.home}\Desktop\dev\invention\ATT\MapViz\CCM.jar" {
permission java.net.SocketPermission
"localhost:1024-",
"accept, connect, listen, resolve";
};
I haven't yet signed the applet, but it was my understanding that if the policy files are in order an applet doesn't need to be signed... if I'm wrong on that please let me know. Anyway, does anyone have any suggestions as to why this security exception is being thrown despite the policy files having the above granted permissions? Is there a naming convention for policy files in working directories that the JRE looks for? My working directory policy file for now is just named ccmPolFile, but I'm not clear on how the JRE is supposed to locate it; is there something I need to add to the applet code to point the JRE at the intended working directory policy file? Further, shouldn't the system policy file grant that I added be enough by itself to satisfy socket permissions for my applet inside CCM.jar?
UPDATE 2:
I signed the applet and added the line policy.url.3=file:${user.home}\Desktop\dev\invention\ATT\MapViz\ccmPolFile.policy to my java.security file in ${java.home}/lib/security (via http://docs.oracle.com/javase/tutorial/security/tour2/step4.html#Approach2 this is apparently how the JRE locates policy files to load)... sadly, the result is exactly the same security exception. The only thing left that I know of is
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
// perform the security-sensitive operation here
return null;
}
});
which should let me do almost anything since the applet is now signed. I wanted to keep signing out of the equation, but policy files aren't working for some reason. I'll be back shortly with how that works out
righto, so following my update 2 above, I change the listenSocket() method in SocketServer.java code to
public void listenSocket(int portNum){
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
int portNum = 4444;
try{
System.out.println("#server Trying to create socket bound to port " + portNum);
server = new ServerSocket(portNum);
System.out.println("the attached socket port is " + server.getLocalPort());
} catch (IOException e) {
System.out.println("Could not listen on port " + portNum);
System.exit(-1);
}
try{
client = server.accept();
System.out.println("Connection accepted!");
} catch (IOException e) {
System.out.println("Accept failed: " + portNum);
System.exit(-1);
}
try{
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.out.println("Accept failed: " + portNum);
System.exit(-1);
}
while(portNum==4444){
try{
System.out.println("trying to read from inputstream...");
line = in.readLine();
System.out.println(line);
//Now that we have a method name, invoke it
try {
serverMethod = hNet.getClass().getDeclaredMethod(line,
String.class);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
serverMethod.invoke(hNet, "Hello from Javascript invoked by the
desktop app!");
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Send data back to client
out.println("awesome " + line);
//System.out.println(line);
//System.out.flush();
} catch (IOException e) {
System.out.println("Read failed");
System.out.flush();
System.exit(-1);
}
}
return null;
}
});//end doPrivileged
}
obviously this is an unsafe kludge, but it does the trick-- I receive no security exception, and the desktop app prints "awesome sendJSAlert" so I know IO is working between the client and server contexts via sockets. The actual js alert function didn't fire, but I think that has something to do with the horrid infinite while loop in listenSocket() above...
Take home message: for some reason, to establish socket connections from an applet in google chrome I needed to sign the applet AND use AccessController.doPrivileged() to invoke my security sensitive code, despite having set my local policy and security files to grant my applet those permissions
googlers see refs:
http://www.coderanch.com/how-to/java/HowCanAnAppletReadFilesOnTheLocalFileSystem
http://docs.oracle.com/javase/7/docs/api/java/security/AccessController.html
http://www-personal.umich.edu/~lsiden/tutorials/signed-applet/signed-applet.html
http://docs.oracle.com/javase/tutorial/security/tour2/step4.html
UPDATE: Finally working 100% :D I changed the listenSocket() method above in SocketServer.java to this:
public void listenSocket(int portNum){
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
int portNum = 4444;
try{
System.out.println("#server Trying to create socket bound to port " + portNum);
server = new ServerSocket(portNum);
System.out.println("the attached socket port is " + server.getLocalPort());
} catch (IOException e) {
System.out.println("Could not listen on port " + portNum);
System.exit(-1);
}
try{
client = server.accept();
System.out.println("Connection accepted!");
} catch (IOException e) {
System.out.println("Accept failed: " + portNum);
System.exit(-1);
}
try{
in = new BufferedReader(new InputStreamReader(client.getInputStream()));
out = new PrintWriter(client.getOutputStream(), true);
} catch (IOException e) {
System.out.println("Accept failed: " + portNum);
System.exit(-1);
}
try {
line = in.readLine();
System.out.println("line is " + line + " from the inputstream to the
serversocket");
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if(line != null){
System.out.println("trying to read from non-null inputstream...");
//line = in.readLine();
System.out.println(line);
//Now that we have a method name, invoke that bitch!
try {
serverMethod = hNet.getClass().getDeclaredMethod(line, String.class);
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
serverMethod.invoke(hNet, "Hello From Javascript invoked by a desktop
app!");
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//Send data back to client
out.println("awesome " + line);
//System.out.println(line);
//System.out.flush();
}
return null;
}
});//end doPrivileged
}
The server.accept() method blocks until a connection is made anyway, so for this scenario where I only want to pass one command at a time to the serversocket inputstream a while loop didn't make sense. The change to an if allowed the program to actually continue on to the java.reflect stuff which invokes a method in the applet which invokes javascript functions directly. Since the port is still hard-coded and the applet utilizes doPrivileged(...) this is still not a great solution, but it does satisfy the use case of invoking javascript in a web browser from a desktop java application via a java applet bridge so it makes for a good springboard into more robust implementations!

Categories