[333327] Repo import doesn't work with cross-packageUnit dependencies
https://bugs.eclipse.org/bugs/show_bug.cgi?id=333327

diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/EMFUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/EMFUtil.java
index 5884524..e60cdd9 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/EMFUtil.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/EMFUtil.java
@@ -12,6 +12,8 @@
  */
 package org.eclipse.emf.cdo.common.model;
 
+import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+
 import org.eclipse.net4j.util.WrappedException;
 
 import org.eclipse.emf.common.notify.Adapter;
@@ -38,6 +40,7 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
@@ -417,4 +420,78 @@
       }
     }
   }
+
+  /**
+   * @see ExtResourceSet
+   * @since 4.0
+   */
+  public static ExtResourceSet createExtResourceSet(InternalCDOPackageRegistry packageRegistry, boolean delegating,
+      boolean demandLoading)
+  {
+    Resource.Factory resourceFactory = new EcoreResourceFactoryImpl();
+
+    ExtResourceSet resourceSet = new ExtResourceSet(delegating, demandLoading);
+    resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("*", resourceFactory); //$NON-NLS-1$
+    resourceSet.setPackageRegistry(packageRegistry);
+    return resourceSet;
+  }
+
+  /**
+   * An extension of {@link ResourceSetImpl} that allows demandLoading of resources and delegation of resource lookups,
+   * to be switched on/off as desired.
+   * 
+   * @since 4.0
+   */
+  public static class ExtResourceSet extends ResourceSetImpl
+  {
+    private boolean delegating;
+
+    private boolean demandLoading;
+
+    ExtResourceSet(boolean delegating, boolean demandLoading)
+    {
+      this.delegating = delegating;
+      this.demandLoading = demandLoading;
+    }
+
+    public boolean isDelegating()
+    {
+      return delegating;
+    }
+
+    public void setDelegating(boolean delegating)
+    {
+      this.delegating = delegating;
+    }
+
+    public boolean isDemandLoading()
+    {
+      return demandLoading;
+    }
+
+    public void setDemandLoading(boolean demandLoading)
+    {
+      this.demandLoading = demandLoading;
+    }
+
+    @Override
+    protected void demandLoad(Resource resource) throws IOException
+    {
+      if (demandLoading)
+      {
+        super.demandLoad(resource);
+      }
+    }
+
+    @Override
+    protected Resource delegatedGetResource(URI uri, boolean loadOnDemand)
+    {
+      if (delegating)
+      {
+        return super.delegatedGetResource(uri, loadOnDemand);
+      }
+
+      return null;
+    }
+  }
 }
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageInfoImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageInfoImpl.java
index dd061c5..09ce376 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageInfoImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageInfoImpl.java
@@ -115,7 +115,7 @@
 
     if (loadOnDemand)
     {
-      packageUnit.load();
+      packageUnit.load(true); // TODO (CD) Dubious: is resolution-on-load really a good idea?
       return (EPackage)getTarget();
     }
 
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageUnitImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageUnitImpl.java
index db4cf51..c158164 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageUnitImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOPackageUnitImpl.java
@@ -234,12 +234,12 @@
     setState(State.DISPOSED);
   }
 
-  public synchronized void load()
+  public synchronized void load(boolean resolve)
   {
-    load(packageRegistry.getPackageLoader());
+    load(packageRegistry.getPackageLoader(), resolve);
   }
 
-  public synchronized void load(PackageLoader packageLoader)
+  public synchronized void load(PackageLoader packageLoader, boolean resolve)
   {
     if (state == State.PROXY)
     {
@@ -257,7 +257,10 @@
         synchronized (ePackage)
         {
           EMFUtil.addAdapter(ePackage, packageInfo);
-          EcoreUtil.resolveAll(ePackage);
+          if (resolve)
+          {
+            EcoreUtil.resolveAll(ePackage);
+          }
         }
       }
 
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/model/InternalCDOPackageUnit.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/model/InternalCDOPackageUnit.java
index 0a0d887..2ac4ea8 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/model/InternalCDOPackageUnit.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/model/InternalCDOPackageUnit.java
@@ -44,12 +44,15 @@
 
   public void setPackageInfos(InternalCDOPackageInfo[] packageInfos);
 
-  public void load();
+  /**
+   * @since 4.0
+   */
+  public void load(boolean resolve);
 
   /**
    * @since 4.0
    */
-  public void load(PackageLoader packageLoader);
+  public void load(PackageLoader packageLoader, boolean resolve);
 
   /**
    * @since 3.0
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerImporter.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerImporter.java
index 52e4565..e8fe70f 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerImporter.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/CDOServerImporter.java
@@ -19,6 +19,7 @@
 import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
 import org.eclipse.emf.cdo.common.model.CDOPackageUnit.Type;
 import org.eclipse.emf.cdo.common.model.EMFUtil;
+import org.eclipse.emf.cdo.common.model.EMFUtil.ExtResourceSet;
 import org.eclipse.emf.cdo.common.model.lob.CDOLobHandler;
 import org.eclipse.emf.cdo.common.model.lob.CDOLobUtil;
 import org.eclipse.emf.cdo.common.revision.CDOList;
@@ -48,7 +49,6 @@
 import org.eclipse.emf.ecore.EClass;
 import org.eclipse.emf.ecore.EPackage;
 import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.resource.ResourceSet;
 
 import org.xml.sax.Attributes;
 import org.xml.sax.SAXException;
@@ -200,10 +200,10 @@
       InternalCDOPackageUnit[] array = packageUnits.toArray(new InternalCDOPackageUnit[packageUnits.size()]);
       packageUnits = null;
 
+      final ExtResourceSet resourceSet = EMFUtil.createExtResourceSet(packageRegistry, false, false);
+
       PackageLoader loader = new PackageLoader()
       {
-        private ResourceSet resourceSet = EMFUtil.newEcoreResourceSet(packageRegistry);
-
         public EPackage[] loadPackages(CDOPackageUnit packageUnit)
         {
           String id = packageUnit.getID();
@@ -217,9 +217,15 @@
       packageRegistry.putPackageUnits(array, CDOPackageUnit.State.PROXY);
       for (InternalCDOPackageUnit packageUnit : array)
       {
-        packageUnit.load(loader);
+        packageUnit.load(loader, false);
       }
 
+      // Before we resolve, we configure the resourceSet to start delegating, which means
+      // it will consult the packageRegistry for packages it didn't just load -- such as the Ecore
+      // package
+      resourceSet.setDelegating(true);
+      EMFUtil.safeResolveAll(resourceSet);
+
       accessor.rawStore(array, monitor);
 
       return packageRegistry;