I'd like to put native Java objects into the ScriptEngine bindings for easier access.
I mean to avoid lots of Java.type(...).
I tried in that way.
jsEngine.getContext().getBindings(ScriptContext.ENGINE_SCOPE).put("manager", Manager.getInstance());
But that's failed with error "Manager has no such function "funcName" in eval...".
Is it possible at all?
UPD:
Example code
public class ManagerClass {
public void test()
{
System.out.println("Hello");
}
public static void test2()
{
System.out.println("Hello Static");
}
}
public class NewClass {
public static void main(String[] args) throws ScriptException {
final ScriptEngine s = new ScriptEngineManager().getEngineByExtension("js");
s.getBindings(ScriptContext.ENGINE_SCOPE).put("manager", new ManagerClass());
s.eval("manager.test(); manager.test2();");
}
}
Solved.
The correct way is
s.eval("manager.test(); manager.class.static.test2();");
Related
I have two java files under the tests directory.
I use the following code to set up Soot for further analysis(i.e., construct a call graph) but meet an error of are the packages set properly?.
Main.java:
public class Main {
static void setupSoot() {
Options.v().set_prepend_classpath(true);
Options.v().set_process_dir(Collections.singletonList("./tests"));
Options.v().set_whole_program(true);
Scene.v().loadNecessaryClasses();
}
// Following function also doesn't work and has a similar error message
//static void setupSoot() {
// Options.v().set_prepend_classpath(true);
// Options.v().set_process_dir(Collections.singletonList("./tests"));
// Scene.v().loadClassAndSupport("FooBar");
//}
public static void main(String[] args) {
setupSoot();
// ....
}
}
And I get the following error message:
Exception in thread "main" java.lang.RuntimeException: Error: couldn't find class: FooBar are the packages set properly?
at soot.JastAddInitialResolver.resolveFromJavaFile(JastAddInitialResolver.java:119)
at soot.JavaClassSource.resolve(JavaClassSource.java:69)
at soot.SootResolver.bringToHierarchyUnchecked(SootResolver.java:253)
at soot.SootResolver.bringToHierarchy(SootResolver.java:221)
at soot.SootResolver.bringToSignatures(SootResolver.java:292)
at soot.SootResolver.bringToBodies(SootResolver.java:332)
at soot.SootResolver.processResolveWorklist(SootResolver.java:171)
at soot.SootResolver.resolveClass(SootResolver.java:141)
at soot.Scene.loadClass(Scene.java:1009)
at soot.Scene.loadClassAndSupport(Scene.java:994)
at soot.Scene.loadNecessaryClasses(Scene.java:1822)
at Main.setupSoot(Main.java:18)
at Main.main(Main.java:21)
If I complie two test files into .class files then I will get following error message:
Exception in thread "main" soot.SootResolver$SootClassNotFoundException: couldn't find class: tests.FooBar (is your soot-class-path set properly?)
at soot.SootResolver.bringToHierarchyUnchecked(SootResolver.java:245)
at soot.SootResolver.bringToHierarchy(SootResolver.java:221)
at soot.SootResolver.bringToSignatures(SootResolver.java:292)
at soot.SootResolver.bringToBodies(SootResolver.java:332)
at soot.SootResolver.processResolveWorklist(SootResolver.java:171)
at soot.SootResolver.resolveClass(SootResolver.java:141)
at soot.Scene.loadClass(Scene.java:1009)
at soot.Scene.loadClassAndSupport(Scene.java:994)
at soot.Scene.loadNecessaryClasses(Scene.java:1822)
at Main.setupSoot(Main.java:18)
at Main.main(Main.java:21)
I beleive that soot prepend_classpath is true since it works well when two test files are not in the package (i.e., remove package tests from both files).
Two files in tests directory are as follows:
Pack.java:
package tests;
public class Pack {
public static void main(String[] args) {
int s = 10;
}
}
FooBar.java
package tests;
public class FooBar {
public static void main(String[] args) {
FooBar callFooBar = new FooBar();
callFooBar.foo(10);
}
void foo(int a) {
bar(a);
}
void bar(int a) {
for (int i = 0; i < a; i++) {
i += a;
}
}
}
I solved this problem. The issue is that the path of the test files is wrong.
Now my project structure is as follows:
-ProjectRoot
|--src
|--Main.java
|--testers
|--easycase
|--FooBar.java
|--Pack.java
and My Main.java:
public class Main {
static void setupSoot() {
Options.v().set_prepend_classpath(true);
// Options.v().set_soot_classpath("xxxxx:xxxxx/xxxxx.jar") // For external packages
Options.v().set_process_dir(Collections.singletonList("./testers"));
Options.v().set_whole_program(true);
Scene.v().loadNecessaryClasses();
}
public static void main(String[] args) {
setupSoot();
Scene.v().loadAndSupport("esaycase.FooBar");
// Do something here
}
}
Note that the first line is package easycase; for both test files.
I am starting to learn Java and was wondering if I it's normal/safe to pass an object of same class as a parameter to a method in the same class? I tried it and it works, just wanted to know if it's a standard practice.
code snippet below;
class App{
private int databaseFlag=0;
private String s;
public App() {
// TODO Auto-generated constructor stub
s = "value";
}
public static void main(String[] args) {
App app = new App();
app.init(app);
app.methodOne();
app.methodTwo();
}
public void init(App app){
DatabaseClass dbc = new DatabaseClass();
app.databaseFlag = dbc.callDatabaseMethodAndGetFlag(s);
}
public void methodOne(){
// do something with databaseFlag
}
public void methodTwo(){
// do something more then reset databaseFlag=0;
}
}
Even though, with in object's method, you can call other method by its name i.e.,
class App {
private void init () {
//some code
someOtherMethod();
}
private void someOtherMethod() {
//someother code
}
public static void main(String[] args) {
App a = new App();
a.init()
}
}
See how someOtherMethod is being called from init? You don't need your class reference here.
To answer your specific question, In Java, every object has access to its reference and that is called this, you don't need to pass in the app object. if you absolutely have to refer the object variables, you can do it by this
class App{
private int databaseFlag=0;
private String s;
public App() {
// TODO Auto-generated constructor stub
s = "value";
}
public static void main(String[] args) {
App app = new App();
app.init();
app.methodOne();
app.methodTwo();
}
public void init(){
DatabaseClass dbc = new DatabaseClass();
this.databaseFlag = dbc.callDatabaseMethodAndGetFlag(s);
}
public void methodOne(){
// do something with databaseFlag
}
public void methodTwo(){
// do something more then reset databaseFlag=0;
}
}
Hi ive been reading on some similar topics here but none of them answer my question. Some say you cant even do this which is not a good thing since I cant finnish my course in that case.
Heres som simple code. Think of each block as a separate class.
public interface Interface {
void printMessage(String meddelande);
}
public class Model implements Interface {
String message = "hej!";
public static void main(String[] args) {
Model model1 = new Model();
View view1 = new View();
model1.printMessage(model1.message); //Ska jag anropa funktionen såhär ens?
}
public void printMessage(String str) {
}
}
public class View implements Interface {
printMessage(String str) {
}
}
So, how is it now possible to tel the view to print this string from the model class without the classes knowing about each other? Its not allowed to send a reference of the model-objekt to the view-object. ; (
Define an Interface:
public interface MyInterface {
void printMessage(String str);
}
Define a class that can trigger the notification:
public class ClassNotifier {
MyInterface mInterface;
public ClassNotifier(MyInterface mInterface) {
this.mInterface = mInterface;
}
public void triggerTheMsg(String msg) {
if (mInterface != null) {
mInterface.printMessage(msg);
}
}
}
Define a class that will be informed:
public class InformedClass implements MyInterface {
public static void main(String[] args) throws Exception {
InformedClass c = new InformedClass();
ClassNotifier cn = new ClassNotifier(c);
}
#Override
public void printMessage(String newMsg) {
System.out.println("A new msg is here: " + newMsg);
}
}
How does it works?:
this is named a callback parttern, the class ClassNotifier has a reference to the interface MyInterface, which is impl. by Informed class to, so every time the ClassNotifier calls the method printMessage, the method printMessage in the class Informed will be triggered too.
I advice you to use dependency injection, for example:
public class Model {
String message = "hej!";
Interface printer;
public void Model(Interface printer) {
printer = printer;
}
public static void main(String[] args) {
Model model1 = new Model(new View());
model1.printMessage(model1.message);
}
public void printMessage(String str) {
printer.printMessage(str);
}
}
Does Java have anything similar to C#'s Action type? Is Java 8 or Pre-Java 8 the way to go? Why or why not? I'm trying to avoid going down any rabbit holes. Please help me understand my options...
Statement:
Driver.NoWait(() => links = rowFindElements(ByLinkText(title)));
Methods:
public static void NoWait(Action action)
{
TurnOffWait();
action();
TurnOnWait();
}
public static void TurnOnWait()
{
Instance.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(5));
}
public static void TurnOffWait()
{
Instance.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(0));
}
UPDATE
Thanks to #Nick Y and a programmer at the office (who told me the history of Java pragmatics vs Java traditionalists). This is the outcome of my findings:
Feature Menu Class 1st Way Post Java 8
public class FeatureMenu
{
static WebElement sideTab;
public static void Expand()
{
try
{
Iframe.Default.SwitchTo();
Driver.NoWait(() -> sideTab = Driver.Instance.findElement(By.cssSelector("div.wijmo-wijsplitter-v-panel1-collapsed")));
sideTab.click();
Log.Info("Feature Menu Expanded.");
}
catch(Exception e)
{
Log.Error("[EXCEPTION CAUGHT] : FeatureMenu.Expand()");
throw(e);
}
}
}
Feature Menu 2nd Way Pre Java 8
public class FeatureMenu
{
static WebElement sideTab;
public static void Expand()
{
try
{
Iframe.Default.SwitchTo();
Driver.NoWait( new Driver.Action(){ public void apply(){
sideTab = Driver.Instance.findElement(By.cssSelector("div.wijmo-wijsplitter-v-panel1-collapsed"));
}
});
sideTab.click();
Log.Info("Feature Menu Expanded.");
}
catch(Exception e)
{
Log.Error("[EXCEPTION CAUGHT] : FeatureMenu.Expand()");
throw(e);
}
}
}
Driver Class that can be used with either approach
public class Driver
{
public static WebDriver Instance;
public static String BaseAddress(String baseAddress)
{
return baseAddress;
}
public static void Initialize(String driverType)
{
Instance = new FirefoxDriver();
Instance.manage().window().maximize();
TurnOnWait();
}
#FunctionalInterface
public interface Action {
void apply();
}
public static void NoWait(Action action)
{
TurnOffWait();
action.apply();
TurnOnWait();
}
public static void TurnOffWait()
{
Instance.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
}
public static void TurnOnWait()
{
Instance.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
}
}
If you want to get closer to the most recent C# version you would want to use Java 8 (not pre-Java 8)
Java 8 has lambdas and functional interfaces which can get you very close to how things are done in C#. Google "functional interface java". There is a lot good information out there.
In the context of your specific question think about functional interfaces in java as delegates in C#.
public delegate void Action()
can be mimicked in java 8 as
#FunctionalInterface
public interface Action() {
void apply();
}
With this in mind, here is the simple usage of Action interface and lambda
public class MainWithAction {
public static void main(String[] args) {
noWait(() -> doSomething());
}
public static void noWait(Action action) {
turnOffWait();
action.apply();
turnOnWait();
}
public static void doSomething() { /* do something */ }
public static void turnOnWait() { /* skipped */ }
public static void turnOffWait() { /* skipped */ }
}
It is not a requirement to use #FunctionalInterface annotation but it helps compiler to generate error messages in certain cases.
apply() method name can be changed to anything else it is more of a convention thing.
Java 8 has a few predefined functional interfaces in package java.util.function however it appears that there is nothing that returns void and takes no parameters so you would need to have your own. Read more here:
https://softwareengineering.stackexchange.com/questions/276859/what-is-the-name-of-a-function-that-takes-no-argument-and-returns-nothing
You may want to consider having NoWaitAction interface which can be a more appropriate name for your scenario instead of a generic Action interface. It's up to you.
Having said all that I am moving to more interesting point of going down the rabbit hole.
Your particular use case may not map 100% into the java code. Let's try to convert this line.
Driver.NoWait(() => links = rowFindElements(ByLinkText(title)));
What caught my eye here is the links variable. It does look like a local variable to me. If this is not the case then the bellow is irrelevant, but may still trigger some thoughts.
For the sake of this exercise I am going to assume that links is a local variable of List of Strings type and rowFindElements takes String parameter and returns a List of Strings
Here is one way of converting this into java (with NoWaitAction as an example of my above point):
#FunctionalInterface
public interface NoWaitAction {
void apply();
}
and the meat
public class MainNoWaitAction {
public static void main(String[] args) {
List<String> links = new ArrayList<>();
String title = "title";
noWait(() -> links.addAll(rowFindElements(title)));
}
public static void noWait(NoWaitAction action) {
turnOffWait();
action.apply();
turnOnWait();
}
public static void turnOnWait() { /* skipped */ }
public static void turnOffWait() { /* skipped */ }
public static List<String> rowFindElements(String title) {
return new ArrayList<>(); // populate the list
}
}
There are various other ways of doing it, but the main point here is that the following will not compile
noWait(() -> links = rowFindElements(title));
Why? Read this answer for example
https://stackoverflow.com/a/4732617/5947137
Update 1
Based on OP comments I would like to suggest another approach
public class MainNoWaitAction {
public static void main(String[] args) {
List<String> links;
Object otherVariable;
String title = "title";
links = noWait(() -> rowFindElements(title));
otherVariable = noWait(() -> createAnObject());
}
public static <T> T noWait(Supplier<T> supplier) {
turnOffWait();
try {
return supplier.get();
} finally {
turnOnWait();
}
}
private static void turnOnWait() { /* skipped */ }
private static void turnOffWait() { /* skipped */ }
private static List<String> rowFindElements(String title) {
return new ArrayList<>(); // populate the list
}
private static Object createAnObject() {
return new Object();
}
}
Yes, you can write code the same way in Java :
public interface Action {
void apply();
}
public static void DoSomething(Action action)
{
action.apply();
}
public static void main(String[] args) throws IOException {
DoSomething(() -> System.out.println("test action"));
}
my code, being practically identical to the code given in BlackBerry's tutorial, has a syntax error in Eclipse. i'm sure there is some small but i'm just not seeing, but my coworker could not find it as well. any ideas would be greatly appreciated. thanks!
Code:
pushScreen(new ABCScreen());
Error:
Cannot make a static reference to the
non-static method pushScreen(Screen)
from the type UiApplication
here is the complete source:
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.container.MainScreen;
public class AwesomeBBCalculator extends UiApplication {
public AwesomeBBCalculator() {
AwesomeBBCalculator app = new AwesomeBBCalculator();
app.enterEventDispatcher();
}
public static void main(String[] args) {
pushScreen(new ABCScreen()); // ERROR LINE
}
}
final class ABCScreen extends MainScreen {
public ABCScreen() {
super();
// add title
LabelField title = new LabelField("Awesome BlackBerry Calculator",
LabelField.ELLIPSIS | LabelField.USE_ALL_WIDTH);
setTitle(title);
}
public boolean onClose() {
Dialog.alert("Thanks for using the Awesome BlackBerry Calculator!\nGoodbye.");
System.exit(0);
return true;
}
}
The pushScreen method can only be called within an instance of UiApplication. You are trying to call it from a static main method. That does not work. Do this instead...
public void foo()
{
pushScreen(this);
}
public static void main(String[] args)
{
(new ABCScreen()).foo();
}
public void class1()
{
pushScreen(this);
}
public static void main(String[] args)
{
(new NewScreen()).class1();
}
try making an object for the ABCScreen class and then use it or u may try this also:
UiApplication.getUiApplication().pushScreen(new ABCScreen());