From 2add4904b8eaabd560f7db70abe5d0263dcf9da0 Mon Sep 17 00:00:00 2001 From: pavels Date: Mon, 22 Feb 2016 13:01:29 +0100 Subject: [PATCH] Issue #341 - DOM access synchronization --- .../incad/kramerius/impl/SolrAccessImpl.java | 16 +- .../cz/incad/kramerius/utils/XMLUtils.java | 213 ++++++++++-------- .../incad/kramerius/utils/solr/SolrUtils.java | 55 +++-- .../rest/api/k5/client/utils/SOLRUtils.java | 165 ++++++++------ 4 files changed, 254 insertions(+), 195 deletions(-) diff --git a/common/src/main/java/cz/incad/kramerius/impl/SolrAccessImpl.java b/common/src/main/java/cz/incad/kramerius/impl/SolrAccessImpl.java index fd0e41386d..c665594c1b 100644 --- a/common/src/main/java/cz/incad/kramerius/impl/SolrAccessImpl.java +++ b/common/src/main/java/cz/incad/kramerius/impl/SolrAccessImpl.java @@ -136,13 +136,15 @@ public ObjectModelsPath[] getPathOfModels(String pid) throws IOException { private ObjectModelsPath[] getPathOfModels(Document doc) throws XPathExpressionException { - List disected = SolrUtils.disectModelPaths(doc); - ObjectModelsPath[] paths = new ObjectModelsPath[disected.size()]; - for (int i = 0; i < paths.length; i++) { - String[] models = disected.get(i).split("/"); - paths[i] = new ObjectModelsPath(models); + synchronized(doc) { + List disected = SolrUtils.disectModelPaths(doc); + ObjectModelsPath[] paths = new ObjectModelsPath[disected.size()]; + for (int i = 0; i < paths.length; i++) { + String[] models = disected.get(i).split("/"); + paths[i] = new ObjectModelsPath(models); + } + return paths; } - return paths; } @@ -214,6 +216,4 @@ public InputStream terms(String req, String type) throws IOException { throw new IOException(e); } } - - } diff --git a/common/src/main/java/cz/incad/kramerius/utils/XMLUtils.java b/common/src/main/java/cz/incad/kramerius/utils/XMLUtils.java index 22813aaf1b..958cd25216 100644 --- a/common/src/main/java/cz/incad/kramerius/utils/XMLUtils.java +++ b/common/src/main/java/cz/incad/kramerius/utils/XMLUtils.java @@ -11,6 +11,8 @@ import java.util.Collections; import java.util.List; import java.util.Stack; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -29,12 +31,17 @@ import org.xml.sax.SAXException; /** - * Simple xml utitlities + * Handle XML; parsing, find, etc.. * @author pavels * + * Implementation note: All DOM access methods are synchronized on Document object + * */ public class XMLUtils { + public static final Logger LOGGER = Logger.getLogger(XMLUtils.class.getName()); + + /** * PArse document from reader * @param reader Reader @@ -44,7 +51,9 @@ public class XMLUtils { * @throws IOException */ public static Document parseDocument(Reader reader) throws ParserConfigurationException, SAXException, IOException { - DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + DocumentBuilderFactory newInstance = DocumentBuilderFactory.newInstance(); + LOGGER.log(Level.FINE, "builder factory instance :"+newInstance.getClass().getResource(newInstance.getClass().getSimpleName()+".class")); + DocumentBuilder builder = newInstance.newDocumentBuilder(); return builder.parse(new InputSource(reader)); } @@ -59,6 +68,7 @@ public static Document parseDocument(Reader reader) throws ParserConfigurationEx */ public static Document parseDocument(Reader reader, boolean namespaceaware) throws ParserConfigurationException, SAXException, IOException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + LOGGER.log(Level.FINE, "builder factory instance :"+factory.getClass().getResource(factory.getClass().getSimpleName()+".class")); factory.setNamespaceAware(namespaceaware); DocumentBuilder builder = factory.newDocumentBuilder(); return builder.parse(new InputSource(reader)); @@ -73,7 +83,9 @@ public static Document parseDocument(Reader reader, boolean namespaceaware) thro * @throws IOException */ public static Document parseDocument(InputStream is) throws ParserConfigurationException, SAXException, IOException { - DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + DocumentBuilderFactory newInstance = DocumentBuilderFactory.newInstance(); + LOGGER.log(Level.FINE, "builder factory instance :"+newInstance.getClass().getResource(newInstance.getClass().getSimpleName()+".class")); + DocumentBuilder builder = newInstance.newDocumentBuilder(); return builder.parse(is); } @@ -88,6 +100,7 @@ public static Document parseDocument(InputStream is) throws ParserConfigurationE */ public static Document parseDocument(InputStream is, boolean namespaceaware) throws ParserConfigurationException, SAXException, IOException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + LOGGER.log(Level.FINE, "builder factory instance :"+factory.getClass().getResource(factory.getClass().getSimpleName()+".class")); factory.setNamespaceAware(namespaceaware); DocumentBuilder builder = factory.newDocumentBuilder(); return builder.parse(is); @@ -99,15 +112,18 @@ public static Document parseDocument(InputStream is, boolean namespaceaware) thr * @return */ public static List getElements(Element topElm) { - List retVals = new ArrayList(); - NodeList childNodes = topElm.getChildNodes(); - for (int i = 0, ll = childNodes.getLength(); i < ll; i++) { - Node n = childNodes.item(i); - if (n.getNodeType() == Node.ELEMENT_NODE) { - retVals.add((Element) n); + if (topElm == null) throw new IllegalArgumentException("topElm cannot be null"); + synchronized(topElm.getOwnerDocument()) { + List retVals = new ArrayList(); + NodeList childNodes = topElm.getChildNodes(); + for (int i = 0, ll = childNodes.getLength(); i < ll; i++) { + Node n = childNodes.item(i); + if (n.getNodeType() == Node.ELEMENT_NODE) { + retVals.add((Element) n); + } } + return retVals; } - return retVals; } /** @@ -117,38 +133,44 @@ public static List getElements(Element topElm) { * @return */ public static List getElements(Element topElm, ElementsFilter filter ) { - List retVals = new ArrayList(); - NodeList childNodes = topElm.getChildNodes(); - for (int i = 0, ll = childNodes.getLength(); i < ll; i++) { - Node n = childNodes.item(i); - if (n.getNodeType() == Node.ELEMENT_NODE) { - Element elm = (Element) n; - if (filter.acceptElement(elm)) { - retVals.add(elm); + if (topElm == null) throw new IllegalArgumentException("topElm cannot be null"); + synchronized(topElm.getOwnerDocument()) { + List retVals = new ArrayList(); + NodeList childNodes = topElm.getChildNodes(); + for (int i = 0, ll = childNodes.getLength(); i < ll; i++) { + Node n = childNodes.item(i); + if (n.getNodeType() == Node.ELEMENT_NODE) { + Element elm = (Element) n; + if (filter.acceptElement(elm)) { + retVals.add(elm); + } } } + return retVals; } - return retVals; } public static List getElementsRecursive(Element topElm, ElementsFilter filter) { - List elms = new ArrayList(); - Stack stack = new Stack(); - stack.push(topElm); - while (!stack.isEmpty()) { - Element curElm = stack.pop(); - if (filter.acceptElement(curElm)) { - elms.add(curElm); - } - NodeList childNodes = curElm.getChildNodes(); - for (int i = 0, ll = childNodes.getLength(); i < ll; i++) { - Node item = childNodes.item(i); - if (item.getNodeType() == Node.ELEMENT_NODE) { - stack.push((Element) item); + if (topElm == null) throw new IllegalArgumentException("topElm cannot be null"); + synchronized(topElm.getOwnerDocument()) { + List elms = new ArrayList(); + Stack stack = new Stack(); + stack.push(topElm); + while (!stack.isEmpty()) { + Element curElm = stack.pop(); + if (filter.acceptElement(curElm)) { + elms.add(curElm); + } + NodeList childNodes = curElm.getChildNodes(); + for (int i = 0, ll = childNodes.getLength(); i < ll; i++) { + Node item = childNodes.item(i); + if (item.getNodeType() == Node.ELEMENT_NODE) { + stack.push((Element) item); + } } } + return elms; } - return elms; } @@ -168,29 +190,32 @@ private static boolean namespacesAreSame(String fNamespace, String sNamespace) { * @return returns found node */ public static Element findElement(Element topElm, String nodeName) { - Stack stack = new Stack(); - stack.push(topElm); - while (!stack.isEmpty()) { - Element curElm = stack.pop(); - if (curElm.getNodeName().equals(nodeName)) { - return curElm; - } - List nodesToProcess = new ArrayList(); + if (topElm == null) throw new IllegalArgumentException("topElm cannot be null"); + synchronized(topElm.getOwnerDocument()) { + Stack stack = new Stack(); + stack.push(topElm); + while (!stack.isEmpty()) { + Element curElm = stack.pop(); + if (curElm.getNodeName().equals(nodeName)) { + return curElm; + } + List nodesToProcess = new ArrayList(); - NodeList childNodes = curElm.getChildNodes(); - for (int i = 0, ll = childNodes.getLength(); i < ll; i++) { - Node item = childNodes.item(i); - if (item.getNodeType() == Node.ELEMENT_NODE) { - //stack.push((Element) item); - nodesToProcess.add(item); + NodeList childNodes = curElm.getChildNodes(); + for (int i = 0, ll = childNodes.getLength(); i < ll; i++) { + Node item = childNodes.item(i); + if (item.getNodeType() == Node.ELEMENT_NODE) { + //stack.push((Element) item); + nodesToProcess.add(item); + } + } + Collections.reverse(nodesToProcess); + for (Node node : nodesToProcess) { + stack.push((Element) node); } } - Collections.reverse(nodesToProcess); - for (Node node : nodesToProcess) { - stack.push((Element) node); - } + return null; } - return null; } /** @@ -201,57 +226,63 @@ public static Element findElement(Element topElm, String nodeName) { * @return found element */ public static Element findElement(Element topElm, String localName, String namespace) { - Stack stack = new Stack(); - stack.push(topElm); - while (!stack.isEmpty()) { - Element curElm = stack.pop(); - if ((curElm.getLocalName().equals(localName)) && (namespacesAreSame(curElm.getNamespaceURI(), namespace))) { - return curElm; - } - List nodesToProcess = new ArrayList(); - NodeList childNodes = curElm.getChildNodes(); - for (int i = 0, ll = childNodes.getLength(); i < ll; i++) { - Node item = childNodes.item(i); - if (item.getNodeType() == Node.ELEMENT_NODE) { - nodesToProcess.add(item); + if (topElm == null) throw new IllegalArgumentException("topElm cannot be null"); + synchronized(topElm.getOwnerDocument()) { + Stack stack = new Stack(); + stack.push(topElm); + while (!stack.isEmpty()) { + Element curElm = stack.pop(); + if ((curElm.getLocalName().equals(localName)) && (namespacesAreSame(curElm.getNamespaceURI(), namespace))) { + return curElm; + } + List nodesToProcess = new ArrayList(); + NodeList childNodes = curElm.getChildNodes(); + for (int i = 0, ll = childNodes.getLength(); i < ll; i++) { + Node item = childNodes.item(i); + if (item.getNodeType() == Node.ELEMENT_NODE) { + nodesToProcess.add(item); + } + } + // because of stack + Collections.reverse(nodesToProcess); + for (Node node : nodesToProcess) { + stack.push((Element) node); + } } - // because of stack - Collections.reverse(nodesToProcess); - for (Node node : nodesToProcess) { - stack.push((Element) node); - - } + return null; } - return null; } public static Element findElement(Element topElm, ElementsFilter filter) { - Stack stack = new Stack(); - stack.push(topElm); - while (!stack.isEmpty()) { - Element curElm = stack.pop(); - if (filter.acceptElement(curElm)) { - return curElm; - } + if (topElm == null) throw new IllegalArgumentException("topElm cannot be null"); + synchronized(topElm.getOwnerDocument()) { + Stack stack = new Stack(); + stack.push(topElm); + while (!stack.isEmpty()) { + Element curElm = stack.pop(); + if (filter.acceptElement(curElm)) { + return curElm; + } - List nodesToProcess = new ArrayList(); - NodeList childNodes = curElm.getChildNodes(); - for (int i = 0, ll = childNodes.getLength(); i < ll; i++) { - Node item = childNodes.item(i); - if (item.getNodeType() == Node.ELEMENT_NODE) { - //stack.push((Element) item); - nodesToProcess.add(item); + List nodesToProcess = new ArrayList(); + NodeList childNodes = curElm.getChildNodes(); + for (int i = 0, ll = childNodes.getLength(); i < ll; i++) { + Node item = childNodes.item(i); + if (item.getNodeType() == Node.ELEMENT_NODE) { + //stack.push((Element) item); + nodesToProcess.add(item); + } + } + Collections.reverse(nodesToProcess); + for (Node node : nodesToProcess) { + stack.push((Element)node); } } - Collections.reverse(nodesToProcess); - for (Node node : nodesToProcess) { - stack.push((Element)node); - } + return null; } - return null; } diff --git a/common/src/main/java/cz/incad/kramerius/utils/solr/SolrUtils.java b/common/src/main/java/cz/incad/kramerius/utils/solr/SolrUtils.java index 452d035622..f3ee39b5fa 100644 --- a/common/src/main/java/cz/incad/kramerius/utils/solr/SolrUtils.java +++ b/common/src/main/java/cz/incad/kramerius/utils/solr/SolrUtils.java @@ -20,6 +20,7 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import java.util.logging.Logger; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.XPathConstants; @@ -44,6 +45,8 @@ * @author pavels */ public class SolrUtils { + + public static final Logger LOGGER = Logger.getLogger(SolrUtils.class.getName()); /** PID query */ public static final String UUID_QUERY="q=PID:"; @@ -90,17 +93,19 @@ public static XPathExpression modelPathExpr() throws XPathExpressionException { * @throws XPathExpressionException cannot disect pid paths */ public static List disectPidPaths( Document parseDocument) throws XPathExpressionException { - List list = new ArrayList(); - NodeList paths = (org.w3c.dom.NodeList) pidPathExpr().evaluate(parseDocument, XPathConstants.NODESET); - if (paths != null) { - for (int i = 0,ll=paths.getLength(); i < ll; i++) { - Node n = paths.item(i); - String text = n.getTextContent(); - list.add(text.trim()); + synchronized(parseDocument) { + List list = new ArrayList(); + NodeList paths = (org.w3c.dom.NodeList) pidPathExpr().evaluate(parseDocument, XPathConstants.NODESET); + if (paths != null) { + for (int i = 0,ll=paths.getLength(); i < ll; i++) { + Node n = paths.item(i); + String text = n.getTextContent(); + list.add(text.trim()); + } + return list; } - return list; + return new ArrayList(); } - return new ArrayList(); } /** @@ -110,12 +115,14 @@ public static List disectPidPaths( Document parseDocument) throws XPathE * @throws XPathExpressionException cannot disect pid */ public static String disectPid(Document parseDocument) throws XPathExpressionException { - Node pidNode = (Node) pidExpr().evaluate(parseDocument, XPathConstants.NODE); - if (pidNode != null) { - Element pidElm = (Element) pidNode; - return pidElm.getTextContent().trim(); + synchronized(parseDocument) { + Node pidNode = (Node) pidExpr().evaluate(parseDocument, XPathConstants.NODE); + if (pidNode != null) { + Element pidElm = (Element) pidNode; + return pidElm.getTextContent().trim(); + } + return null; } - return null; } /** @@ -125,17 +132,19 @@ public static String disectPid(Document parseDocument) throws XPathExpressionExc * @throws XPathExpressionException cannot disect models path */ public static List disectModelPaths(Document parseDocument) throws XPathExpressionException { - List list = new ArrayList(); - NodeList pathNodes = (NodeList) modelPathExpr().evaluate(parseDocument, XPathConstants.NODESET); - if (pathNodes != null) { - for (int i = 0,ll=pathNodes.getLength(); i < ll; i++) { - Node n = pathNodes.item(i); - String text = n.getTextContent(); - list.add(text.trim()); + synchronized(parseDocument) { + List list = new ArrayList(); + NodeList pathNodes = (NodeList) modelPathExpr().evaluate(parseDocument, XPathConstants.NODESET); + if (pathNodes != null) { + for (int i = 0,ll=pathNodes.getLength(); i < ll; i++) { + Node n = pathNodes.item(i); + String text = n.getTextContent(); + list.add(text.trim()); + } + return list; } - return list; + return new ArrayList(); } - return new ArrayList(); } diff --git a/rest/src/main/java/cz/incad/kramerius/rest/api/k5/client/utils/SOLRUtils.java b/rest/src/main/java/cz/incad/kramerius/rest/api/k5/client/utils/SOLRUtils.java index ae1ea2aa05..a426d26b89 100644 --- a/rest/src/main/java/cz/incad/kramerius/rest/api/k5/client/utils/SOLRUtils.java +++ b/rest/src/main/java/cz/incad/kramerius/rest/api/k5/client/utils/SOLRUtils.java @@ -20,6 +20,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.logging.Logger; import org.apache.commons.collections.map.HashedMap; import org.w3c.dom.Document; @@ -33,6 +34,8 @@ public class SOLRUtils { + public static final Logger LOGGER = Logger.getLogger(SOLRUtils.class.getName()); + public static Map SOLR_TYPE_NAMES = new HashMap(); static { SOLR_TYPE_NAMES.put(String.class, "str"); @@ -54,112 +57,128 @@ else if (clz.equals(Integer.class)) } public static Element value(Document doc, String val) { - return value(doc, null, val); + synchronized (doc) { + return value(doc, null, val); + } } public static Element value(Document doc, String attname, String val) { - Element strElm = doc.createElement("str"); - if (attname != null) - strElm.setAttribute("name", attname); - strElm.setTextContent(val); - return strElm; + synchronized (doc) { + Element strElm = doc.createElement("str"); + if (attname != null) + strElm.setAttribute("name", attname); + strElm.setTextContent(val); + return strElm; + } } public static Element value(Document doc, Integer val) { - return value(doc, null, val); + synchronized (doc) { + return value(doc, null, val); + } } public static Element value(Document doc, String attname, Integer val) { - Element strElm = doc.createElement("int"); - if (attname != null) - strElm.setAttribute("name", attname); - strElm.setTextContent("" + val); - return strElm; + synchronized(doc) { + Element strElm = doc.createElement("int"); + if (attname != null) + strElm.setAttribute("name", attname); + strElm.setTextContent("" + val); + return strElm; + } } public static Element arr(Document doc, String attname, List vals) { - Element arrElm = doc.createElement("arr"); - if (attname != null) - arrElm.setAttribute("name", attname); - for (Object obj : vals) { - if (obj instanceof String) { - arrElm.appendChild(value(doc, (String) obj)); - } else if (obj instanceof Integer) { - arrElm.appendChild(value(doc, (Integer) obj)); - } else - throw new IllegalArgumentException("unsupported type " - + obj.getClass().getName() + ""); + synchronized(doc) { + Element arrElm = doc.createElement("arr"); + if (attname != null) + arrElm.setAttribute("name", attname); + for (Object obj : vals) { + if (obj instanceof String) { + arrElm.appendChild(value(doc, (String) obj)); + } else if (obj instanceof Integer) { + arrElm.appendChild(value(doc, (Integer) obj)); + } else + throw new IllegalArgumentException("unsupported type " + + obj.getClass().getName() + ""); + } + return arrElm; } - return arrElm; } public static T value(final Element doc, final String attributeName, Class clz) { - final String expectedTypeName = SOLR_TYPE_NAMES.get(clz); if (doc == null) { throw new IllegalArgumentException("element must not be null"); } - List elms = XMLUtils.getElements(doc, - new XMLUtils.ElementsFilter() { - - @Override - public boolean acceptElement(Element element) { - return (element.getNodeName().equals(expectedTypeName) - && element.hasAttribute("name") && element - .getAttribute("name").equals(attributeName)); - } - }); - Object obj = elms.isEmpty() ? null : elms.get(0).getTextContent(); - if (obj != null) - return value(obj.toString(), clz); - else - return null; + synchronized(doc.getOwnerDocument()) { + final String expectedTypeName = SOLR_TYPE_NAMES.get(clz); + List elms = XMLUtils.getElements(doc, + new XMLUtils.ElementsFilter() { + + @Override + public boolean acceptElement(Element element) { + return (element.getNodeName().equals(expectedTypeName) + && element.hasAttribute("name") && element + .getAttribute("name").equals(attributeName)); + } + }); + Object obj = elms.isEmpty() ? null : elms.get(0).getTextContent(); + if (obj != null) + return value(obj.toString(), clz); + else + return null; + } } public static List array(final Element doc, final String attributeName, Class clz) { - List ret = new ArrayList(); - List elms = XMLUtils.getElements(doc, - new XMLUtils.ElementsFilter() { - - @Override - public boolean acceptElement(Element element) { - return (element.getNodeName().equals("arr") - && element.hasAttribute("name") && element - .getAttribute("name").equals(attributeName)); - } - }); - for (Element e : elms) { - ret.add(value(e.getTextContent(), clz)); - } - return ret; + synchronized(doc.getOwnerDocument()) { + List ret = new ArrayList(); + List elms = XMLUtils.getElements(doc, + new XMLUtils.ElementsFilter() { + + @Override + public boolean acceptElement(Element element) { + return (element.getNodeName().equals("arr") + && element.hasAttribute("name") && element + .getAttribute("name").equals(attributeName)); + } + }); + for (Element e : elms) { + ret.add(value(e.getTextContent(), clz)); + } + return ret; + } } //TODO: CDK Bugfix !! change basic array method ! public static List narray(final Element doc, final String attributeName, Class clz) { - List ret = new ArrayList(); - List elms = XMLUtils.getElements(doc, - new XMLUtils.ElementsFilter() { - @Override - public boolean acceptElement(Element element) { - return (element.getNodeName().equals("arr") - && element.hasAttribute("name") && element - .getAttribute("name").equals(attributeName)); + synchronized(doc.getOwnerDocument()) { + List ret = new ArrayList(); + List elms = XMLUtils.getElements(doc, + new XMLUtils.ElementsFilter() { + @Override + public boolean acceptElement(Element element) { + return (element.getNodeName().equals("arr") + && element.hasAttribute("name") && element + .getAttribute("name").equals(attributeName)); + } + }); + + if (elms.size() >= 1) { + Element parentE = elms.get(0); + NodeList chnds = parentE.getChildNodes(); + for (int i = 0,ll=chnds.getLength() ; i < ll; i++) { + Node n = chnds.item(i); + if (n.getNodeType() == Node.ELEMENT_NODE) { + ret.add(value(n.getTextContent(), clz)); } - }); - - if (elms.size() >= 1) { - Element parentE = elms.get(0); - NodeList chnds = parentE.getChildNodes(); - for (int i = 0,ll=chnds.getLength() ; i < ll; i++) { - Node n = chnds.item(i); - if (n.getNodeType() == Node.ELEMENT_NODE) { - ret.add(value(n.getTextContent(), clz)); } } + return ret; } - return ret; } }