Support GenerateAll().

- Expect calls on GenerateAll() and not Generate().
- Parse the prefix validation file once, and then check all the files.
diff --git a/objectivec/DevTools/compile_testing_protos.sh b/objectivec/DevTools/compile_testing_protos.sh
index 8295313..9a6b7bf 100755
--- a/objectivec/DevTools/compile_testing_protos.sh
+++ b/objectivec/DevTools/compile_testing_protos.sh
@@ -99,26 +99,26 @@
   src/google/protobuf/descriptor.proto
 )
 
-compile_proto() {
+compile_protos() {
   src/protoc                                   \
     --objc_out="${OUTPUT_DIR}/google/protobuf" \
     --proto_path=src/google/protobuf/          \
     --proto_path=src                           \
-    $*
+    "$@"
 }
 
+# Note: there is overlap in package.Message names between some of the test
+# files, so they can't be generated all at once. This works because the overlap
+# isn't linked into a single binary.
 for a_proto in "${CORE_PROTO_FILES[@]}" ; do
-  compile_proto "${a_proto}"
+  compile_protos "${a_proto}"
 done
 
-OBJC_PROTO_FILES=(
-  objectivec/Tests/unittest_cycle.proto
-  objectivec/Tests/unittest_runtime_proto2.proto
-  objectivec/Tests/unittest_runtime_proto3.proto
-  objectivec/Tests/unittest_objc.proto
+# Objective C specific testing protos.
+compile_protos \
+  --proto_path="objectivec/Tests" \
+  objectivec/Tests/unittest_cycle.proto \
+  objectivec/Tests/unittest_runtime_proto2.proto \
+  objectivec/Tests/unittest_runtime_proto3.proto \
+  objectivec/Tests/unittest_objc.proto \
   objectivec/Tests/unittest_objc_startup.proto
-)
-
-for a_proto in "${OBJC_PROTO_FILES[@]}" ; do
-  compile_proto --proto_path="objectivec/Tests" "${a_proto}"
-done
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
index a0b6d6c..3640746 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
@@ -45,10 +45,22 @@
 
 ObjectiveCGenerator::~ObjectiveCGenerator() {}
 
+bool ObjectiveCGenerator::HasGenerateAll() const {
+  return true;
+}
+
 bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
                                    const string& parameter,
-                                   OutputDirectory* output_directory,
+                                   GeneratorContext* context,
                                    string* error) const {
+  *error = "Unimplemented Generate() method. Call GenerateAll() instead.";
+  return false;
+}
+
+bool ObjectiveCGenerator::GenerateAll(const vector<const FileDescriptor*>& files,
+                                      const string& parameter,
+                                      GeneratorContext* context,
+                                      string* error) const {
   // -----------------------------------------------------------------
   // Parse generator options. These options are passed to the compiler using the
   // --objc_opt flag. The options are passed as a comma separated list of
@@ -117,29 +129,32 @@
 
   // -----------------------------------------------------------------
 
-  // Validate the objc prefix/package pairing.
-  if (!ValidateObjCClassPrefix(file, generation_options, error)) {
+  // Validate the objc prefix/package pairings.
+  if (!ValidateObjCClassPrefixes(files, generation_options, error)) {
     // *error will have been filled in.
     return false;
   }
 
-  FileGenerator file_generator(file, generation_options);
-  string filepath = FilePath(file);
+  for (int i = 0; i < files.size(); i++) {
+    const FileDescriptor* file = files[i];
+    FileGenerator file_generator(file, generation_options);
+    string filepath = FilePath(file);
 
-  // Generate header.
-  {
-    scoped_ptr<io::ZeroCopyOutputStream> output(
-        output_directory->Open(filepath + ".pbobjc.h"));
-    io::Printer printer(output.get(), '$');
-    file_generator.GenerateHeader(&printer);
-  }
+    // Generate header.
+    {
+      scoped_ptr<io::ZeroCopyOutputStream> output(
+          context->Open(filepath + ".pbobjc.h"));
+      io::Printer printer(output.get(), '$');
+      file_generator.GenerateHeader(&printer);
+    }
 
-  // Generate m file.
-  {
-    scoped_ptr<io::ZeroCopyOutputStream> output(
-        output_directory->Open(filepath + ".pbobjc.m"));
-    io::Printer printer(output.get(), '$');
-    file_generator.GenerateSource(&printer);
+    // Generate m file.
+    {
+      scoped_ptr<io::ZeroCopyOutputStream> output(
+          context->Open(filepath + ".pbobjc.m"));
+      io::Printer printer(output.get(), '$');
+      file_generator.GenerateSource(&printer);
+    }
   }
 
   return true;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
index 09266b0..9d801d5 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_generator.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
@@ -47,8 +47,15 @@
   ~ObjectiveCGenerator();
 
   // implements CodeGenerator ----------------------------------------
-  bool Generate(const FileDescriptor* file, const string& parameter,
-                OutputDirectory* output_directory, string* error) const;
+  bool HasGenerateAll() const;
+  bool Generate(const FileDescriptor* file,
+                const string& parameter,
+                GeneratorContext* context,
+                string* error) const;
+  bool GenerateAll(const vector<const FileDescriptor*>& files,
+                   const string& parameter,
+                   GeneratorContext* context,
+                   string* error) const;
 
  private:
   GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectiveCGenerator);
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
index 009d57f..847be98 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -980,28 +980,20 @@
       generation_options.expected_prefixes_path, &collector, out_error);
 }
 
-}  // namespace
-
-bool ValidateObjCClassPrefix(const FileDescriptor* file,
-                             const Options& generation_options,
-                             string* out_error) {
+bool ValidateObjCClassPrefix(
+    const FileDescriptor* file,
+    const string& expected_prefixes_path,
+    const map<string, string>& expected_package_prefixes,
+    string* out_error) {
   const string prefix = file->options().objc_class_prefix();
   const string package = file->package();
 
   // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
   // error cases, so it seems to be ok to use as a back door for warnings.
 
-  // Load any expected package prefixes to validate against those.
-  map<string, string> expected_package_prefixes;
-  if (!LoadExpectedPackagePrefixes(generation_options,
-                                   &expected_package_prefixes,
-                                   out_error)) {
-    return false;
-  }
-
   // Check: Error - See if there was an expected prefix for the package and
   // report if it doesn't match (wrong or missing).
-  map<string, string>::iterator package_match =
+  map<string, string>::const_iterator package_match =
       expected_package_prefixes.find(package);
   if (package_match != expected_package_prefixes.end()) {
     // There was an entry, and...
@@ -1050,7 +1042,7 @@
 
   // Look for any other package that uses the same prefix.
   string other_package_for_prefix;
-  for (map<string, string>::iterator i = expected_package_prefixes.begin();
+  for (map<string, string>::const_iterator i = expected_package_prefixes.begin();
        i != expected_package_prefixes.end(); ++i) {
     if (i->second == prefix) {
       other_package_for_prefix = i->first;
@@ -1068,7 +1060,7 @@
            << "protoc:0: warning: File '" << file->name() << "' has no "
            << "package. Consider adding a new package to the proto and adding '"
            << "new.package = " << prefix << "' to the expected prefixes file ("
-           << generation_options.expected_prefixes_path << ")." << endl;
+           << expected_prefixes_path << ")." << endl;
       cerr.flush();
     } else {
       // ... another package has declared the same prefix.
@@ -1078,7 +1070,7 @@
            << prefix << "' as its prefix. Consider either adding a new package "
            << "to the proto, or reusing one of the packages already using this "
            << "prefix in the expected prefixes file ("
-           << generation_options.expected_prefixes_path << ")." << endl;
+           << expected_prefixes_path << ")." << endl;
       cerr.flush();
     }
     return true;
@@ -1094,7 +1086,7 @@
         "'; that prefix is already used for 'package " +
         other_package_for_prefix + ";'. It can only be reused by listing " +
         "it in the expected file (" +
-        generation_options.expected_prefixes_path + ").";
+        expected_prefixes_path + ").";
     return false;  // Only report first usage of the prefix.
   }
 
@@ -1105,13 +1097,39 @@
          << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
          << prefix << "\";' in '" << file->name() << "';"
          << " consider adding it to the expected prefixes file ("
-         << generation_options.expected_prefixes_path << ")." << endl;
+         << expected_prefixes_path << ")." << endl;
     cerr.flush();
   }
 
   return true;
 }
 
+}  // namespace
+
+bool ValidateObjCClassPrefixes(const vector<const FileDescriptor*>& files,
+                               const Options& generation_options,
+                               string* out_error) {
+  // Load the expected package prefixes, if available, to validate against.
+  map<string, string> expected_package_prefixes;
+  if (!LoadExpectedPackagePrefixes(generation_options,
+                                   &expected_package_prefixes,
+                                   out_error)) {
+    return false;
+  }
+
+  for (int i = 0; i < files.size(); i++) {
+    bool is_valid =
+        ValidateObjCClassPrefix(files[i],
+                                generation_options.expected_prefixes_path,
+                                expected_package_prefixes,
+                                out_error);
+    if (!is_valid) {
+      return false;
+    }
+  }
+  return true;
+}
+
 TextFormatDecodeData::TextFormatDecodeData() { }
 
 TextFormatDecodeData::~TextFormatDecodeData() { }
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
index 344723a..b05983d 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -185,12 +185,12 @@
 // Checks if the file is one of the proto's bundled with the library.
 bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file);
 
-// Checks the prefix for a given file and outputs any warnings needed, if
-// there are flat out errors, then out_error is filled in and the result is
-// false.
-bool ValidateObjCClassPrefix(const FileDescriptor* file,
-                             const Options& generation_options,
-                             string* out_error);
+// Checks the prefix for the given files and outputs any warnings as needed. If
+// there are flat out errors, then out_error is filled in with the first error
+// and the result is false.
+bool ValidateObjCClassPrefixes(const vector<const FileDescriptor*>& files,
+                               const Options& generation_options,
+                               string* out_error);
 
 // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
 // the input into the expected output.