In the j2objc wrapper script, add the ability to process more than one source jars.
In the j2objc dead code removal script, quote the object file names when invoking ar. They may contain special shell characeters.

--
PiperOrigin-RevId: 143993977
MOS_MIGRATED_REVID=143993977
diff --git a/tools/j2objc/j2objc_wrapper.py b/tools/j2objc/j2objc_wrapper.py
index 003cf08..1c55d7e 100755
--- a/tools/j2objc/j2objc_wrapper.py
+++ b/tools/j2objc/j2objc_wrapper.py
@@ -215,28 +215,32 @@
   return [os.path.splitext(java_file)[0] + '.m' for java_file in java_files]
 
 
-def UnzipGenJarSources(gen_src_jar):
-  """Unzips the gen srcjar containing outputs from Java annotation processors.
+def UnzipSourceJarSources(source_jars):
+  """Unzips the source jars containing Java source files.
 
   Args:
-    gen_src_jar: The path of the gen srcjar.
+    source_jars: The list of input Java source jars.
   Returns:
     A tuple of the temporary output root and a list of root-relative paths of
     unzipped Java files
   """
-  genjar_java_files = []
-  if gen_src_jar:
+  srcjar_java_files = []
+  if source_jars:
     tmp_input_root = tempfile.mkdtemp()
-    zip_ref = zipfile.ZipFile(gen_src_jar, 'r')
+    for source_jar in source_jars:
+      zip_ref = zipfile.ZipFile(source_jar, 'r')
+      zip_entries = []
 
-    for file_entry in zip_ref.namelist():
-      # We only care about Java source files.
-      if file_entry.endswith('.java'):
-        genjar_java_files.append(file_entry)
+      for file_entry in zip_ref.namelist():
+        # We only care about Java source files.
+        if file_entry.endswith('.java'):
+          zip_entries.append(file_entry)
 
-    zip_ref.extractall(tmp_input_root, genjar_java_files)
-    zip_ref.close()
-    return (tmp_input_root, genjar_java_files)
+      zip_ref.extractall(tmp_input_root, zip_entries)
+      zip_ref.close()
+      srcjar_java_files.extend(zip_entries)
+
+    return (tmp_input_root, srcjar_java_files)
   else:
     return None
 
@@ -438,11 +442,16 @@
       required=False,
       help=('The archive file path that will be produced by ObjC compile action'
             ' later'))
+  # TODO(rduan): Remove this flag once it is fully replaced by flag --src_jars.
   parser.add_argument(
       '--gen_src_jar',
       required=False,
       help='The jar containing Java sources generated by annotation processor.')
   parser.add_argument(
+      '--src_jars',
+      required=False,
+      help='The list of Java source jars containg Java sources to translate.')
+  parser.add_argument(
       '--output_gen_source_dir',
       required=False,
       help='The output directory of ObjC source files translated from the gen'
@@ -455,16 +464,22 @@
 
   args, pass_through_args = parser.parse_known_args()
   normal_java_files, j2objc_flags = _ParseArgs(pass_through_args)
-  genjar_java_files = []
+  srcjar_java_files = []
   j2objc_source_paths = [os.getcwd()]
 
-  # Unzip the gen jar, so J2ObjC can translate the contained sources.
+  # Unzip the source jars, so J2ObjC can translate the contained sources.
   # Also add the temporary directory containing the unzipped sources as a source
   # path for J2ObjC, so it can find these sources.
-  genjar_source_tuple = UnzipGenJarSources(args.gen_src_jar)
-  if genjar_source_tuple:
-    j2objc_source_paths.append(genjar_source_tuple[0])
-    genjar_java_files = genjar_source_tuple[1]
+  source_jars = []
+  if args.gen_src_jar:
+    source_jars.append(args.gen_src_jar)
+  if args.src_jars:
+    source_jars.extend(args.src_jars.split(','))
+
+  srcjar_source_tuple = UnzipSourceJarSources(source_jars)
+  if srcjar_source_tuple:
+    j2objc_source_paths.append(srcjar_source_tuple[0])
+    srcjar_java_files = srcjar_source_tuple[1]
 
   # Run J2ObjC over the normal input Java files and unzipped gen jar Java files.
   # The output is stored in a temporary directory.
@@ -476,11 +491,11 @@
             tmp_objc_file_root,
             j2objc_flags,
             j2objc_source_paths,
-            normal_java_files + genjar_java_files)
+            normal_java_files + srcjar_java_files)
 
   # Calculate the relative paths of generated objc files.
   normal_objc_files = _J2ObjcOutputObjcFiles(normal_java_files)
-  genjar_objc_files = _J2ObjcOutputObjcFiles(genjar_java_files)
+  genjar_objc_files = _J2ObjcOutputObjcFiles(srcjar_java_files)
 
   # Generate J2ObjC mapping files needed for distributed builds.
   GenerateJ2objcMappingFiles(normal_objc_files,
diff --git a/tools/objc/j2objc_dead_code_pruner.py b/tools/objc/j2objc_dead_code_pruner.py
index a5dac5c..a5693fb 100755
--- a/tools/objc/j2objc_dead_code_pruner.py
+++ b/tools/objc/j2objc_dead_code_pruner.py
@@ -378,8 +378,15 @@
         # Remove the unreachable objects from the archive
         unreachable_object_names = MatchObjectNamesInArchive(
             xcrunwrapper, input_archive, unreachable_object_names)
+        # We need to quote the object names because they may contains special
+        # shell characters.
+        quoted_unreachable_object_names = [
+            "'" + unreachable_object_name + "'"
+            for unreachable_object_name in unreachable_object_names]
         j2objc_cmd += '%s ar -d -s %s %s && ' % (
-            xcrunwrapper, output_archive, ' '.join(unreachable_object_names))
+            xcrunwrapper,
+            output_archive,
+            ' '.join(quoted_unreachable_object_names))
         # Update the table of content of the archive file
         j2objc_cmd += '%s ranlib %s' % (xcrunwrapper, output_archive)
     # There are no unreachable objects, we just copy over the original archive