refreshLocal in Eclipse does not work properly - java

I have a program that changes an input Java project loaded in Eclipse. After changes I use the below code to refresh the project and extract compilation unit.
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = workspace.getRoot();
//projectName is the name of project loaded in eclipse
IProject project = root.getProject(projectName);
try {
project.refreshLocal(IResource.DEPTH_INFINITE, null);
} catch (CoreException e) {
e.printStackTrace();
}
IJavaProject iJavaproject = JavaCore.create(project);
/** Extract ICompilationUnit. "classFullName" is the name of class contains new changes.*/
ICompilationUnit iCompilationUnit = getICompilationUnit(javaProject, classFullName);
/** Extract compilation unit.*/
CompilationUnit compilationUnit = getCompilationUnit(iCompilationUnit);
I have these two functions to extract iCompilationUnit and compilationUnit.
private ICompilationUnit getICompilationUnit(IJavaProject javaProject, String classFullName) {
ICompilationUnit iUnit = null;
try {
IType iType = javaProject.findType(classFullName);
iUnit = iType.getCompilationUnit();
/** Create working copy. It is safer to work with a copy.*/
WorkingCopyOwner owner = iUnit.getOwner();
iUnit = (owner == null ? iUnit.getWorkingCopy(null) : iUnit.getWorkingCopy(owner, null));
} catch (JavaModelException e) {
e.printStackTrace();
}
return iUnit;
}
CompilationUnit getCompilationUnit(ICompilationUnit iCompilationUnit) {
#SuppressWarnings("deprecation")
ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(iCompilationUnit);
/** we need bindings later on.*/
parser.setResolveBindings(true);
return (CompilationUnit) parser.createAST(null);
}
However, the problem I am facing is that first call to this method (first time that any changes is applied to the project), the above code cannot detect changes and return original version. However, after that the project is refreshed correctly and final compilationUnit contains applied changes.
I am not sure the problem is for refreshLocal and maybe it is for other two functions: getCompilationUnit and getICompilationUnit.
Please let me know if any one has any idea.

I think the JDT is probably running background jobs to recompile and rebuild indices. So you need to wait for those jobs to finish. Try
IJobManager jobManager = Job.getJobManager();
jobManager.join(ResourcesPlugin.FAMILY_MANUAL_BUILD, monitor);
jobManager.join(ResourcesPlugin.FAMILY_AUTO_BUILD, monitor);
do this after the refreshLocal but before you do anything else.

Related

How to properly set the content of an IFile in Eclipse plugin when the editor is opened

I'm using the following code to set the content of an IFile:
public static IFile updateFile(IFile file, String content) {
if (file.exists()) {
InputStream source = new ByteArrayInputStream(content.getBytes());
try {
file.setContents(source, IResource.FORCE, new NullProgressMonitor());
source.close();
} catch (CoreException | IOException e) {
e.printStackTrace();
}
}
return file;
}
This works fine when the file is not opened in the editor, but if the file is opened I get the following warning as if the file was modified outside of Eclipse:
I tried to refresh the file (by calling refreshLocal() method) before and after calling setContents() but that didn't help.
Is there a way to avoid this warning?
Wrap your method in a WorkspaceModifyOperation.
The editor reaction looks correct, because there is a modification outside of org.eclipse.jface.text.IDocument that bound to the editor instance.
The right approach will be to modify not the file content, but an instance of "model" that represents the file content, something like IJavaElement for JDT.
Also you can try to manipulate the document content directly (needs polishing for production):
IWorkbenchWindow[] windows = PlatformUI.getWorkbench().getWorkbenchWindows();
for (IWorkbenchWindow window : windows) {
IWorkbenchPage[] pages = window.getPages();
for (IWorkbenchPage page : pages) {
IEditorReference[] editorReferences = page.getEditorReferences();
for (IEditorReference editorReference : editorReferences) {
IEditorPart editorPart = editorReference.getEditor(false/*do not restore*/);
IEditorInput editorInput = editorPart.getEditorInput();
//skip editors that are not related
if (inputAffected(editorInput)) {
continue;
}
if (editorPart instanceof AbstractTextEditor) {
AbstractTextEditor textEditor = (AbstractTextEditor) editorPart;
IDocument document = textEditor.getDocumentProvider().getDocument(editorInput);
document.set(content);
}
}
}
}
Honestly, I do not understand the scenario you are trying to cover, probably there are better ways to do this.

Rhapsody API reload project

I am creating a Rhapsody JavaAPI plugin that will clean the current project files and copy in a fresh model. This is to have a fresh working copy for developers so they do not have to close rhapsody and copy in the clean models manually.
My dilemma is when i close the active project, it removes it from the rhapsody view as expected. When I try reloading the new rpy file, the view does not change nor is the model reload.
How would I go about reloading the project?
Here is my plugin (note the class call works fine. Its in the method clean that I am having issues).
public class CMMCleaner {
private Path rootDir;
private Path rpyFile;
private IRPApplication rpyApp;
public CMMCleaner(final Path rootDir, final IRPApplication rpyApp) {
this.rootDir = rootDir;
if (!Files.exists(rootDir)) throw new IllegalArgumentException(rootDir + " does not exist");
this.rpyApp = rpyApp;
this.rpyFile = Paths.get(this.rpyApp.activeProject().getCurrentDirectory()).resolve(this.rpyApp.activeProject().getFilename());
}
public void clean() {
try {
rpyApp.activeProject.close();
Path cleanDir = this.rootDir.resolve("CMM_starting_model");
Path oldDir = this.rootDir.resolve("CMM_model");
Files.walk(oldDir)
.sorted(Comparator.reverseOrder())
.map(Path::toFile)
.forEach(File::delete);
Files.walk(cleanDir)
.filter(p -> Files.isRegularFile(p))
.forEach(cleanFile -> {
Path path = oldDir.resolve(cleanDir.relativize(cleanFile));
try {
Files.createDirectories(path.getParent());
Files.copy(cleanFile, path, StandardCopyOption.REPLACE_EXISTING);
} catch (Exception ex) {
ex.printStackTrace();
}
});
rpyApp.openProject(this.rpyFile.toAbsolutePath().toString());
rpyApp.insertProject(this.rpyFile.toAbsolutePath().toString());
rpyApp.activeProject();
rpyApp.refreshAllViews();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
No Exceptions are thrown, but as stated the project does close and I can visually see the files being deleted and copied in, but nothing happens in rhapsody after that.
I was able to solve the problem by removing the following lines:
rpyApp.activeProject.close(); and rpyApp.insertProject(this.rpyFile.toAbsolutePath().toString());

eclipse plugin project plugin dependency hell

I have this code:
ThreadPoolExecutor t;
IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
final IWorkspace workspace = ResourcesPlugin.getWorkspace();
System.out.println("root" + root.getLocation().toOSString());
Runnable runnable = new Runnable() {
public void run() {
try {
IPath projectDotProjectFile = new Path("C:\\Users\\rezbi\\eclipse-workspace\\AutoRefactor-master\\AutoRefactor-master" + "/.project");
IProjectDescription projectDescription = workspace.loadProjectDescription(projectDotProjectFile);
IProject project = workspace.getRoot().getProject(projectDescription.getName());
JavaCapabilityConfigurationPage.createProject(project, projectDescription.getLocationURI(), null);
//project.create(null);
} catch (CoreException e) {
e.printStackTrace();
}
}
};
// and now get the workbench to do the work
final IWorkbench workbench = PlatformUI.getWorkbench();
workbench.getDisplay().syncExec(runnable);
IProject[] projects = root.getProjects();
for(IProject project: projects){
System.out.println(project.getName());
}
I followed the instructions as mentioned in the link below:
http://techdc.blogspot.com/2015/01/eclipse-workbench-has-not-been-created.html
I added the following dependencies only:
org.apache.felix.gogo.command
org.apache.felix.gogo.runtime
org.apache.felix.gogo.shell
org.eclipse.equinox.console
org.eclipse.osgi
Unfortunately it is giving plugin dependency hello - I run the app, I get unresolved dependencies, I add the dependencies and there are more unresolved dependencies. And if I select "add required bundles" from run configuration, then I get "Workbench has not been created yet. Error while creating OSGi modules"
So is there an easier way to get around this?
Update:
How I am creating the project is here:
http://codeandme.blogspot.com/2012/02/creating-headless-application.html
So this is a plugin project.
And to run I right click on the manifest file. Select run as and then osgi framework. Note: I also tried including the plugin dependencies from run configuration. Then I tried to run > Eclipse Application. Either way I get the same result : workbench not created yet.
In the same java class the following code works:
public Object start(IApplicationContext context) throws Exception {
// TODO Auto-generated method stub
//String PACKAGE_NAME = "cucumber";
//final IPackageFragment packageFragment = JavaCoreHelper.getPackageFragment(PACKAGE_NAME);
//System.out.println(packageFragment);
//final ICompilationUnit cu = packageFragment.createCompilationUnit("Application5.java", "", true, null);
//IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
//IProject m_project = root.getProject("cucumber");
//System.out.println("m_project "+m_project);
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
System.out.println("HELLO ");
IProject[] projects = root.getProjects();
for (IProject project : projects) {
try {
printProjectInfo(project);
} catch (CoreException e) {
e.printStackTrace();
}
}
// createAProject();
//System.out.println("test "+root.getProject(name));
return null;
}
But as soon as I try accessing workbench things break.

Convert IFile to XtextResource

I have an eclipse project with Xtext files.I need to find get all the files in the eclipse project to be XtextResource in order to find metrics about them. so far,I tried the following things :
1.Iterate all over the list of files in the project and got them as IFile .but I cant convert IFile to XtextResource.
2.I success get XtextResource from only active page in IWorkBenchPage,so if I can find all the Pages in the project and not only the active (in IworkBenchPage)or maybe set all pages in the project as active I think it can work.
this is an example code to what I have done if I have private static void setResource()
{
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
IEditorPart activeEditor = page.getActiveEditor();
if (activeEditor instanceof XtextEditor) {
XtextEditor xtextEditor = (XtextEditor) activeEditor;
xtextEditor.getDocument().readOnly((XtextResource resource) -> {
ResourceHandler.resource = resource;
return null;
});
}
}
I am not an expert with all those relations in eclipse and hope somecan can save me here.
thanks!
The following should work (assuming you create the place where this is used via guice aware extension factory...
#Inject
IResourceSetProvider resourceSetProvider;
...
IProject project = file.getProject();
URI uri = URI.createPlatformResourceURI(file.getFullPath().toString(), true);
ResourceSet rs = resourceSetProvider.get(project);
Resource r = rs.getResource(uri, true);
r.load(null)
if you dont have guice at your place use
ResourceSet rs = IResourceServiceProvider.Registry.INSTANCE.getResourceServiceProvider(uri).get(IResourceSetProvider.class).get(project);

Project running fine in IDE but not as Jar

I'm programming an application which uses translation strings (.properties files); those strings are also made of non-latin characters (actually, they are copypastas like lenny smiles and stuff like this). My problem is, when I launch it inside my IDE Netbeans clicking on "clean and build" and then "run", everything goes fine and all the strings are displayed properly... the program acts as intended; but when I export my project as a fat jar (I use Maven shade plugin which also includes my properties files) and when I launch it double-clicking on its icon (still being on Windows) everything is messed up as some strings are not displayed:
inside my program, I use the class LocalisationService (code follows) to load strings inside different ArrayList. Running my project using Netbeans, strings are all loaded correctly (that's the supposed behaviour). Running my jar outside Netbeans, only 1/5 are loaded properly. I have a huge number of "String not found" entries in my arraylists and this means that, inside my LocalisationService class, method getString catches MissingResourceException exception. But actually those resources aren't missing, I mean, I include them properly in my Jar and Netbeans runs my project straight as it is supposed to do, so...
I have totally no idea on what could cause this issue: my IDE project encoding is set on UTF-8 so there shouldn't be any problems... Maven runs my project using:
cd C:\Users\utente\Documents\NetBeansProjects\mavenproject1; "JAVA_HOME=C:\\Program Files\\Java\\jdk1.8.0_40" cmd /c "\"\"C:\\Program Files\\NetBeans 8.0.2\\java\\maven\\bin\\mvn.bat\" -Dexec.args=\"-classpath %classpath bot.Main\" -Dexec.executable=\"C:\\Program Files\\Java\\jdk1.8.0_40\\bin\\java.exe\" -Dmaven.ext.class.path=\"C:\\Program Files\\NetBeans 8.0.2\\java\\maven-nblib\\netbeans-eventspy.jar\" -Dfile.encoding=UTF-8 org.codehaus.mojo:exec-maven-plugin:1.2.1:exec\""
I have the same problem on Ubuntu, strings are messed up launching my file from terminal with
/usr/bin/java -jar myproject.jar
Here is the class LocalisationService I use to retrieve the correct localisation string using a key:
public class LocalisationService {
private static LocalisationService instance = null;
private final HashMap<String, String> supportedLanguages = new HashMap<>();
private ResourceBundle english;
private ResourceBundle italian;
private class CustomClassLoader extends ClassLoader {
public CustomClassLoader(ClassLoader parent) {
super(parent);
}
public InputStream getResourceAsStream(String name) {
InputStream utf8in = getParent().getResourceAsStream(name);
if (utf8in != null) {
try {
byte[] utf8Bytes = new byte[utf8in.available()];
utf8in.read(utf8Bytes, 0, utf8Bytes.length);
byte[] iso8859Bytes = new String(utf8Bytes, "UTF-8").getBytes("ISO-8859-1");
return new ByteArrayInputStream(iso8859Bytes);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
utf8in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
/**
* Singleton
* #return Instance of localisation service
*/
public static LocalisationService getInstance() {
if (instance == null) {
synchronized (LocalisationService.class) {
if (instance == null) {
instance = new LocalisationService();
}
}
}
return instance;
}
/**
* Private constructor due to singleton
*/
private LocalisationService() {
CustomClassLoader loader = new CustomClassLoader(Thread.currentThread().getContextClassLoader());
english = ResourceBundle.getBundle("localisation.strings", new Locale("en", "US"), loader);
supportedLanguages.put("en", "English");
italian = ResourceBundle.getBundle("localisation.strings", new Locale("it", "IT"), loader);
supportedLanguages.put("it", "Italiano");
}
/**
* Get a string in default language (en)
* #param key key of the resource to fetch
* #return fetched string or error message otherwise
*/
public String getString(String key) {
String result;
try {
result = english.getString(key);
} catch (MissingResourceException e) {
System.out.println("not found key... "+key);
result = "String not found";
}
return result;
}
/**
* Get a string in default language
* #param key key of the resource to fetch from localisations
* #param language code key for language (such as "EN" for english)
* #return fetched string or error message otherwise
*/
public String getString(String key, String language) {
String result;
try {
switch (language.toLowerCase()) {
case "en":
result = english.getString(key);
break;
case "it":
result = italian.getString(key);
break;
default:
result = english.getString(key);
break;
}
} catch (MissingResourceException e) {
result = english.getString(key);
}
return result;
}
public HashMap<String, String> getSupportedLanguages() {
return supportedLanguages;
}
public String getLanguageCodeByName(String language) {
return supportedLanguages.entrySet().stream().filter(x -> x.getValue().equals(language)).findFirst().get().getKey();
}
}
My project has no errors at all, neither warnings...
I also tried running my jar file using, on Ubuntu:
/usr/bin/java -Dfile.encoding=UTF-8 -jar myproject.jar
but still with no luck.
I really hope you guys may help me, I'm stuck on this issue since 2 days with no solutions at all...
Do not expect InputStream.available() to provide you with accurate information.
See the correct way to convert an InputStream to a ByteArrayInputStream here > Convert InputStream(Image) to ByteArrayInputStream
It seems clear that the InputStream provided by the Parent Classloader is somehow different when loaded in Netbeans than when run from your command line JVM implementation. Your code doesn't show the complete context that this code is executed from but it is possible that the InputStream implementation by Netbeans fully populated the available() method giving you the false impression that the code was correct.
See the documentation at https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#available()
InputStream implementations are not required to populate this method with an accurate value so the results of your code will vary by JVM implementation.

Categories