How do I use SOOT to build at Call graph? Or are there any better programs for this? I have been sent around the same five pages looking for answers and I can't find what I am looking for. There are also a problem with the plugin version to Eclipse. It is installed correct but I cant choose it when I want to run the code.
Small modification to previous answer
private static void visit(CallGraph cg, SootMethod method) {
String identifier = method.getSignature();
visited.put(method.getSignature(), true);
dot.drawNode(identifier);
// iterate over unvisited parents
Iterator<MethodOrMethodContext> ptargets = new Sources(cg.edgesInto(method));
if (ptargets != null) {
while (ptargets.hasNext()) {
SootMethod parent = (SootMethod) ptargets.next();
if (!visited.containsKey(parent.getSignature())) visit(cg, parent);
}
}
Here are some examples include call graph for Java. http://www.brics.dk/SootGuide/
And call graph for apk.
https://github.com/secure-software-engineering/soot-infoflow/issues/38
If you want to get the dot file, you can iterate over the callgraph and write the contents out in dot format like this.
private static void visit(CallGraph cg, SootMethod method) {
String identifier = method.getSignature();
visited.put(method.getSignature(), true);
dot.drawNode(identifier);
// iterate over unvisited parents
Iterator<MethodOrMethodContext> ptargets = new Targets(cg.edgesInto(method));
if (ptargets != null) {
while (ptargets.hasNext()) {
SootMethod parent = (SootMethod) ptargets.next();
if (!visited.containsKey(parent.getSignature())) visit(cg, parent);
}
}
// iterate over unvisited children
Iterator<MethodOrMethodContext> ctargets = new Targets(cg.edgesOutOf(method));
if (ctargets != null) {
while (ctargets.hasNext()) {
SootMethod child = (SootMethod) ctargets.next();
dot.drawEdge(identifier, child.getSignature());
System.out.println(method + " may call " + child);
if (!visited.containsKey(child.getSignature())) visit(cg, child);
}
}
}
Related
I am using OPC UA project https://github.com/OPCFoundation/UA-Java. I was able to browse all the nodes on an OPCUA Server using UAExpert.
Now I am trying to browse all nodes using my java client. I am able to retrieve references for the nodes in the first level of the node hierarchy where
rootnameSpace = 1 and rootIdentifier = "simsre"
BrowseDescription browse = new BrowseDescription();
browse.setNodeId(new NodeId(rootnameSpace, rootIdentifier));
browse.setBrowseDirection(BrowseDirection.Forward);
browse.setIncludeSubtypes(true);
browse.setNodeClassMask(NodeClass.Object, NodeClass.Variable);
browse.setResultMask(BrowseResultMask.All );
BrowseResponse res = mySession.Browse(null, null, null, browse);
ReferenceDescription[] references = res.getResults()[0].getReferences();
When I call the code for other nodes like rootnameSpace = 31 and rootIdentifier = "/simsrede/" beneath I still get a result but no references ( so res.getResults()[0].getReferences() returns null)
- The status code of the browseResponse is something like "GOOD" -
According to specification all unicode characters are allowed in the identifiers so slashes and '|' shouldn't be the problem.
I also tried adding entries into my namespacetable and using the table to set the node id in consecutive browse requests starting at the root node with
NamespaceTable table = NamespaceTable.getDefaultInstance();
table.add(1, "urn:something:UnifiedAutomation:Uagateway");
...
//consecutive browse request starting from reference returned by first call
browse1.setNodeId(table.toNodeId(references[0].getNodeId()));
BrowseResponse res1 = mySession.Browse(null, null, null, browse);
ReferenceDescription[] references1 = res.getResults()[0].getReferences();
Anybody having an idea on why this is returning null references, or how to debug this ?
I used a Browse function
Byte[] cp;ReferenceDescriptionCollection refs; m_session.Browse(null, null, ObjectIds.ObjectsFolder, 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out cp, out refs)
and i get if refs collection of the nodes from first level. Foreach node I called Browse function in recursion where I add nodes to the collection of OPCTreeNode
public void GetChildNodes(Session sesja, ReferenceDescription Parametr, OPCTreeNode treeNode)
{
ReferenceDescriptionCollection nodes;
byte[] tmpbytes;
sesja.Browse(null, null, ExpandedNodeId.ToNodeId(Parametr.NodeId, sesja.NamespaceUris), 0u, BrowseDirection.Forward, ReferenceTypeIds.HierarchicalReferences, true, (uint)NodeClass.Variable | (uint)NodeClass.Object | (uint)NodeClass.Method, out tmpbytes, out nodes);
foreach (var tmpnode in nodes)
{
OPCTreeNode tmpNode = new OPCTreeNode($"{tmpnode.DisplayName}", $"{tmpnode.NodeId}");
treeNode.ChildTreeNodes.Add(tmpNode);
GetChildNodes(sesja, tmpnode, tmpNode);
}
}
OPCTreeNode class
public class OPCTreeNode // element struktury parametrów sesji
{
public string DiplayName { get; set; }
public string NodeId { get; set; }
public List<OPCTreeNode> ChildTreeNodes;
public OPCTreeNode()
{
ChildTreeNodes = new List<OPCTreeNode>();
}
public OPCTreeNode(string displayName, string nodeId)
{
this.DiplayName = displayName;
this.NodeId = nodeId;
ChildTreeNodes = new List<OPCTreeNode>();
}
}
The idea of the function is that it will build a map that contains a key (path) and the data corresponding to that path. This is why I keep passing the map back as it's being built.
The problem seems to be that it gets to the point where there are no children, yet still appends the next path onto the current path:
Input for the path will always start with "/". We get the children for this, which may be level_1A, level_1C, level_1B. Then I recurse on each of these to see if they have children.
Assume that level_1A has children level_2A, level_2B. Somehow, the algorithm gets caught up and is appending like so:
/level_1A/level_2B/level_2A
Whereas, it should be treating these seperately, like this:
/level_1A/level_2A
/level_1A/level_2B
Here's what the entire structure would look like:
/level_1A data_1A
/level_1A/level_2A data_2A
/level_1A/level_2B data_2B
/level_1B (empty)
/level_1C (empty)
Here's the recursive method:
public Map<String, String> getAll(String path, Map<String, String> all) throws Exception {
List<String> children = client.getChildren().forPath(path);
if(children != null && children.size() > 0) {
for(String child: children) {
System.out.println("child: " + child);
if(!path.equals("/")) {
path = path + "/" + child;
} else {
path = path + child;
}
Stat stat = client.checkExists().watched().forPath(path);
if(stat != null && stat.getDataLength() > 0) {
all.put(path, new String(client.getData().forPath(path)));
}
getAll(path, all);
}
}
return all;
}
The error is here:
for(String child: children) {
if(!path.equals("/")) {
path = path + "/" + child;
} else {
path = path + child;
}
...
}
path variable is out of for loop scope, so in the first iteration you've modified path variable and in the second iteration that modified value is been concatenated with second child and then been passed deeper.
So Just provide for-loop scoped variable and use it in iteration:
for(String child: children) {
String pathChild = path;
if(!path.equals("/")) {
pathChild = path + "/" + child;
} else {
pathChild = path + child;
}
//pathChild is used below
...
}
i have list of departments and each department might have a parent or not,department domain object is as follows:
- departmentId
- parentDepartmentId (null if current department has no parent i,e should be under root directly, and have value if current department have parent).
.
.
.
looking at icefaces tutorial code for creating basic tree:
// create root node with its children expanded
DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode();
IceUserObject rootObject = new IceUserObject(rootTreeNode);
rootObject.setText("Root Node");
rootObject.setExpanded(true);
rootTreeNode.setUserObject(rootObject);
// model is accessed by by the ice:tree component via a getter method, this object is what's needed in the view to display the tree
model = new DefaultTreeModel(rootTreeNode);
// add some child nodes
for (int i = 0; i <3; i++) {
DefaultMutableTreeNode branchNode = new DefaultMutableTreeNode();
IceUserObject branchObject = new IceUserObject(branchNode);
branchObject.setText("node-" + i);
branchNode.setUserObject(branchObject);
rootTreeNode.add(branchNode);
}
it's all about constructing basic node, and adding childs.
my case is complex that child A which is under root may have child nodes B,C,D and D have for example child nodes and so on so on.
so i am thinking of a best practice about how to accomplish something like that, i need a sample code or hints if anyone can help.
You would need a recursive method to construct the tree from your model.
public void buildRecursiveTreeNode(DefaultMutableTreeNode parentTreeNode,
String treeId, String treeName, GenericTreeVo modelVo)
{
// if the database model contains more children.
// add the current nodes first and pass in this nodes tree id and name to construct the children for this parent nodes.
}
Updated answer to include recursion example.
http://www.danzig.us/java_class/recursion.html
just added a recursion link, all I am saying is when you iterate the data from the database, you would see if you have any child records, if you have child records you would call the same method by passing the DefaultMutableTreeNode and that would become the parent.
finally i was able to do it as follows:
List<Department> departmentList = getAllDepartments();
// create root node with its children expanded
DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode();
IceUserObject rootObject = new IceUserObject(rootTreeNode);
rootObject.setText("Root");
rootObject.setExpanded(true);
rootTreeNode.setUserObject(rootObject);
HashMap<Department, DefaultMutableTreeNode> createdNodesMap = new HashMap<Department, DefaultMutableTreeNode>(
0);
for (Department department : departmentList) {
DefaultMutableTreeNode currentNode = null;
if (createdNodesMap.get(department) == null) {
log.debug("############ CREATING NODE "
+ department.getName());
currentNode = new DefaultMutableTreeNode();
IceUserObject currentObject = new IceUserObject(currentNode);
currentObject.setText(department.getName());
currentObject.setExpanded(true);
currentNode.setUserObject(currentObject);
if (department.getParentDepartment() == null) {
rootTreeNode.add(currentNode);
log.debug("######### NODE " + department.getName()
+ " ADDED UNDER ROOT");
}
createdNodesMap.put(department, currentNode);
} else {
log.debug("############ GETTING CREATED NODE "
+ department.getName());
currentNode = createdNodesMap.get(department);
}
if (department.getChildren().size() > 0)
log.debug("############ NODE " + department.getName()
+ " HAVE " + department.getChildren().size()
+ " CHILDREN");
else
log.debug("############ NODE " + department.getName()
+ " DOES NOT HAVE CHILDREN");
for (Department department2 : department.getChildren()) {
log.debug("############ CREATING CHILD "
+ department2.getName() + " FOR PARENT "
+ department.getName());
DefaultMutableTreeNode branchNode;
if (createdNodesMap.get(department2) == null) {
branchNode = new DefaultMutableTreeNode();
IceUserObject branchObject = new IceUserObject(
branchNode);
branchObject.setText(department2.getName());
branchObject.setExpanded(true);
branchNode.setUserObject(branchObject);
} else
branchNode = createdNodesMap.get(department2);
createdNodesMap.put(department2, branchNode);
currentNode.add(branchNode);
}
}
model = new DefaultTreeModel(rootTreeNode);
Check http://click.avoka.com/click-examples/tree/checkbox-tree-page.htm
The latter is done via the Apache Click framework. Right now I'm developing a project where this data structure (hierarchy tree) is heavily used. You can set the root node or if you need to have several starting points, you can create a wildcard root node that won't affect the functionality, the subclasses, like others have commented, need to be created recursively.
I have two emf models A and B where B only differs from A because it has an extra child node.
Now I would like to use emf compare from code to do:
1) Read model A and B and create model C which is a merged model from A and B. Basically this corresponds to A + the extra nodes from B.
I have looked at:
http://dev.eclipse.org/viewcvs/viewvc.cgi/org.eclipse.emf/org.eclipse.emf.compare/examples/org.eclipse.emf.compare.examples.standalone/src/org/eclipse/emf/compare/examples/standalone/ExampleLauncher.java?view=co&root=Modeling_Project
But I don't see how I can compute the final merged model using the code:
DiffModel diff = CompareUtils.compare(model1, model2, Collections.<String, Object> emptyMap());
CompareUtils.merge(diff);
Any examples that shows how to compute the merged model??
I have now tried:
private void bob() {
ResourceSet resourceSet = new ResourceSetImpl();
Map extensionMap = (Map) resourceSet.getResourceFactoryRegistry()
.getExtensionToFactoryMap().put("xmi", new XMIResourceFactoryImpl());
try {
Region region01 = StatemachineFactoryImpl.eINSTANCE.createRegion();
addResourceToModel(resourceSet, region01, "st1.xmi");
State state01 = StatemachineFactoryImpl.eINSTANCE.createState();
state01.setName("aaaa");
region01.getState().add(state01);
if (state01.eResource() == null) {
System.out.println("state01 NOT contained in resource!");
return;
}
Region region02 = StatemachineFactoryImpl.eINSTANCE.createRegion();
addResourceToModel(resourceSet, region02, "st2.xmi");
State state02 = StatemachineFactoryImpl.eINSTANCE.createState();
state02.setName("bbbb");
region02.getState().add(state02);
if (state02.eResource() == null) {
System.out.println("state02 NOT contained in resource!");
return;
}
final MatchModel match = MatchService.doMatch(region01, region02,
Collections.<String, Object> emptyMap());
final DiffModel diff = DiffService.doDiff(match, false);
final List<DiffElement> differences = new ArrayList<DiffElement>(
diff.getOwnedElements());
MergeService.merge(differences, true);
// Prints the results
addResourceToModel(resourceSet, match, "match.xmi");
addResourceToModel(resourceSet, diff, "diff.xmi");
if (match.eResource() != null)
System.out.println(ModelUtils.serialize(match)); // Throws an
// exception!
if (diff.eResource() != null)
System.out.println(ModelUtils.serialize(diff));
} catch (final InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void addResourceToModel(ResourceSet resourceSet, EObject obj,
String path) {
Resource res = resourceSet.createResource(URI.createURI(path));
res.getContents().add(obj);
}
But the line:
if (match.eResource() != null)
System.out.println(ModelUtils.serialize(match)); // Throws an
// exception!
even though match.eResource() != null
I get this error:
org.eclipse.emf.ecore.resource.Resource$IOWrappedException: The object 'statemachine.impl.StateImpl#11ce012 (name: bbbb)' is not contained in a resource.
at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.endSave(XMLSaveImpl.java:306)
at org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl.save(XMLSaveImpl.java:235)
at org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl.doSave(XMLResourceImpl.java:254)
at org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl.save(XMLResourceImpl.java:229)
at org.eclipse.emf.compare.util.ModelUtils.serialize(ModelUtils.java:429)
I have added Region to a resource based on the documentation here:
http://wiki.eclipse.org/index.php/EMF-FAQ#I_get_a_DanglingHREFException:e.g..2C.22org.eclipse.emf.ecore.xmi.DanglingHREFException:_The_object_.27com.example.Foo.402f5dda_.28.29.27_is_not_contained_in_a_resource..22_What_do_I_need_to_do.3F
and the State is contained in the Region so I don't understand why I get the exception...any ideas?
Tul,
The stack trace you get means that one of the 'merged' objects is not contained into a resource : when merging, we copy an object that references a statemachine (which name is 'bbbb'), we then need to reference this state machine from the copied object ... and that statemachine we reference (is it copied or directly referenced from your other model? You should debug to see this) isn't itself contained in any resource.
State state02 = StatemachineFactoryImpl.eINSTANCE.createState();
state02.setName("bbbb");
region02.getState().add(state02);
if (state02.eResource() == null) {
System.out.println("state02 NOT contained in resource!");
return;
}
This should ensures that "bbbb" is indeed contained in a resource.
After this line :
MergeService.merge(differences, true);
Could you try to check once more if "state02.eResource() == null" ? If it is, then that is your issue. Otherwise, you'll have to make sure that this doesn't return :
for (State state : region01.getState()) {
if (state.eResource() == null) {
System.err.println(state.getName() + " is not contained in a resource);
return;
}
}
What about this?
Model1 targetModel = EcoreUtil.copy(model1);
addResourceToModel(targetModel) // assign the copied model to a resource
MatchModel match = MatchService.doMatch(targetModel, model2,
Collections.<String, Object> emptyMap());
DiffModel diff = DiffService.doDiff(match, false);
EList<DiffElement> differences = diff.getDifferences();
for (DiffElement diffElement : differences) {
MergeService.merge(diffElement, true);
}
Your exception:" org.eclipse.emf.ecore.resource.Resource$IOWrappedException: The object 'statemachine.impl.StateImpl#11ce012 (name: bbbb)' is not contained in a resource.". The StateImpl#11ce012 (name: bbbb) is in one resource named st2.xmi,but the match elememt is in another resource named "match.xml". The two resources are different and they do not refer each other. So the match element can NOT refer StateImpl. To solve this problem, all elements(state01, state02, match, diff) must be saved in ONE resource. The code is:
res.getContents().add(stat01);
res.getContents().add(stat02);
res.getContents().add(match);
res.getContents().add(diff);
By the way, the condition "state02.eResource() == null" is not nessary.
Can i get the full xpath from the org.w3c.dom.Node ?
Say currently node is pointing to some where the middle of the xml document. I would like extract the xpath for that element.
The output xpath I'm looking for is //parent/child1/chiild2/child3/node. A parent to node xpath. Just ignore the xpath's which are having expressions and points to the same node.
There's no generic method for getting the XPath, mainly because there's no one generic XPath that identifies a particular node in the document. In some schemas, nodes will be uniquely identified by an attribute (id and name are probably the most common attributes.) In others, the name of each element (that is, the tag) is enough to uniquely identify a node. In a few (unlikely, but possible) cases, there's no one unique name or attribute that takes you to a specific node, and so you'd need to use cardinality (get the n'th child of the m'th child of...).
EDIT:
In most cases, it's not hard to create a schema-dependent function to assemble an XPath for a given node. For example, suppose you have a document where every node is uniquely identified by an id attribute, and you're not using namespaces. Then (I think) the following pseudo-Java would work to return an XPath based on those attributes. (Warning: I have not tested this.)
String getXPath(Node node)
{
Node parent = node.getParent();
if (parent == null) {
return "/" + node.getTagName();
}
return getXPath(parent) + "/" + "[#id='" + node.getAttribute("id") + "']";
}
I am working for the company behind jOOX, a library that provides many useful extensions to the Java standard DOM API, mimicking the jquery API. With jOOX, you can obtain the XPath of any element like this:
String path = $(element).xpath();
The above path will then be something like this
/document[1]/library[2]/books[3]/book[1]
I've taken this code from
Mikkel Flindt post & modified it so it can work for Attribute Node.
public static String getFullXPath(Node n) {
// abort early
if (null == n)
return null;
// declarations
Node parent = null;
Stack<Node> hierarchy = new Stack<Node>();
StringBuffer buffer = new StringBuffer();
// push element on stack
hierarchy.push(n);
switch (n.getNodeType()) {
case Node.ATTRIBUTE_NODE:
parent = ((Attr) n).getOwnerElement();
break;
case Node.ELEMENT_NODE:
parent = n.getParentNode();
break;
case Node.DOCUMENT_NODE:
parent = n.getParentNode();
break;
default:
throw new IllegalStateException("Unexpected Node type" + n.getNodeType());
}
while (null != parent && parent.getNodeType() != Node.DOCUMENT_NODE) {
// push on stack
hierarchy.push(parent);
// get parent of parent
parent = parent.getParentNode();
}
// construct xpath
Object obj = null;
while (!hierarchy.isEmpty() && null != (obj = hierarchy.pop())) {
Node node = (Node) obj;
boolean handled = false;
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element) node;
// is this the root element?
if (buffer.length() == 0) {
// root element - simply append element name
buffer.append(node.getNodeName());
} else {
// child element - append slash and element name
buffer.append("/");
buffer.append(node.getNodeName());
if (node.hasAttributes()) {
// see if the element has a name or id attribute
if (e.hasAttribute("id")) {
// id attribute found - use that
buffer.append("[#id='" + e.getAttribute("id") + "']");
handled = true;
} else if (e.hasAttribute("name")) {
// name attribute found - use that
buffer.append("[#name='" + e.getAttribute("name") + "']");
handled = true;
}
}
if (!handled) {
// no known attribute we could use - get sibling index
int prev_siblings = 1;
Node prev_sibling = node.getPreviousSibling();
while (null != prev_sibling) {
if (prev_sibling.getNodeType() == node.getNodeType()) {
if (prev_sibling.getNodeName().equalsIgnoreCase(
node.getNodeName())) {
prev_siblings++;
}
}
prev_sibling = prev_sibling.getPreviousSibling();
}
buffer.append("[" + prev_siblings + "]");
}
}
} else if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
buffer.append("/#");
buffer.append(node.getNodeName());
}
}
// return buffer
return buffer.toString();
}
For me this one worked best ( using org.w3c.dom elements):
String getXPath(Node node)
{
Node parent = node.getParentNode();
if (parent == null)
{
return "";
}
return getXPath(parent) + "/" + node.getNodeName();
}
Some IDEs specialised in XML will do that for you.
Here are the most well known
oXygen
Stylus Studio
xmlSpy
For instance in oXygen, you can right-click on an element part of an XML document and the contextual menu will have an option 'Copy Xpath'.
There are also a number of Firefox add-ons (such as XPather that will happily do the job for you. For Xpather, you just click on a part of the web page and select in the contextual menu 'show in XPather' and you're done.
But, as Dan has pointed out in his answer, the XPath expression will be of limited use. It will not include predicates for instance. Rather it will look like this.
/root/nodeB[2]/subnodeX[2]
For a document like
<root>
<nodeA>stuff</nodeA>
<nodeB>more stuff</nodeB>
<nodeB cond="thisOne">
<subnodeX>useless stuff</subnodeX>
<subnodeX id="MyCondition">THE STUFF YOU WANT</subnodeX>
<subnodeX>more useless stuff</subnodeX>
</nodeB>
</root>
The tools I listed will not generate
/root/nodeB[#cond='thisOne']/subnodeX[#id='MyCondition']
For instance for an html page, you'll end-up with the pretty useless expression :
/html/body/div[6]/p[3]
And that's to be expected. If they had to generate predicates, how would they know which condition is relevant ? There are zillions of possibilities.
Something like this will give you a simple xpath:
public String getXPath(Node node) {
return getXPath(node, "");
}
public String getXPath(Node node, String xpath) {
if (node == null) {
return "";
}
String elementName = "";
if (node instanceof Element) {
elementName = ((Element) node).getLocalName();
}
Node parent = node.getParentNode();
if (parent == null) {
return xpath;
}
return getXPath(parent, "/" + elementName + xpath);
}