How to show arguments of java function in vim + eclim? - java

I have configured vim + eclim OK. Now I can use Ctrl+X and Ctrl+U complete functions. But there is no arguments hint. For example,
FileInputStream fins = new FileInputStream(/* what arguments can be used here? eclipse will show those but eclim not */);
how to show arguments hint in vim + eclim?

Resurrecting this old question, since I stumbled on this.
You can use eclim to lookup the java docs of the class and look through the list of constructors that way using the :JavaDocSearch command.
Because the command uses a browser to render the javadocs, you'll need to add to your .vimrc:
let g:EclimBrowser = 'browser-executable-name'
Replacing browser-executable-name with your console-based browser of choice. Example: lynx, links, w3m
Then navigate over FileInputStream with your cursor and run the command :JavaDocSearch and it will pop up the java doc for the class.
Or enter the class name manually: :JavaDocSearch java.io.FileInputStream

You can use the YouCompleteMe (YCM) plugin with options
let g:ycm_add_preview_to_completeopt = 1
let g:ycm_autoclose_preview_window_after_insertion = 1
Note that this does not work for your Constructor invocations. But at least prototypes for method calls will be shown.
Also, if you don't like the auto-popup of YCM, it can be switched off.

Related

How to Add a <script> into Head Using Selenium's JavascriptExecutor

Summary
I want to figure out a way to add a <script> tag into the head of DOM using Selenium's JavascriptExecutor, or any other way of doing this would be nice.
I have tried many ways and also found a few similar topics and none of them solved my problem which is why I felt the need to ask it on here.
For example :
Suggested solutions in this question did not solve my problem. Some people say it worked for them but nope, it didn't for me.
What I've been trying to execute?
Here is the small snippet of the code that I want to execute:
WebDriver driver = new FirefoxDriver();
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript("var s = document.createElement('script');");
jse.executeScript("s.type = 'text/javascript';");
jse.executeScript("s.text = 'function foo() {console.log('foo')}';");
jse.executeScript("window.document.head.appendChild(s);");
I just skipped the code above where you navigate to a webpage using driver.get() etc. and then try to execute the scripts.
Also, s.text would contain the actual script that I want to use so I just put there a foo() function just to give the idea.
The above code throws this error when you run it:
Exception in thread "main" org.openqa.selenium.JavascriptException: ReferenceError: s is not defined
So far I've tried every possible solution I could find on the Internet but none of them seems to work.
OP came up with the following solution:
jse.executeScript("var s=window.document.createElement('script');" +
"s.type = 'text/javascript';" + "s.text = function foo() {console.log('foo')};" +
"window.document.head.appendChild(s);");
For one, this line is invalid.
jse.executeScript("s.text = 'function foo() {console.log('foo')}';");
Note how you wrap single-quote text in single quotes. Use one set as "\""
I would personally do this by doing (edited to make it a global function):
using OpenQA.Selenium.Support.Extensions;
driver.ExecuteJavascript("window.foo = function foo() {console.log('foo')}");
It's as simple as that. You are registering foo as a method by doing this. After you execute this javascript, you can manually go in to the browser developer tools and call "foo()" to check. Additionally, you can check this by registering it directly in the console. Just enter "function foo() {console.log('foo')}" into your browser console, and then call "foo()".
No need to add this as a script tag.
EDIT #2: I fixed my above code suggestion so that the method is assigned to the window, and thus accessible globally, and outside of the anonymous script that javascript executor runs the code in. The original issues with this not working are resolved by this, at least in my testing of it.

In the startup scripts generated by gradle's application plugin, how can I have the program name passed in to the application?

Executing the gradle application plugin's installDist task creates a directory build/install/my-application-name/bin that contains wrapper scripts, my-application-name and my-application-name.bat. Running either of these scripts runs the application, and arguments passed to these scripts are passed to the underlying application.
In UNIX shell scripts you can access the name that was used to execute the program as $0. In fact, the UNIX version of the gradle-generated startup script uses $0 several times.
How can I configure the gradle application plugin such that these scripts will pass the value of $0 (and whatever the Windows equivalent is on Windows) into the underlying application, perhaps as a Java system property?
Since parameter for obtaining the name of the script being run is referenced differently in Linux($0) and in Windows(%0), the most straightforward way to generate custom scripts would be to use separate custom templates for the respective start script generators:
startScripts {
unixStartScriptGenerator.template = resources.text.fromFile('unixStartScript.txt')
windowsStartScriptGenerator.template = resources.text.fromFile('windowsStartScript.txt')
}
The default templates are easy to obtain invoking e.g. unixStartScriptGenerator.template.asString()
Documentation on customizing the start scripts can be found here.
This is what I ended up doing, based on jihor's answer. I'm posting it here just so that there's a working answer for anyone else interested:
startScripts {
def gen = unixStartScriptGenerator
gen.template = resources.text.fromString(
gen.template.asString().replaceFirst('(?=\nDEFAULT_JVM_OPTS=.*?\n)') {
'\nJAVA_OPTS="\\$JAVA_OPTS "\'"-Dprogname=\\$0"\''
})
// TODO: do something similar for windowsStartScriptGenerator
}
This uses replaceFirst is instead of replace so we can match a pattern. This is a little less brittle, and also lets us use lookahead so we don't have to actually replace what we're looking for. (This is groovy's variant of replaceFirst that takes a closure, by the way. This requires far less escaping than the version that takes a replacement string in this case.)
Also, instead of:
JAVA_OPTS="$JAVA_OPTS -Dprogname=$0"
we actually need something like:
JAVA_OPTS="$JAVA_OPTS "'"-Dprogname=$0"'
This is because $0 may contains special character (like spaces), and the startup script removes one level of quoting in the value of $JAVA_OPTS using eval set --.
(If anyone knows how to make this work on Windows, pleas feel free to update this answer.)
I took an alternative approach. According to the documentation, as far back as Gradle 2.4 and all the way through Gradle 4.8, we should be able to set the following properties within the startScripts task:
applicationName
optsEnvironmentVar
exitEnvironmentVar
mainClassName
executableDir
defaultJvmOpts
appNameSystemProperty
appHomeRelativePath
classpath
Unfortunately, this is not true for the following properties, which seem to have never been exposed:
appNameSystemProperty
appHomeRelativePath
If appNameSystemProperty were exposed as the documentation describes, then we should be able to simply do the following:
startScripts {
applicationName = 'foo'
appNameSystemProperty = 'appName'
}
This would then result in the addition of -DappName=foo to the Java command constructed within both of the start scripts.
Since this is not the case, I took the following approach, which is a bit more verbose than the earlier solution to this question, but is perhaps less brittle because it does not rely on tweaking the out-of-box templates. Instead, it results in the documented behavior.
startScripts {
mainClassName = '...'
applicationName = 'foo'
unixStartScriptGenerator =
new CustomStartScriptGenerator(generator: unixStartScriptGenerator)
windowsStartScriptGenerator =
new CustomStartScriptGenerator(generator: windowsStartScriptGenerator)
}
class CustomStartScriptGenerator implements ScriptGenerator {
#Delegate
ScriptGenerator generator
void generateScript(JavaAppStartScriptGenerationDetails details,
Writer destination) {
details = new CustomDetails(details: details)
this.generator.generateScript(details, destination)
}
static class CustomDetails implements JavaAppStartScriptGenerationDetails {
#Delegate
JavaAppStartScriptGenerationDetails details
#Override
String getAppNameSystemProperty() { 'appName' }
}
}

Vim Syntastic Java Unaware of Current Project Classes

Using Vim Syntastic with an android project. (e.g. com.myproject.project) It's not aware of classes declared within my project but outside of the current file. e.g. the following flags errors:
import com.myproject.project.SomeClass;
...
SomeClass someclass = new SomeClass();
Saw this post Configure syntastic to work fine with Android projects which solve the problem:
Method 1:
Inside vim editor
:SyntasticJavacEditClasspath
Then add the following to the buffer window
/path-to-your-app/bin/classes
/path-to-your-android-sdk/platforms/android-19/*.jar
Method 2:
Add the following to the .vimrc:
let g:syntastic_java_javac_classpath = "/<path-to-your-app>/bin/classes:/<path-to-your-android-sdk>/platforms/android-19/*.jar"
Here is a summary of the various methods which worked for me in linux vim7.4 and Syntastic3.7.0-224 with credit to each.
Method 1 - manual creation of .syntastic_javac_config
1. Edit .vimrc and use this syntax:
let g:syntastic_java_javac_config_file_enabled = 1
2. Where you edit your vim files, add this to a file named .syntastic_javac_config
let g:syntastic_java_javac_classpath = '/home/davis/progs/princeton-algos/week1/libs/algs4.jar'
Method 2 - advantage no matter where you edit the class path is known.
1. Edit .vimrc and use this syntax:
let g:syntastic_java_javac_classpath = "/home/davis/progs/princeton-algos/week1/libs/algs4.jar"
This adds the jar and
Method 3 - Automatic generation of .syntastic_javac_config file
1. Edit .vimrc and use this syntax:
let g:syntastic_java_javac_config_file_enabled = 1
2. Edit a java file with vim
3. :SyntasticJavacEditClasspath
When the edit window opens, add the class path without quotes and a newline after each entry the class path. In my case, this is the entry
for the setting includes the current folder as well:
/home/davis/progs/princeton-algos/week1/libs/algs4.jar
.
4 :wq the edit setting window
5. Now the class path is set for syntastic when editing files from that location. If you edit from a new directory, you will need to repeat the process.
Besides the comments above, this post also helped.

Pinning a Java application to the Windows 7 taskbar

I use Launch4j as a wrapper for my Java application under Windows 7, which, to my understanding, in essence forks an instance of javaw.exe that in turn interprets the Java code. As a result, when attempting to pin my application to the task bar, Windows instead pins javaw.exe. Without the required command line, my application will then not run.
As you can see, Windows also does not realize that Java is the host application: the application itself is described as "Java(TM) Platform SE binary".
I have tried altering the registry key HKEY_CLASSES_ROOT\Applications\javaw.exe to add the value IsHostApp. This alters the behavior by disabling pinning of my application altogether; clearly not what I want.
After reading about how Windows interprets instances of a single application (and a phenomenon discussed in this question), I became interested in embedding a Application User Model ID (AppUserModelID) into my Java application.
I believe that I can resolve this by passing a unique AppUserModelID to Windows. There is a shell32 method for this, SetCurrentProcessExplicitAppUserModelID. Following Gregory Pakosz suggestion, I implemented it in an attempt to have my application recognized as a separate instance of javaw.exe:
NativeLibrary lib;
try {
lib = NativeLibrary.getInstance("shell32");
} catch (Error e) {
Logger.out.error("Could not load Shell32 library.");
return;
}
Object[] args = { "Vendor.MyJavaApplication" };
String functionName = "SetCurrentProcessExplicitAppUserModelID";
try {
Function function = lib.getFunction(functionName);
int ret = function.invokeInt(args);
if (ret != 0) {
Logger.out.error(function.getName() + " returned error code "
+ ret + ".");
}
} catch (UnsatisfiedLinkError e) {
Logger.out.error(functionName + " was not found in "
+ lib.getFile().getName() + ".");
// Function not supported
}
This appears to have no effect, but the function returns without error. Diagnosing why is something of a mystery to me. Any suggestions?
Working implementation
The final implementation that worked is the answer to my follow-up question concerning how to pass the AppID using JNA.
I had awarded the bounty to Gregory Pakosz' brilliant answer for JNI that set me on the right track.
For reference, I believe using this technique opens the possibility of using any of the APIs discussed in this article in a Java application.
I don't have Windows 7 but here is something that might get you started:
On the Java side:
package com.stackoverflow.homework;
public class MyApplication
{
static native boolean setAppUserModelID();
static
{
System.loadLibrary("MyApplicationJNI");
setAppUserModelID();
}
}
And on the native side, in the source code of the `MyApplicationJNI.dll library:
JNIEXPORT jboolean JNICALL Java_com_stackoverflow_homework_MyApplication_setAppUserModelID(JNIEnv* env)
{
LPCWSTR id = L"com.stackoverflow.homework.MyApplication";
HRESULT hr = SetCurrentProcessExplicitAppUserModelID(id);
return hr == S_OK;
}
Your question explicitly asked for a JNI solution. However, since your application doesn't need any other native method, jna is another solution which will save you from writing native code just for the sake of forwarding to the windows api. If you decide to go jna, pay attention to the fact that SetCurrentProcessExplicitAppUserModelID() is expecting a UTF-16 string.
When it works in your sandbox, the next step is to add operating system detection in your application as SetCurrentProcessExplicitAppUserModelID() is obviously only available in Windows 7:
you may do that from the Java side by checking that System.getProperty("os.name"); returns "Windows 7".
if you build from the little JNI snippet I gave, you can enhance it by dynamically loading the shell32.dll library using LoadLibrary then getting back the SetCurrentProcessExplicitAppUserModelID function pointer using GetProcAddress. If GetProcAddress returns NULL, it means the symbol is not present in shell32 hence it's not Windows 7.
EDIT: JNA Solution.
References:
The JNI book for more JNI examples
Java Native Access (JNA)
There is a Java library providing the new Windows 7 features for Java. It's called J7Goodies by Strix Code. Applications using it can be properly pinned to the Windows 7 taskbar. You can also create your own jump lists, etc.
I have implemented access to the SetCurrentProcessExplicitAppUserModelID method using JNA and it works quite well when used as the MSDN documentation suggests. I've never used the JNA api in the way you have in your code snippet. My implementation follows the typical JNA usage instead.
First the Shell32 interface definition:
interface Shell32 extends StdCallLibrary {
int SetCurrentProcessExplicitAppUserModelID( WString appID );
}
Then using JNA to load Shell32 and call the function:
final Map<String, Object> WIN32API_OPTIONS = new HashMap<String, Object>() {
{
put(Library.OPTION_FUNCTION_MAPPER, W32APIFunctionMapper.UNICODE);
put(Library.OPTION_TYPE_MAPPER, W32APITypeMapper.UNICODE);
}
};
Shell32 shell32 = (Shell32) Native.loadLibrary("shell32", Shell32.class,
WIN32API_OPTIONS);
WString wAppId = new WString( "Vendor.MyJavaApplication" );
shell32.SetCurrentProcessExplicitAppUserModelID( wAppId );
Many of the API's in the last article you mentioned make use of Windows COM which is quite difficult to use directly with JNA. I have had some success creating a custom DLL to call these API's (eg. using the SHGetPropertyStoreForWindow to set a different app ID for a submodule window) which I then use JNA to access at runtime.
Try to use JSmooth. I use always this one. In JSmooth is there an option under Skeleton by Windowed Wrapper called
Lauch java app in exe process
See on this image.
(source: andrels.com)
Also command line arguments can be passed.
I think this can be a solution for you.
Martijn
SetCurrentProcessExplicitAppUserModelID (or SetAppID()) would in fact do what you're trying to do. However, it might be easier to modify your installer to set the AppUserModel.ID property on your shortcut - quoting from the Application User Model ID document mentioned above:
In the System.AppUserModel.ID property of the application's shortcut file. A shortcut (as an IShellLink, CLSID_ShellLink, or a .lnk file) supports properties through IPropertyStore and other property-setting mechanisms used throughout the Shell. This allows the taskbar to identify the proper shortcut to pin and ensures that windows belonging to the process are appropriately associated with that taskbar button.
Note: The System.AppUserModel.ID property should be applied to a shortcut when that shortcut is created. When using the Microsoft Windows Installer (MSI) to install the application, the MsiShortcutProperty table allows the AppUserModelID to be applied to the shortcut when it is created during installation.
The latest jna-platform library now includes JNA bindings for SetCurrentProcessExplicitAppUserModelID:
https://github.com/java-native-access/jna/pull/680
I fixed mine without any ID settings.
There is an option in Launch4J if you are using it and you say you do then...
You can change the header to JNI Gui and then wrap it around the jar with the JRE.
The good thing is that it runs .exe in the process now instead on running javaw.exe with your jar. It probably does it under the hood (not sure).
Also I have noticed also that it takes around 40-50% less CPU resource which is even better!
And the pinning works fine and all that window features are enabled.
I hope it helps to someone as I spent nearly 2 days trying to solve that issue with my undecorated javafx app.

Java reports alias (symlink) as size 0 on Mac OSX. How do I get the true file size?

File file = new File("path to file alias foo");
where "path to file alias foo" is an alias reports file size to be 0 instead of the actual file size. I found a workaround to test for aliases:
public boolean isLink() {
try {
if (file.getAbsolutePath().equals(file.getCanonicalPath())) {
return false;
}
} catch (IOException ex) {
logger.severe(ex.getMessage());
}
return true;
}
EDIT Actually this code does not work, as pointed out by a poster below. I was trying to adapt a solution from a linux symlink example, but I didn't realize that finder aliases and symlinks were not the same.
NOT! this seems to work, but ....
file.getCanonicalFile().length();
still reports file length to be 0. Can anyone point me in the right direction?
Finder aliases are a different beast altogether from normal symbolic links. The *nix tools on OS X are not aware of aliases at all, because they're stored in the resource fork, I believe. If you install osxutils, you can use this shell command to get the target of an alias:
hfsdata -e the-alias
From Java, I don't know of a better way of doing this other than calling Runtime.exec(...).
Also, I just a did a quick check, and your function for detecting aliases does not work. AFAICT, Java is not aware of Finder aliases. If you really want to support them, then you'll either need to use something like osxutils, or use some platform-specific code to read resource forks (will probably involve JNI). Neither option is pretty.
If you go the JNI route, check out the Alias Manager Reference documentation. The relevant functions are FSIsAliasFile and FSResolveAliasFile.
You can use the FileRef Interface from the O'Reilly Java NIO API. I believe the getAttribute() method can handle symbolic links as you want, but I have not tried it on Mac OSX. From the docs:
The options array may be used to
indicate how symbolic links are
handled for the case that the file is
a symbolic link. By default, symbolic
links are followed and the file
attribute of the final target of the
link is read. If the option
NOFOLLOW_LINKS is present then
symbolic links are not followed and so
the method returns the file attribute
of the symbolic link.
size = new File(file.getCanonicalPath()).length();

Categories