Creating a symlink on Windows during JVM runtime - java

Slightly bizarre set of questions but I'm running into issues creating a symlink using mklink on Windows 7. I'm doing something a little weird due to the 260 character limit that exists when using cmd.exe by creating symlinks inside of my Java source code by using Process. Since I can't quite explain it, here's the code:
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
public class WindowsSymlinkUtility {
private List<String> command, currentSymlinks;
public WindowsSymlinkUtility() {
this.command = this.currentSymlinks = new ArrayList<String>();
this.command.add("cmd.exe");
this.command.add("/C");
}
/**
* Automatically creates a directory junction
* #param String link - the path and name of the symlink
* #param String target - the directory to point the symlink to
* #return boolean
* #see http://ss64.com/nt/mklink.html
*/
public boolean createSymlink(String link, String target) {
return createSymlink("\\J", link, target);
}
/**
*
* #param String flag - the flag for mklink
* #param String link - the path and name of the symlink
* #param String target - the directory to point the symlink to
* #return boolean
* #see http://ss64.com/nt/mklink.html
*/
public boolean createSymlink(String flag, String link, String target) {
this.command.clear();
this.command.add("mklink");
this.command.add(flag);
this.command.add(link);
this.command.add(target);
this.currentSymlinks.add(link);
return this.runner() == 0;
}
public boolean removeSymlink(String link) {
this.command.clear();
this.command.add("RD");
this.command.add(link);
if(this.runner() != 0) {
this.command.clear();
this.command.add("DEL");
this.command.add(link);
} else {
return true;
}
return this.runner() == 0;
}
public boolean removeAllSymlinks() {
for(String link : this.currentSymlinks) {
if(!this.removeSymlink(link)) {
return false;
}
}
return true;
}
/**
* Leave for debugging purposes
* #return String
*/
public String getCurrentCommand() {
String cmd = "";
for(String part : this.command) {
cmd += part + " ";
}
return cmd;
}
private int runner() {
Process process = null;
String message = null;
BufferedInputStream bis = null;
int exitVal = -1;
StringBuilder strBuff = new StringBuilder();
try {
if(this.command.size() < 1) throw new Exception("Length of Windows command cannot be zero");
ProcessBuilder pb = new ProcessBuilder(this.command);
Map<String, String> envVars = pb.environment();
pb.directory();
pb.redirectErrorStream(true);
process = pb.start();
bis = new BufferedInputStream(process.getInputStream());
byte[] bArr = new byte[2048];
while (bis.read(bArr) != -1) {
strBuff.append(new String(bArr).trim());
bArr = new byte[2048];
}
exitVal = process.waitFor();
message = strBuff.toString();
} catch(Exception e) {
e.printStackTrace();
System.err.println(e.getMessage());
System.err.println(message);
}
return exitVal;
}
public static void main(String[] args) {
WindowsSymlinkUtility foo = new WindowsSymlinkUtility();
foo.createSymlink("%TEMP%\\foo", "C:\\Users\\djthomps\\Downloads");
}
}
The error I'm getting:
java.io.IOException: Cannot run program "mklink": CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessBuilder.start(Unknown Source)
at WindowsSymlinkUtility.runner(WindowsSymlinkUtility.java:113)
at WindowsSymlinkUtility.createSymlink(WindowsSymlinkUtility.java:56)
at WindowsSymlinkUtility.createSymlink(WindowsSymlinkUtility.java:37)
at WindowsSymlinkUtility.main(WindowsSymlinkUtility.java:134)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot find the file specified
at java.lang.ProcessImpl.create(Native Method)
at java.lang.ProcessImpl.<init>(Unknown Source)
at java.lang.ProcessImpl.start(Unknown Source)
... 5 more
Cannot run program "mklink": CreateProcess error=2, The system cannot find the file specified
null
Some questions you might have:
Why are you doing this?
Because the length of the full command runs well over 260 characters due to relevant files and folders being deeply nested in the file system.
How will symlinks help?
I have done tests to ensure that symlinks allow me to "bypass" the 260 character limit.
Here are my questions:
Is there another way to create a symlink in Java such that Windows will behave when a command exceeds the 260 character limit?
Can SET be used in lieu of mklink?
Is it possible to use java.nio.file for this even if the command runs over 260 characters?
Again, I understand this is an odd question. Ask for clarification if something is amiss.

I've modified your program a bit just to provide a working sample... essentially the problem is that you're not concatenating the variables and passing them as one argument to cmd.
One implementation note :: Do Not use del to remove a symlink otherwise all the files in the target directory will be erased. Use rmdir, which I've added for posterity.
/**
* #author Edward Beckett :: <Edward#EdwardBeckett.com>
* #since :: 7/21/2015
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.List;
public class WindowsSymlinkUtility {
public static final String D_LINK = "/D";
public static final String H_LINK = "/H";
public static final String J_LINK = "/J";
public static final String REM_LINK = "rmdir";
private String command = "";
private String link = "";
private String target = "";
private List<String> commands = Arrays.asList( D_LINK, H_LINK, J_LINK, REM_LINK );
public void createSymlink( String command, String link, String target ) {
this.command = command;
this.link = link;
this.target = target;
if( !commands.contains( command ) ) {
System.out.println( command + " Is not a valid command \n " );
return;
}
runner();
}
private void runner() {
try {
String[] values = { "CMD", "/C", "mklink", this.command, this.link, this.target };
ProcessBuilder builder = new ProcessBuilder( values );
builder.directory( new File( this.link ) );
Process process = builder.start();
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader( is );
BufferedReader br = new BufferedReader( isr );
String line;
System.out.printf( "Output of running %s is:\n",
Arrays.toString( values ) );
while( ( line = br.readLine() ) != null ) {
System.out.println( line );
int exitValue = process.waitFor();
System.out.println( "\n\nExit Value is " + exitValue );
}
} catch( InterruptedException | IOException e ) {
e.printStackTrace();
}
}
public static void main( String[] args ) {
( new WindowsSymlinkUtility() ).createSymlink( J_LINK, "C:\\Foo", "C:\\Temp" );
}
}
output
Output of running [CMD, /C, mklink, /J, C:\Foo, C:\Temp] is:
Junction created for C:\Foo <<===>> C:\Temp
Exit Value is 0

Eddie B's solution was on the right track but I kept getting errors when Java as attempting to run the command. Here's my rendition that works:
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
public class WindowsSymlinkUtility {
public static final String D_LINK = "/D";
public static final String H_LINK = "/H";
public static final String J_LINK = "/J";
public static final String REM_LINK = "rmdir";
private String command, flag, link, target;
private List<String> commands = Arrays.asList(D_LINK, H_LINK, J_LINK, REM_LINK), symlinks;
public WindowsSymlinkUtility() {
this.command = this.flag = this.link = this.target = "";
this.symlinks = new ArrayList<>();
}
/**
* Automatically creates a directory junction
* #param String link - the path and name of the symlink
* #param String target - the directory to point the symlink to
* #return boolean
* #see http://ss64.com/nt/mklink.html
*/
public boolean createSymlink(String link, String target) {
return createSymlink(J_LINK, link, target);
}
/**
*
* #param String flag - the flag for mklink
* #param String link - the path and name of the symlink
* #param String target - the directory to point the symlink to
* #return boolean
* #see http://ss64.com/nt/mklink.html
*/
public boolean createSymlink(String flag, String link, String target) {
if(!this.commands.contains(flag)) {
System.err.printf("%s is not a valid command\n", flag);
return false;
}
this.command = "mklink";
this.flag = flag;
this.link = link;
this.target = target;
if(this.runner() == 0) {
this.symlinks.add(this.link);
return true;
}
return false;
}
private int runner() {
Process process = null;
String message = null;
BufferedInputStream bis = null;
StringBuilder strBuff = new StringBuilder();
int exitVal = -1;
try {
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/C", this.command, this.flag, this.link, this.target);
Map<String, String> envVars = pb.environment();
pb.directory();
pb.redirectErrorStream(true);
process = pb.start();
bis = new BufferedInputStream(process.getInputStream());
byte[] bArr = new byte[2048];
while (bis.read(bArr) != -1) {
strBuff.append(new String(bArr).trim());
bArr = new byte[2048];
}
exitVal = process.waitFor();
message = strBuff.toString();
System.out.println(message);
} catch(Exception e) {
e.printStackTrace();
System.err.println(e.getMessage());
System.err.println(message);
}
return exitVal;
}
public static void main(String[] args) {
(new WindowsSymlinkUtility()).createSymlink(J_LINK, "%TEMP%\\node", "C:\\users\\djthomps\\Downloads");
}
}

Related

How to print java compiler error log using tools.jar compile method?

In my idea IDE, I can see the compile error with red font in the console.But when I deploy the jar in the linux server.I can not see the compile log.How to print the compile error log?
public static void main(String[] args) throws Exception {
String compliePath="D:\\testFole";
String filename="D:\\test.java";
String[] arg = new String[] { "-d", compliePath, filename };
System.out.println(com.sun.tools.javac.Main.compile(arg));
}
Well if I got your question right, here is an approach to the outcome.
I think this will be platform-independent.
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
private static Process process;
public static void main(String[] args) {
runCommand();
getErrorMessage();
}
/**
* This method executes/runs the commands
*/
private static void runCommand()
{
File file = new File("D:\\\\test.java");
String changeDirectory = "cmd start cmd.exe /c cd D:\\";
String compile = " && javac D:\\test.java";
String run = " && java "+file.getName().replace(".java","");
String command = changeDirectory + compile + run;
try {
process = Runtime.getRuntime().exec(command);
}catch (IOException e){}
}
/**
* This method will get the errorStream from process
* and output it on the console.
*/
private static void getErrorMessage()
{
try (BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())))
{
String line;
if(errorReader.readLine() != null)
while ((line = errorReader.readLine()) != null)
System.out.println(line); //display error message
}catch (IOException e){}
}
}

How to edit a file inside a zip remotely on Secure_CRT?

I have a task to edit a file inside of a zip on SecureCRT.
I am able to run Linux commands remotely using JSCH library (com.jcraft.jsch)
Here is part of my code:
Session session = setUpSession(testParameters, softAsserter);
Channel channel = session.openChannel("exec");
((ChannelExec)channel).setCommand(command);
channel.setInputStream(null);
((ChannelExec)channel).setErrStream(System.err);
InputStream inputStream = channel.getInputStream();
channel.connect();
I wish to know what is the best way, or the right commands in order to edit a file (for example Test.txt) inside of a zip file on a SecureCRT server.
The contends inside the zip file can be modified in significant number of ways.
I have mentioned some ways which actually might work for you. In order to do that
We should securely transfer the source file/compiled file from local machine to server. The below link would help to transfer the file securely .
https://www.vandyke.com/int/drag_n_drop.html
As a first step , We should develop a snippet which is capable of modifying the contends of the zip file, Then we should copy the file to the server . Then we execute the command to run the file so that the contends inside the zip gets modified.
The below approach has been mentioned only to modify the zip contends.
Approach 1: Using a Simple Java snippet to achieve
We can write a simple java snippet which can open the zip file and edit , Keep the file in the machine and then execute the class file by just running "java filename" which would actually modify contends in the zip file.
Link which would help :
Modifying a text file in a ZIP archive in Java
import java.io.*;
import java.nio.file.*;
class RemoteEditFileContends {
/**
* Edits the text file in zip.
*
* #param zipFilePathInstance
* the zip file path instance
* #throws IOException
* Signals that an I/O exception has occurred.
*/
public static void editTextFileInZip(String zipFilePathInstance) throws IOException {
Path pathInstance = Paths.get(zipFilePathInstance);
try (FileSystem fileSystemIns = FileSystems.newFileSystem(pathInstance, null)) {
Path pathSourceInstance = fileSystemIns.getPath("/abc.txt");
Path tempCopyIns = generateTempFile(fileSystemIns);
Files.move(pathSourceInstance, tempCopyIns);
streamCopy(tempCopyIns, pathSourceInstance);
Files.delete(tempCopyIns);
}
}
/**
* Generate temp file.
*
* #param fileSystemIns
* the file system ins
* #return the path
* #throws IOException
* Signals that an I/O exception has occurred.
*/
public static Path generateTempFile(FileSystem fileSystemIns) throws IOException {
Path tempCopyIns = fileSystemIns.getPath("/___abc___.txt");
if (Files.exists(tempCopyIns)) {
throw new IOException("temp file exists, generate another name");
}
return tempCopyIns;
}
/**
* Stream copy.
*
* #param sourecInstance
* the src
* #param destinationInstance
* the dst
* #throws IOException
* Signals that an I/O exception has occurred.
*/
public static void streamCopy(Path sourecInstance, Path destinationInstance) throws IOException {
try (
BufferedReader bufferInstance = new BufferedReader(new InputStreamReader(Files.newInputStream(sourecInstance)));
BufferedWriter writerInstance = new BufferedWriter(
new OutputStreamWriter(Files.newOutputStream(destinationInstance)))) {
String currentLine = null;
while ((currentLine = bufferInstance.readLine()) != null) {
currentLine = currentLine.replace("key1=value1", "key1=value2");
writerInstance.write(currentLine);
writerInstance.newLine();
}
}
}
public static void main(String[] args) throws IOException {
editTextFileInZip("test.zip");
}
}
Approach 2: Using python to modify the zip files
How to update one file inside zip file using python
Approach 3 : Writing a shell script to modify the contends of zip file directly, So that we can copy the shell script to the server and then execute directly the shell script.
https://superuser.com/questions/647674/is-there-a-way-to-edit-files-inside-of-a-zip-file-without-explicitly-extracting
The below snippet would help you to connect and execute using the library.
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
public class ConnetionManager {
private static final Logger _logger = Logger.getLogger(ConnetionManager.class.getName());
private JSch jschSSHChannel;
private String strUserName;
private String strConnectionIP;
private int intConnectionPort;
private String strPassword;
private Session sesConnection;
private int intTimeOut;
private void doCommonConstructorActions(String userNameInstance, String tokenpassword, String connetionServerIo,
String hostFileName) {
jschSSHChannel = new JSch();
try {
jschSSHChannel.setKnownHosts(hostFileName);
} catch (JSchException exceptionInstance) {
_logError(exceptionInstance.getMessage());
}
strUserName = userNameInstance;
strPassword = tokenpassword;
strConnectionIP = connetionServerIo;
}
public ConnetionManager(String userName, String password, String connectionIP, String knownHostsFileName) {
doCommonConstructorActions(userName, password, connectionIP, knownHostsFileName);
intConnectionPort = 22;
intTimeOut = 60000;
}
public ConnetionManager(String userName, String password, String connectionIP, String knownHostsFileName,
int connectionPort) {
doCommonConstructorActions(userName, password, connectionIP, knownHostsFileName);
intConnectionPort = connectionPort;
intTimeOut = 60000;
}
public ConnetionManager(String userName, String password, String connectionIP, String knownHostsFileName,
int connectionPort, int timeOutMilliseconds) {
doCommonConstructorActions(userName, password, connectionIP, knownHostsFileName);
intConnectionPort = connectionPort;
intTimeOut = timeOutMilliseconds;
}
public String connect() {
String errorMessage = null;
try {
sesConnection = jschSSHChannel.getSession(strUserName, strConnectionIP, intConnectionPort);
sesConnection.setPassword(strPassword);
sesConnection.connect(intTimeOut);
} catch (JSchException exceptionInstance) {
errorMessage = exceptionInstance.getMessage();
}
return errorMessage;
}
private String _logError(String errorMessage) {
if (errorMessage != null) {
_logger.log(Level.SEVERE, "{0}:{1} - {2}", new Object[] { strConnectionIP, intConnectionPort, errorMessage });
}
return errorMessage;
}
private String _logWarnings(String warnMessage) {
if (warnMessage != null) {
_logger.log(Level.WARNING, "{0}:{1} - {2}", new Object[] { strConnectionIP, intConnectionPort, warnMessage });
}
return warnMessage;
}
public String sendCommand(String executionCommand) {
StringBuilder outputBuffer = new StringBuilder();
try {
Channel channelInstance = sesConnection.openChannel("exec");
((ChannelExec) channelInstance).setCommand(executionCommand);
InputStream commandOutputStream = channelInstance.getInputStream();
channelInstance.connect();
int readByte = commandOutputStream.read();
while (readByte != 0xffffffff) {
outputBuffer.append((char) readByte);
readByte = commandOutputStream.read();
}
channelInstance.disconnect();
} catch (IOException ioExceptionInstance) {
_logWarnings(ioExceptionInstance.getMessage());
return null;
} catch (JSchException schExceptionInstance) {
_logWarnings(schExceptionInstance.getMessage());
return null;
}
return outputBuffer.toString();
}
public void close() {
sesConnection.disconnect();
}
}

Java ProcessBuilder Output to String

How to redirect or get the system output to String?
ProcessBuilder pb = new ProcessBuilder().inheritIO();
...
for (...){
pb.command(...);
pb.start();
//here >>> assign output string to variable
}
Here is an opinion on how to capture the standard output of a system command process into a string container.
Adapted from the web:
try {
ProcessBuilder pb = new ProcessBuilder("echo", "dummy io");
final Process p=pb.start();
BufferedReader br=new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
StringBuilder sb = new StringBuilder();
while((line=br.readLine())!=null) sb.append(line);
}
System.out.println(sb.toString());
In congruence with my original comment on what would be a good example of Basic I/O. I hacked out some code, with a few more features than basic.
Extras
An environment shell for variables and
A working directory
These features add "profile-style" execution to your System commands.
Foundational Work
Java Threading and Joining by Oracle.
Code
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
/**
* Created by triston on 11/2/17.
*/
public class Commander {
private Commander(){} // no construction
public static class StreamHandler implements Runnable {
Object source;
Object destination;
StreamHandler(Object source, Object oDestination) {
this.source = source; this.destination = oDestination;
}
public void run() {
if (source instanceof InputStream) {
BufferedReader br = new BufferedReader(new InputStreamReader((InputStream) source));
String line;
try {
while ((line = br.readLine()) != null) ((StringBuilder) destination).append(line + '\n');
} catch (IOException oE) {
}
} else {
PrintWriter pw = new PrintWriter((OutputStream)destination);
pw.print((String)source);
pw.flush(); pw.close();
}
}
public static Thread read(InputStream source, StringBuilder dest) {
Thread thread = new Thread(new StreamHandler(source, dest));
(thread).start();
return thread;
}
public static Thread write(String source, OutputStream dest) {
Thread thread = new Thread(new StreamHandler(source, dest));
(thread).start();
return thread;
}
}
static Map<String, String> environment = loadEnvironment();
static String workingDirectory = ".";
static Map<String, String> loadEnvironment() {
ProcessBuilder x = new ProcessBuilder();
return x.environment();
}
static public void resetEnvironment() {
environment = loadEnvironment();
workingDirectory = ".";
}
static public void loadEnvirons(HashMap input) {
environment.putAll(input);
}
static public String getEnviron(String name) {
return environment.get(name);
}
static public void setEnviron(String name, String value) {
environment.put(name, value);
}
static public boolean clearEnviron(String name) {
return environment.remove(name) != null;
}
static public boolean setWorkingDirectory(String path) {
File test = new File(path);
if (!test.isDirectory()) return false;
workingDirectory = path;
return true;
}
static public String getWorkingDirectory() {
return workingDirectory;
}
static public class Command {
ProcessBuilder processBuilder = new ProcessBuilder();
Process process;
public Command(String... parameters) {
processBuilder.environment().putAll(environment);
processBuilder.directory(new File(workingDirectory));
processBuilder.command(parameters);
}
public int start(String input, StringBuilder output, StringBuilder error) throws IOException {
// start the process
process = processBuilder.start();
// start the error reader
Thread errorBranch = StreamHandler.read(process.getErrorStream(), error);
// start the output reader
Thread outputBranch = StreamHandler.read(process.getInputStream(), output);
// start the input
Thread inputBranch = StreamHandler.write(input, process.getOutputStream());
int rValue = 254;
try {
inputBranch.join(); rValue--;
outputBranch.join(); rValue--;
errorBranch.join(); rValue--;
return process.waitFor();
} catch (InterruptedException oE) {
oE.printStackTrace();
return rValue;
}
}
}
Testing
#Test public void foo() {
Command cmd = new Command("sh", "--");
StringBuilder output = new StringBuilder();
StringBuilder error = new StringBuilder();
int pValue = 127;
try {
pValue = cmd.start("echo well done > /dev/stderr\n\necho oh, wow; false", output, error);
} catch (IOException oE) {
}
System.out.println("output: "+output.toString());
System.out.println("error: "+error.toString());
System.out.println("\nExit code: "+pValue);
System.exit(pValue);
}
Bring your own package and JUnit annotations. This sample code demonstrates return value, command input, command standard output, and command error output.
My original design, called for the main thread to perform the standard output processing.
Have a great day.

How to debug this java code? The code is designed to get the CPU usage and memory info in the Linux System

This is a java code I search from the internet: http://avery-leo.iteye.com/blog/298724
Its goal is to get the CPU usage and memory info in the Linux System. I compiled it in eclipse and found two errors as follows:
private Config config=Config.getInstance();
SnmpUtil util=new SnmpUtil();
which I also mark in bold in the note part.
I think these two errors are caused by the lack of class Config and SnmpUtil, I tried to search and download a config.jar from the Internet and add it to the lib, but still it does not work!! I need your help!!
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.util.StringTokenizer;
import org.apache.log4j.Logger;
/**
* To get the cpu usage and memory in Linux system
*
* <p>
*/
public final class LinuxSystemTool implements Runnable{
private Logger log = Logger.getLogger(LinuxSystemTool.class);
private Config config=Config.getInstance(); //**Error when compiled**
/**
* get memory by used info
*
* #return int[] result
*
* result.length==4; int[0]=MemTotal;int[1]=MemFree;
* int[2]=SwapTotal;int[3]=SwapFree;
* #throws IOException
* #throws InterruptedException
*/
public void run() {
// TODO Auto-generated method stub
while (true) {
try {
exec();
Thread.sleep(config.getThreadTime());
} catch (Exception e) {
// TODO Auto-generated catch block
log.error("Performance Monitoring error:"+e.getMessage());
e.printStackTrace();
}
}
}
public void exec() throws Exception {
// ServerStatus ss = new ServerStatus();
InetAddress inet = InetAddress.getLocalHost();
System.out.println("Performance Monitoring ip:"+inet.toString());
String ip=inet.toString().substring(inet.toString().indexOf("/")+1);
log.info("Performance Monitoring ip:"+ip);
int[] memInfo = LinuxSystemTool.getMemInfo();
System.out.println("MemTotal:" + memInfo[0]);
System.out.println("MemFree:" + memInfo[1]);
SnmpUtil util=new SnmpUtil(); //**Error when compiled**
util.setCPU(getCpuInfo());
// util.setDISK(1);
util.setMEM(memInfo[0]/memInfo[1]);
util.setIP(ip);
}
public static int[] getMemInfo() throws IOException, InterruptedException {
File file = new File("/proc/meminfo");
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(file)));
int[] result = new int[4];
String str = null;
StringTokenizer token = null;
while ((str = br.readLine()) != null) {
token = new StringTokenizer(str);
if (!token.hasMoreTokens())
continue;
str = token.nextToken();
if (!token.hasMoreTokens())
continue;
if (str.equalsIgnoreCase("MemTotal:"))
result[0] = Integer.parseInt(token.nextToken());
else if (str.equalsIgnoreCase("MemFree:"))
result[1] = Integer.parseInt(token.nextToken());
else if (str.equalsIgnoreCase("SwapTotal:"))
result[2] = Integer.parseInt(token.nextToken());
else if (str.equalsIgnoreCase("SwapFree:"))
result[3] = Integer.parseInt(token.nextToken());
}
return result;
}
/**
* get memory by used info
*
* #return float efficiency
* #throws IOException
* #throws InterruptedException
*/
public static float getCpuInfo() throws IOException, InterruptedException {
File file = new File("/proc/stat");
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(file)));
StringTokenizer token = new StringTokenizer(br.readLine());
token.nextToken();
int user1 = Integer.parseInt(token.nextToken());
int nice1 = Integer.parseInt(token.nextToken());
int sys1 = Integer.parseInt(token.nextToken());
int idle1 = Integer.parseInt(token.nextToken());
Thread.sleep(1000);
br = new BufferedReader(
new InputStreamReader(new FileInputStream(file)));
token = new StringTokenizer(br.readLine());
token.nextToken();
int user2 = Integer.parseInt(token.nextToken());
int nice2 = Integer.parseInt(token.nextToken());
int sys2 = Integer.parseInt(token.nextToken());
int idle2 = Integer.parseInt(token.nextToken());
return (float) ((user2 + sys2 + nice2) - (user1 + sys1 + nice1))
/ (float) ((user2 + nice2 + sys2 + idle2) - (user1 + nice1
+ sys1 + idle1));
}
/**
*
* <p>
*
* #author
* </p>
* #date
*/
public static void main(String[] args) throws Exception {
int[] memInfo = LinuxSystemTool.getMemInfo();
System.out.println("MemTotal:" + memInfo[0]);
System.out.println("MemFree:" + memInfo[1]);
System.out.println("SwapTotal:" + memInfo[2]);
System.out.println("SwapFree:" + memInfo[3]);
System.out.println("CPU use ratio:" + LinuxSystemTool.getCpuInfo());
}
}
You need snmp4j jar for snmp related java development. you can get if from here.
Hope this will work for you.

File/Directory synchronization in Java using JSch?

Is it possible to do file/directory sync in Java using JSch ? I need to sync directory from a remote linux machine to my local windows machine. Is this possible ?
-Tivakar
The easiest way to download files from SCP server is using Commons VFS along with JSch:
import java.io.*;
import org.apache.commons.io.FileUtils;
import org.apache.commons.vfs2.*;
public class CopyRemoteFile {
public static void copyRemoteFiles(String host, String user, String remotePath, String localPath) throws IOException {
FileSystemOptions fsOptions = new FileSystemOptions();
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(fsOptions, "no");
SftpFileSystemConfigBuilder.getInstance().setIdentities(fsOptions,
new File[] { new File(FileUtils.getUserDirectoryPath() + "/.ssh/id_dsa") });
DefaultFileSystemManager fsManager = (DefaultFileSystemManager) VFS.getManager();
String uri = "sftp://" + user + "#" + host + "/" + remotePath;
FileObject fo = fsManager.resolveFile(uri, fsOptions);
FileObject[] files = fo.getChildren();
for (FileObject file : files) {
// We will be dealing with the files here only
if (file.getType() == FileType.FILE) {
FileUtils.copyInputStreamToFile(file.getContent().getInputStream(),
new File(localPath + "/" + file.getName().getBaseName()));
}
file.close();
}
fo.close();
fsManager.close();
}
}
It's just an example I got in my Wiki, so nothing fancy. But do keep in mind that if you'll close fsManager, you will not be able to open it again in the same VM. I got this issue while testing this solution...
Although the example above does not import any JSch classes, you need to put it in the classpath anyway.
The above example is using private key to authenticate with the remote host. You can easily change that by providing password and modifying the uri to include that.
If you need to sync files, you can compare dates of the files on the local file system (or DB, or any other source of the information) and the remote files:
import java.io.*;
import org.apache.commons.io.*;
import org.apache.commons.vfs2.*;
import org.apache.commons.vfs2.impl.*;
import org.apache.commons.vfs2.provider.sftp.*;
public class CopyRemoteFile {
public static void copyRemoteFiles(final String host, final String user, final String remotePath, final String localPath)
throws IOException {
FileSystemOptions fsOptions = new FileSystemOptions();
SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(fsOptions, "no");
SftpFileSystemConfigBuilder.getInstance().setIdentities(fsOptions,
new File[] { new File(FileUtils.getUserDirectoryPath() + "/.ssh/id_dsa") });
DefaultFileSystemManager fsManager = (DefaultFileSystemManager) VFS.getManager();
String uri = "sftp://" + user + "#" + host + "/" + remotePath;
FileObject fo = fsManager.resolveFile(uri, fsOptions);
FileObject[] files = fo.getChildren();
for (FileObject file : files) {
// We will be dealing with the files here only
File newFile = new File(localPath + "/" + file.getName().getBaseName());
if (file.getType() == FileType.FILE && newFile.lastModified() != file.getContent().getLastModifiedTime()) {
FileUtils.copyInputStreamToFile(file.getContent().getInputStream(), newFile);
newFile.setLastModified(file.getContent().getLastModifiedTime());
}
file.close();
}
fo.close();
fsManager.close();
}
}
Look at: http://the-project.net16.net/Projekte/projekte/Projekte/Programmieren/sftp-synchronisierung.html
There is a whole Programm uploadet.
Here is the sync Part:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Vector;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.SftpException;
/*
* This is the heart of the whole Program. I hope, the descriptions are precise enought.
*/
public class Sync{
public String ServerPath;
public File LocalFolder;
public sFTPclient client;
public ArrayList<String> serverContentList;
public ArrayList<String> pathList;
public Sync(File local, String to, sFTPclient client){
this.LocalFolder = local;
this.ServerPath = to;
this.client = client;
}
/*
* Executed once. Sets the Server Directory if it exists.
* If the local folder doesn't exist on the Server, it creates it.
*/
public void setServerDirectory() throws SftpException{
try{
client.sftpChannel.cd(ServerPath);
}catch(Exception e){
GUI.addToConsole(ServerPath + " don't exist on your server!");
}
String serverFolder = ServerPath.substring(ServerPath.lastIndexOf('/')+1, ServerPath.length());
if(!LocalFolder.getName().equals(serverFolder)){
try{
client.sftpChannel.mkdir(LocalFolder.getName());
client.sftpChannel.cd(LocalFolder.getName());
} catch (Exception e){
client.sftpChannel.cd(LocalFolder.getName());
}
this.ServerPath = ServerPath + "/" + LocalFolder.getName();
GUI.setNewServerFolder(ServerPath);
}
serverContentList = new ArrayList<String>();
pathList = new ArrayList<String>();
}
//The contentlist contains all Filenames, that should be synchronized
public void setToContentList(String ServerFolder) throws SftpException{
#SuppressWarnings("unchecked")
Vector<LsEntry> fileList = client.sftpChannel.ls(ServerFolder);
int size = fileList.size();
for(int i = 0; i < size; i++){
if(!fileList.get(i).getFilename().startsWith(".")){
serverContentList.add(fileList.get(i).getFilename());
pathList.add(ServerFolder);
}
}
}
/*
* Deletes the synchronized elements from the Lists
*/
public void deleteFromLists(String name){
int position = serverContentList.lastIndexOf(name);
if(position >= 0){
serverContentList.remove(position);
pathList.remove(position);
}
}
/*
* Main function for synchronizing. Works recursive for local folders.
*/
#SuppressWarnings("unchecked")
public void synchronize(File localFolder, String ServerDir) throws SftpException, FileNotFoundException{
if(client.sftpChannel.pwd() != ServerDir){
client.sftpChannel.cd(ServerDir);
}
setToContentList(ServerDir);
File[] localList = localFolder.listFiles();
Vector<LsEntry> ServerList = client.sftpChannel.ls(ServerDir);
ServerList.remove(0); ServerList.remove(0);
/*
* Upload missing Files/Folders
*/
int size = localList.length;
for(int i = 0; i < size; i++){
if(localList[i].isDirectory()){
if(checkFolder(localList[i], ServerDir)){
synchronize(localList[i], ServerDir + "/" + localList[i].getName());
deleteFromLists("SubFolder");
}else {
newFileMaster(true, localList[i], ServerDir);
}
} else {
checkFile(localList[i], ServerDir);
}
deleteFromLists(localList[i].getName());
}
}
/*
* Deletes all files on the server, which are not in the local Folder. Deletes also all missing folders
*/
public void deleteRest() throws SftpException, FileNotFoundException{
int size = serverContentList.size();
for(int i = 0; i < size; i++){
client.sftpChannel.cd(pathList.get(i));
newFileMaster(false, null, serverContentList.get(i));
}
}
/*
* Copy or delete Files/Folders
*/
public void newFileMaster(boolean copyOrNot, File sourcePath, String destPath) throws FileNotFoundException, SftpException{
FileMaster copy = new FileMaster(copyOrNot, sourcePath, destPath, client.sftpChannel);
copy.runMaster();
}
/*
*Useful to find errors - Prints out the content-List every time you call the method.
*If you have Problems, call it before and after every changes of the serverContentList!
*/
/*public void printServerContent(){
System.out.println("SERVER-Content: " + "\n");
for(int i = 0; i < serverContentList.size(); i++){
System.out.println(serverContentList.get(i) + " in " + pathList.get(i));
}
}*/
/*
* Looks ond the server, if the file is there. If not, or the local file has changed, it copies the file on the server.
*/
public void checkFile(File file, String path) throws SftpException, FileNotFoundException{
client.sftpChannel.cd(path);
if(!serverContentList.contains(file.getName())){
newFileMaster(true, file, ServerPath);
} else {
Long localTimeStamp = file.lastModified();
Long timeStamp = client.sftpChannel.stat(file.getName()).getATime()*1000L;
if(localTimeStamp > timeStamp){
newFileMaster(false, null, path + "/" + file.getName());
newFileMaster(true, file, path);
}
}
deleteFromLists(file.getName());
}
/*
* The same as the checkFile function. But it returns a boolean. (Easier to handle in the synchronized funtion)
* Don't check, if the folder has changed (I think this can't be the case)
*/
public boolean checkFolder(File folder, String path) throws SftpException{
client.sftpChannel.cd(path);
if(serverContentList.contains(folder.getName())){
return true;
}else { return false; }
}
}

Categories

Resources