I want to retrieve data from a website using Nashorn script engine
I have the java code where I can retrieve data from a sample website template.
Now I want to call that java file from java script file.
following is the code:
JAVA CODE(Nsample.java):
package sample;
import java.net.*;
import java.io.*;
public class Nsample
{
public static void main(String[] args)
{
String output = getUrlContents("https://freewebsitetemplates.com/");
System.out.println(output);
}
public static String getUrlContents(String theUrl)
{
StringBuilder content = new StringBuilder();
try
{
URL url = new URL(theUrl);
URLConnection urlConnection = url.openConnection();
BufferedReader bufferedReader = new BufferedReader(new
InputStreamReader(urlConnection.getInputStream()));
String line;
while ((line = bufferedReader.readLine()) != null)
{
content.append(line + "\n");
}
bufferedReader.close();
}
catch(Exception e)
{
e.printStackTrace();
}
return content.toString();
}
}
JAVASCRIPT code:(sample.js)
var n = Java.type('C.JavaFolder.sample.Nsample');
var result = n.getUrlContents("https://freewebsitetemplates.com/");
print(result);
I'm trying to compile javascript code using command prompt but it is showing CLASSNOTFOUNDEXCEPTION.
The command was jjs sample.js.Im assuming I did some mistake in Java.type() function.
Can anyone solve this?
This line is the problematic line:
var n = Java.type('C.JavaFolder.sample.Nsample');
Java.type accepts fully qualified java type name. Based on your Java code, your package seems to be "sample" and class name is "Nsample". So the fully qualified class name would be "sample.Nsample".
You should compile your Java classes and specify the directory in -classpath option (of jjs tool or your java application if you use javax.script API with nashorn).
Instead of calling Java from JavaScript , I tried to call JavaScript from java and worked well.
I created some functions in JavaScript and invoked those functions from Java code.
Following is the code.Hope this helps.
Test.java:
import javax.script.*;
import java.io.*;
import java.util.*;
public class Test{
public static void main(String[] args) throws Exception{
ScriptEngine engine = new ScriptEngineManager().getEngineByName("Nashorn");
engine.eval(new FileReader("test.js"));
Invocable invoke = (Invocable)engine;
Object res = invoke.invokeFunction("httpGet","https://www.javaworld.com");
System.out.println(res);
}
}
test.js:
var httpGet = function(theUrl){
var con = new java.net.URL(theUrl).openConnection();
con.requestMethod = "GET";
return asResponse(con);
}
function asResponse(con){
var d = read(con.inputStream);
return d;
}
function read(inputStream){
var inReader = new java.io.BufferedReader(new
java.io.InputStreamReader(inputStream));
var inputLine;
var response = new java.lang.StringBuffer();
while ((inputLine = inReader.readLine()) != null) {
response.append(inputLine);
}
inReader.close();
return response.toString();
}
Related
I have a path (eg: "C:/Users/aaa/bbb/ccc/"), my aim to get the parent path (i.e. "C:/Users/aaa/bbb/")
For this I tried using java.nio.file.Paths, which worked in java and I tried converting the same into nashorn js:
import java.nio.file.Paths;
public class ReadPropertiesFile {
public static void main(String[] args) {
String myPath = "C:/Users/aaa/bbb/ccc/";
System.out.println(Paths.get(myPath).getParent());
}
}
Nashorn script:
var testPath = "C:/Users/aaa/bbb/ccc/";
var Paths = java.import("java.nio.file.Paths");
try{
var test = Paths.get(testPath).getParent();
console.log("++++++MyFINALPATH+++++"+test);
}catch (e){ console.log("++++++MyFINALPATH+++++"+e);
}
Expected output: C:/Users/aaa/bbb/
Error-
TypeError: Paths.get(...).getParent is not a function
You need to use this instead:
var Paths = Java.type("java.nio.file.Paths");
https://docs.oracle.com/javase/9/scripting/using-java-scripts.htm#JSJSG117
Using the browser if I visit a certain direct download URL, it automatically downloads the file. However, when I use Java code to download the file, I get the HTML code instead of the file contents:
<html>
<body>
<script type="text/javascript" src="/aes.js"></script>
<script>function toNumbers(d) {
var e = [];
d.replace(/(..)/g, function (d) {
e.push(parseInt(d, 16))
});
return e
}
function toHex() {
for (var d = [], d = 1 == arguments.length && arguments[0].constructor == Array ? arguments[0] : arguments, e = "", f = 0; f < d.length; f++) e += (16 > d[f] ? "0" : "") + d[f].toString(16);
return e.toLowerCase()
}
var a = toNumbers("f655ba9d09a112d4968c63579db590b4"), b = toNumbers("98344c2eee86c3994890592585b49f80"),
c = toNumbers("b5eb8dc5c53e5107faa7ec1c1f3e3dc7");
document.cookie = "__test=" + toHex(slowAES.decrypt(c, 2, a, b)) + "; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/";
location.href = "http://example.com/Test.txt?i=1";</script>
<noscript>This site requires Javascript to work, please enable Javascript in your browser or use a browser with
Javascript support
</noscript>
</body>
</html>
My file downloading code is e.g. the following:
URL url = new URL("...");
try (InputStream inputStream = url.openStream())
{
Files.copy(inputStream, downloadedFilePath, REPLACE_EXISTING);
}
How would it be possible to download the file programmatically in Java? There are ways to execute JavaScript but how is it supposed to work exactly? It seems like the document.cookie has to be set (correctly) to download.
Downloading works by passing the correct cookie value alongside of the request. The cookie value can be retrieved using e.g. the Google Chrome DevTools -> Application -> Cookies. Since in my example the cookie value does not change, a code like the following would do the trick:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class DownloadWithCookieExample
{
public static void main(String[] arguments)
{
try
{
URL url = new URL("...");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestProperty("Cookie", "blabla"); // Hard-coded correct cookie value
String readStream = readStream(con.getInputStream());
System.out.println(readStream);
} catch (Exception exception)
{
exception.printStackTrace();
}
}
private static String readStream(InputStream inputStream) throws IOException
{
StringBuilder stringBuilder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)))
{
String line;
while ((line = reader.readLine()) != null)
{
stringBuilder.append(line);
stringBuilder.append(System.lineSeparator());
}
}
return stringBuilder.toString().trim();
}
}
An even better solution would be to execute the JavaScript to receive the cookie value and to pass the result. This task is left as an exercise for another answer for whoever knows how to do this elegantly.
So I'm trying to make a webservice that allows someone to obtain data from a server. Right now, the server I'm using is written using java's HttpServer class. I plan to make the server accessible using fetch() in javascript, but it's not working.
When I was first testing out my server, I used Apache's HttpComponents library, and that client(written in java). was able to receive the test json that came from my server. However, when I used fetch() on my javascript client, nothing is received when I console.log everything. It doesn't make sense to me why it would work in Java, but not javascript. Does anyone know why this is not working? Am I just doing the javascript part wrong, and it does actually work? Thanks!
Code snippets for reference:
java server:
public class Main {
private static final int PORT = 1337;
private static final int BACKLOG = 1;
public static void main(String[] args) {
try {
HttpServer server = HttpServer.create(new InetSocketAddress(PORT), BACKLOG);
System.out.print("started on" + PORT);
HttpContext context = server.createContext("/ex", new Handler());
server.start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Handler implements HttpHandler {
#Override
public void handle(HttpExchange he) throws IOException {
System.out.println("handled");
JSONObject obj = new JSONObject();
obj.put("name", "value");
obj.put("num", new Integer(100));
obj.put("balance", new Double(1000.21));
obj.put("is_vip", new Boolean(true));
obj.put("array", new int[]{1, 2, 3});
String response = obj.toJSONString();
he.sendResponseHeaders(200, response.length());
he.getResponseBody().write(response.getBytes());
}
}
java client:
public class PostTest {
public static void main(String[] args) throws IOException {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpPost httppost = new HttpPost("http://localhost:1337/ex");
CloseableHttpResponse response = httpClient.execute(httppost);
System.out.println("STATUS LINE");
System.out.println(response.getStatusLine().toString());
System.out.println("HEADER");
Header[] h = response.getAllHeaders();
for(int i = 0; i < h.length; i++) {
System.out.println(h[i]);
}
System.out.println("ENTITY.CONTENT");
try(BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"))) {
String s;
while((s = br.readLine()) != null) {
System.out.println(s);
}
}
}
}
Javascript:
var init = {mode: "no-cors"};
async function f() {
return fetch("http://localhost:1337/ex", init).then(res => res.text()).then(posts => console.log(posts));
}
f();
I have Silverlight app. For example I want add some JS script which can interact with SL app. For example I want add google map use JS api. Can I do this, But I must send some data from SL to JS to add pins on map, draw figures on map ect.
If you are using Windows Phone and you dont mind that part of the xaml to be a webview yo can.
First add a webview to the xaml
<phone:WebBrowser Name="webView" BorderThickness="0" BorderBrush="Transparent" IsScriptEnabled="True"
ScriptNotify="WebBrowser_ScriptNotify" />
Then you have to bind the webview with the load event and then saveg files to storage and load your html and js files
webView.Loaded += WebBrowser_OnLoaded;
private void WebBrowser_OnLoaded(object sender, RoutedEventArgs e)
{
SaveFilesToIsoStore();
chatView.Navigate(new Uri("Assets/HtmlContent/index.html", UriKind.Relative));
}
private void SaveFilesToIsoStore()
{
//These files must match what is included in the application package,
//or BinaryStream.Dispose below will throw an exception.
string[] files = {
"Assets/HtmlContent/index.html",
"Assets/HtmlContent/js/libs/jquery-1.11.0.min.js", "Assets/HtmlContent/js/pagejs.js", "Assets/HtmlContent/css/style.css"
};
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
if (false == isoStore.FileExists(files[0]))
{
foreach (string f in files)
{
StreamResourceInfo sr = Application.GetResourceStream(new Uri(f, UriKind.Relative));
using (BinaryReader br = new BinaryReader(sr.Stream))
{
byte[] data = br.ReadBytes((int)sr.Stream.Length);
SaveToIsoStore(f, data);
}
}
}
}
private void SaveToIsoStore(string fileName, byte[] data)
{
string strBaseDir = string.Empty;
string delimStr = "/";
char[] delimiter = delimStr.ToCharArray();
string[] dirsPath = fileName.Split(delimiter);
//Get the IsoStore.
IsolatedStorageFile isoStore = IsolatedStorageFile.GetUserStoreForApplication();
//Re-create the directory structure.
for (int i = 0; i < dirsPath.Length - 1; i++)
{
strBaseDir = System.IO.Path.Combine(strBaseDir, dirsPath[i]);
isoStore.CreateDirectory(strBaseDir);
}
//Remove the existing file.
if (isoStore.FileExists(fileName))
{
isoStore.DeleteFile(fileName);
}
//Write the file.
using (BinaryWriter bw = new BinaryWriter(isoStore.CreateFile(fileName)))
{
bw.Write(data);
bw.Close();
So on the js you have to talk to the c# like this
function sendMessageToCodeBehind(someData) {
window.external.notify(JSON.stringify({ method: 'AddMessage', data: someData }));
}
On the code behind you would recibe the messages from the webview like this:
private void WebBrowser_ScriptNotify(object sender, NotifyEventArgs e)
{
var example = new { method = string.Empty, data = new object() };
var obj = JsonConvert.DeserializeAnonymousType(e.Value, example);
switch (obj.method) {
case "methodName":
}
}
And you would send back messages to the js like this
webView.InvokeScript("jsMethodName", JsonConvert.SerializeObject(new { Message = "some json message" }));
How is this achieved? Here it says the java version is:
WebDriver driver; // Assigned elsewhere
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("return document.title");
But I can't find the C# code to do this.
The object, method, and property names in the .NET language bindings do not exactly correspond to those in the Java bindings. One of the principles of the project is that each language binding should "feel natural" to those comfortable coding in that language. In C#, the code you'd want for executing JavaScript is as follows
IWebDriver driver; // assume assigned elsewhere
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
string title = (string)js.ExecuteScript("return document.title");
Note that the complete documentation of the WebDriver API for .NET can be found at this link.
I prefer to use an extension method to get the scripts object:
public static IJavaScriptExecutor Scripts(this IWebDriver driver)
{
return (IJavaScriptExecutor)driver;
}
Used as this:
driver.Scripts().ExecuteScript("some script");
the nuget package Selenium.Support already contains an extension method to help with this. Once it is included, one liner to executer script
Driver.ExecuteJavaScript("console.clear()");
or
string result = Driver.ExecuteJavaScript<string>("console.clear()");
How about a slightly simplified version of #Morten Christiansen's nice extension method idea:
public static object Execute(this IWebDriver driver, string script)
{
return ((IJavaScriptExecutor)driver).ExecuteScript(script);
}
// usage
var title = (string)driver.Execute("return document.title");
or maybe the generic version:
public static T Execute<T>(this IWebDriver driver, string script)
{
return (T)((IJavaScriptExecutor)driver).ExecuteScript(script);
}
// usage
var title = driver.Execute<string>("return document.title");
You could also do:
public static IWebElement FindElementByJs(this IWebDriver driver, string jsCommand)
{
return (IWebElement)((IJavaScriptExecutor)driver).ExecuteScript(jsCommand);
}
public static IWebElement FindElementByJsWithWait(this IWebDriver driver, string jsCommand, int timeoutInSeconds)
{
if (timeoutInSeconds > 0)
{
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
wait.Until(d => d.FindElementByJs(jsCommand));
}
return driver.FindElementByJs(jsCommand);
}
public static IWebElement FindElementByJsWithWait(this IWebDriver driver, string jsCommand)
{
return FindElementByJsWithWait(driver, jsCommand, s_PageWaitSeconds);
}
public void javascriptclick(String element)
{
WebElement webElement=driver.findElement(By.xpath(element));
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].click();",webElement);
System.out.println("javascriptclick"+" "+ element);
}
public static class Webdriver
{
public static void ExecuteJavaScript(this IWebDriver driver, string scripts)
{
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteScript(scripts);
}
public static T ExecuteJavaScript<T>(this IWebDriver driver, string scripts)
{
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
return (T)js.ExecuteScript(scripts);
}
}
In your code you can then do:
IWebDriver driver = new WhateverDriver();
string test = driver.ExecuteJavaScript<string>(" return 'hello World'; ");
int test = driver.ExecuteJavaScript<int>(" return 3; ");
Please use the below extension methods added to execute javascript and to take screenshot in Selenium.Support (.dll) of Selenium C#
https://www.nuget.org/packages/Selenium.Support/
IWebDriver driver = new ChromeDriver();
driver.Manage().Window.Maximize();
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(20);
driver.Url = "https://phptravels.net/";
driver.ExecuteJavaScript("document.querySelector('#checkin').value='07-12-2022'");
driver.ExecuteJavaScript("document.querySelector('#checkout').value='17-12-2022'");
IWebElement ele1 = driver.FindElement(By.Id("checkin"));
driver.ExecuteJavaScript("arguments[0].value='07-12-2022'",ele1);
string output=driver.ExecuteJavaScript<string>("return
document.querySelector('#checkin').value");
Console.WriteLine(output);
Screenshot sc= driver.TakeScreenshot();
sc.SaveAsFile("C:\\error.png");
The shortest code
ChromeDriver drv = new ChromeDriver();
drv.Navigate().GoToUrl("https://stackoverflow.com/questions/6229769/execute-javascript-using-selenium-webdriver-in-c-sharp");
drv.ExecuteScript("return alert(document.title);");