Guest User

HttpBugzillaSession

a guest
Jan 30th, 2013
155
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2.  * This file is part of Bugzilla for Java.
  3.  *
  4.  *  Bugzilla for Java is free software: you can redistribute it
  5.  *  and/or modify it under the terms of version 3 of the GNU
  6.  *  Lesser General Public  License as published by the Free Software
  7.  *  Foundation.
  8.  *  
  9.  *  Bugzilla for Java is distributed in the hope that it will be useful,
  10.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *  GNU Lesser General Public License for more details.
  13.  *
  14.  *  You should have received a copy of the GNU Lesser General Public
  15.  *  License along with Bugzilla for Java.  If not, see
  16.  *  <http://www.gnu.org/licenses/lgpl-3.0.html>.
  17.  */
  18. package b4j.core.session;
  19.  
  20. import java.io.BufferedReader;
  21. import java.io.IOException;
  22. import java.io.InputStream;
  23. import java.io.InputStreamReader;
  24. import java.io.PrintWriter;
  25. import java.io.StringReader;
  26. import java.io.StringWriter;
  27. import java.net.HttpURLConnection;
  28. import java.text.ParseException;
  29. import java.util.ArrayList;
  30. import java.util.Iterator;
  31. import java.util.List;
  32. import java.util.regex.Matcher;
  33. import java.util.regex.Pattern;
  34.  
  35. import javax.xml.parsers.ParserConfigurationException;
  36. import javax.xml.parsers.SAXParser;
  37. import javax.xml.parsers.SAXParserFactory;
  38.  
  39. import org.apache.commons.io.IOUtils;
  40. import org.xml.sax.Attributes;
  41. import org.xml.sax.InputSource;
  42. import org.xml.sax.SAXException;
  43. import org.xml.sax.XMLReader;
  44. import org.xml.sax.ext.DefaultHandler2;
  45.  
  46. import b4j.core.Attachment;
  47. import b4j.core.Issue;
  48. import b4j.core.LongDescription;
  49. import b4j.core.SearchData;
  50. import b4j.core.SearchResultCountCallback;
  51. import b4j.util.BugzillaUtils;
  52. import b4j.util.UrlParameters;
  53.  
  54. /**
  55.  * Implements Bugzilla access via HTTP. Use this session object when you cannot
  56.  * access Bugzilla directly per JDBC. This implementation does not implement
  57.  * access via proxy yet.
  58.  *
  59.  * @author Ralph Schuster
  60.  *
  61.  */
  62. public class HttpBugzillaSession extends AbstractHttpSession {
  63.  
  64.     /** Constant for requesting URL connection to login page */
  65.     public static final int BUGZILLA_LOGIN = 0;
  66.     /** Constant for requesting URL connection to search result page */
  67.     public static final int BUGZILLA_SEARCH = 1;
  68.     /** Constant for requesting URL connection to logout page */
  69.     public static final int BUGZILLA_LOGOUT = 2;
  70.     /** Constant for requesting URL connection to show bug page */
  71.     public static final int BUGZILLA_SHOW_BUG = 3;
  72.     /** Constant for requesting URL connection to get attachment content */
  73.     public static final int BUGZILLA_GET_ATTACHMENT = 4;
  74.  
  75.     private static final String MINIMUM_BUGZILLA_VERSION = "2.20";
  76.     private static final String MAXIMUM_BUGZILLA_VERSION = null;
  77.  
  78.     /** The URL paths to the Bugzilla pages */
  79.     protected static final String[] PAGES = new String[] { "/index.cgi",
  80.             "/buglist.cgi", "/relogin.cgi", "/show_bug.cgi", "/attachment.cgi" };
  81.     private static UrlParameters DEFAULT_SEARCH_PARAMETERS;
  82.  
  83.     /**
  84.      * Default constructor.
  85.      */
  86.     public HttpBugzillaSession() {
  87.     }
  88.  
  89.     /**
  90.      * Returns the minimum Bugzilla version this session class supports.
  91.      *
  92.      * @see #MINIMUM_BUGZILLA_VERSION
  93.      * @return minimum version of supported Bugzilla software.
  94.      */
  95.     @Override
  96.     public String getMinimumBugzillaVersion() {
  97.         return MINIMUM_BUGZILLA_VERSION;
  98.     }
  99.  
  100.     /**
  101.      * Returns the maximum Bugzilla version this session class supports.
  102.      *
  103.      * @see #MAXIMUM_BUGZILLA_VERSION
  104.      * @return maximum version of supported Bugzilla software.
  105.      */
  106.     @Override
  107.     public String getMaximumBugzillaVersion() {
  108.         return MAXIMUM_BUGZILLA_VERSION;
  109.     }
  110.  
  111.     /**
  112.      * Opens the session with configured Bugzilla instance.
  113.      *
  114.      * @return true when session could be established successfully, false
  115.      *         otherwise
  116.      */
  117.     @Override
  118.     public boolean open() {
  119.         if (isLoggedIn())
  120.             return true;
  121.         setBugzillaVersion(null);
  122.  
  123.         // Exception: No login required
  124.         if (getLogin() == null) {
  125.             getLog().debug("No Auth required");
  126.             setLoggedIn(true);
  127.             return true;
  128.         }
  129.  
  130.         try {
  131.             // Bugzilla_login = xxx
  132.             // Bugzilla_password = xxx
  133.             // GoAheadAndLogIn = Login
  134.             UrlParameters params = new UrlParameters();
  135.             params.setParameter("Bugzilla_login", getLogin());
  136.             params.setParameter("Bugzilla_password", getPassword());
  137.             params.setParameter("GoAheadAndLogIn", "Login");
  138.             String paramString = params.getUrlEncodedString();
  139.  
  140.             // make a connection
  141.             HttpURLConnection con = getConnection(BUGZILLA_LOGIN);
  142.             con.setRequestMethod("POST");
  143.             con.setRequestProperty("Content-type",
  144.                     "application/x-www-form-urlencoded");
  145.             con.setRequestProperty("Content-Length", "" + paramString.length());
  146.             con.setDoOutput(true);
  147.             PrintWriter out = new PrintWriter(con.getOutputStream());
  148.             out.print(paramString);
  149.             out.flush();
  150.             out.close();
  151.  
  152.             // Read the response;
  153.             if (con.getResponseCode() == 200) {
  154.                 // debugResponse(con);
  155.                 boolean rc = retrieveCookies(con);
  156.  
  157.                 // Get Bugzilla version and test for compatibility
  158.                 BufferedReader r = new BufferedReader(new InputStreamReader(
  159.                         con.getInputStream()));
  160.                 Pattern p = Pattern.compile(".*version\\s+([\\d\\.]+).*",
  161.                         Pattern.CASE_INSENSITIVE);
  162.  
  163.                 String line;
  164.                 while ((line = r.readLine()) != null) {
  165.                     // Search for: version 3.0.5
  166.                     Matcher m = p.matcher(line);
  167.                     if (m.matches()) {
  168.                         setBugzillaVersion(m.group(1));
  169.                         break;
  170.                     }
  171.                 }
  172.  
  173.                 setLoggedIn(rc);
  174.                 if (getLog().isInfoEnabled()) {
  175.                     if (rc) {
  176.                         getLog().info("Session opened:   " + getBaseUrl());
  177.                         if (getLog().isDebugEnabled())
  178.                             getLog().debug(
  179.                                     "Bugzilla-Version: " + getBugzillaVersion());
  180.                     } else
  181.                         getLog().info("Bugzilla did not sent Cookie");
  182.                 }
  183.  
  184.                 if (rc)
  185.                     checkBugzillaVersion();
  186.  
  187.                 return rc;
  188.             } else {
  189.                 getLog().error(
  190.                         "Cannot open session: Response was \""
  191.                                 + con.getResponseMessage() + "\"");
  192.             }
  193.         } catch (IOException e) {
  194.             getLog().error("Cannot open session:", e);
  195.         }
  196.         return false;
  197.     }
  198.  
  199.     /**
  200.      * Closes the previously established Bugzilla session.
  201.      */
  202.     @Override
  203.     public void close() {
  204.         if (!isLoggedIn())
  205.             return;
  206.  
  207.         // Only when login was required
  208.         if (getLogin() != null) {
  209.             try {
  210.                 // make a connection
  211.                 HttpURLConnection con = getConnection(BUGZILLA_LOGOUT);
  212.                 con.getResponseCode();
  213.             } catch (IOException e) {
  214.  
  215.             }
  216.         }
  217.         super.close();
  218.     }
  219.  
  220.     /**
  221.      * {@inheritDoc}
  222.      */
  223.     @Override
  224.     public Issue getIssue(String id) {
  225.         List<String> idList = new ArrayList<String>();
  226.         idList.add(id);
  227.         BugzillaBugIterator i = new BugzillaBugIterator(idList);
  228.         if ((i != null) && i.hasNext())
  229.             return i.next();
  230.         return null;
  231.     }
  232.  
  233.     /**
  234.      * {@inheritDoc}
  235.      */
  236.     @Override
  237.     public InputStream getAttachment(Attachment attachment) throws IOException {
  238.         HttpURLConnection con = getConnection(BUGZILLA_GET_ATTACHMENT, "id="
  239.                 + attachment.getId());
  240.         return con.getInputStream();
  241.     }
  242.  
  243.     /**
  244.      * Performs a search for Bugzilla bugs. This method returns an iterator over
  245.      * all bug records found. The returned iterator will query its data when the
  246.      * first call to its {@link Iterator#next()} method is made. A separate
  247.      * thread will then be spawned to retrieve the required details.
  248.      *
  249.      * @param searchData
  250.      *            - all search parameters
  251.      * @param callback
  252.      *            - a callback object that will retrieve the number of bugs
  253.      *            found for this search
  254.      * @return iterator on all bugs fulfilling the criteria expressed by search
  255.      *         parameters.
  256.      */
  257.     @Override
  258.     public Iterator<Issue> searchBugs(SearchData searchData,
  259.             SearchResultCountCallback callback) {
  260.         if (!isLoggedIn())
  261.             return null;
  262.  
  263.         // Perform the search
  264.         try {
  265.             UrlParameters params = UrlParameters
  266.                     .createUrlParameters(searchData);
  267.             params.addDefaultParameters(getDefaultSearchParameters());
  268.             String paramString = params.getUrlEncodedString();
  269.  
  270.             // make a connection
  271.             HttpURLConnection con = getConnection(BUGZILLA_SEARCH, paramString);
  272.  
  273.             // Read the response;
  274.             if (con.getResponseCode() == 200) {
  275.                 // debugResponse(con);
  276.                 // if (true) return null;
  277.  
  278.                 List<String> idList = new ArrayList<String>();
  279.  
  280.                 // Parse the data for all bugs found
  281.                 BufferedReader r = new BufferedReader(new InputStreamReader(
  282.                         con.getInputStream()));
  283.                 Pattern p = Pattern
  284.                         .compile(".*href=\"show_bug\\.cgi\\?id=(\\d+)\">\\d+</a>.*");
  285.  
  286.                 String line;
  287.                 while ((line = r.readLine()) != null) {
  288.                     // Search for: <a href="show_bug.cgi?id=2349">2349</a>
  289.                     Matcher m = p.matcher(line);
  290.                     if (m.matches()) {
  291.                         idList.add(m.group(1));
  292.                     } // else if (line.indexOf("show_bug.cgi") >= 0)
  293.                         // log.info(line);
  294.                 }
  295.                 if (callback != null)
  296.                     callback.setResultCount(idList.size());
  297.                 if (getLog().isDebugEnabled())
  298.                     getLog().debug("Found " + idList.size() + " bugs");
  299.  
  300.                 // Return the bug iterator
  301.                 return new BugzillaBugIterator(idList);
  302.             } else {
  303.                 getLog().debug("Response invalid: " + con.getResponseCode());
  304.             }
  305.         } catch (IOException e) {
  306.             getLog().error("Cannot perform search", e);
  307.         }
  308.  
  309.         return null;
  310.     }
  311.  
  312.     /**
  313.      * Makes a request to Bugzilla without any GET parameters.
  314.      *
  315.      * @param bugzillaPage
  316.      *            - ID of page to make the request to.
  317.      * @return HTTP connection object
  318.      */
  319.     protected HttpURLConnection getConnection(int bugzillaPage) {
  320.         return getConnection(bugzillaPage, null);
  321.     }
  322.  
  323.     /**
  324.      * Makes a request to Bugzilla including eventual GET parameters. The method
  325.      * applies all cookies registered previously to allow a successful session
  326.      * connection.
  327.      *
  328.      * @param bugzillaPage
  329.      *            - ID of page to make the request to
  330.      * @return HTTP connection object
  331.      */
  332.     protected HttpURLConnection getConnection(int bugzillaPage, String getParams) {
  333.         return getConnection(getBaseUrl() + PAGES[bugzillaPage], getParams);
  334.     }
  335.  
  336.     /**
  337.      * Returns default search parameters. DO NOT modify these defaults!
  338.      *
  339.      * @return default search parameters.
  340.      */
  341.     public static UrlParameters getDefaultSearchParameters() {
  342.         if (DEFAULT_SEARCH_PARAMETERS == null) {
  343.             DEFAULT_SEARCH_PARAMETERS = new UrlParameters();
  344.             DEFAULT_SEARCH_PARAMETERS.setParameter("query_format", "advanced");
  345.             DEFAULT_SEARCH_PARAMETERS.setParameter("short_desc_type",
  346.                     "allwordssubstr");
  347.             // DEFAULT_SEARCH_PARAMETERS.setParameter("short_desc", "");
  348.             // DEFAULT_SEARCH_PARAMETERS.setParameter("classification", "");
  349.             // DEFAULT_SEARCH_PARAMETERS.setParameter("product", "");
  350.             // DEFAULT_SEARCH_PARAMETERS.setParameter("component", "");
  351.             // DEFAULT_SEARCH_PARAMETERS.setParameter("long_desc_type", "");
  352.             // DEFAULT_SEARCH_PARAMETERS.setParameter("long_desc", "");
  353.             DEFAULT_SEARCH_PARAMETERS.setParameter("bug_file_loc_type",
  354.                     "allwordssubstr");
  355.             // DEFAULT_SEARCH_PARAMETERS.setParameter("bug_file_loc", "");
  356.             DEFAULT_SEARCH_PARAMETERS.setParameter("keywords_type", "allwords");
  357.             // DEFAULT_SEARCH_PARAMETERS.setParameter("keywords", "");
  358.             // DEFAULT_SEARCH_PARAMETERS.setParameter("bug_status", "");
  359.             DEFAULT_SEARCH_PARAMETERS.setParameter("emailassigned_to1", "1");
  360.             DEFAULT_SEARCH_PARAMETERS.setParameter("emailtype1", "substring");
  361.             // DEFAULT_SEARCH_PARAMETERS.setParameter("email1", "");
  362.             DEFAULT_SEARCH_PARAMETERS.setParameter("emailassigned_to2", "1");
  363.             DEFAULT_SEARCH_PARAMETERS.setParameter("emailreporter2", "1");
  364.             DEFAULT_SEARCH_PARAMETERS.setParameter("emailqa_contact2", "1");
  365.             DEFAULT_SEARCH_PARAMETERS.setParameter("emailcc2", "1");
  366.             DEFAULT_SEARCH_PARAMETERS.setParameter("emailtype2", "substring");
  367.             // DEFAULT_SEARCH_PARAMETERS.setParameter("email2", "");
  368.             DEFAULT_SEARCH_PARAMETERS.setParameter("bugidtype", "include");
  369.             // DEFAULT_SEARCH_PARAMETERS.setParameter("bug_id", "");
  370.             // DEFAULT_SEARCH_PARAMETERS.setParameter("chfieldfrom", "");
  371.             DEFAULT_SEARCH_PARAMETERS.setParameter("chfieldto", "Now");
  372.             // DEFAULT_SEARCH_PARAMETERS.setParameter("chfieldvalue", "");
  373.             DEFAULT_SEARCH_PARAMETERS.setParameter("cmdtype", "doit");
  374.             DEFAULT_SEARCH_PARAMETERS.setParameter("order", "Bug Number");
  375.             DEFAULT_SEARCH_PARAMETERS.setParameter("field0-0-0", "noop");
  376.             DEFAULT_SEARCH_PARAMETERS.setParameter("type0-0-0", "noop");
  377.             // DEFAULT_SEARCH_PARAMETERS.setParameter("value0-0-0", "");
  378.         }
  379.         return DEFAULT_SEARCH_PARAMETERS;
  380.     }
  381.  
  382.     /**
  383.      * Implementation of a bug iterator. This implementation is based on
  384.      * Silberschatz' proposal for synchronizing a reader and a writer thread.
  385.      * The first call to {@link BugzillaBugIterator#next()} will spawn the
  386.      * writer thread that actually retrieves bug data from Bugzilla.
  387.      *
  388.      * @author Ralph Schuster
  389.      *
  390.      */
  391.     protected class BugzillaBugIterator implements Iterator<Issue> {
  392.  
  393.         private List<String> bugList;
  394.         private int delivered;
  395.         private List<Issue> availableBugs;
  396.         private XmlParser xmlParser;
  397.  
  398.         /**
  399.          * Default constructor.
  400.          *
  401.          * @param bugList
  402.          *            - bug ID list to retrieve
  403.          */
  404.         public BugzillaBugIterator(List<String> bugList) {
  405.             delivered = 0;
  406.             this.bugList = bugList;
  407.             availableBugs = new ArrayList<Issue>();
  408.         }
  409.  
  410.         /**
  411.          * Returns true while number of delivered bugs (calls to {@link #next()}
  412.          * are less than number of bugs in request list.
  413.          *
  414.          * @return true if there are still bugs in the queue to read.
  415.          */
  416.         @Override
  417.         public boolean hasNext() {
  418.             return delivered < bugList.size();
  419.         }
  420.  
  421.         /**
  422.          * Delivers the next bug. The first call will trigger spawning of the
  423.          * writer thread. This implementation is based on Silberschatz'
  424.          * synchronization solution for reader and writer threads (reader's part
  425.          * here). That means, the call will wait until the next bug is available
  426.          * if required.
  427.          *
  428.          * @return next bug in queue
  429.          */
  430.         @Override
  431.         public synchronized Issue next() {
  432.             Issue rc;
  433.             if (xmlParser == null)
  434.                 startXmlParser();
  435.             if (delivered >= bugList.size())
  436.                 throw new IllegalStateException("Empty queue");
  437.  
  438.             while (availableBugs.isEmpty()) {
  439.                 try {
  440.                     wait();
  441.                 } catch (InterruptedException e) {
  442.                 }
  443.             }
  444.             rc = availableBugs.remove(0);
  445.             delivered++;
  446.  
  447.             notify();
  448.  
  449.             return rc;
  450.         }
  451.  
  452.         /**
  453.          * Adds a new bug to the list of available bugs. This implementation is
  454.          * based on Silberschatz' synchronization solution for reader and writer
  455.          * threads (writer's part here).
  456.          *
  457.          * @param bug
  458.          *            - bug to add to queue
  459.          */
  460.         protected synchronized void addBug(Issue bug) {
  461.             while (availableBugs.size() >= 20) {
  462.                 try {
  463.                     wait();
  464.                 } catch (InterruptedException e) {
  465.                 }
  466.             }
  467.             availableBugs.add(bug);
  468.  
  469.             notify();
  470.         }
  471.  
  472.         /**
  473.          * Always throws an exception.
  474.          */
  475.         @Override
  476.         public void remove() {
  477.             throw new UnsupportedOperationException(
  478.                     "This is a read-only iterator");
  479.         }
  480.  
  481.         /**
  482.          * Starts the writer's thread. This method will create the appropriate
  483.          * POST request to the Bugzilla instance and hand over the connection to
  484.          * the new thread. Internal variables are set to indicate that the
  485.          * writer thread is running.
  486.          */
  487.         protected void startXmlParser() {
  488.             try {
  489.                 if (getLog().isTraceEnabled())
  490.                     getLog().trace("Requesting XML file...");
  491.  
  492.                 // Build parameters
  493.                 UrlParameters parameters = new UrlParameters();
  494.                 parameters.addAll("id", bugList);
  495.                 parameters.setParameter("ctype", "xml");
  496.                 parameters.setParameter("excludefield", "attachmentdata");
  497.                 parameters.setParameter("submit", "XML");
  498.                 String paramString = parameters.getUrlEncodedString();
  499.  
  500.                 // make a connection
  501.                 HttpURLConnection con = getConnection(BUGZILLA_SHOW_BUG);
  502.                 con.setRequestMethod("POST");
  503.                 con.setRequestProperty("Content-type",
  504.                         "application/x-www-form-urlencoded");
  505.                 con.setRequestProperty("Content-Length",
  506.                         "" + paramString.length());
  507.                 con.setDoOutput(true);
  508.                 PrintWriter out = new PrintWriter(con.getOutputStream());
  509.                 out.print(paramString);
  510.                 out.flush();
  511.                 out.close();
  512.  
  513.                 if (getLog().isTraceEnabled())
  514.                     getLog().trace("Awaiting XML file...");
  515.                 // Read the response
  516.                 if (con.getResponseCode() == 200) {
  517.                     if (getLog().isTraceEnabled())
  518.                         getLog().trace("Receiving XML file...");
  519.                     xmlParser = new XmlParser(con.getInputStream(), this);
  520.                     Thread t = new Thread(xmlParser);
  521.                     t.start();
  522.                 }
  523.             } catch (IOException e) {
  524.  
  525.             }
  526.         }
  527.     }
  528.  
  529.     /**
  530.      * Does the actual meat by parsing the XML response. Implementation of the
  531.      * separate writer thread. The XML will be parsed (SAX implementation) and
  532.      * all found bugs will be added to the corresponding iterator object (
  533.      * {@link BugzillaBugIterator#addBug(Issue)}).
  534.      *
  535.      * @author Ralph Schuster
  536.      */
  537.     protected class XmlParser extends DefaultHandler2 implements Runnable {
  538.  
  539.         private InputStream xmlStream;
  540.         private BugzillaBugIterator iterator;
  541.         private XMLReader xmlReader;
  542.         private Issue currentBug;
  543.         private LongDescription currentLongDescription;
  544.         private Attachment currentAttachment;
  545.         private StringBuffer currentContent;
  546.         private String currentCustomField;
  547.         private String bugzillaVersion;
  548.         private String bugzillaUri;
  549.  
  550.         /**
  551.          * Constructor.
  552.          *
  553.          * @param xmlStream
  554.          *            - input stream with XML response from Bugzilla
  555.          * @param iterator
  556.          *            - corresponding iterator that receives the results
  557.          */
  558.         public XmlParser(InputStream xmlStream, BugzillaBugIterator iterator) {
  559.             this.xmlStream = xmlStream;
  560.             this.iterator = iterator;
  561.         }
  562.  
  563.         /**
  564.          * Runs the extraction.
  565.          */
  566.         public void run() {
  567.             try {
  568.                 SAXParserFactory factory = SAXParserFactory.newInstance();
  569.                 // Prevent fetching the DTD
  570.                 factory.setValidating(false);
  571.                 factory.setFeature(
  572.                         "http://apache.org/xml/features/nonvalidating/load-external-dtd",
  573.                         false);
  574.  
  575.                 // Create the XMLReader
  576.                 SAXParser xmlParser = factory.newSAXParser();
  577.                 xmlReader = xmlParser.getXMLReader();
  578.  
  579.                 // This class itself will take care of the elements
  580.                 xmlReader.setContentHandler(this);
  581.  
  582.                 StringWriter writer = new StringWriter();
  583.                 IOUtils.copy(xmlStream, writer, "UTF-8");
  584.                 String xmlString = writer.toString();
  585.                 String escapedXML = stripNonValidXMLCharacters(xmlString);
  586.  
  587.                 xmlReader.parse(new InputSource(new StringReader(escapedXML)));
  588.                 if (getLog().isTraceEnabled())
  589.                     getLog().trace("XML file completed");
  590.             } catch (IOException e) {
  591.                 getLog().error("Error while retrieving Bugzilla XML response:",
  592.                         e);
  593.             } catch (ParserConfigurationException e) {
  594.                 getLog().error("SAXParser not configured:", e);
  595.             } catch (SAXException e) {
  596.                 if (e.getMessage().indexOf("invalid XML character") >= 0) {
  597.                     getLog().error(
  598.                             "The XML file received contains illegal characters. This is not a B4J error but a Bugzilla problem. Sorry",
  599.                             e);
  600.                 } else {
  601.                     getLog().error(
  602.                             "Error while parsing Bugzilla XML response:", e);
  603.                 }
  604.             }
  605.         }
  606.  
  607.         /**
  608.          * This method cleans all the invalid characters in the XML and makes it
  609.          * conform to XML 1.0 standard
  610.          *
  611.          * @param in
  612.          *            The XML as String whose in-valid characters we want to
  613.          *            remove.
  614.          * @return The XML as String, stripped of all invalid characters
  615.          */
  616.         private String stripNonValidXMLCharacters(String in) {
  617.             StringBuffer out = new StringBuffer(); // Used to hold the output.
  618.             char current; // Used to reference the current character.
  619.  
  620.             if (in == null || ("".equals(in)))
  621.                 return ""; // vacancy test.
  622.             for (int i = 0; i < in.length(); i++) {
  623.                 current = in.charAt(i); // NOTE: No IndexOutOfBoundsException
  624.                                         // caught here; it should not happen.
  625.                 if ((current == 0x9) || (current == 0xA) || (current == 0xD)
  626.                         || ((current >= 0x20) && (current <= 0xD7FF))
  627.                         || ((current >= 0xE000) && (current <= 0xFFFD))
  628.                         || ((current >= 0x10000) && (current <= 0x10FFFF)))
  629.                     out.append(current);
  630.             }
  631.             return out.toString();
  632.         }
  633.  
  634.         /**
  635.          * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String,
  636.          *      java.lang.String, java.lang.String, org.xml.sax.Attributes)
  637.          */
  638.         @Override
  639.         public void startElement(String uri, String localName, String name,
  640.                 Attributes attributes) throws SAXException {
  641.             super.startElement(uri, localName, name, attributes);
  642.             if (name.equals("bugzilla")) {
  643.                 bugzillaUri = attributes.getValue("urlbase");
  644.                 bugzillaVersion = attributes.getValue("version");
  645.                 setBugzillaVersion(bugzillaVersion);
  646.             } else if (name.equals("bug")) {
  647.                 currentBug = createIssue();
  648.                 currentBug.setBugzillaUri(bugzillaUri);
  649.                 currentBug.setBugzillaVersion(bugzillaVersion);
  650.             } else if (name.equals("bug_id")) {
  651.                 currentContent = new StringBuffer();
  652.             } else if (name.equals("creation_ts")) { // 2008-07-23 12:28
  653.                 currentContent = new StringBuffer();
  654.             } else if (name.equals("short_desc")) {
  655.                 currentContent = new StringBuffer();
  656.             } else if (name.equals("delta_ts")) { // 2008-07-23 12:28:22
  657.                 currentContent = new StringBuffer();
  658.             } else if (name.equals("reporter_accessible")) {
  659.                 currentContent = new StringBuffer();
  660.             } else if (name.equals("cclist_accessible")) {
  661.                 currentContent = new StringBuffer();
  662.             } else if (name.equals("classification_id")) {
  663.                 currentContent = new StringBuffer();
  664.             } else if (name.equals("classification")) {
  665.                 currentContent = new StringBuffer();
  666.             } else if (name.equals("product")) {
  667.                 currentContent = new StringBuffer();
  668.             } else if (name.equals("component")) {
  669.                 currentContent = new StringBuffer();
  670.             } else if (name.equals("version")) {
  671.                 currentContent = new StringBuffer();
  672.             } else if (name.equals("rep_platform")) {
  673.                 currentContent = new StringBuffer();
  674.             } else if (name.equals("op_sys")) {
  675.                 currentContent = new StringBuffer();
  676.             } else if (name.equals("bug_status")) {
  677.                 currentContent = new StringBuffer();
  678.             } else if (name.equals("resolution")) {
  679.                 currentContent = new StringBuffer();
  680.             } else if (name.equals("priority")) {
  681.                 currentContent = new StringBuffer();
  682.             } else if (name.equals("bug_severity")) {
  683.                 currentContent = new StringBuffer();
  684.             } else if (name.equals("target_milestone")) {
  685.                 currentContent = new StringBuffer();
  686.             } else if (name.equals("everconfirmed")) {
  687.                 currentContent = new StringBuffer();
  688.             } else if (name.equals("reporter")) {
  689.                 currentContent = new StringBuffer();
  690.             } else if (name.equals("assigned_to")) {
  691.                 currentContent = new StringBuffer();
  692.             } else if (name.equals("qa_contact")) {
  693.                 currentContent = new StringBuffer();
  694.             } else if (name.equals("long_desc")) { // multiple
  695.                 currentLongDescription = currentBug.addLongDescription();
  696.             } else if (name.equals("commentid")) {
  697.                 currentContent = new StringBuffer();
  698.             } else if (name.equals("who")) {
  699.                 currentContent = new StringBuffer();
  700.             } else if (name.equals("bug_when")) { // 2008-07-23 12:28:22
  701.                 currentContent = new StringBuffer();
  702.             } else if (name.equals("thetext")) {
  703.                 currentContent = new StringBuffer();
  704.             } else if (name.equals("bug_file_loc")) {
  705.                 currentContent = new StringBuffer();
  706.             } else if (name.equals("cc")) { // multiple
  707.                 currentContent = new StringBuffer();
  708.             } else if (name.equals("attachment")) { // multiple
  709.                 currentAttachment = currentBug.addAttachment();
  710.             } else if (name.equals("attachid")) {
  711.                 currentContent = new StringBuffer();
  712.             } else if (name.equals("date")) {
  713.                 currentContent = new StringBuffer();
  714.             } else if (name.equals("desc")) {
  715.                 currentContent = new StringBuffer();
  716.             } else if (name.equals("filename")) {
  717.                 currentContent = new StringBuffer();
  718.             } else if (name.equals("type")) {
  719.                 currentContent = new StringBuffer();
  720.             } else if (name.equals("blocked")) {
  721.                 currentContent = new StringBuffer();
  722.             } else if (name.equals("alias")) {
  723.                 currentContent = new StringBuffer();
  724.             } else if (name.equals("status_whiteboard")) {
  725.                 currentContent = new StringBuffer();
  726.             } else if (name.equals("estimated_time")) {
  727.                 currentContent = new StringBuffer();
  728.             } else if (name.equals("remaining_time")) {
  729.                 currentContent = new StringBuffer();
  730.             } else if (name.equals("actual_time")) {
  731.                 currentContent = new StringBuffer();
  732.             } else if (name.equals("deadline")) {
  733.                 currentContent = new StringBuffer();
  734.             } else {
  735.                 currentCustomField = name;
  736.                 currentContent = new StringBuffer();
  737.                 // log.warn("Custom field: "+name);
  738.             }
  739.         }
  740.  
  741.         /**
  742.          * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String,
  743.          *      java.lang.String, java.lang.String)
  744.          */
  745.         @Override
  746.         public void endElement(String uri, String localName, String name)
  747.                 throws SAXException {
  748.             if (name.equals("bug")) {
  749.                 iterator.addBug(currentBug);
  750.                 currentBug = null;
  751.             } else if (name.equals("bug_id")) {
  752.                 currentBug.setId(currentContent.toString());
  753.                 currentContent = null;
  754.             } else if (name.equals("creation_ts")) { // 2008-07-23 12:28
  755.                 try {
  756.                     currentBug.setCreationTimestamp(BugzillaUtils
  757.                             .parseDate(currentContent.toString()));
  758.                 } catch (ParseException e) {
  759.                     getLog().error(
  760.                             "Cannot parse this time: "
  761.                                     + currentContent.toString());
  762.                 }
  763.                 currentContent = null;
  764.             } else if (name.equals("short_desc")) {
  765.                 currentBug.setShortDescription(currentContent.toString());
  766.                 currentContent = null;
  767.             } else if (name.equals("delta_ts")) { // 2008-07-23 12:28:22
  768.                 try {
  769.                     currentBug.setDeltaTimestamp(BugzillaUtils
  770.                             .parseDate(currentContent.toString()));
  771.                 } catch (ParseException e) {
  772.                     getLog().error(
  773.                             "Cannot parse this time: "
  774.                                     + currentContent.toString());
  775.                 }
  776.                 currentContent = null;
  777.             } else if (name.equals("reporter_accessible")) {
  778.                 currentBug.setReporterAccessible(parseBoolean(currentContent
  779.                         .toString()));
  780.                 currentContent = null;
  781.             } else if (name.equals("cclist_accessible")) {
  782.                 currentBug.setCclistAccessible(parseBoolean(currentContent
  783.                         .toString()));
  784.                 currentContent = null;
  785.             } else if (name.equals("classification_id")) {
  786.                 currentBug.setType(Long.parseLong(currentContent.toString()));
  787.                 currentContent = null;
  788.             } else if (name.equals("classification")) {
  789.                 currentBug.setTypeName(currentContent.toString());
  790.                 currentContent = null;
  791.             } else if (name.equals("product")) {
  792.                 currentBug.setProduct(currentContent.toString());
  793.                 currentContent = null;
  794.             } else if (name.equals("component")) {
  795.                 currentBug.setComponent(currentContent.toString());
  796.                 currentContent = null;
  797.             } else if (name.equals("version")) {
  798.                 currentBug.setVersion(currentContent.toString());
  799.                 currentContent = null;
  800.             } else if (name.equals("rep_platform")) {
  801.                 currentBug.setRepPlatform(currentContent.toString());
  802.                 currentContent = null;
  803.             } else if (name.equals("op_sys")) {
  804.                 currentBug.setOpSys(currentContent.toString());
  805.                 currentContent = null;
  806.             } else if (name.equals("bug_status")) {
  807.                 currentBug.setStatus(currentContent.toString());
  808.                 currentContent = null;
  809.             } else if (name.equals("resolution")) {
  810.                 currentBug.setResolution(currentContent.toString());
  811.                 currentContent = null;
  812.             } else if (name.equals("priority")) {
  813.                 currentBug.setPriority(currentContent.toString());
  814.                 currentContent = null;
  815.             } else if (name.equals("bug_severity")) {
  816.                 currentBug.setSeverity(currentContent.toString());
  817.                 currentContent = null;
  818.             } else if (name.equals("target_milestone")) {
  819.                 currentBug.setTargetMilestone(currentContent.toString());
  820.                 currentContent = null;
  821.             } else if (name.equals("everconfirmed")) {
  822.                 currentBug.setEverConfirmed(parseBoolean(currentContent
  823.                         .toString()));
  824.                 currentContent = null;
  825.             } else if (name.equals("reporter")) {
  826.                 currentBug.setReporter(currentContent.toString());
  827.                 currentContent = null;
  828.             } else if (name.equals("assigned_to")) {
  829.                 currentBug.setAssignee(currentContent.toString());
  830.                 currentContent = null;
  831.             } else if (name.equals("qa_contact")) {
  832.                 currentBug.setQaContact(currentContent.toString());
  833.                 currentContent = null;
  834.             } else if (name.equals("long_desc")) { // multiple
  835.                 currentLongDescription = null;
  836.             } else if (name.equals("commentid")) {
  837.                 currentLongDescription.setId(currentContent.toString());
  838.             } else if (name.equals("who")) {
  839.                 currentLongDescription.setWho(currentContent.toString());
  840.                 currentContent = null;
  841.             } else if (name.equals("bug_when")) { // 2008-07-23 12:28:22
  842.                 try {
  843.                     currentLongDescription.setWhen(BugzillaUtils
  844.                             .parseDate(currentContent.toString()));
  845.                 } catch (ParseException e) {
  846.                     getLog().error(
  847.                             "Cannot parse this time: "
  848.                                     + currentContent.toString());
  849.                 }
  850.                 currentContent = null;
  851.             } else if (name.equals("thetext")) {
  852.                 currentLongDescription.setTheText(currentContent.toString());
  853.                 currentContent = null;
  854.             } else if (name.equals("bug_file_loc")) {
  855.                 currentBug.setFileLocation(currentContent.toString());
  856.                 currentContent = null;
  857.             } else if (name.equals("attachment")) { // multiple
  858.                 currentAttachment = null;
  859.             } else if (name.equals("attachid")) {
  860.                 if (currentAttachment != null) {
  861.                     currentAttachment.setId(Long.parseLong(currentContent
  862.                             .toString()));
  863.                 } else if (currentLongDescription != null) {
  864.                     currentLongDescription.addAttachment(Long
  865.                             .parseLong(currentContent.toString()));
  866.                 }
  867.                 currentContent = null;
  868.             } else if (name.equals("date")) {
  869.                 currentContent = null;
  870.             } else if (name.equals("desc")) {
  871.                 currentAttachment.setDescription(currentContent.toString());
  872.                 currentContent = null;
  873.             } else if (name.equals("filename")) {
  874.                 currentAttachment.setFilename(currentContent.toString());
  875.                 currentContent = null;
  876.             } else if (name.equals("type")) {
  877.                 currentAttachment.setType(currentContent.toString());
  878.                 currentContent = null;
  879.             } else if (name.equals("cc")) { // multiple
  880.                 currentBug.addCc(currentContent.toString());
  881.                 currentContent = null;
  882.             } else if (name.equals("blocked")) {
  883.                 currentBug
  884.                         .setBlocked(Long.parseLong(currentContent.toString()));
  885.                 currentContent = null;
  886.             } else if (name.equals("alias")) {
  887.                 currentBug.setAlias(currentContent.toString());
  888.                 currentContent = null;
  889.             } else if (name.equals("status_whiteboard")) {
  890.                 currentBug.setWhiteboard(currentContent.toString());
  891.                 currentContent = null;
  892.             } else if (name.equals("estimated_time")) {
  893.                 currentBug.setEstimatedTime(Double.parseDouble(currentContent
  894.                         .toString()));
  895.                 currentContent = null;
  896.             } else if (name.equals("remaining_time")) {
  897.                 currentBug.setRemainingTime(Double.parseDouble(currentContent
  898.                         .toString()));
  899.                 currentContent = null;
  900.             } else if (name.equals("actual_time")) {
  901.                 currentBug.setActualTime(Double.parseDouble(currentContent
  902.                         .toString()));
  903.                 currentContent = null;
  904.             } else if (name.equals("deadline")) {
  905.                 try {
  906.                     currentBug.setDeadline(BugzillaUtils
  907.                             .parseDate(currentContent.toString()));
  908.                 } catch (ParseException e) {
  909.                     getLog().error(
  910.                             "Cannot parse this date: "
  911.                                     + currentContent.toString());
  912.                 }
  913.                 currentContent = null;
  914.             } else {
  915.                 if ((currentCustomField != null) && (currentContent != null)) {
  916.                     if (currentBug != null) {
  917.                         currentBug.setCustomField(currentCustomField,
  918.                                 currentContent.toString());
  919.                         currentCustomField = null;
  920.                         currentContent = null;
  921.                     }
  922.                 }
  923.             }
  924.             super.endElement(uri, localName, name);
  925.         }
  926.  
  927.         /**
  928.          * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
  929.          */
  930.         @Override
  931.         public void characters(char[] ch, int start, int length)
  932.                 throws SAXException {
  933.             if (currentContent != null)
  934.                 currentContent.append(ch, start, length);
  935.             super.characters(ch, start, length);
  936.         }
  937.  
  938.         /**
  939.          * @see org.xml.sax.helpers.DefaultHandler#startDocument()
  940.          */
  941.         @Override
  942.         public void startDocument() throws SAXException {
  943.             // Nothing to do
  944.             super.startDocument();
  945.         }
  946.  
  947.         /**
  948.          * @see org.xml.sax.helpers.DefaultHandler#endDocument()
  949.          */
  950.         @Override
  951.         public void endDocument() throws SAXException {
  952.             // Nothing to do
  953.             super.endDocument();
  954.         }
  955.  
  956.         /**
  957.          * Parses a boolean for Bugzilla XML. Bugzilla uses "1" to represent a
  958.          * TRUE value in its XML.
  959.          *
  960.          * @param s
  961.          *            - boolean to parse
  962.          * @return true if string represented the TRUE value
  963.          */
  964.         public boolean parseBoolean(String s) {
  965.             if (s == null)
  966.                 return false;
  967.             s = s.trim();
  968.             if (s.length() == 0)
  969.                 return false;
  970.             if (s.equals("1"))
  971.                 return true;
  972.             if (s.equals("0"))
  973.                 return false;
  974.             return Boolean.parseBoolean(s);
  975.         }
  976.     }
  977. }
  978.  
  979. /*
  980.  *
  981.  * query_format=advanced short_desc_type=allwordssubstr short_desc=
  982.  * classification= product= long_desc_type=substring long_desc=
  983.  * bug_file_loc_type=allwordssubstr bug_file_loc= keywords_type=allwords
  984.  * keywords= bug_status= emailassigned_to1=1 emailtype1=substring email1=
  985.  * emailassigned_to2=1 emailreporter2=1 emailqa_contact2=1 emailcc2=1
  986.  * emailtype2=substring email2= bugidtype=include bug_id= chfieldfrom=
  987.  * chfieldto=Now chfieldvalue= cmdtype=doit order=Bug+Number field0-0-0=noop
  988.  * type0-0-0=noop value0-0-0=
  989.  */
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×