Пример #1
0
  /**
   * Create a splash screen image on disk and return its name, or null if no splash screen is
   * created. A splash screen is not created if the widget config specifies no loading screen data.
   *
   * @param directory the destination folder for the image file, if one is created. Also used to
   *     locate the foreground and background images.
   * @return the name of the splash screen image file on disk, or null if none created.
   */
  private String createSplashscreen(String directory) throws IOException {
    // Get string args from widget config. They may be null.
    String arg0 = _widgetConfig.getLoadingScreenColour();
    String arg1 = _widgetConfig.getBackgroundImage();
    String arg2 = _widgetConfig.getForegroundImage();

    //
    // If the widget config doesn't specify loading screen data,
    // do not create a splash screen.
    //
    if (arg0 == null && arg1 == null && arg2 == null) {
      return null;
    }

    Color bgcolor = arg0 == null ? Color.WHITE : Color.decode(arg0);
    BufferedImage bgImage = arg1 == null ? null : ImageIO.read(new File(directory, arg1));
    BufferedImage fgImage = arg2 == null ? null : ImageIO.read(new File(directory, arg2));
    BufferedImage composition =
        new BufferedImage(SCREEN_WIDTH, SCREEN_HEIGHT, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = composition.createGraphics();

    g.setBackground(bgcolor);
    g.clearRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

    if (bgImage != null) {
      g.drawImage(bgImage, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, null);
    }

    if (fgImage != null) {
      g.drawImage(
          fgImage,
          (SCREEN_WIDTH - fgImage.getWidth()) / 2,
          (SCREEN_HEIGHT - fgImage.getHeight()) / 2,
          null);
    }

    File out =
        File.createTempFile(FILE_SPSH, DELIMITER_DOT + SPLASHSCREEN_FORMAT, new File(directory));
    ImageIO.write(composition, SPLASHSCREEN_FORMAT, out);

    return out.getName();
  }
Пример #2
0
  /**
   * Parses XML from the specified input file, replaces the text content of the <content> with
   * the specified replacement string, and writes the result to the specified output file. If the
   * <content> 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) {
        }
      }
    }
  }
Пример #3
0
  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) {
        }
      }
    }
  }
Пример #4
0
  /**
   * Packages the files in the specified source path, using the AIR packager to create a BAR file.
   *
   * @param sourcePath the folder containing the files to be packaged.
   * @param archiveName the name of the Widget archive.
   * @throws ValidationException
   */
  public int run() throws PackageException, ValidationException {
    try {
      String sourcePath = SessionManager.getInstance().getSourceFolder();
      String bindebugPath = sourcePath + File.separator + PATH_BIN_DEBUG;
      String archiveName = SessionManager.getInstance().getArchiveName();

      //
      // First we copy the files in the source path to the bin-debug folder.
      //
      deleteDirectory(new File(bindebugPath));
      new File(bindebugPath).mkdir(); // just in case

      List<File> fileList = new ArrayList<File>();
      File desFile;

      // Check if the icon file actually exists
      // Needs to be done first in order to avoid putting the icon.png filename into the fileList
      String iconPath = EMPTY_STRING;
      if (_widgetConfig.getIconSrc().size() > 0) {
        iconPath = _widgetConfig.getIconSrc().firstElement().toString();
        File iconFile = new File(sourcePath, iconPath);
        if (!iconFile.isFile()) {
          iconPath = EMPTY_STRING;
        } else {
          iconPath = PATH_ICON_APPICON_PNG;
          iconFile.renameTo(new File(sourcePath, iconPath));
        }
      }

      //
      // Create a splash screen consistent with the loading screen.
      // If the widget config doesn't specify loading screen data,
      // splashscreenFilename will be null.
      //
      String splashscreenFilename = createSplashscreen(sourcePath);

      //
      // Copy src files to the bin-debug folder
      //
      List<File> srcFiles =
          listFiles(
              sourcePath,
              new FileFilter() {
                public boolean accept(File pathname) {
                  return !pathname.getName().endsWith(FILE_EXT_AS)
                      && !pathname.getName().endsWith(APP_XML_SUFFIX)
                      && !pathname
                          .getName()
                          .equals(
                              SessionManager.getInstance().getArchiveName() + SWF_FILE_EXTENSION)
                      && !pathname.getName().contains(PATH_MACOSX);
                }
              });

      for (File f : srcFiles) {
        String relativePath = f.getAbsolutePath().substring(sourcePath.length() + 1);
        desFile = new File(bindebugPath, relativePath);
        FileManager.copyFile(f, desFile);
      }

      // Add the top level file/folder under bin-debug folder to the file list,
      // so it will greatly shorten the length of final command line
      File[] archiveFiles =
          new File(bindebugPath)
              .listFiles(
                  new FileFilter() {
                    // APP_XML_SUFFIX and SWF_FILE_EXTENSION will be added afterwards
                    public boolean accept(File pathname) {
                      return !pathname.getName().endsWith(APP_XML_SUFFIX)
                          && !pathname
                              .getName()
                              .endsWith(
                                  SessionManager.getInstance().getArchiveName()
                                      + SWF_FILE_EXTENSION)
                          && !pathname.getName().contains(PATH_MACOSX);
                    }
                  });

      for (File f : archiveFiles) {
        fileList.add(f);
      }

      //
      // Copy the SWF
      //
      String swfName = archiveName + SWF_FILE_EXTENSION;
      desFile = new File(bindebugPath, swfName);
      FileManager.copyFile(new File(sourcePath, swfName), desFile);
      fileList.add(desFile);

      //
      // Copy and replace the text in the app XML with the name of the SWF file.
      // Prepare the complete version of app.xml including a custom icon.
      //

      String appXmlName = archiveName + APP_XML_SUFFIX;
      desFile = new File(bindebugPath, appXmlName);
      prepareAppXML(new File(sourcePath, FILE_WEBWORKSAPPTEMPLATE_APP_XML), desFile, swfName);
      fileList.add(desFile);

      File bbt = new File(sourcePath, FILE_BLACKBERRY_TABLET_XML);
      File bbtDes = new File(bindebugPath, FILE_BLACKBERRY_TABLET_XML);
      prepareBBTXML(bbt, bbtDes, iconPath, splashscreenFilename);

      bbt.delete();

      int size = fileList.size();
      String[] files = new String[size];
      int i = 2;
      for (File f : fileList) {
        String relativePath = f.getAbsolutePath().substring(bindebugPath.length() + 1);
        if (relativePath.equalsIgnoreCase(appXmlName)) {
          files[0] = relativePath;
        } else if (relativePath.equalsIgnoreCase(swfName)) {
          files[1] = relativePath;
        } else {
          files[i++] = relativePath;
        }
      }

      //
      // Now we can package it all.
      //
      String outputFolder = SessionManager.getInstance().getOutputFolder();
      new File(outputFolder).mkdirs();
      String outputPath =
          SessionManager.getInstance()
              .getOutputFilepath(); // _airTemplatePath + File.separator + archiveName +
      // BAR_FILE_EXTENSION

      //
      // For AIR, the build number is specified separately from the
      // version string using the -buildId parameter.
      //
      // For signing, the bbwp command-line interface supports -buildId
      // as an override.
      //
      String buildId;
      String buildIdOverride = SessionManager.getInstance().getBuildId();
      if (!buildIdOverride.isEmpty()) {
        buildId = buildIdOverride;
      } else if (_widgetConfig.getNumVersionParts() > 3) {
        buildId = _widgetConfig.getVersionParts(3);
      } else {
        buildId = NUM_0;
      }

      String debugToken = _bbwpProperties.getDebugToken();
      String[] cmd;
      if (SessionManager.getInstance().requireSigning()) {
        cmd =
            new String[] {
              _airPackagerPath,
              FLAG_PACKAGE,
              FLAG_TARGET,
              FILE_EXT_BAR,
              FLAG_BUILDID,
              buildId,
              outputPath
            };
      } else if (!SessionManager.getInstance().debugMode() || debugToken.isEmpty()) {
        cmd =
            new String[] {
              _airPackagerPath,
              FLAG_PACKAGE,
              FLAG_DEV_MODE,
              FLAG_TARGET,
              SessionManager.getInstance().debugModeInternal() ? PATH_BAR_DEBUG : FILE_EXT_BAR,
              FLAG_BUILDID,
              buildId,
              outputPath
            };
      } else {
        if (!(new File(debugToken).isFile())) {
          //
          // It is an error for the <debug_token> element to
          // contain a pathname that does not point to a file.
          //
          throw new PackageException(EXCEPTION_DEBUG_TOKEN_INVALID);
        } else {
          cmd =
              new String[] {
                _airPackagerPath,
                FLAG_PACKAGE,
                FLAG_DEV_MODE,
                FLAG_DEBUG_TOKEN,
                debugToken,
                FLAG_TARGET,
                SessionManager.getInstance().debugModeInternal() ? PATH_BAR_DEBUG : FILE_EXT_BAR,
                FLAG_BUILDID,
                buildId,
                outputPath
              };
        }
      }
      int n = files.length;
      String[] join = new String[cmd.length + n];
      System.arraycopy(cmd, 0, join, 0, cmd.length);
      System.arraycopy(files, 0, join, cmd.length, n);
      Process p = buildProcess(join, new File(bindebugPath));

      OutputBuffer stdout = new OutputBuffer(p);
      ErrorBuffer stderr = new ErrorBuffer(p);
      ExitBuffer exitcode = new ExitBuffer(p);

      stdout.waitFor();
      stderr.waitFor();
      exitcode.waitFor();

      if (exitcode.getExitValue().intValue() != 0) {
        System.out.write(stderr.getStderr());
        System.out.write(stdout.getStdout());
        System.out.flush();
        return exitcode.getExitValue().intValue();
      }
    } catch (IOException ioe) {
      ioe.printStackTrace();
      throw new PackageException(EXCEPTION_AIRPACKAGER);
    } catch (InterruptedException ie) {
      throw new PackageException(EXCEPTION_AIRPACKAGER);
    }
    return 0;
  }