How to create dataset on mainframe using FTP from java - java

I am trying to FTP a text file to mainframe using java. I am able to create a member in PDS using below code.
//Function to FTP the report
public void sendReport() throws IOException
{
FTPSClient ftp = null;
InputStream in = null;
String protocol="TLS";
//Connecting to mainframe server for ftp transfer
ftp = new FTPSClient(protocol);
ftp.connect(hostname);
ftp.login(user,password);
ftp.execPBSZ(0);
ftp.execPROT("P");
ftp.enterLocalPassiveMode();
ftp.setFileType(FTP.ASCII_FILE_TYPE);
int reply = ftp.getReplyCode();
System.out.println("Received Reply from FTP Connection:" + reply);
if (FTPReply.isPositiveCompletion(reply))
System.out.println("Connected To Mainframe");
else
System.out.println("Not connected to Mainframe..Check ID or Password");
//Setting mainframe PDS for reports
boolean success = ftp.changeWorkingDirectory("***Mainframe Directory***");
if (success)
System.out.println("Successfully changed PDS.");
else
System.out.println("Failed to change PDS. See Mainframe's reply.");
//Sending Report to mainframe PDS
File f1 = new File(dkReportName);
in = new FileInputStream(f1);
boolean done = ftp.storeFile("DKI"+dkReportName.substring(14,18), in);
in.close();
if (done)
System.out.println("FILE FTP SUCCESSFUL");
else
System.out.println("FILE FTP NOT SUCCESSFUL");
ftp.logout();
ftp.disconnect();
}
user,password and hostname variables are being set in appContext.xml.
However, I want to create a PS dataset.
Could anyone please suggest a way of doing it.

Based on your question, this is for the MVS file space and not USS.
When creating a dataset with FTP you need to give the host some information about files size, attributes, etc.
This page on IBM's website outlines a list of commands that you can execute to setup for the transfer. The basic sequence would be something like:
site cyl
site pri=5
site sec=5
site recfm=fb
and you can combine more than one command on a line:
site lrecl=80 blksize=3120
Execute these commands before the transfer and the file should be allocated with your desired characteristics.
Based on your coding example here is a sample that should work:
ftp.sendCommand("site",
"cyl pri=5 sec=5 recfm=fb filetype=seq lrecl=80 blksize=3120");

Related

How do I deserialize the Minecraft player.dat?

I'm trying to make a plugin for Velocity to sync player data among different sub servers.
I want to deserialize the player.dat which is saved in the /world/playerdata/ directory, then upload ut to MySQL. When a player connect a different sub server, I'll read the data in MySQL and send the data to the targeted sub server to make the player data synchronous.
It's solved by myself.
We can use NBTCompressedStreamTools, which you need to know about NMS, like this
File playerDataFolder = new File(getDataFolder().getParentFile().getParentFile(), "world\\playerdata\\");
File playerDat = new File(playerDataFolder, player.getUniqueId().toString() + ".dat");
try {
FileInputStream inputStream = new FileInputStream(playerDat);
NBTTagCompound nbt = NBTCompressedStreamTools.a(inputStream);
}catch (Exception e) {
e.printStackTrace();
}

Rsync with AWS lambda(java) between Bucket and Remote Server

I want to perform an one direction rsync between an AWS S3 Bucket and a remote ftp server (accepts ftps) with a java lambda function. So if one file in bucket is deleted the lambda cron should remove it from the remote ftp server.
I read that aws cli offers the function s3 sync. Could this be an option?
best regards
Jannik
This would be pretty straight forward. The Lambda would be setup to be triggered on an S3 delete. The basic code (untested) would be something like:
public class Handler implements RequestHandler<S3Event, String> {
public String handleRequest(S3Event s3event, Context context) {
try {
S3EventNotificationRecord record = s3event.getRecords().get(0);
// Object key may have spaces or unicode non-ASCII characters.
String srcKey = record.getS3().getObject().getUrlDecodedKey();
// now use Apache Commons Net
// (https://commons.apache.org/proper/commons-net/)
// to delete the file on the FTP server
FTPClient ftpClient = new FTPClient();
ftpClient.connect(server, port);
int replyCode = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(replyCode)) {
contect.getLogger().log("SFTP Connect failed");
return;
}
boolean success = ftpClient.login(user, pass);
if (!success) {
contect.getLogger().log("Could not login to the FTP server");
return;
}
String fileToDelete = "/some/ftp/directory/" + srcKey;
boolean deleted = ftpClient.deleteFile(fileToDelete);
if (deleted) {
contect.getLogger().log("The file was deleted successfully.");
} else {
contect.getLogger().log("Could not delete the file, it may not exist.");
}
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
On the S3 side, you will need to enable your S3 bucket to send a delete event to your Lambda. This can be done in the AWS console by selecting the bucket and in the advanced section, add select Events, add a notification, select "Permanently deleted" (or "All object delete events") and add your Lambda.

Connect to MySQL with Java - JDBC without showing credentials in Java source code

I am trying to learn how you would tackle the task of creating a Java console application, connect to a (in this case) MySQL DB and send or retrieve data, without showing your username and password in the source code of the Java application. I currently have no trouble
creating a connection showing credentials.
// JDBC driver name and database URL
private static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
private static final String DB_URL = "jdbc:mysql://192.168.1.159:3306/javahelper";
// Database credentials
private static final String USER = "xxxx";
private static final String PASS = "RandomString";
/**
* #return
*/
public Connection openConnection() {
Connection connection = null;
try {
Class.forName(JDBC_DRIVER);
// opening connection
connection = (Connection) DriverManager.getConnection(DB_URL,USER,PASS);
} catch (ClassNotFoundException e) {
System.out.println("This is from openConnection method");
e.printStackTrace();
} catch (SQLException f) {
System.out.println("This is from openConnection method");
f.printStackTrace();
}
return connection;
}
From what information I can gather you always need to show your credentials somewhere in the application. But how do you than achieve "safe" connection between a application and a DB, so others can't misuse your credentials for malicious reasons?
one way of doing it is using a properties file having your credentials or having your data in a xml file.
create a properties file like the one below
// database.properties
DB_URL=jdbc:mysql://localhost:3306/UserDB
DB_USERNAME=user_name
DB_PASSWORD=password
Use this information in your code to get the username and passwords.
Properties properties= new Properties();
FileInputStream input = null;
try{
input = new FileInputStream("database.properties");
props.load(input );
con = DriverManager.getConnection(props.getProperty("DB_URL"),props.getProperty("DB_USERNAME"),props.getProperty("DB_PASSWORD"));
}
you can use encrypt the username and password.The best opensource encryptor(My personal view) is jbcrypt
// Hash a password for the first time
String hashed = BCrypt.hashpw(password, BCrypt.gensalt());
// gensalt's log_rounds parameter determines the complexity
// the work factor is 2**log_rounds, and the default is 10
String hashed = BCrypt.hashpw(password, BCrypt.gensalt(12));
// Check that an unencrypted password matches one that has
// previously been hashed
if (BCrypt.checkpw(candidate, hashed))
System.out.println("It matches");
else
System.out.println("It does not match");
Sharing what i find
Creating and using the propertise file
I created a database.properties file(normal text file) and placed it in the src folder of the Java project.
JDBC_DRIVER=com.mysql.jdbc.Driver
USER=YourUser
PASS=YourPassword
DB_URL=jdbc:mysql://IP:PORT/DB
Afterwards i edited my openConnection() method to use the properties file for loading the credientials of the connection.
public Connection openConnection() {
Properties properties = new Properties();
Connection connection = null;
String path = System.getProperty("user.dir");
path += "/src/database.properties";
try(FileInputStream fin = new FileInputStream(path);) {
properties.load(fin);
try {
Class.forName(properties.getProperty("JDBC_DRIVER"));
// opening connection
connection = (Connection) DriverManager.getConnection(properties.getProperty("DB_URL"),properties.getProperty("USER"),properties.getProperty("PASS"));
} catch (ClassNotFoundException e) {
System.out.println("This is from openConnection method");
e.printStackTrace();
} catch (SQLException f) {
System.out.println("This is from openConnection method");
f.printStackTrace();
}
} catch (IOException io) {
System.out.println("This is from openConnection method");
io.printStackTrace();
}
return connection;
}
Sending username and password, Java application -> MySQL
From what i can read on the web, it dosent matter much if you encrypt or hash the password before you send it towards the sequel service from your Java application. An example i found is that the sequel service dosent have a "receive hash method and authenticate". And even if it did the hash would need to be in the program somewhere. And when the program has access to it, others also have access to it if they really want it. Also if the hash is whats needed to authenticate than your back to where you can just as well use the clear text password.
The discussion than ends on "what is the best approach". Some suggest a keyserver / auth system in between the application and sequel service, using a datastore setup on the server side, using the OS "wallet" (example Windows registry) or creating a database user with minimum permissions to just get the job done / or a read only DB "read_only=1 in my.cnf".
I tried the 3'rd option and created a "DBaccess" user, with only the select permission to retrieve data, no administrative rights and random generated password by MySQL.

Java FTP Transfer disconnect detect

I am working on a simple piece of java code for transferring a file from an HTTP site to the local machine. All works well and I can download without any problem. The code below updates my progress bar status during the download also without any problem.
My Question: How do I detect that the FTP site is no longer available/connected wile downloading? A separate thread monitoring the ftp isAvailible () and isConnected () methods always returns true even with the network switched off?
Please see code below:
// Disable the download button
BTNdownload.setText("Downloading...");
BTNdownload.setEnabled (false);
// Create a instance of the FTP client
ftpClient = new FTPClient();
// Setup the FTP client
ftpClient.connect(server, port);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
// Create a file in destination folder
output = new File(destination);
// Request the download file size
ftpClient.sendCommand("SIZE", origin);
// Get the size of the file
String size = ftpClient.getReplyString().split(" ") [1].trim();
total = Long.parseLong(size);
// Set the JProgressBar limits
JPBprogress.setMinimum(0);
JPBprogress.setMaximum((int) total/1024);
// Enable the progress bar
JPBprogress.setEnabled(true);
// Create a input stream from the remote file
stO = ftpClient.retrieveFileStream(origin);
// Create a output stream to the output file
OutputStream stD = new BufferedOutputStream(new FileOutputStream(output));
// Add a progress listener to the copy process
org.apache.commons.net.io.Util.copyStream(stO, stD, ftpClient.getBufferSize(),
org.apache.commons.net.io.CopyStreamEvent.UNKNOWN_STREAM_SIZE,
new org.apache.commons.net.io.CopyStreamAdapter() {
public void bytesTransferred(long totalBytesTransferred,
int bytesTransferred,
long streamSize) {
// Update the progress bar
JPBprogress.setValue((int) totalBytesTransferred/1024);
}
});
// Close the input & output stream
stO.close();
stD.close ();
// Send the FTP completed command
ftpClient.completePendingCommand();
// Close the connection
ftpClient.abort();
// Set the update button enabled
BTNinstall.setEnabled(true);
You can use sendNoOp() to ping the ftp server in order to keep the connection alive on a long running download.

Android/Java - ClassNotFoundException for ServerSocket and Socket communication

I'm developing an app where the phone (Android program) is the client trying to send data through a socket to a Java receiver program on my computer.
So far I've been able to send simple strings or whatever, but now I'm trying to send custom objects that I create. I should note that both programs are separate Eclipse projects, and I seem to be having trouble including the same custom class "Order" on the server side (even though I have Order.java in the src folder of the server project).
Some code, for reference:
Server:
private void run() throws Exception {
ServerSocket mySS = new ServerSocket(4443);
while(true) {
Socket SS_accept = mySS.accept();
InputStream is = SS_accept.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
Order order = (Order) ois.readObject();
if (order!=null){
java.util.List<String> items = order.getOrders();
int chair = order.getChair();
int table = order.getTable();
double price = order.getPrice();
System.out.println("Table: "+ table + " || Chair: " +chair);
for(String food: items) {
System.out.println(food);
}
System.out.println("Price: $"+price);
}
is.close();
SS_accept.close();
mySS.close();
}
And the relevant part of the client:
try {
mySocket = new Socket(serverService.ipAddress, serverService.port);
os = mySocket.getOutputStream();
oos = new ObjectOutputStream(os);
} catch(Exception e) {
Toast.makeText(PlaceOrder.this, "Error - not connected to server.", Toast.LENGTH_SHORT).show();
}
try {
oos.writeObject(order);
Toast.makeText(PlaceOrder.this, "Order Submitted!", Toast.LENGTH_SHORT).show();
refreshOrderPage(); //refresh page, allow waiter to make more orders
oos.close();
os.close();
mySocket.close();
} catch (Exception e) {
Toast.makeText(PlaceOrder.this, "Error - not connected to server.", Toast.LENGTH_SHORT).show();
}
Any ideas why I'm getting this error when trying to send objects through sockets?
Thanks.
You should probably set the serialVersionUID in the class, then build a jar with the shared classes and include that jar in both projects.
However, given you are using different JVMs (Oracle and Dalvik) there's no guarantee that the byte-level encoding is the same. You should either manually override the serialization using readObject/writeObject or use a different object encoding system that is guaranteed to be identical independent of the environment.
A stack trace would help, but almost certainly you're serializing an object on one side, sending it to the other, and the other side doesn't have a class definition with which it can reconstruct the object. In this case, it sounds like maybe your Server doesn't know about the com.foo.Order class.
You can also serialize object to some string format (json, yaml, xml) and pass it. It would much easier to maintain, I suppose.

Categories

Resources