Replace <Unknown Source> in Java Rhino (JSR223) with actual file name - java

In my code, all of the scripts are contained in .js files. Whenever one of the scripts contains an error, I get this:
javax.script.ScriptException: sun.org.mozilla.javascript.internal.EcmaError: ReferenceError: "nonexistant" is not defined. (<Unknown source>#5) in <Unknown source> at line number 5
What bugs me is the <Unknown Source>. Multiple files are in one ScriptContext, and it can be hard to track down an error. It also looks horrible.
Is there a way to replace <Unknown Source> with the actual file name? None of the methods I see support passing a File object, so I'm really confused here.

Use the ScriptEngine.FILENAME constant:
scriptEngine.put(ScriptEngine.FILENAME, scriptFile.toString());

The question hasn't been specifically asked yet, but I thought I'd offer this to anyone who stumbles upon this topic in the future: this will change when Java 8 is released and we move from Rhino to Nashorn as the underlying JavaScript engine. Under Nashorn, the file name is applied to the ScriptContext, rather than to the ScriptEngine itself:
ScriptContext context = new SimpleScriptContext();
context.setAttribute(ScriptEngine.FILENAME, "test.js", ScriptContext.ENGINE_SCOPE);
try
{
engine.eval(script, context);
}
catch (ScriptException e)
{
/* e.getFileName() will return "test.js" */
}
If you attempt to apply the file name using ScriptEngine.put(), as you do under Rhino, nothing will happen and your exceptions will return "<eval>" as the file name.
I would imagine that a few people will run into this issue in the coming months, so thought I'd offer it. This does not appear to be documented anywhere. I had to dig into the Nashorn source code to figure it out.

The Java 8 (Nashorn) way of setting the filename for the script engine through the ScriptContext figured out by mattj65816, works for the Rhino engine as well. So, I'd recommend using only
context.setAttribute(ScriptEngine.FILENAME, "test.js", ScriptContext.ENGINE_SCOPE);
since this piece of code works for both common JavaScript engines. You don't event need to create you own context, but only set the attribute to the engine's default context:
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("JavaScript");
if (engine != null) {
ScriptContext ctx = engine.getContext();
ctx.setAttribute(ScriptEngine.FILENAME, "test.js", ScriptContext.ENGINE_SCOPE);
...
}

perfect!
ScriptEngine engine = new ScriptEngineManager().getEngineByExtension("js");
// javax.script.filename
engine.put(ScriptEngine.FILENAME, "test1.js");
try {
engine.eval("function throwError1(){throw new Error('test, haha')}");
} catch (ScriptException e) {
}
engine.put(ScriptEngine.FILENAME, "test2.js");
try {
engine.eval("function throwError2(){throw new Error('test2, haha')}");
} catch (ScriptException e) {
}
try {
engine.eval("throwError1()");
} catch (ScriptException e) {
System.out.println(e.getMessage());
}
try {
engine.eval("throwError2()");
} catch (ScriptException e) {
System.out.println(e.getMessage());
}
output :
Error: test, haha in test1.js at line number 1
Error: test2, haha in test2.js at line number 1

Related

FileUtils.copyURLToFile Getting Stuck

I'm using a Jave program to get NSE share price data from NSE's website like this for example:
url = new URL("https://archives.nseindia.com/archives/equities/bhavcopy/pr/PR071122.zip");
f = new File("NSEData.zip");
try {
FileUtils.copyURLToFile(url, f);
} catch (Exception e) {
}
The above code works for dates where market data exists, like 07/11/22 . However, where data does not exist, like on 08/11/22, the url is broken and the copyURLToFile line gets stuck indefinitely during runtime (replacing 071122 with 081122 in the url/code above will cause it to get stuck). Is there an easy way to get the program to recognize that the url for a certain date is broken (eg. https://archives.nseindia.com/archives/equities/bhavcopy/pr/PR081122.zip) and therefore ignore and continue past the try block without getting stuck?
My current workaround is to check whether a certain date is a market holiday using a DayOfWeek check as well as a HashSet containing a list of public holidays, but this is not perfect.
So, basically your URL is returning 500 error upon requesting for invalid date. You can simply use the another method available in FileUtils
https://commons.apache.org/proper/commons-io/javadocs/api-2.5/org/apache/commons/io/FileUtils.html#copyURLToFile(java.net.URL,%20java.io.File,%20int,%20int)
Example code : (Adjust timeouts as per your requirement)
var url = new URL("https://archives.nseindia.com/archives/equities/bhavcopy/pr/PR081122.zip");
var f = new File("NSEData.zip");
try {
FileUtils.copyURLToFile(url, f, 5000, 5000);
} catch (Exception e) {
}

ini4j INI key length > 80 chars

I need to communicate with a 3th party software through INI files, and I'm using the ini4j library for this.
All was going well, until I need to be able to use a key length of >80 chars.
The library is returning :
Exception in thread "main" java.lang.IllegalArgumentException: Key too
long:
0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
at
java.util.prefs.AbstractPreferences.put(AbstractPreferences.java:243)
The library has set this in Preferences.java:
public static final int MAX_KEY_LENGTH = 80;
Is there any clean way around this?
I found something related here, but I'm not sure how to use it:
http://ini4j.sourceforge.net/apidocs/index.html?org/ini4j/addon/StrictPreferences.html
This is the sample code:
try {
Wini ini = new Wini(new File("test.ini"));
ini.getConfig().setStrictOperator(true);
ini.getConfig().setEscape(false);
java.util.prefs.Preferences prefs = new IniPreferences(ini);
prefs.node("Section").put("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789", "Test");
ini.store();
} catch (IOException e) {
e.printStackTrace();
}
I was able to fix my problem by using the JIniFile library (https://github.com/SubZane/JIniFile) instead of the Ini4j library.
All working fine now.

android add java.lang.management API

Now I have a problem with Android non-supported libraries. In fact it does not support this API: "java.lang.management".
Eclipse shows me this error :
10-25 17:53:03.460: java.lang.NoClassDefFoundError: java.lang.management.ManagementFactory.
I wonder how I can add this API to be supported by my android application.
Any help please.
That API is not a part of Android, and is not compatible with Android.
The java.lang.management API is for managing and monitoring the Java VM. Android's Dalvik VM is not a Java VM.
It seems that with Android Version 23, situation has slightly improved. For example I found a replacement for:
GarbageCollectorMXBean gb = ....
long gctime = gb.getCollectionTime();
Thanks to #Jacob, I am now using this code. First the getRuntimeStat() method is not available in all android versions. So I am doing some reflection first:
static {
try {
Class<?> debugClass = Debug.class;
getRuntimeStat = debugClass.getDeclaredMethod(
"getRuntimeStat", String.class);
} catch (NoSuchMethodException x) {
getRuntimeStat = null;
}
}
Retrieving the GC time is then a matter of calling the method handle, with the correct property name. I am currently using this property name:
String gctimestr;
try {
gctimestr = (String) (getRuntimeStat != null ?
getRuntimeStat.invoke(null, "art.gc.gc-time") : null);
} catch (IllegalAccessException e) {
gctimestr = null;
} catch (InvocationTargetException e) {
gctimestr = null;
}
The gctimestr can then be converted to a long value, if its non-null. On the other hand if its null the statistics is not available, through this API.

How to use ESAPI to fix Resource Injection (URL) issues

I am new to the Stack Overflow forum. I have a question in remediating the fortify scan issues.
HP Fortify scan reporting the Resource Injection issue for following code.
String testUrl = "http://google.com";
URL url = null;
try {
url = new URL(testUrl);
} catch (MalformedURLException mue) {
log.error("MalformedUrlException URL " + testUrl + " Exception : " + mue);
}
In the above code fortify showing Resource injection in line => url = new URL(testUrl);
I have done following code changes for URL validation using ESAPI to remediate this issue,
String testUrl = "http://google.com";
URL url = null;
try {
String canonURL = ESAPI.encoder().canonicalize(strurl, false, false);
if(ESAPI.validator().isValidInput("URLContext", canonURL, "URL", canonURL.length(), false)) {
url = new URL(canonURL);
} else {
log.error("In Valid script URL passed"+ canonURL);
}
} catch (MalformedURLException mue) {
log.error("MalformedUrlException URL " + canonURL + " Exception : " + mue);
}
However, still Fortify scan reporting as en error. It is not remeditaing this issue. Anything am doing wrong?
Any solution will help lot.
Thanks,
Marimuthu.M
I think that the real issue here is not that the URL may be somehow malformed, but, that the URL may not reference a valid site. More specifically, if I, the bad guy, am able to cause your URL to point to my web site, then you obtain data from my location that is not tested and I can return data that may be used to compromise your system. I might use that to say return a record for "bob the bad guy" that makes bob look like a good guy.
I suspect that in your code you do not set a hard coded value in a string, since this is usually described with words such as
When an application permits a user input to define a resource, like a
file name or port number, this data can be manipulated to execute or
access different resources.
(see https://www.owasp.org/index.php/Resource_Injection)
I think that the proper response will be some combination of:
Do not get the result from the user, but, use the input to choose from your own internal list.
Argue that the value came from a trusted source. For example, read from a strictly controlled database or configuration file.
You do not need to remove the warnings, you need to demonstrate that you understand the risk and indicate why it is OK to use the value in your case.
boolean isValidInput(java.lang.String context,
java.lang.String input,
java.lang.String type,
int maxLength,
boolean allowNull)
throws IntrusionException
type filed in isValidInput function defines a Regular expression or pattern to match with your testUrl.
Like:
try {
ESAPI.validator().getValidInput("URI_VALIDATION", requestUri, "URL", 80, false);
} catch (ValidationException e) {
System.out.println("Validation exception");
e.printStackTrace();
} catch (IntrusionException e) {
System.out.println("Inrusion exception");
e.printStackTrace();
}
It will pass if requestUri matches pattern defined in validation.properties under Validator.URL and its length is less than 80.
Validator.URL=^(ht|f)tp(s?)\:\/\/0-9a-zA-Z(:(0-9))(\/?)([a-zA-Z0-9\-\.\?\,\:\'\/\\\+=&%\$#_])?$
This is piggybacking on Andrew's answer, but the problem Fortify is warning you of is user control of a URL. If your application later decides to make connections to that website, and it is untrusted, this is an issue.
If this is an application where you care more about sharing public URIs, than you'll have to accept the risk, and make sure users are properly trained on the inherent risk, as well as make sure if you redisplay those URLs, that someone doesn't try to embed malicious data.

JUnit test for jdt.core Java Models

I am trying to make some JUnit tests for my code. But the problem is, I make use of the Java Models like ICompilationUnit, IPackageFragment, ITypes and etc. I did not get how to create some ICompilationUnit and then test. I searched google and stackoverflow for information but did not find something.
My question is, how can I make Junit test with classes of the jdt.core...can somebody give me may be some code examples.
Thanks
Here is a Method I coded:
private void updateLists() {
if(!getCompilationUnit().isEmpty()){
for(int i = 0; i < getCompilationUnit().size(); i++){
try {
Document doc = new Document(getCompilationUnit().get(i).getSource());
int totalNumberOfCode = doc.getNumberOfLines();
IType type = getCompilationUnit().get(i).findPrimaryType();
IType[] types = getCompilationUnit().get(i).getTypes();
updateListPrimaryType(type, totalNumberOfCode, types);
updateListIMethod(type);
updateListMember(type,types);
} catch (JavaModelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
This snippet of code shows how to take some Java source (in variable javaSource) and get an ICompilationUnit from it by using the Java AST parser. You get these classes by using plugin org.eclipse.jdt.core as a dependency.
import org.eclipse.jdt.core.dom.ASTParser;
String javaSource = "some java source"'
// see org.eclipse.jdt.core.dom.AST for a complete
// list of supported levels.
ASTParser parser = ASTParser.newParser(AST.JLS2);
parser.setSource(javaSource.toCharArray());
CompilationUnit unit = (CompilationUnit) parser.createAST(null);

Categories