Android arp table - developing questions - java

I've got two problems with the android app I'm writing.
I'm reading out the local arp table from /proc/net/arp and save ip and corresponding mac address in a hash map. See my function. It's working properly.
/**
* Extract and save ip and corresponding MAC address from arp table in HashMap
*/
public Map<String, String> createArpMap() throws IOException {
checkMapARP.clear();
BufferedReader localBufferdReader = new BufferedReader(new FileReader(new File("/proc/net/arp")));
String line = "";
while ((line = localBufferdReader.readLine()) != null) {
String[] ipmac = line.split("[ ]+");
if (!ipmac[0].matches("IP")) {
String ip = ipmac[0];
String mac = ipmac[3];
if (!checkMapARP.containsKey(ip)) {
checkMapARP.put(ip, mac);
}
}
}
return Collections.unmodifiableMap(checkMapARP);
}
First problem:
I'm also using a broadcast receiver. When my app receives the State WifiManager.NETWORK_STATE_CHANGED_ACTION i check if the connection to the gateway is established. If true i call my function to read the arp table. But in this stage the system has not yet builded up the arp table. Sometimes when i receive the connection state the arp table is sill empty.
Anyone got an idea to solve this?
Second problem:
I want to save the ip and mac address of the gateway in a persistent way. Right now i'm using Shared Preferences for this. Maybe it's better to write to an internal storage?
Any tips?

For the first problem you could start a new thread that runs that method after sleeping for a set amount of time or until it has some entries (Make a Runnable with a mailbox to get the Map) - unless you need to use the map directly, then I think the only way is to wait for the entries. For example (if you need to use the map directly):
public Map<String, String> createArpMap() throws IOException {
checkMapARP.clear();
BufferedReader localBufferdReader = new BufferedReader(new FileReader(new File("/proc/net/arp")));
String line = "";
while ((line = localBufferdReader.readLine()) == null) {
localBufferdReader.close();
Thread.sleep(1000);
localBufferdReader = new BufferedReader(new FileReader(new File("/proc/net/arp")));
}
do {
String[] ipmac = line.split("[ ]+");
if (!ipmac[0].matches("IP")) {
String ip = ipmac[0];
String mac = ipmac[3];
if (!checkMapARP.containsKey(ip)) {
checkMapARP.put(ip, mac);
}
}
} while ((line = localBufferdReader.readLine()) != null);
return Collections.unmodifiableMap(checkMapARP);
}

Related

JNA - How to get processID by .exe

So I'm using "findWindow" atm to get the processID, but lets say instead of using find window for example to get "Call Of Duty Black Ops", I want to straight up get the processID with the process name itself which is "BlackOps.exe". How would I do this?
here is my code to find proccess id with java "
public static void main(String[] args) {
String taskListCommand = System.getenv("windir") + "\\system32\\" + "tasklist.exe";
try {
final Process p = Runtime.getRuntime().exec(taskListCommand);
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
try {
while ((line = input.readLine()) != null) {
if (line.contains("BlackOps.exe")) {
System.out.println(line);
PID = (line.split("\\s+"))[1];
System.out.println("PID = " + PID);
break;
}
}
input.close();
} catch (IOException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
#using<System.dll>
using namespace System;
using namespace System::Diagnostics;
using namespace System::ComponentModel;
int main()
{
// Get the current process.
Process^ currentProcess = Process::GetCurrentProcess();
// Get all processes running on the local computer.
array<Process^>^localAll = Process::GetProcesses();
// Get all instances of Notepad running on the local computer.
// This will return an empty array if notepad isn't running.
array<Process^>^localByName = Process::GetProcessesByName("notepad");
// Get a process on the local computer, using the process id.
// This will throw an exception if there is no such process.
Process^ localById = Process::GetProcessById(1234);
// Get processes running on a remote computer. Note that this
// and all the following calls will timeout and throw an exception
// if "myComputer" and 169.0.0.0 do not exist on your local network.
// Get all processes on a remote computer.
array<Process^>^remoteAll = Process::GetProcesses("myComputer");
// Get all instances of Notepad running on the specific computer, using machine name.
array<Process^>^remoteByName = Process::GetProcessesByName( "notepad", "myComputer" );
// Get all instances of Notepad running on the specific computer, using IP address.
array<Process^>^ipByName = Process::GetProcessesByName( "notepad", "169.0.0.0" );
// Get a process on a remote computer, using the process id and machine name.
Process^ remoteById = Process::GetProcessById( 2345, "myComputer" );
}
The code above is written by microsoft itself, you can see the full answer here:
https://msdn.microsoft.com/en-us/library/z3w4xdc9(v=vs.110).aspx?cs-save-lang=1&cs-lang=cpp#code-snippet-2

garbage collector does not work

I have a program that download stocks data from the internet and then create a Stock objects that contains a stock meta data and an array of historical prices.
At first I ran over more then 20000 stocks created them and entered them into an arraylist for writing them to the db(all of them in one transaction). this wasn't a good idea and before i ended to download all the stocks i wanted the program died because of OutOfMemory.
Then i decided that after every 500 stocks that i am adding to the arraylist i will write them to the DB and clean the arraylist(arraylist.clear() for GC to make it's "magic") and then fill the arraylist with another new 500 Stocks and go through the same proccess all over again.
That didn't work either, and my program died again because of an OutOfMemory Exception.
I thought that the problem may be in some where else in my code and I made an experiment and ran the same code but one little difference: after i create each Stock object i do not put it into the arraylist and i just continue and create Stock objects all over again without adding them into the arraylist.
The result was that my program didn't consume almost any memory at all and that make me really confused and frustrated.
Please help me find out if something is wrong with my program.
Here are some lines of the code:
The first version:
ArrayList<Stock> stocksData = new ArrayList<Stock>();
Stock stock;
BufferedReader br = null;
String line = "";
try {
br = new BufferedReader(new FileReader(YAHOO_STOCKS_SYMBOLS));
while ((line = br.readLine()) != null) {
String[] stockMetaData = line.split(CSV_SPLIT);
stock = new Stock();
if (stockMetaData.length >= 4) {
stock.setSymbol(stockMetaData[0]);
stock.setName(stockMetaData[1]);
stock.setExchange(stockMetaData[2]);
stock.setCategory(stockMetaData[3]);
DATA_UPDATER.updateStockData(stock, fromDate, toDate);
if (stock.getHistoricalData() != null
&& stock.getHistoricalData().size() > 0) {
stocksData.add(stock);
}
}
}
}
the second version:
ArrayList<Stock> stocksData = new ArrayList<Stock>();
Stock stock;
BufferedReader br = null;
String line = "";
try {
br = new BufferedReader(new FileReader(YAHOO_STOCKS_SYMBOLS));
while ((line = br.readLine()) != null) {
String[] stockMetaData = line.split(CSV_SPLIT);
stock = new Stock();
if (stockMetaData.length >= 4) {
stock.setSymbol(stockMetaData[0]);
stock.setName(stockMetaData[1]);
stock.setExchange(stockMetaData[2]);
stock.setCategory(stockMetaData[3]);
DATA_UPDATER.updateStockData(stock, fromDate, toDate);
if (stock.getHistoricalData() != null
&& stock.getHistoricalData().size() > 0) {
stocksData.add(stock);
}
}
if (stocksData.size() == 500) {
WritingUtils.getInstance().updateStocks(stocksData);
stocksData.clear();
// I also tried
//System.gc();
}
}
}
Im adding some more information:
Stock fields:
protected String _symbol;
protected String _name;
protected String _exchange;
protected Date _upToDate;
protected ArrayList<DailyData> _historicalData;
DailyData fields:
private Date _date;
private double _open;
private double _close;
private double _adjClose;
private double _high;
private double _low;
private double _volume;
First I would start by profiling the application with a tool like JVisualVM (which comes with the JDK) and pinpointing exactly what objects are being retained in the heap.
Second, there is no 'clean()' method on ArrayList, so its not clear what you actually did to prevent your list from growing indefinitely.
Lastly, consider setting a conditional breakpoint in your program to 'catch' when the List is growing beyond your expectation.
EDIT: If what you're asking now is :
'Can my OutOfMemoryError be due to the fact that:
protected ArrayList<DailyData> _historicalData;
is growing and contributing to the memory pressure?'
The answer is yes. Have you also tried to increase the memory to your process? Try running:
java -Xms1g -Xmx1g *yourProgram*
to see if it still fails. You may not have a leak, it may just be that your application needs more memory for what you are doing.

How to get the remote user's username in java

I am working on application which doesn't have any login mechanism, any user in my organization can use that. But I want to pick the username of the remote users who will use my tool. I have a button clicking on that I want to get their usernames.
I tried request.getRemoteUser got null. tried System.getenv("USERNAME") getting the logged in user of the localhost where the server resides. Tried getHostName, System.getProperty got the localhost name. Tried this also - new com.sun.security.auth.module.NTSystem().getName() but same result.
I am using java6, windows server and glassfish3 server.
Please suggest something as I don't want to use any external link and tool.
You want to do something called SSO (Single Sign On): A user is logged in somewhere (in your case his Windows computer) and you want to authenticate the user with this (already done) login. This is a very common use case and there are different ways to do that. However, the big question is always how you can trust those third party system. And this is where the trouble begins.
Since your question is not very clear, I assume you have a Java Glassfish server running on Windows Server and a Java client (because you asked for Java code). So the Java server must authenticate who the user of the Java client is. And the server must trust this information.
Using System.getProperty("user.name"); isn't a good idea since anybody can change it. You can start your Java program with java -Duser.name=Joe <your_program> and that's it.
But since you are on Windows, you could use Windows to help you. If both, your client and server, are in the same domain, they are authenticated against the same system. You can ask this system for the user identity. Typically machines of a company are in the same domain.
To do this there is a tool called Waffle. It does a secure Windows authentication between machines in the same domain. If your client and server are in the same domain, it is an easy way to perform an SSO (a single sign on). You can find it on GitHub: http://dblock.github.io/waffle/
Here is a simple example from one of my own questions a couple of months ago (see here):
// client credentials handle
IWindowsCredentialsHandle credentials= WindowsCredentialsHandleImpl.getCurrent("Negotiate");
credentials.initialize();
// initial client security context
WindowsSecurityContextImpl clientContext = new WindowsSecurityContextImpl();
clientContext.setPrincipalName(Advapi32Util.getUserName());
clientContext.setCredentialsHandle(credentials.getHandle());
clientContext.setSecurityPackage(securityPackage);
clientContext.initialize();
// accept on the server
WindowsAuthProviderImpl provider = new WindowsAuthProviderImpl();
IWindowsSecurityContext serverContext = null;
do {
if (serverContext != null) {
// initialize on the client
SecBufferDesc continueToken = new SecBufferDesc(Sspi.SECBUFFER_TOKEN, serverContext.getToken());
clientContext.initialize(clientContext.getHandle(), continueToken);
}
// accept the token on the server
serverContext = provider.acceptSecurityToken(clientContext.getToken(), "Negotiate");
} while (clientContext.getContinue() || serverContext.getContinue());
System.out.println(serverContext.getIdentity().getFqn());
for (IWindowsAccount group : serverContext.getIdentity().getGroups())
System.out.println(" " + group.getFqn());
You can use Waffle also for websites. However, I didn't do that and cannot explain you what to do in this case.
And one important remark: I think you are a little bit confused. If you do request.getRemoteHost() on your server, you try to get the identity of the client who send the request (by the way, it is not secure, a client could send anything). However, if you do System.getProperty("user.name") on your server, you try to get the name of the server itself. Be aware where you are (on client or server) and what you want. And make sure whether you can trust this information or not. Security is difficult.
java class code to find who loggedin into a remote computer in a domain
package com.test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import com.test.Pubfun;
public class UserName {
public static HashMap <String,String> hmun=new HashMap<String, String>();
public String setUserFromIP(String arg1) {
String m = arg1;
StringBuilder user = new StringBuilder();
String u = "";
String user2 = null;
try {
Process p = Runtime.getRuntime().exec("query user /server:" + m);
p.waitFor();
BufferedReader reader = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line = reader.readLine();
while (line != null) {
line = reader.readLine();
user.append(line);
line=null;
}
} catch (IOException e1) {
} catch (InterruptedException e2) {
}
u = user.toString().replace("null", "");
try {
user2 = this.getUserFromString(u);
} catch (ArrayIndexOutOfBoundsException ae) {
}
u.replace("null", " ");
System.out.println(user2);
hmun.put("username",user2);
return user2;
}
public static String gethmun()
{
String t=hmun.get("username");
return t;
}
public String getUserFromString(String u) {
HashMap <String,String> hmun=new HashMap<String, String>();
String input = u;
int length, size;
length = input.length();
size = length ;
String strarray[] = new String[size];
strarray = input.split("\\s+");
for (int i = 0; i < strarray.length; i++) {
if(strarray[i].equals("Active")){
hmun.put("username", strarray[i-3]);
}
}
String user1=hmun.get("username");
return user1;
}
}
HttpServletRequest.getRemoteUser() might optionally return the login of user making the request (if authenticated), but it is not the username of the user logged in on the remote machine.
There is no way to query the username of the remote machine. Browsers or applications making the requests might send this info voluntarily, but if they don't, you won't find a way to get it. And by default they don't send it so don't count on this.
This gives you the current logged in Username from your local Windows System System.getProperty("user.name");

in this case it is better to use database or read for file to increase performance?

This my class TagVertex contain one method that read the tag value=string from textual file
and return it
public class TagVertex extends Vertex<String> {
#Override
public String computeVertexValue() {
String s = null;
try {
BufferedReader bf = new BufferedReader(new FileReader(MyDataSource.TagList1K));
for(int i = 1; i < Integer.parseInt(this.getVertexId().substring(this.getVertexId().indexOf("g")+1)); i++){
bf.readLine();
}
s= bf.readLine();
bf.close();
} catch (Exception e) {
e.printStackTrace();
}
this.setVertexValue(s);
return s;
}
the method is called 1000 times ==>the file is read 1000 times too
It is better to use database instead of textual file?
Accessing the hard drive is always a very slow operation. Databases usually also access the hard drive, so they aren't necessarily faster. They can be even slower, because when the database doesn't run on the same system, the network latency is added (even when it runs on localhost, you have latency due to interprocess communication).
I would recommend you to read the file once and cache the value. When you need to be aware immediately when the file is changed, you could use the new WatchService API to reload the file when it was changed. Here is a tutorial. When it isn't that important that changes on filesystem level are registred immediately, you could also save the time the vertex information was read from the hard drive, and only re-read the value when it's older than a few seconds.
You can create your own in memory database like this.
private static final List<String> lines = new ArrayList<>();
#Override
public String computeVertexValue() {
if (lines.isEmpty())
try {
BufferedReader br = new BufferedReader(new FileReader(MyDataSource.TagList1K));
for (String line; (line = br.readLine()) != null; )
lines.add(line);
br.close();
} catch (Exception e) {
e.printStackTrace();
}
return lines.get(Integer.parseInt(this.getVertexId().substring(this.getVertexId().indexOf("g") + 1)));
}

Java - Wifi API

I am trying to find out if there is a Wifi API for Java. Something that can connect to Wifi networks and scan them (to find devices). I can't seem to find something like that. Any suggestions? Thanks!
P.S.
I know about the WifiManager for Android, but I am not developing for Android, I am developing with JDK 6.
Wireless networking cards differ greatly depending on manufacturer and even version, and most operating systems do not have a standardized way of interacting with them. Some computers do not even come with wireless cards. The reason it works so well with Android is because Google can guarantee that every phone that has Android installed has a proper wireless networking interface.
tl;dr no, sorry
You can take help of command line tools to get list of available networks using command "netsh wlan show networks mode=Bssid".
Try below java method.
public static ArrayList scanWiFi() {
ArrayList<String> networkList = new ArrayList<>();
try {
// Execute command
String command = "netsh wlan show networks mode=Bssid";
Process p = Runtime.getRuntime().exec(command);
try {
p.waitFor();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
BufferedReader reader = new BufferedReader(
new InputStreamReader(p.getInputStream())
);
String line;
StringBuilder sb = new StringBuilder();
String ssidArr[];
while ((line = reader.readLine()) != null) {
//System.out.println(line);
if (line.contains("SSID ") && !line.contains("BSSID ")) {
sb.append(line);
networkList.add(line.split(":")[1]);
//System.out.println("data : " + ssidArr[1]);
}
}
//System.out.println(networkList);
} catch (IOException e) {
}
return networkList;
}

Categories