How to setup the connection time out with "file://" protocol - java

Let said I have a file call ext.properties that was located in SERVER_A/Config folder
If the code can access the SERVER_A, then following code is working fine, and handle the work for the InputStream
try{
String remote = "SERVER_A/Config/ext.properties";
String remoteFilePath = "file://" + remote;
URL url = new URL(remoteFilePath);
System.out.println("Begin to open " + LocalDateTime.now());
URLConnection con = url.openConnection();
InputStream is = con.getInputStream();
//do somework with InputStream
System.out.println("Finish open " + LocalDateTime.now());
}catch(Exception e){
System.out.println("Error occur " + LocalDateTime.now());
e.printStackTrace();
}
However, for some reason SERVER_A cannot be accessed, the code above will run into Exception block after like 5-40 seconds. I want the code to handle like this if it cannot get the connection in 2 seconds, throw the exception.
I also try to add con.setConnectionTimeout(2000) after URLConnection con = url.openConnection(); But it doesn't work... How can I resolve this?

Access to UNC-paths are passed to the operating system, so setting timeouts in the URLConnection won't work (and the whole thing wouldn't work on an e.g. Linux system). There are libraries like jcifs that allow you to access UNC-paths without going via the operating system (limited to SMBv1 though) where you can set timeouts and other things.

Related

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.

Scraping a site

I am trying to write an alert system to scrape complaints board site periodically to look for any complaints about my product. I am using Jsoup for the same. Below is the the code fragment that gives me error.
doc = Jsoup.connect(finalUrl).timeout(10 * 1000).get();
This gives me error
java.net.SocketException: Unexpected end of file from server
When I copy paste the same finalUrl String in the browser, it works. I then tried simple URL connection
BufferedReader br = null;
try {
URL a = new URL(finalUrl);
URLConnection conn = a.openConnection();
// open the stream and put it into BufferedReader
br = new BufferedReader(new InputStreamReader(
conn.getInputStream()));
doc = Jsoup.parse(br.toString());
} catch (IOException e) {
e.printStackTrace();
}
But as it turned out, the connection itself is returning null (br is null). Now the question is, why does the same string when copy pasted in browser opens the site without any error?
Full stacktrace is as below:
java.net.SocketException: Unexpected end of file from server
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:774)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:633)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:771)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:633)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1195)
at ComplaintsBoardScraper.main(ComplaintsBoardScraper.java:46)
That one was tricky! :-)
The server blocks all requests which don't have a proper user agent. And that’s why you succeeded with your browser but failed with Java.
Fortunately changing user agent is not a big thing in jsoup:
final String url = "http://www.complaintsboard.com/?search=justanswer.com&complaints=Complaints";
final String userAgent = "Mozilla/5.0 (X11; U; Linux i586; en-US; rv:1.7.3) Gecko/20040924 Epiphany/1.4.4 (Ubuntu)";
Document doc = Jsoup.connect(url) // you get a 'Connection' object here
.userAgent(userAgent) // ! set the user agent
.timeout(10 * 1000) // set timeout
.get(); // execute GET request
I've taken the first user agent I found … I guess you can use any valid one instead too.

Checking for a file on a remote server, and if it exists, download it

I have recently been trying to create an updater for my program. The updater is supposed to go to dropbox, look through the files in the 'public' folder, and decide if it exists. It works, and can DOWNLOAD the file, but it can't CHECK if the file exists. I saw this and I thought it was a solution, but it doesn't seem to be working.
Here is the code I'm using to check for the file's existence:
public static boolean exists(String URLName) {
try {
HttpURLConnection.setFollowRedirects(false);
HttpURLConnection con = (HttpURLConnection) new URL(URLName)
.openConnection();
con.setRequestMethod("HEAD");
return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
However, it seems to always return true. The files I'm accessing all begin with "App_" and end with ".zip". The only thing that varies is the version, which is in the #.### format.
Here is the FULL code for how I'm checking it:
public static void main(String[] args) throws IOException,
InterruptedException {
double origVersion = 0.008;
double versionTimes = 0.000;
while(exists("http://dl.dropbox.com/u/.../" + "App_"+ String.valueOf(origVersion + versionTimes) + ".zip")) {
versionTimes = round(versionTimes + 0.001);
//origVersion = round(origVersion + 0.001);
System.exit(0);
}
}
public static boolean exists(String URLName) {
try {
HttpURLConnection.setFollowRedirects(false);
// note : you may also need
// HttpURLConnection.setInstanceFollowRedirects(false)
HttpURLConnection con = (HttpURLConnection) new URL(URLName)
.openConnection();
con.setRequestMethod("HEAD");
return (con.getResponseCode() == HttpURLConnection.HTTP_OK);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
static double round(double d) {
DecimalFormat twoDForm = new DecimalFormat("#.###");
return Double.valueOf(twoDForm.format(d));
}
Sorry about that... That code was too long. Anyway. To test this, right now it will check if version 0.009 is available. Which it is. Its full version is in the variable double origVersion. Now, if you set origVersion to 0.009, it will check for 0.01. Which is fine, except for the fact that App_0.01.zip DOES NOT exist, and yet it still says it does!
I have also looked into wget to solve this problem, by starting up wget with the arguments
THEFILENAME --no-proxy --spider
but that didn't work either. Can anyone help me? I would greatly appreciate it.
I also saw somewhere else that you could establish a connection with the file and if it secures, the file exists. If not, it doesn't. However, I have no idea how to do that. Can anyone bring me out of the dark?
[EDIT]
Also, running the THEFILENAME --no-proxy --spider on wget worked, and outputted the following, when checking for version 0.009:
Spider mode enabled. Check if remote file exists.
--2012-03-16 08:59:55-- http://dl.dropbox.com/u/.../....zip
Resolving dl.dropbox.com... 107.21.103.249, 107.20.135.4, 107.20.198.68, ...
Connecting to dl.dropbox.com|107.21.103.249|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 758067 (740K) [application/zip]
Remote file exists.
And when checking for version 0.01:
Spider mode enabled. Check if remote file exists.
--2012-03-16 09:01:15-- http://dl.dropbox.com/u/.../....zip
Resolving dl.dropbox.com... 107.22.196.64, 50.19.217.32, 174.129.218.194, ...
Connecting to dl.dropbox.com|107.22.196.64|:80... connected.
HTTP request sent, awaiting response... 404 NOT FOUND
Remote file does not exist -- broken link!!!
I also tried reading the output of wget using this, and using if(input.indexOf("404 NOT FOUND") == -1), but still to no avail.
Doing a HEAD request is definitely the right way to check if a file exists on a remote server.
I can't see anything wrong with your exists(String URLName) method so I would check that it is being passed the URL you think it is.
What looks odd to be is this line:
versionTimes = round(versionTimes + 0.001);
You're changing the value of versionTimes in between checking for the existence of the file and printing your message.

How to check server is up?

I have got a cluster of two server nodes IBM Websphere Application Server on two different physical machine.Can anybody help me with java code to check whether my server instance is running or when one of the server is not up and running?
To do it quickly and portably, you can check for a page if it's served by the server.
For example you can:
boolean isAlive = true;
try {
URL hp = new URL("http://yourserver/TestPage.html");
URLConnection hpCon = hp.openConnection();
// add more checks...
} catch (Exception e) {
isAlive = false;
}
This not much sophisticated method will work with every http server.
Hope below is what you want...
URL url = new URL( "http://google.com/" );
HttpURLConnection httpConn = (HttpURLConnection)url.openConnection();
httpConn.setInstanceFollowRedirects( false );
httpConn.setRequestMethod( "HEAD" );
httpConn.connect();
System.out.println( "google.com : " + httpConn.getResponseCode());
or for failure:
URL url = new URL( "http://google.com:666/" );
HttpURLConnection httpConn = (HttpURLConnection)url.openConnection();
httpConn.setInstanceFollowRedirects( false );
httpConn.setRequestMethod( "HEAD" );
try{
httpConn.connect();
System.out.println( "google.com : " + httpConn.getResponseCode());
}catch(java.net.ConnectException e){
System.out.println( "google.com:666 is down ");
}
Good Luck!!!
I think what you may be looking for is the use of the WebSphere Thin Administrative Client, which exposes Java APIs and provides access to the WAS MBeans that allow you to query the status of your servers/applications (along with many other management and monitoring tasks).
First, you'll want to obtain a connection to WAS (the AdminClient) as follows:
Properties clientProps = new Properties();
clientProps.setProperty(AdminClient.CONNECTOR_TYPE, AdminClient.CONNECTOR_TYPE_SOAP);
clientProps.setProperty(AdminClient.CONNECTOR_HOST, dmgrHostname);
clientProps.setProperty(AdminClient.CONNECTOR_PORT, dmgrSoapConnectorPort);
if (dmgrIsSecure) {
clientProps.setProperty(AdminClient.CONNECTOR_SECURITY_ENABLED, "true");
clientProps.setProperty(AdminClient.USERNAME, wasUsername);
clientProps.setProperty(AdminClient.PASSWORD, wasUserPassword);
}
AdminClient adminClient = AdminClientFactory.createAdminClient(clientProps);
Next, you'll want to query for the relevant MBeans, and then perform the relevant operations. In your case, you may be interested in the ClusterMgr and/or J2EEApplication MBeans. Here is an example that queries for the Cluster's state:
AdminClient adminClient = getAdminClient(target);
ObjectName clusterMgr =
(ObjectName)adminClient.queryNames(
ObjectName.getInstance("WebSphere:*,type=ClusterMgr"), null).iterator().next();
String state = adminClient.invoke(clusterMgr, "getClusterState",
new Object[] {clusterName}, new String[] {String.class.getName()});
You can invoke further operations as desired, such as querying the individual cluster member's status.
Also, in addition to querying, you can also register notifications so that your program can be notified when certain events happen, such as a change in state of clusters, servers, or applications.
We get the specialized connection for the URL we want using openConnection(). It will return a subclass of the abstract class URLConnection, depending on the URL's public protocol, for example a HttpURLConnection. Then with the method connect() opens the communication link
private String server = "http://testserver:9086";
try {
URLConnection hpCon = new URL(SERVER).openConnection();
hpCon.connect();
} catch (Exception e) {
// Anything you want to do when there is a failure
}

How to pass URL parameters from Java to local HTML file in Windows 7?

I desperately need your expertise in resolving a Windows-7 issue.
Scenario: I have a frame-based Help package that is set up for context-sensitive help calls. A Java application is able to control what page the Help packages opens to by passing a tag representing the desired HTML named anchor to an HTML file called pophelp. This file has javascripting that reads the passed tag from the end of the URL and maps it to the appropriate HTML file in the help package and opens it.
Issue: The above scenario works in Windows XP, but no longer in Windows 7.
Calling mechanism from Java application: rundll32 url.dll,FileProtocolHandler file://filepath/pophelp.html?tag
Summary of findings so far: It appears that url.dll no longer allows parameters to be passed with URLs in Windows 7. Parameters are being stripped. I also tried the same type of call using Desktop.getDesktop().browse() from Java, but it too seems to strip off all parameters after .html.
Sample code:
Original call that works in Windows XP --
Running command: rundll32 url.dll,FileProtocolHandler file://C:\Program Files\App System\App-Editor-8.0.1\help\pophelp.html?TAG=callsubflow
Result: ?TAG=callsubflow is not passed.
New code using Desktop.getDesktop().browse() --
public static void main(String[] args) {
String url = "file:///C:/Program Files/App System/App-Editor-8.0.1/help/pophelp.html?TAG=callsubflow";
try {
if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
if (desktop.isSupported(Desktop.Action.BROWSE)) {
desktop.browse(new URI(url.replace(" ", "%20")));
}
}
} catch (IOException e) {
System.out.println("Unable to open "+url+": "+e.getMessage());
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
Result: ?TAG=callsubflow is not passed.
Any assistance would be appreciated!
I really can't tell why Windows removes parameters on local files. As mentioned in the comments this seams to be some kind of weird restrictions for security. But I once had a similar problem and I found a workaround that fits in this situation as well.
Simply create a local temporary HTML file (without parameters) that redirects you to the desired one (with parameters).Have a look at these two methods:
// creates w3c conform redirect HTML page
public String createRedirectPage(String url){
return "<!DOCTYPE HTML>" +
"<meta charset=\"UTF-8\">" +
"<meta http-equiv=\"refresh\" content=\"1; url=" + url + "\">" +
"<script>" +
"window.location.href = \"" + url + "\"" +
"</script>" +
"<title>Page Redirection</title>" +
"<!-- Note: don't tell people to `click` the link, just tell them that it is a link. -->" +
"If you are not redirected automatically, follow the <a href='" + url + "'>link</a>";
}
// creates temporary file with content of redirect HTML page
public URI createRedirectTempFile(String url) {
BufferedWriter writer = null;
File tmpFile = null;
try {
// creates temporary file
tmpFile = File.createTempFile("pophelp", ".html", null);
// deletes file when the virtual machine terminate
tmpFile.deleteOnExit();
// writes redirect page content to file
writer = new BufferedWriter(new FileWriter(tmpFile));
writer.write(createRedirectPage(url));
writer.close();
}
catch (IOException e) {
return null;
}
return tmpFile.toURI();
}
Now you can use these like this:
String url = "file:///C:/Program Files/App System/App-Editor-8.0.1/help/pophelp.html?TAG=callsubflow";
if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
if (desktop.isSupported(Desktop.Action.BROWSE)) {
desktop.browse(createRedirectTempFile(url.replace(" ", "%20")));
}
}
I have a solution, not a quick (or pretty) solution, but a solution nonetheless :)
rundll32 url.dll,FileProtocolHandler does pass params when using URLs with http/s protocol (try rundll32 url.dll,FileProtocolHandler http://www.google.com?q=google), so you can setup small http server (like Jetty i guess) to serve your help files and show them using
rundll32 url.dll,FileProtocolHandler http://localhost:[helpServerIp]/help/pophelp.html?TAG=callsubflow

Categories

Resources