Invoking Remote Systems LPEX Editor using java - java

We have a set of plugins installed in RDI where they display a list of native RPGLE programs and have got a set of classes that invoke the LPEX editor to allow editing the source file in the traditional Library/SoureFile/Member settings.
I now want to extend this to be able to add/edit RPGLE source in the IFS but cannot find the IBM classes that allow this.
For the normal native source the code is
IQSYSMember memberObj;
IBMiConnection iSeriesConnection = RSEConnectionFactory.getISeriesConnection(connection);
memberObj = iSeriesConnection.getMember(
a.getSourceLibrary(),
a.getSourceFile(),
a.getSourceMember(),
null);
QSYSEditableRemoteSourceFileMember editableMember = new QSYSEditableRemoteSourceFileMember(memberObj);
editableMember.open(Display.getCurrent().getActiveShell(), false);
Obviously for source that are in IFS, all I have is a path (/home/path/QRPGLESRC/nnn.RPGLE).
I know I can go to Remote System Explorer and right hand click and select "Open with Remote Systems LPEX Editor" but need to do this from my plugins.
Anyone know which IBM classes allow this to happen?
Many thanks.

Use the open(boolean,progressmonitor) method on QSYSEditableRemoteSourceFileMember

This has fixed my issue:
FileServiceSubSystem fileService = LpexHelper.getFileServiceSubsystem(iSeriesConnection);
IRemoteFile remoteFile = fileService.getRemoteFileObject(path, new NullProgressMonitor());
SystemEditableRemoteFile file = new SystemEditableRemoteFile(remoteFile);
if (file.exists()) {
file.open(Display.getCurrent().getActiveShell(), true);
}

Related

Can't import model from MPS file to IloCplex - IBM ILOG CPLEX - Java - Intellij

I'm currently developing a project in java using the Ilog Cplex libraries, I'm using the Intellij-Idea IDE.
I'm having troubles importing a model from MPS file, this is the piece of code that gives me problems
IloCplex iloCplexInstance = new IloCplex();
iloCplexInstance.importModel(fileName);
It fires this exception:
ilog.cplex.CpxException: CPLEX Error 1423: Could not open file 'models\20_70_45_05_100.mps' for reading.
at ilog.cplex.CplexI.CALL(CplexI.java:5204)
at ilog.cplex.CplexI._readModel(CplexI.java:5584)
at ilog.cplex.CplexI.importModel(CplexI.java:1032)
at ilog.cplex.IloCplex.importModel(IloCplex.java:902)
at heuristics.ziround.LPUtils.fromMPS(LPUtils.java:34)
at heuristics.test.LPUtilsTestCompile.main(LPUtilsTestCompile.java:13)
I tried running it in unit tests using junit4, junit.runners.Parameterized, and in a simple class from its main method. Same result in each case. I've also tried to set the full path to the file and it gives the same result.
I know that the file I used is ok, I'm able to read it using the cplex terminal commands, I also tried other files.
The code that uses the Ilog's libraries can compile, I'm not sure if it can run though since I'm not able to import a model I can't try to solve one.
I'm using windows, launching the IDE as admin sorts no effects, and the file is not blocked from reading (nor writing).
I'm following the documentation from IBM:
https://www.ibm.com/support/knowledgecenter/SSSA5P_12.7.0/ilog.odms.cplex.help/refjavacplex/html/ilog/cplex/IloCplex.html#importModel(java.lang.String)
In the official support pages, I found this about the error: http://www-eio.upc.es/lceio/manuals/cplex-11/html/refcallablelibrary/html/macros/CPXERR_FAIL_OPEN_READ.html
But I can't find anything useful.
Also, the IBM forum is currently closed and no one seems to have had this kind of problem :(
Does anyone know what could be the trouble? What can I do? Do you know of any other alternative?
Thanks to anyone that will stop by!!
The exception message says:
ilog.cplex.CpxException: CPLEX Error 1423: Could not open file
'models\20_70_45_05_100.mps' for reading.
Try using an absolute path instead, like c:\path\to\your\models\20_70_45_05_100.mps.
You can also add code to your program to make sure the path exists. Something like:
import java.nio.file.Files;
...
IloCplex iloCplexInstance = new IloCplex();
if (!Files.exists(fileName))
throw new AssertionError("path does not exist: " + fileName);
iloCplexInstance.importModel(fileName);
Following #rkersh answer i did this:
String modelsPath = "absolute\\folder\\path";
Collection<Object[]> models = new ArrayList<>();
File folder = new File(modelsPath);
for (final File fileEntry : Objects.requireNonNull(folder.listFiles())) {
if (fileEntry.isFile())
models.add(new String[]{fileEntry.getAbsolutePath()});
}
return models;
This makes sure that the absolute path is correct and now iloCplexInstance.importModel(fileName); accepts it fine

Is there a way that I can override a file within the JRE on execution? That is, without editing the JRE?

I want to add a numberpad to JavaFX's virtual keyboard.
I've tried several other solutions (including using a keyboard from GitHub or trying JavaFX's numeric virtual keyboard), but this would be the easiest and most practical.
I found the text file (com.sun.scene.control.skin.TextBoard.txt) that is read by com.sun.scene.control.skin.FXVKSkin.class to create the normal keyboard. I added the numpad, and it works fine. However, I want to do this without actually editing the JRE.
This is the relevant part of FXVKSkin.java that loads the keyboard.
private List<List<Key>> loadBoard(String type) {
List<List<Key>> tmpBoard = boardMap.get(type);
if (tmpBoard != null) {
return tmpBoard;
}
String boardFileName = type.substring(0,1).toUpperCase() + type.substring(1).toLowerCase() + "Board.txt";
try {
tmpBoard = new ArrayList<List<Key>>(5);
List<Key> keys = new ArrayList<Key>(20);
InputStream boardFile = FXVKSkin.class.getResourceAsStream(boardFileName);
BufferedReader reader = new BufferedReader(new InputStreamReader(boardFile));
Alternatively, would I be able to just keep TextBoard.txt in my project's classpath and somehow point to that copy instead of the one within the JRE when FXVKSkin.java says "FXVKSkin.class.getResourceAsStream("TextBoard.txt")?
I found a solution!
I took jre/lib/ext/jfxrt.jar, which is the jar file in which com.sun.scene.control.skin.TextBoard.txt resides, and copied it into my project's working directory. I deleted everything within the copy except for the path com/sun/javafx/scene/control/skin/TextBoard.txt, and added "-Xbootclasspath/a:jfxrt.jar" as a boot option. I am still on Java 8, so this might not work for later versions, but it's working for me.

Programmatically list open projects in an eclipse workspace from outside of eclipse

I want to write a Gradle plugin which can inspect an eclipse workspace directory and iterate over the open projects within the workspace and determine the location of each.
Something like
Workspace workspace = EclipseUtils.parseWorkspace("c:/myEclipseWorkspace");
Collection<Project> projects = workspace.getProjects();
for (Project project : projects) {
System.out.println(String.format("name=%s, location=%s, open=%s",
project.getName(), project.getLocation(), project.isOpen()));
}
I've looked at my workspace and can see some .location files under c:\myEclipseWorkspace\.metadata\.plugins\org.eclipse.core.resources\.projects\
But these files are a custom binary format
Is there an eclipse API that I can invoke to parse these? Or some other solution to iterate the open projects in a workspace.
Please note that I want to do this externally to eclipse and NOT within an eclipse plugin.
Reading the Private Description to Obtain Location
Since you are writing in Java, then reuse the Eclipse code from your external location.
i.e. Pull out some of the key code from org.eclipse.core.resources.ResourcesPlugin. Start with the impl of org.eclipse.core.resources.ResourcesPlugin.getWorkspace() and then work your way to org.eclipse.core.resources.IWorkspaceRoot.getProjects()
The above code reads the project description here: org.eclipse.core.internal.resources.LocalMetaArea.readPrivateDescription(IProject, ProjectDescription) and that is called from org.eclipse.core.internal.localstore.FileSystemResourceManager.read(IProject, boolean) which has some logic about default locations.
This is the joy of EPL, as long as your new program/feature is EPL you can reuse Eclipse's core code to do new and wonderful things.
Reading Workspace State to Obtain Open/Close State
When reading workspace state, you are moving into the ElementTree data structures. Reading this without using the ElementTree classes is probably unrealistic. Using the ElementTree classes without full OSGi is probably unrealistic. I provide the following notes to help you on your way.
Working backwards:
ICoreConstants.M_OPEN is the flag value indicating project is open or closed (set for open, clear for closed)
M_OPEN is tested when Project.isOpen() is called
The flags at runtime are in ResourceInfo.flags
The flags are loaded by ResourceInfo.readFrom() called from SaveManager.readElement()
The DataInput input passed to readElement is from the Element Tree stored in the workspace meta directory in .metadata/.plugins/org.eclipse.core.resources/.root/<id>.tree. The specific version (id) of the file to use is recorded in the safe table .metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources
The safe table is part of the SaveManager's internal state stored in a MasterTable
I've managed to parse the file using this as a reference
protected Location parseLocation(File locationFile) throws IOException {
String name = locationFile.getParentFile().getName();
DataInputStream in = new DataInputStream(new FileInputStream(locationFile));
try {
in.skip(ILocalStoreConstants.BEGIN_CHUNK.length);
String path = in.readUTF();
int numRefs = in.readInt();
String[] refNames = new String[numRefs];
for (int i = 0; i < numRefs; ++ i) {
refNames[i] = in.readUTF();
}
in.skipBytes(ILocalStoreConstants.END_CHUNK.length);
return new Location(name, path, refNames);
} finally {
in.close();
}
}
Unfortunately this doesn't seem to be able to detect if a project is closed or not. Any pointers on getting the closed flag would be much appreciated

Creating a new Java project

I am able to create a default project in PDE just like mentioned here.
However I want to know how to create a Java project. How can I do that?
As a minimum you need to add the Java project nature to the project you create. Use something like:
private void addNatureToProject(IProject proj, String natureId, IProgressMonitor monitor) throws CoreException
{
IProjectDescription description = proj.getDescription();
String[] prevNatures = description.getNatureIds();
String[] newNatures = new String[prevNatures.length + 1];
System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
newNatures[prevNatures.length] = natureId;
description.setNatureIds(newNatures);
proj.setDescription(description, monitor);
}
The nature id for a Java project is 'org.eclipse.jdt.core.javanature' (also in the JavaCore.NATURE_ID constant).
Note that this does not add the various builders that are normally used in a Java project. The IProjectDescription.setBuildSpec method adds those in a similar way. Create a command for the build spec with:
ICommand command = description.newCommand();
command.setBuilderName(builderID);
where 'builderId' is 'org.eclipse.jdt.core.javabuilder' for the main Java builder (JavaCore.BUILDER_ID constant).
All this information is stored in the '.project' file in the project root folder. This is an XML file which you can look at to see the set up of existing projects.
Window->Open Perspective->Java
then
File->New->Java Project (you may have to go via "Project..." to get to the "Java Project" option)
Please refer to New Project Creation Wizards
On the Plug-in Project page, use com.example.helloworld as the name
for your project and check the box for Create a Java project (this
should be the default). Leave the other settings on the page with
their default settings and then click Next to accept the default
plug-in project structure.

Programmatically analyze java heap dump file

I want to write a program (preferably in java) that will parse and analyze a java heap dump file (created by jmap). I know there are many great tools that already do so (jhat, eclipse's MAT, and so on), but I want to analyze the heap from a specific perspective to my application.
Where can I read about the structure of the heap dump file, examples how to read it, and so on? Didn't find anything useful searching for it...
Many thanks.
The following was done with Eclipse Version: Luna Service Release 1 (4.4.1) and Eclipse Memory Analyzer Version 1.4.0
Programmatically Interfacing with the Java Heap Dump
Environment Setup
In eclipse, Help -> Install New Software -> install Eclipse Plug-in Development Environment
In eclipse, Window -> Preferences -> Plug-in Development -> Target Platform -> Add
Nothing -> Locations -> Add -> Installation
Name = MAT
Location = /path/to/MAT/installation/mat
Project Setup
File -> new -> Other -> Plug-in Project
Name: MAT Extension
Next
Disable Activator
Disable Contributions to the UI
Disable API analysis
Next
Disable template
Finish
Code Generation
Open plugin.xml
Dependencies -> Add
select org.eclipse.mat.api
Extensions -> Add
select org.eclipse.mat.report.query
right click on report.query -> New
Name: MyQuery
click "impl" to generate the class
Implementing IQuery
#CommandName("MyQuery") //for the command line interface
#Name("My Query") //display name for the GUI
#Category("Custom Queries") //list this Query will be put under in the GUI
#Help("This is my first query.") //help displayed
public class MyQuery implements IQuery
{
public MyQuery{}
#Argument //snapshot will be populated before the call to execute happens
public ISnapshot snapshot;
/*
* execute : only method overridden from IQuery
* Prints out "My first query." to the output file.
*/
#Override
public IResult execute(IProgressListener arg0) throws Exception
{
CharArrayWriter outWriter = new CharArrayWriter(100);
PrintWriter out = new PrintWriter(outWriter);
SnapshotInfo snapshotInfo = snapshot.getSnapshotInfo();
out.println("Used Heap Size: " + snapshotInfo.getUsedHeapSize());
out.println("My first query.")
return new TextResult(outWriter.toString(), false);
}
}
ctrl+shift+o will generate the correct "import" statements.
Custom queries can be accessed within the MAT GUI by accessing the toolbar's "Open Query Browser" at the top of the hprof file you have opened.
The ISnapshot interface
The most important interface one can use to extract data from a heap dump is ISnapshot. ISnapshot represents a heap dump and offers various methods for reading object and classes from it, getting the size of objects, etc…
To obtain an instance of ISnapshot one can use static methods on the SnapshotFactory class. However, this is only needed if the API is used to implement a tool independent of Memory Analyzer. If you are writing extensions to MAT, then your coding will get an instance corresponding to an already opened heap dump either by injection or as a method parameter.
Reference
Built in Command Line Utility
If you're looking to have a program generate the usual reports, there is a command line utility called ParseHeapDump available with any download of Eclipse's MAT tool. You'll be able to get useful html dumps of all the information MAT stores.
> ParseHeapDump <heap dump> org.eclipse.mat.api:suspects org.eclipse.mat.api:top_components org.eclipse.mat.api:overview #will dump out all general reports available through MAT
Hopefully this is enough information to get you started.
I'm not familiar with jhat, but Eclipse's MAT is open source. Their SVN link is available, perhaps you could look through that for their parser, perhaps even use it.

Categories