docs: @Override
      public Map<String, Object> generate(String encoding, String locale, String productExt) {
  
          Map<String, Object> returnMap;
          try {
              //keeps list of commands
              final ArrayList<String> commandList = new ArrayList<String>();
  
              //Get java home
              final String javaHome = AccessController.doPrivileged(
                              new PrivilegedAction<String>() {
                                  @Override
                                  public String run() {
                                      return System.getProperty("java.home");
                                  }
                              });
  
              //Build path to ws-featurelist.jar
              final String featureListGenPath = getWsLocationAdmin().resolveString(WsLocationConstants.SYMBOL_INSTALL_DIR + "bin/tools/ws-featurelist.jar");
  
              //First command is to invoke the featureList jar
              commandList.add(javaHome + "/bin/java");
              commandList.add("-jar");
              commandList.add(featureListGenPath);
  
              //Encoding
              if (encoding != null && !encoding.trim().isEmpty()) {
                  commandList.add("--encoding=" + encoding);
              }
  
              //Locale
              if (locale != null && !locale.trim().isEmpty()) {
                  commandList.add("--locale=" + locale);
              }
  
              //Product Extension
              if (productExt != null && !productExt.trim().isEmpty()) {
                  commandList.add("--productExtension=" + productExt);
              }
  
              //Create empty file that will be populated
              final File targetDirectory = new File(getWsLocationAdmin().resolveString(WsLocationConstants.SYMBOL_SERVER_STATE_DIR));
              if (!FileUtils.fileExists(targetDirectory)) {
                  FileUtils.fileMkDirs(targetDirectory);
              }
  
              final File generatedFile = File.createTempFile(FEAT_LIST_PREFIX, FEAT_LIST_SUFFIX, targetDirectory);
  
              //Filename goes last in the script's invoke
              commandList.add(generatedFile.getAbsolutePath());
  
              //Debug command list
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  StringBuilder sb = new StringBuilder();
                  for (String command : commandList) {
                      sb.append(command);
                      sb.append("\n");
                  }
                  Tr.debug(tc, "List of commands:\n" + sb.toString());
              }
  
              //Run the command
              ProcessBuilder builder = new ProcessBuilder(commandList);
              builder.redirectErrorStream(true); //merge error and output together
  
              Process featureListGenProc = builder.start();
              String output = getOutput(featureListGenProc);
              int exitVal = featureListGenProc.waitFor();
  
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "ExitVal: " + exitVal);
              }
  
              if (exitVal != 0) {
                  return retError(output);
              }
  
              returnMap = new HashMap<String, Object>();
              returnMap.put(FeatureListMBean.KEY_FILE_PATH, generatedFile.getAbsolutePath());
              returnMap.put(FeatureListMBean.KEY_OUTPUT, output);
              returnMap.put(FeatureListMBean.KEY_RETURN_CODE, FeatureListMBean.RETURN_CODE_OK);
  
          } catch (IOException ioe) {
              return retError(ioe.getMessage());
          } catch (InterruptedException ie) {
              return retError(ie.getMessage());
          }
  
          return returnMap;
      }