Commit 7c04055a authored by 皮皮蟹's avatar 皮皮蟹 Committed by Evan W. Patton

Handle transitive nature of disabled blocks in conditional permissions

Null value shouldn't add to map, and blocks under a disabled block should be ignored.
parent bec5507f
......@@ -9,15 +9,13 @@ package com.google.appinventor.buildserver;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
......@@ -161,87 +159,59 @@ public class FormPropertiesAnalyzer {
* @return A mapping of component type names to sets of blocks used
*/
public static Map<String, Set<String>> getComponentBlocksFromBlocksFile(String source) {
Map<String, Set<String>> result = new HashMap<>();
final Map<String, Set<String>> result = new HashMap<>();
if (source == null || source.isEmpty()) {
return result;
}
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new ByteArrayInputStream(source.getBytes(StandardCharsets.UTF_8)));
NodeList blocks = doc.getElementsByTagName("block");
for (int i = 0; i < blocks.getLength(); i++) {
Element block = (Element) blocks.item(i);
String type = block.getAttribute("type");
// Skip non-component and disabled blocks
if (!isComponentBlock(type) || "true".equals(block.getAttribute("disabled"))) continue;
Element mutation = getMutation(block);
if (mutation != null) { // Should always be true, in theory...
String componentType = mutation.getAttribute("component_type");
String blockName = getBlockName(type, mutation);
if (!result.containsKey(componentType)) {
result.put(componentType, new HashSet<String>());
XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setContentHandler(new DefaultHandler() {
private int skipBlocksCounter = 0;
private String blockType;
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
if ("block".equals(qName)) {
if ("true".equals(attributes.getValue("disabled")) || skipBlocksCounter > 0) {
skipBlocksCounter++;
}
blockType = attributes.getValue("type");
} else if ("next".equals(qName) && skipBlocksCounter == 1) {
skipBlocksCounter = 0;
} else if (skipBlocksCounter == 0 && "mutation".equals(qName)) {
String blockName = null;
if ("component_event".equals(blockType)) {
blockName = attributes.getValue("event_name");
} else if ("component_method".equals(blockType)) {
blockName = attributes.getValue("method_name");
} else if ("component_set_get".equals(blockType)) {
blockName = attributes.getValue("property_name");
}
if (blockName != null) {
String componentType = attributes.getValue("component_type");
if (!result.containsKey(componentType)) {
result.put(componentType, new HashSet<String>());
}
result.get(componentType).add(blockName);
}
}
result.get(componentType).add(blockName);
}
}
} catch(SAXException | IOException | ParserConfigurationException e) {
throw new IllegalStateException(e);
}
return result;
}
/**
* Tests a block to see if it is a component block.
* @param type The type string from the block element
* @return true if the type string represents a component block, otherwise
* false.
*/
private static boolean isComponentBlock(String type) {
return type != null && type.startsWith("component_");
}
/**
* Extracts the &lt;mutation&gt; element from the block XML.
*
* @param block The &lt;block&gt; element being processed
* @return An Element representing the &lt;mutation&gt; element of the block
* if one exists, otherwise null.
*/
private static Element getMutation(Element block) {
NodeList children = block.getChildNodes();
for (int j = 0; j < children.getLength(); j++) {
Node child = children.item(j);
if (child instanceof Element) {
Element childEl = (Element) child;
if ("mutation".equals(childEl.getTagName())) {
return childEl;
super.startElement(uri, localName, qName, attributes);
}
}
}
return null;
}
/**
* Gets the name of a component block from the mutation.
*
* @param type The type of the block, e.g. component_event
* @param mutation The mutation element extracted from the XML
* @return the name of the block's event, method, or property, if the block
* is one of those types (either a specific instance or generic). Otherwise,
* null.
*/
private static String getBlockName(String type, Element mutation) {
if ("component_event".equals(type)) {
return mutation.getAttribute("event_name");
} else if ("component_method".equals(type)) {
return mutation.getAttribute("method_name");
} else if ("component_set_get".equals(type)) {
return mutation.getAttribute("property_name");
} else {
return null;
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if ("block".equals(qName) && skipBlocksCounter > 0) {
skipBlocksCounter--;
}
super.endElement(uri, localName, qName);
}
});
reader.parse(new InputSource(new ByteArrayInputStream(source.getBytes(StandardCharsets.UTF_8))));
} catch (SAXException | IOException e) {
throw new IllegalStateException(e);
}
return result;
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment