public void run() {
      for (int i = start; i <= end; ++i) {
        XmlvmResource resource = allResources[i];
        if (resource == null) {
          continue;
        }
        Log.debug("JavaScriptOutputProcess: Processing " + resource.getName());
        OutputFile file = generateJavaScript(resource);
        file.setLocation(arguments.option_out());
        String packageName = resource.getPackageName().replace('.', '_');
        String resourceName = resource.getName();
        Log.debug("RESOURCE NAME: " + resourceName);

        String fileName = resourceName + JS_EXTENSION;
        if (!packageName.isEmpty()) {
          fileName = packageName + '_' + fileName;
        }
        file.setFileName(fileName);
        resources.addOutputFile(file);
      }
    }
  /**
   * Generates the string constant pool for this application. This method iterates over all <code>
   * XmlvmResources</code> and builds up a list of unique string constants. Those string constants
   * are added as another <code>XmlvmResource</code> (of type <code>CONST_POOL</code>) to the
   * bundle. The XML markup of the constant pool looks as follows:
   *
   * <pre>
   * &lt;vm:constant-pool&gt;
   *     &lt;entry id="..." length="..." encoded-constant="..." escaped-constant="..."/&gt;
   *     ...
   * &lt/constant-pool&gt;
   * </pre>
   */
  private void generateStringConstantPool(BundlePhase2 bundle) {
    List<ConstantPoolEntry> constantPool = new ArrayList<ConstantPoolEntry>();
    Map<String, Integer> constantPoolIDs = new HashMap<String, Integer>();
    for (XmlvmResource resource : bundle.getResources()) {
      List<XmlvmConstantStringElement> instructions = new ArrayList<XmlvmConstantStringElement>();
      resource.collectInstructions(instructions);
      for (XmlvmConstantStringElement inst : instructions) {
        String escapedConstant = inst.getEscapedStringConstant();
        String encodedConstant = inst.getEncodedStringConstant();
        int len = inst.getLength();
        int id = -1;
        if (constantPoolIDs.containsKey(encodedConstant)) {
          id = constantPoolIDs.get(encodedConstant);
        } else {
          id = constantPool.size();
          ConstantPoolEntry entry =
              new ConstantPoolEntry(id, len, escapedConstant, encodedConstant);
          constantPool.add(entry);
          constantPoolIDs.put(encodedConstant, id);
        }
        inst.setContantPoolID(id);
      }
    }

    Element xmlRoot = new Element("constant-pool", XmlvmResource.nsXMLVM);
    for (ConstantPoolEntry entry : constantPool) {
      Element xmlEntry = new Element("entry", XmlvmResource.nsXMLVM);
      xmlEntry.setAttribute("id", "" + entry.id);
      xmlEntry.setAttribute("length", "" + entry.length);
      xmlEntry.setAttribute("escaped-constant", entry.escapedString);
      xmlEntry.setAttribute("encoded-constant", entry.encodedString);
      xmlRoot.addContent(xmlEntry);
    }

    XmlvmResource resource =
        new XmlvmResource(XmlvmResource.Type.CONST_POOL, new Document(xmlRoot));
    bundle.addAdditionalResource(resource);
  }
  public boolean processPhase2(BundlePhase2 bundle) {
    Map<String, XmlvmResource> mappedResources = new HashMap<String, XmlvmResource>();
    for (XmlvmResource resource : bundle.getResources()) {
      mappedResources.put(resource.getFullName(), resource);
    }

    long startTime = System.currentTimeMillis();

    XmlvmResource[] allResources = mappedResources.values().toArray(new XmlvmResource[0]);
    int threadCount = Runtime.getRuntime().availableProcessors();
    int itemsPerThread = (int) Math.ceil(allResources.length / (float) threadCount);
    Log.debug(TAG, "Threads: " + threadCount);
    Log.debug(TAG, "Items per thread: " + itemsPerThread);
    JavaScriptTranslationThread[] threads = new JavaScriptTranslationThread[threadCount];

    // Divide work and start the threads.
    for (int i = 0; i < threadCount; ++i) {
      int start = i * itemsPerThread;
      int end = Math.min(start + itemsPerThread - 1, allResources.length - 1);
      threads[i] = new JavaScriptTranslationThread(allResources, start, end, bundle);
      threads[i].start();
    }

    // Wait for threads to finish.
    for (int i = 0; i < threadCount; ++i) {
      try {
        threads[i].join();
      } catch (InterruptedException e) {
        e.printStackTrace();
        return false;
      }
    }

    long endTime = System.currentTimeMillis();
    Log.debug(TAG, "JS Processing took: " + (endTime - startTime) + " ms.");
    return true;
  }
 protected OutputFile generateJavaScript(XmlvmResource xmlvm) {
   return XsltRunner.runXSLT("xmlvm2js.xsl", xmlvm.getXmlvmDocument());
 }