I've inherited a Java based project that includes a cron job to upload a file via SFTP to a third-party server. Here's the relevant code.
String filePath = IUtil.getInstance().getProperties("cheetah_sftp_filepath");
try{
SshClient ssh = new SshClient();
ssh.connect(host, port);
//Authenticate
PasswordAuthenticationClient passwordAuthenticationClient = new PasswordAuthenticationClient();
passwordAuthenticationClient.setUsername(userName);
passwordAuthenticationClient.setPassword(password);
int result = ssh.authenticate(passwordAuthenticationClient);
if(result != AuthenticationProtocolState.COMPLETE){
throw new Exception("Login to " + host + ":" + port + " " + userName + "/" + password + " failed");
}
//Open the SFTP channel
SftpClient client = ssh.openSftpClient();
client.cd("autoproc");
client.put(filePath);
//disconnect
client.quit();
ssh.disconnect();
} catch(Exception e) {
String message = "Failed during sftp: " + e.getMessage();
addJobMessage(message, JobMessageType.JOB_MESSAGE_TYPE_ERROR);
e.printStackTrace();
return false;
}
Pretty straightforward, but it's not working. When client.put() executes, it fails with "java.io.IOException: No such file". Here's the stack trace.
java.io.IOException: No such file
at com.sshtools.j2ssh.sftp.SftpSubsystemClient.getOKRequestStatus(Unknown Source)
at com.sshtools.j2ssh.sftp.SftpSubsystemClient.setAttributes(Unknown Source)
at com.sshtools.j2ssh.sftp.SftpSubsystemClient.changePermissions(Unknown Source)
at com.sshtools.j2ssh.SftpClient.chmod(Unknown Source)
at com.sshtools.j2ssh.SftpClient.put(Unknown Source)
at com.sshtools.j2ssh.SftpClient.put(Unknown Source)
at com.sshtools.j2ssh.SftpClient.put(Unknown Source)
at com.sshtools.j2ssh.SftpClient.put(Unknown Source)
at com.dez.store.scripts.SendEmailShellCommand.sftpToCheetah(SendEmailToCheetahShellCommand.java:99)
at com.dez.store.scripts.SendEmailShellCommand.execute(SendEmailToCheetahShellCommand.java:34)
at com.fry.ocp.common.ShellCommandExecutor.main(ShellCommandExecutor.java:90)
filePath is an absolute path to the file. Yes, I've checked the obvious: the path is correct and the file exists. File permissions are 664 so a read shouldn't be failing in any case, but the process is running as root to boot.
I've tried everything I can think of.
I've checked read permissions all the way up the directory tree (which is kind of deep).
I've tried lcd() to the directory and once I get there lpwd(). That seems fine, but put still fails so a long path name doesn't seem to be the issue.
I double checked to make sure the file streams that originally wrote the file were all being closed correctly. I don't see anything that makes me think that could be the issue.
I tried creating and instance of j2ssh.sftp.SftpFile with the full path to see if it could access the file and make sure the "No such file" error wasn't related to the remote host. When I execute SftpFile.canRead() I get a null pointer exception, so I'm thinking it's a local problem.
I haven't touched Java in years. To say that I am rusty would be a gross understatement. However, our last "Java guy" just quit and I'm the only person left in my shop who has touched Java ever, so I'm the new "Java guy".
Am I missing something simple? Any other ideas?
-Sean
From the callstack and your description, I would expect the error refers to the remote file.
The chmod has to be done only after the transfer completes, so I assume the SftpClient believes the transfer is done and it tries to update the remote file permissions. And it seems like it fails, because the file is actually not there. Once you get the error, use SftpClient.ls(), to check, if the file is there. Chances are that you have some remote-side process that takes the file away the moment the upload finishes.
As a workaround, you can also try to prevent the SftpClient trying to modify the permissions after the upload finishes. I do not know J2SSH. Having a quick look, I have not found any API for this though. Maybe the SftpClient.umask().
You can try to switch to JSch. It does not seem to do implicit chmod after upload.
Also it's worth checking the remote server log.
Related
i need to send some messages from my java web application to some servers using Diameter protocol, in particular CCR-CCA scenario. I had a look at jdiameter opensource project, but my usecase does not require such complexity, since that i just need to send a single request and log the response (actually i don't even need the CER-CEA part).
So i thought i could just have used Seagull running under my webapp. I downloaded Seagull (for Windows), and what i'm trying to do is basically to run the .bat file coming from Seagull for the diameter environment from my java environment.
That's what i've done till now..
1) A simple test to invoke the client.. Here wrapper simply sets working dir and starts the process
public static void main(String[] args) {
List<String> cmd=new ArrayList<>();
cmd.add("cmd.exe");
cmd.add("/c");
cmd.add("my_start_client.bat");
JavaProcessBuilderWrapper wrapper = new JavaProcessBuilderWrapper();
Process p = wrapper.createProcess(RedirectErrorsTo.STDERR,
new HashMap<>(), new File("my_working_dir"), cmd);
BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuilder output = new StringBuilder();
String line;
try {
while ((line = reader.readLine()) != null) {
output.append(line);
}
System.out.println(line);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
2) I modified the client's and server's .bat files coming from Seagull to use CCR-CCA protocol.
Running Java main with this configuration caused a
Fatal: Keyboard saved configuration failure error
on my logs.
3) So, as mentioned here i further modified my client's .bat file to run in background mode, adding -bg at the end. Now my client's bat look like this
#ECHO OFF
rem
"Diameter Start Script Sample"
"Local env"
SET RUN_DIR=C:\Program Files\Seagull
set PATH=%PATH%;%RUN_DIR%
set LD_LIBRARY_PATH=%RUN_DIR%
set RUN_DIR=%RUN_DIR%\diameter-env\run
cd %RUN_DIR%
cls
mode 81,25
echo "Seagull Diameter Client Sample Start"
seagull -conf ..\config\conf.client.xml -dico ..\config\base_ro_3gpp.xml -scen ..\scenario\ccr-cca.ro.client.xml -log ..\logs\ccr-cca.client.log -llevel ETM -bg
pause
Since i was facing some troubles, to keep things simple, i just tried to make it work at least via cmd (not using my java method), but i think background mode is messing around, because now when i start my server and then my client in bg mode, sometimes i get a
Fatal: Forking error
but the most of the times, the client send a single message and then on my console i see that my software is causing connection abort (error code -1), and from the log i see that the channel just get closed, and my client does not even receive an answer. (NB for now i left the configuration files untouched)
Has any of you faced this behaviour? Is something else closing the connection (firewall perhaps)? Do i have to provide other configurations to make this work?
Once i can get this working, can i use my java web app (with a method similar to the one i already mentioned) to make diameter calls?
Thanks in advance, any help is really welcomed.
I'm trying to get all the database on my server. But specifying my server name in getDbDirectory() parameter as NALLN304/40/LLN/IBM gives me a error.
Directory NALLN304/40/LLN/IBM!! does not exist
it always add two exclamation mark at the end. I tried also as server name and mail file adding .nsf format at the end of mail file. NALLN304/40/LLN/IBM!!data0\126\1000031540.nsf also gives me the same error.
Snipper code below:
Session session = null;
Database db = null;
DbDirectory dir = null;
try
{
NotesThread.sinitThread();
session = NotesFactory.createSession();
System.out.println("User = " + session.getUserName());
dir = session.getDbDirectory("NALLN304/40/LLN/IBM");
System.out.println(dir.getName());
db = dir.getFirstDatabase(DbDirectory.DATABASE);
do
{
System.out.println("Title: " +db.getTitle());
}
while(dir.getNextDatabase() != null);
}
catch(NotesException ex)
{
ex.printStackTrace();
}
The error always points out to the db = dir.getFirstDatabase(DbDirectory.DATABASE); because dir.getFirstDatabase(DbDirectory.DATABASE) expects .nsf file even I specify the file format. Any reasons why I got this error?
Your problem is that your ID is not authenticating with the server. You need to take the output from this line:
System.out.println("User = " + session.getUserName());
And take it to your server administrators, ask why it is not being allowed to access the server, and ask them to assist you either by granting the necessary permissions or by giving you another ID that you can use.
Check the logs for server connection errors. Even if the server has to connect to itself. Faced the same problem. The server gave an error because it did not find a route for the connection. Added a new connection for the server to itself and everything was fixed
I am using svnkit (standalone 1.8.12) to checkout an svn repository with java.
I tried several possibilities to do so (1, 2). Unfortunately, as soon as SVNkit starts to connect to the SVN server it crashes with the following stack trace (checkout, test connection, get revision number and so on). Checkout via terminal works just fine (using Ubuntu 14 with subversion installed), also open the used repo-url with a browser works just fine.
Exception in thread "main" java.lang.IndexOutOfBoundsException: Bounds exceeds available space : size=7, offset=8
at com.sun.jna.Memory.boundsCheck(Memory.java:185)
at com.sun.jna.Memory.getPointer(Memory.java:509)
at org.tmatesoft.svn.core.internal.util.jna.SVNGnomeKeyring.setPassword(SVNGnomeKeyring.java:334)
at org.tmatesoft.svn.core.internal.util.jna.SVNGnomeKeyring.setPassword(SVNGnomeKeyring.java:308)
at org.tmatesoft.svn.core.internal.util.jna.SVNJNAUtil.addPasswordToGnomeKeyring(SVNJNAUtil.java:170)
at org.tmatesoft.svn.core.internal.wc.DefaultSVNPersistentAuthenticationProvider$GnomeKeyringPasswordStorage.savePassword(DefaultSVNPersistentAuthenticationProvider.java:696)
at org.tmatesoft.svn.core.internal.wc.DefaultSVNPersistentAuthenticationProvider.savePasswordCredential(DefaultSVNPersistentAuthenticationProvider.java:416)
at org.tmatesoft.svn.core.internal.wc.DefaultSVNPersistentAuthenticationProvider.saveAuthentication(DefaultSVNPersistentAuthenticationProvider.java:323)
at org.tmatesoft.svn.core.internal.wc.DefaultSVNAuthenticationManager.acknowledgeAuthentication(DefaultSVNAuthenticationManager.java:274)
at org.tmatesoft.svn.core.auth.BasicAuthenticationManager.acknowledgeAuthentication(BasicAuthenticationManager.java:105)
at org.tmatesoft.svn.core.internal.io.dav.http.HTTPConnection.request(HTTPConnection.java:771)
at org.tmatesoft.svn.core.internal.io.dav.http.HTTPConnection.request(HTTPConnection.java:398)
at org.tmatesoft.svn.core.internal.io.dav.http.HTTPConnection.request(HTTPConnection.java:386)
at org.tmatesoft.svn.core.internal.io.dav.DAVConnection.performHttpRequest(DAVConnection.java:863)
at org.tmatesoft.svn.core.internal.io.dav.DAVConnection.exchangeCapabilities(DAVConnection.java:699)
at org.tmatesoft.svn.core.internal.io.dav.DAVConnection.open(DAVConnection.java:118)
at org.tmatesoft.svn.core.internal.io.dav.DAVRepository.openConnection(DAVRepository.java:1049)
at org.tmatesoft.svn.core.internal.io.dav.DAVRepository.testConnection(DAVRepository.java:100)
at Main.svnCheckout(Main.java:131)
at Main.svnCheckoutPrep(Main.java:106)
at Main.main(Main.java:76)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
The code that produces this error is the following
static void svnCheckout(String url, String dest) throws SVNException {
/* Setup SVNKIT library */
setupSVNKit();
SVNRepository repository = null;
try {
repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url));
} catch (SVNException svne) {
System.err.println("error while creating an SVNRepository for the location '"
+ url + "': " + svne.getMessage());
System.exit(1);
}
ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager("someName", "somePWD");
repository.setAuthenticationManager(authManager);
repository.testConnection();
}
...
static void setupSVNKit(){
/* For using http:// and https:// */
DAVRepositoryFactory.setup();
}
Does anyone have an idea what I do wrong?
I would be so happy, if only the testConnection() function would work.
Since it is https, do I need to setup SVNkit to accept the fingerprint or similar?
Any help is highly appreciated!
markus
Alright, after many trials and errors I figured it out. Actually, I run into a different error using another repository. I did two things (not sure which one was the actual reason, maybe both of them).
Added the untrusted certificate (yes it was not validated) to the JVM
Added the following line to the VM options: -Dsvnkit.library.gnome-keyring.enabled=false
Further Reading:
Point 1: https://issues.tmatesoft.com/issueMobile/SVNOLD-290
Point 2: https://issues.tmatesoft.com/issue/SVNKIT-231
I am trying to download a xml text file from a web server using this method:
static void download (String url , String fileName) throws IOException{
FileWriter xmlWriter;
xmlWriter = new FileWriter(fileName);
System.out.println("URL to download is : " + url);
// here Exception is thrown/////////////////////////////////
BufferedReader inputTxtReader = new BufferedReader
(new BufferedReader(new InputStreamReader(addURL.openStream())));
////////////////////////////////////////////////////////
String str ;
String fileInStr = "";
str = inputTxtReader.readLine();
while (!(str == null) ){///&& !(str.equals("</tv>"))
fileInStr += (str + "\r\n");
str = inputTxtReader.readLine();
}
xmlWriter.write(fileInStr);
xmlWriter.flush();
xmlWriter.close();
System.out.println("File Downloaded");
}
Sometimes this exception is thrown (where I specified is code):
java.net.SocketException: Network is unreachable: connect
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:333)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:195)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:182)
at java.net.Socket.connect(Socket.java:518)
at java.net.Socket.connect(Socket.java:468)
at sun.net.NetworkClient.doConnect(NetworkClient.java:157)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:389)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:516)
at sun.net.www.http.HttpClient.<init>(HttpClient.java:233)
at sun.net.www.http.HttpClient.New(HttpClient.java:306)
at sun.net.www.http.HttpClient.New(HttpClient.java:318)
at sun.net.www.protocol.http.HttpURLConnection.getNewHttpClient(HttpURLConnection.java:788)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:729)
at sun.net.www.protocol.http.HttpURLConnection.connect(HttpURLConnection.java:654)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:977)
at java.net.URL.openStream(URL.java:1009)
at MessagePanel.download(MessagePanel.java:640)
at WelcomThread.run(MainBody2.java:891)
Please guide me
Thank you all.
You are facing a connection breakdown. Does this happen in 3G, WiFi or "plain" connection on a computer?
Anyway, you must assume that the connection may be lost from time to time, when writing your app. For example, with mobiles, this happens frequently in the tube, in basements, etc. With PC apps, this is less frequent but occurs sometimes.
A retry can be a good solution. And a clean error message that explains the network is not available at this moment too.
I faced situation of getting java.net.SocketException not sometimes but every time. I've added -Djava.net.preferIPv4Stack=true to java command line and my program started to work properly.
"Network is unreachable" means just that. You're not connected to a network. It's something outside of your program. Could be a bad OS setting, NIC, router, etc.
I haven't tested with your code so it would be totally different case though, still I'd like to share my experience. (Also this must be too late answer though, I hope this answer still would help somebody in the future)
I recently faced similar experience like you such as some times Network is unreachable, but sometimes not. In short words, what was cause is too small time out. It seems Java throws IOException with stating "Network is unreachable" when the connection fails because of it. It was so misleading (I would expect something like saying "time out") and I spent almost a month to detect it.
Here I found another post about how to set time out.
Alternative to java.net.URL for custom timeout setting
Again, this might not the same case as you got experienced, but somebody for the future.
this just happened to me. None of the answers helped, as the issue was I have recently changed the target host configuration and put incorrect host value there. So it could just be wrong connection details as well.
I faced this error after updating my network adapter configuration (migration to a NIC coupled network by PowerShell commandlet New-NetSwitchTeam). My guess is, that something in the java configuration must be adapted to reflect this change to the java system. But it is unclear where the changes should take place. I am investigating further.
Hey I'm getting a AccessControlException: access denied when attempting to start up a RMI app I'm writing, I can't work out why I get this exception if I open it on the default port 1099, or on another dynamic port, my policy file currently grants everything (will change when app is finished).
I am stuck as to where it is going wrong, any help would be of great use
My code
public class Main {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws RemoteException, AlreadyBoundException, MalformedURLException {
if (System.getSecurityManager() == null)
{
System.setSecurityManager ( new RMISecurityManager() );
}
CreditCardServer ccs = new CreditCardServer();
int port = 1099;
try {
port = Integer.valueOf(args[0]);
}
catch (Exception e)
{
System.out.println("Invlaid Port");
}
if (((port <= 65535) && (port >= 49152)) || port ==1099)
{
System.out.println("Valid Port");
}
else
{
port = 1099;
System.out.println("Port not in Dynamic Range 49152<-->65535");
}
System.out.println(port);
LocateRegistry.createRegistry(port);
LocateRegistry.getRegistry().bind("CreditCardServer", ccs);
while (true)
{
//hum?
}
}
}
The Stack Trace
vega3 [ia32.linux] 23% java -Djava.security.policy=wideopen.policy -jar "BookStore-CreditCardServer.jar 65000"
Valid Port
65000
Exception in thread "main" java.security.AccessControlException: access denied (java.net.SocketPermission 127.0.0.1:1099 connect,resolve)
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:342)
at java.security.AccessController.checkPermission(AccessController.java:553)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at java.lang.SecurityManager.checkConnect(SecurityManager.java:1051)
at java.net.Socket.connect(Socket.java:536)
at java.net.Socket.connect(Socket.java:492)
at java.net.Socket.<init>(Socket.java:389)
at java.net.Socket.<init>(Socket.java:203)
at sun.rmi.transport.proxy.RMIDirectSocketFactory.createSocket(RMIDirectSocketFactory.java:40)
at sun.rmi.transport.proxy.RMIMasterSocketFactory.createSocket(RMIMasterSocketFactory.java:146)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:613)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
at sun.rmi.server.UnicastRef.newCall(UnicastRef.java:340)
at sun.rmi.registry.RegistryImpl_Stub.bind(Unknown Source)
at bookstorecreditcardserver.Main.main(Main.java:56)
My Policy File
grant {
// Allow everything for now
permission java.security.AllPermission;
};
I've been stuck on this all day (after figuring out I had to start the rmiregistry from the commandline), trying to make this work locally with Eclipse, and finally solved it. A few pointers to save others this cruel fate:
1 - assign the policy file correctly, either with a commandline flag:
java -Djava.security.policy=/home/.../<filename>.policy ...
or by putting this directly in your code:
System.setProperty("java.security.policy","file:///home/.../<filename>.policy");
You can also put it in the same folder as your project root), to reduce the URI to
file:./<filename>.policy
(use a relative instead of absolute URI - I actually didn't understand this until today).
2 - make sure the format of the policy file is correct, e.g.:
grant codeBase "file:<path>/bin/-" {
permission java.security.AllPermission;
};
This should refer to the folder where your binary is located! A thorough explanation of the format of the policy file is here.
That's about it, I'd also recommend this tutorial, I found it very helpful to get on the right track.
Basically, I'm stupid, i assumed that because Java was not complaining it was finding the .policy file AOK, turns out it was not moving a new copy of the.policy file into the working directory solves all :-D
I found most of the answers on this topic vague and unhelpful, and spent several hours debugging this. More than likely, your error is because the policy file is either incorrectly formatted or you're not correctly setting it as a command line argument.
If you're getting a java.security.AccessControlException: access denied ("java.net.SocketPermission" "127.0.0.1:1099" "connect,resolve")
Create a security policy file with all permissions, just to test it out
grant codeBase "file:/-" {
permission java.security.AllPermission;
};
Use this security file for both the client and the server, just to get it running.
Make sure you don't have any typos. I spent hours trying to figure out why it wasn't working, and i had typed -Djava.rmi.security.policy instead of -Djava.security.policy=...
For those of us that just want to get the RMI tutorial from Oracle up and running, this security policy will be more than enough for that example.