| /******************************************************************************* |
| * Copyright (c) 2005, 2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.releng.generators.rss; |
| |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.io.PrintStream; |
| import java.util.Date; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| import javax.xml.transform.Transformer; |
| import javax.xml.transform.TransformerException; |
| import javax.xml.transform.dom.DOMSource; |
| import javax.xml.transform.stream.StreamResult; |
| import javax.xml.xpath.XPath; |
| import javax.xml.xpath.XPathConstants; |
| import javax.xml.xpath.XPathExpressionException; |
| import javax.xml.xpath.XPathFactory; |
| |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.Task; |
| import org.apache.tools.ant.util.DateUtils; |
| import org.w3c.dom.Attr; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| import org.w3c.dom.Text; |
| import org.xml.sax.SAXException; |
| |
| import org.eclipse.releng.util.rss.Messages; |
| import org.eclipse.releng.util.rss.RSSFeedUtil; |
| |
| /** |
| * Parameters: |
| * debug - more output to console - eg., 0|1|2 |
| * |
| * file - path to the XML file that will be read - eg., /path/to/file.to.read.xml |
| * xpath - xpath string representing the object to modify |
| * replacement - string to use as replacement |
| * |
| * @author nickb |
| * |
| */ |
| public class RSSFeedUpdateEntryTask extends Task { |
| |
| private int debug = 0; |
| |
| private static final String now = getTimestamp(); |
| |
| private static final XPath xp = XPathFactory.newInstance().newXPath(); |
| |
| private static final String NS = ""; //$NON-NLS-1$ |
| private static final String SEP = "----"; //$NON-NLS-1$ |
| private static final String SP = " "; //$NON-NLS-1$ |
| |
| //required fields |
| private File file; |
| |
| private String xpath; |
| private String replacement; |
| |
| private Transformer transformer = null; |
| |
| private boolean isNodeFound = false; |
| private boolean isNodeChanged = false; |
| private Node foundNode = null; |
| |
| //optional |
| public void setDebug(int debug) { this.debug = debug; } |
| |
| //required fields |
| public void setFile(String file) { |
| if (isNullString(file)) |
| { System.err.println(Messages.getString("RSSFeedCommon.FileError")); } //$NON-NLS-1$ |
| else |
| { this.file = new File(file); } |
| } |
| public void setXpath(String xpath) { |
| if (isNullString(xpath)) |
| { System.err.println(Messages.getString("RSSFeedCommon.XpathError")); } //$NON-NLS-1$ |
| else |
| { this.xpath = xpath; } |
| } |
| |
| //optional - if null, display value found instead of changing it - see RSSFeedGetPropertyTask |
| public void setReplacement(String replacement) { this.replacement = replacement; } |
| |
| // The method executing the task |
| public void execute() throws BuildException { |
| if (debug>0) { |
| System.out.println(Messages.getString("RSSFeedUpdateEntryTask.SearchingFor") + SP + xpath + (!isNullString(replacement)?", " + Messages.getString("RSSFeedUpdateEntryTask.ReplacingWith") + " '" + replacement + "'":NS)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ |
| } |
| updateFeedXML(file); // load previous |
| } |
| |
| //$ANALYSIS-IGNORE codereview.java.rules.exceptions.RuleExceptionsSpecificExceptions |
| private void updateFeedXML(File file){ |
| if (file.exists()) { |
| DocumentBuilderFactory documentBuilderFactory=DocumentBuilderFactory.newInstance(); |
| documentBuilderFactory.setNamespaceAware(true); |
| DocumentBuilder documentBuilder=null; |
| try { |
| documentBuilder=documentBuilderFactory.newDocumentBuilder(); |
| } |
| catch (ParserConfigurationException e) { |
| e.printStackTrace(); |
| } |
| Document document=null; |
| try { |
| document=documentBuilder.parse(file); |
| } |
| catch (SAXException e) { |
| e.printStackTrace(); |
| } |
| catch (IOException e) { |
| e.printStackTrace(); |
| } |
| |
| try { |
| transformer = RSSFeedAddEntryTask.createTransformer("UTF-8"); //$NON-NLS-1$ |
| } catch (TransformerException e) { |
| e.printStackTrace(); |
| } |
| |
| if (!isNullString(replacement)) { |
| setEntryNodeUpdate(document.getDocumentElement()); |
| } |
| Node newNode=findAndReplace(document); |
| if (debug > 1 && newNode != null) { |
| try { |
| System.out.println(SEP); |
| transformer.transform(new DOMSource(newNode),new StreamResult(System.out)); |
| System.out.println(SEP); |
| } |
| catch (TransformerException e) { |
| e.printStackTrace(); |
| } |
| } |
| if (!isNullString(replacement) && newNode != null) { |
| try { |
| transformer.transform(new DOMSource(document),new StreamResult(new PrintStream(file))); |
| } |
| catch (FileNotFoundException e) { |
| e.printStackTrace(); |
| } |
| catch (TransformerException e) { |
| e.printStackTrace(); |
| } |
| } |
| } |
| else { |
| System.out.println(Messages.getString("RSSFeedCommon.RSSFeedFile") + SP + file.toString()+ " "+ Messages.getString("RSSFeedUpdateEntryTask.DoesNotExist")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ |
| } |
| } |
| |
| // get/set the desired node |
| public Node getFoundNode() |
| { |
| return this.foundNode; |
| } |
| private void setFoundNode(Node foundNode) |
| { |
| this.foundNode = foundNode; |
| } |
| |
| // has the desired node been found? |
| public boolean getNodeFound() |
| { |
| return this.isNodeFound; |
| } |
| private void setNodeFound(boolean isNodeFound) |
| { |
| this.isNodeFound = isNodeFound; |
| } |
| |
| // has the desired node been changed? |
| public boolean getNodeChanged() |
| { |
| return this.isNodeChanged; |
| } |
| private void setNodeChanged(boolean isNodeChanged) |
| { |
| this.isNodeChanged = isNodeChanged; |
| } |
| |
| /** |
| * Modify an entry: |
| * |
| * <entry> |
| * <title/> |
| * <link href=""/> |
| * <id/> |
| * <updated/> |
| * <summary> |
| * ... |
| * </summary> |
| * </entry> |
| */ |
| private Node findAndReplace(Document document) { |
| Node parentEntryNode = null; |
| Node aNode = null; |
| if (debug==0) { System.out.print(xpath + (isNullString(replacement)?" = ":" :: ")); } //$NON-NLS-1$ //$NON-NLS-2$ |
| NodeList nodelist = getNodeList(document, xpath); |
| // Process the elements in the nodelist |
| if (nodelist != null && nodelist.getLength()>0) { |
| for (int i=0; i<nodelist.getLength(); i++) { |
| Node node = (Node)nodelist.item(i); |
| switch (node.getNodeType()) |
| { |
| case Node.ATTRIBUTE_NODE : |
| aNode = (Attr)nodelist.item(i); |
| if (debug>0) { System.out.print(Messages.getString("RSSFeedUpdateEntryTask.DebugFoundAttribute")); } //$NON-NLS-1$ |
| break; |
| |
| case Node.ELEMENT_NODE : |
| aNode = (Element)nodelist.item(i); |
| if (debug>0) { System.out.print(Messages.getString("RSSFeedUpdateEntryTask.DebugFoundElement")); } //$NON-NLS-1$ |
| break; |
| |
| case Node.TEXT_NODE : |
| aNode = (Text)nodelist.item(i); |
| if (debug>0) { System.out.print(Messages.getString("RSSFeedUpdateEntryTask.DebugFoundText")); } //$NON-NLS-1$ |
| break; |
| |
| default: |
| aNode = null; |
| break; |
| } |
| if (aNode != null) { |
| setFoundNode(aNode); |
| setNodeFound(true); |
| System.out.print((debug>0?aNode.getNodeName() + " = ":NS) + aNode.getNodeValue()); //$NON-NLS-1$ //$NON-NLS-2$ |
| if (!isNullString(replacement)) { aNode.setTextContent(replacement); } |
| System.out.println(isNullString(replacement)?NS:" => " + replacement); //$NON-NLS-1$ //$NON-NLS-2$ |
| if (debug>0) { |
| try |
| { |
| // write to console |
| System.out.println(SEP); //$NON-NLS-1$ |
| transformer.transform(new DOMSource(getParentNode(document,aNode,null,NS)), new StreamResult(System.out)); //$NON-NLS-1$ |
| System.out.println(SEP); //$NON-NLS-1$ |
| } |
| catch (TransformerException e) |
| { |
| e.printStackTrace(); |
| } |
| } |
| if (!isNullString(replacement)) { |
| parentEntryNode = getParentNode(document, aNode, "entry", NS); //$NON-NLS-1$ //$NON-NLS-2$ |
| setEntryNodeUpdate(parentEntryNode); |
| } |
| } |
| } |
| } else { |
| System.out.println(Messages.getString("RSSFeedUpdateEntryTask.XpathNodeNotFound")); //$NON-NLS-1$ |
| } |
| return parentEntryNode; |
| } |
| |
| private Node getParentNode(Document document, Node nodeIn, String target, String indent) |
| { |
| Node node = nodeIn; |
| if (node.getNodeType() != Node.ELEMENT_NODE) { |
| if (debug>1) { System.out.println(indent + Messages.getString("RSSFeedUpdateEntryTask.DebugGotATNode") + node.getNodeName()); } //$NON-NLS-1$ |
| // get the element for the attrib/text node |
| NodeList nodelist = getNodeList(document, xpath.substring(0, xpath.lastIndexOf("/"))); |
| if (nodelist !=null && nodelist.getLength()>0) |
| { |
| for (int i=0; i<nodelist.getLength(); i++) { |
| node = (Node)nodelist.item(i); |
| break; |
| } |
| } |
| } |
| if (debug>1) { System.out.println(indent + Messages.getString("RSSFeedUpdateEntryTask.DebugGotENode") + node.getNodeName() + " (" + node.getNodeType() + ")"); } //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| if (!isNullString(target) && !node.getNodeName().equals(target)) |
| { |
| node = getParentNode(document, node.getParentNode(), target, indent + "_ "); //$NON-NLS-1$ |
| } |
| return node; |
| } |
| |
| private NodeList getNodeList(Document document, String xpath) |
| { |
| NodeList nodelist = null; |
| try |
| { |
| xp.reset(); |
| Object o = xp.evaluate(xpath, document, XPathConstants.NODESET); |
| if (o instanceof NodeList) |
| { |
| nodelist = (NodeList)o; |
| } |
| } |
| catch (XPathExpressionException e) |
| { |
| e.printStackTrace(); |
| } |
| return nodelist; |
| } |
| |
| //$ANALYSIS-IGNORE codereview.java.rules.exceptions.RuleExceptionsSpecificExceptions |
| private void setEntryNodeUpdate(Node parentEntryNode){ |
| for (Node child=parentEntryNode.getFirstChild(); child != null; child=child.getNextSibling()) { |
| if ("updated".equals(child.getLocalName())) { //$NON-NLS-1$ |
| if (debug > 0) { |
| System.out.println(Messages.getString("RSSFeedCommon.Set") + " <" + child.getLocalName()+ ">"+ now+ "</"+ child.getLocalName()+ ">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ |
| } |
| ((Element)child).setTextContent(now); |
| setNodeChanged(true); |
| break; |
| } |
| } |
| } |
| |
| |
| private static String getTimestamp() { // eg., 2006-04-10T20:40:08Z |
| return DateUtils.format(new Date(), DateUtils.ISO8601_DATETIME_PATTERN) + "Z"; //$NON-NLS-1$ |
| } |
| |
| private static boolean isNullString(String str) |
| { |
| return RSSFeedUtil.isNullString(str); |
| } |
| |
| } |