private void prepareBBTXML(
      File infile, File destFile, String iconPath, String splashscreenFilename) // may be null
      throws IOException {
    Writer w = null;
    try {
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document d = db.parse(infile);
      Element e = d.getDocumentElement();

      // Add icon
      if (iconPath.length() > 0) {

        // add icon node
        Element icon = d.createElement(DOC_ELM_ICON);
        Node root = d.getFirstChild();
        root.appendChild(icon);

        // add image72x72 node
        Element image = d.createElement(DOC_ELM_IMAGE);
        image.appendChild(d.createTextNode(iconPath));
        icon.appendChild(image);
      }

      // Splash screen
      if (splashscreenFilename != null) {
        Element splashscreen = d.createElement(DOC_ELM_SPLASHSCREEN);
        splashscreen.appendChild(d.createTextNode(splashscreenFilename));
        d.getFirstChild().appendChild(splashscreen);
      }

      if (e != null && !_bbwpProperties.getCopyright().isEmpty()) {
        NodeList nl = e.getElementsByTagName(DOC_ELM_PUBLISHER);
        if (nl.getLength() > 0 && nl.item(0) instanceof Element) {
          Element e2 = (Element) nl.item(0);
          e2.setTextContent(_bbwpProperties.getCopyright());
        }
      }

      String[] permissions = _widgetConfig.getPermissions();
      Boolean has_access_internet = false;
      if (permissions != null && permissions.length > 0) {
        for (int i = 0; i < permissions.length; i++) {
          Element curPer = d.createElement("action");
          String permissionString = (_permissionMappings.get(permissions[i]));
          if (permissionString != null && !permissionString.isEmpty()) {
            curPer.setTextContent(permissionString);
            Node root = d.getFirstChild();
            root.appendChild(curPer);
          }
          if (permissions[i] == "access_internet") {
            has_access_internet = true;
          }
        }
      }
      if (!has_access_internet) // hardcoded access_internet to ensure user has internet (whitelist
      // takes care of security)
      {
        Element curPer = d.createElement("action");
        String permissionString = "access_internet";
        curPer.setTextContent(permissionString);
        Node root = d.getFirstChild();
        root.appendChild(curPer);
      }

      XPath xpathCategory = XPathFactory.newInstance().newXPath();
      NodeList categoryNL =
          (NodeList) xpathCategory.evaluate(DOC_ELM_CATEGORY_XPATH, d, XPathConstants.NODESET);

      if (categoryNL == null || categoryNL.getLength() == 0) {
        Element categoryE = d.createElement(DOC_ELM_CATEGORY);
        categoryE.setTextContent(_widgetConfig.getAppHomeScreenCategory());
        Node rootN = (Node) xpathCategory.evaluate(DOM_ELM_ROOT_XPATH, d, XPathConstants.NODE);
        rootN.appendChild(categoryE);
      } else {

        for (int i = 0; i < categoryNL.getLength(); i++) {
          categoryNL.item(i).setTextContent(_widgetConfig.getAppHomeScreenCategory());
        }
      }

      TransformerFactory tf = TransformerFactory.newInstance();
      Transformer t = tf.newTransformer();
      DOMSource s = new DOMSource(d);
      w = new FileWriter(destFile);
      StreamResult r = new StreamResult(w);
      t.transform(s, r);
    } catch (Exception e) {
    } finally {
      if (w != null) {
        try {
          w.close();
        } catch (IOException ioe) {
        }
      }
    }
  }
  /**
   * Parses XML from the specified input file, replaces the text content of the &lt;content&gt; with
   * the specified replacement string, and writes the result to the specified output file. If the
   * &lt;content&gt; element is not found in the expected location, this method is at liberty to do
   * nothing.
   *
   * @param infile the input XML file, expected to be in app XML format.
   * @param outfile the destination file, to hold the result.
   * @param replacementText the replacement string.
   * @exception java.io.IOException if an i/o error occurs.
   * @throws ValidationException
   */
  private void prepareAppXML(File infile, File outfile, String replacementText)
      throws IOException, ValidationException {
    Writer w = null;
    try {
      DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
      DocumentBuilder db = dbf.newDocumentBuilder();
      Document d = db.parse(infile);

      Element e = d.getDocumentElement();

      if (e != null) {
        // Replace initialWindow/content
        NodeList nl = e.getElementsByTagName(DOC_ELM_INITIALWINDOW);
        if (nl.getLength() > 0 && nl.item(0) instanceof Element) {
          Element e2 = (Element) nl.item(0);

          NodeList nl2 = e2.getElementsByTagName(DOC_ELM_CONTENT);
          if (nl2.getLength() > 0 && nl2.item(0) instanceof Element) {
            Element e3 = (Element) nl2.item(0);
            e3.setTextContent(replacementText);
          }

          // Add AutoOrientation
          if (_widgetConfig.getAutoOrientation() != null
              && _widgetConfig.getAutoOrientation().length() > 0) {
            Element autoOrientation = d.createElement(DOC_ELM_AUTOORIENTS);
            autoOrientation.setTextContent(_widgetConfig.getAutoOrientation());
            e2.appendChild(autoOrientation);
          }

          // Add Orientation
          if (_widgetConfig.getOrientation() != null
              && _widgetConfig.getOrientation().length() > 0) {
            Element orientation = d.createElement(DOC_ELM_ASPECTRATIO);
            orientation.setTextContent(_widgetConfig.getOrientation());
            e2.appendChild(orientation);
          }
        }

        // Replace id
        NodeList nl2 = e.getElementsByTagName(DOC_ELM_ID);
        if (nl2.getLength() > 0 && nl2.item(0) instanceof Element) {
          Element e3 = (Element) nl2.item(0);
          e3.setTextContent(
              SessionManager.getInstance().getArchiveName()
                  + genPackageName(SessionManager.getInstance().getArchiveName()));
        }

        // Replace name
        nl2 = e.getElementsByTagName(DOC_ELM_NAME);
        if (nl2.getLength() > 0 && nl2.item(0) instanceof Element) {
          Element e3 = (Element) nl2.item(0);
          e3.setTextContent(_widgetConfig.getName());
        }

        // Replace version
        nl2 = e.getElementsByTagName(DOC_ELM_VERSIONNUMBER);
        if (nl2.getLength() > 0 && nl2.item(0) instanceof Element) {
          Element e3 = (Element) nl2.item(0);
          e3.setTextContent(
              _widgetConfig.getVersionParts(0, 3)); // AIR supports only 3-part version strings
        }

        // Add description
        if (_widgetConfig.getDescription() != null && _widgetConfig.getDescription().length() > 0) {
          Element description = d.createElement(DOC_ELM_DESCRIPTION);
          description.setTextContent(_widgetConfig.getDescription());
          Node root = d.getFirstChild();
          root.appendChild(description);
        }

        // Add copyright
        if (_bbwpProperties.getCopyright().length() > 0) {
          Element copyright = d.createElement(DOC_ELM_COPYRIGHT);
          copyright.setTextContent(_bbwpProperties.getCopyright());
          Node root = d.getFirstChild();
          root.appendChild(copyright);
        }
      }

      TransformerFactory tf = TransformerFactory.newInstance();
      Transformer t = tf.newTransformer();
      DOMSource s = new DOMSource(d);
      w = new FileWriter(outfile);
      StreamResult r = new StreamResult(w);
      t.transform(s, r);
    } catch (ParserConfigurationException pce) {
      throw new IOException(pce);
    } catch (SAXException se) {
      throw new IOException(se);
    } catch (TransformerConfigurationException tce) {
      throw new IOException(tce);
    } catch (TransformerException te) {
      throw new IOException(te);
    } finally {
      if (w != null) {
        try {
          w.close();
        } catch (IOException ioe) {
        }
      }
    }
  }