You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@daffodil.apache.org by sl...@apache.org on 2023/02/06 21:01:38 UTC

[daffodil] 01/02: Add refactor scripts for OSGI compliance

This is an automated email from the ASF dual-hosted git repository.

slawrence pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/daffodil.git

commit 068d08f0dfe77fe370c312c32c8755fb350004a5
Author: Mike McGann <mm...@owlcyberdefense.com>
AuthorDate: Mon Feb 6 10:47:05 2023 -0500

    Add refactor scripts for OSGI compliance
    
    Daffodil shares package namespaces across different libraries such that
    library A can have a class named foo.bar.One and library B can have a
    class named foo.bar.Two. This can cause issues with class loaders that
    prohibit different jars from owning the same package (i.e., in an
    OSGI container). These scripts refactor the code to ensure that each
    package is only owned by a single jar. An sbt task, osgiCheck, has
    been added to enforce compilance in the future.
    
    DAFFODIL-2683
---
 build.sbt                                          |   1 +
 .../apache/daffodil/reflection/FieldFinder.scala   | 145 ------------
 .../daffodil/reflection/FieldFinder.scala.md       | 146 ++++++++++++
 .../daffodil/reflection/TestFieldFinder.scala      | 122 ----------
 .../daffodil/reflection/TestFieldFinder.scala.md   | 124 +++++++++++
 project/OsgiCheck.scala                            | 100 +++++++++
 scripts/osgi-refactor/.gitignore                   |  16 ++
 scripts/osgi-refactor/README.md                    |  25 +++
 scripts/osgi-refactor/Rat.scala                    | 193 ++++++++++++++++
 scripts/osgi-refactor/add-imports.scala            | 247 +++++++++++++++++++++
 scripts/osgi-refactor/fix-gen.sh                   |  45 ++++
 scripts/osgi-refactor/fix-imports.scala            | 209 +++++++++++++++++
 scripts/osgi-refactor/gen-symbol-table.scala       | 134 +++++++++++
 scripts/osgi-refactor/git-restore.sh               |  67 ++++++
 scripts/osgi-refactor/refactor.sh                  |  28 +++
 scripts/osgi-refactor/rename-dirs.sh               | 154 +++++++++++++
 16 files changed, 1489 insertions(+), 267 deletions(-)

diff --git a/build.sbt b/build.sbt
index 17d7a29c7..43e848c63 100644
--- a/build.sbt
+++ b/build.sbt
@@ -42,6 +42,7 @@ lazy val daffodil         = project.in(file(".")).configs(IntegrationTest)
 lazy val macroLib         = Project("daffodil-macro-lib", file("daffodil-macro-lib")).configs(IntegrationTest)
                               .settings(commonSettings, nopublish)
                               .settings(libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value)
+                              .disablePlugins(OsgiCheckPlugin)
 
 lazy val propgen          = Project("daffodil-propgen", file("daffodil-propgen")).configs(IntegrationTest)
                               .settings(commonSettings, nopublish)
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/reflection/FieldFinder.scala b/daffodil-runtime1/src/main/scala/org/apache/daffodil/reflection/FieldFinder.scala
deleted file mode 100644
index dad514779..000000000
--- a/daffodil-runtime1/src/main/scala/org/apache/daffodil/reflection/FieldFinder.scala
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//
-// Please leave this code here for now.
-// It's unused, but documents how to use reflection, many of its foibles,
-// and in other sitautions we may want to use these techniques.
-//
-
-//package org.apache.daffodil.reflection
-//
-//import scala.reflect.runtime.{ universe => ru }
-//import ru._
-//import scala.reflect.ClassTag
-//import org.apache.daffodil.util.Maybe
-//import org.apache.daffodil.exceptions.Assert
-//
-///**
-// * Uses reflection to find all members of a class having a particular type.
-// */
-//object FieldFinder {
-//
-//  //  private def typesOf[T: TypeTag](v: T): List[Type] =
-//  //    typeOf[T].baseClasses.map(typeOf[T].baseType)
-//
-//  /**
-//   * The object passed as argument a, must be an instance of a top-level class.
-//   * It cannot be a nested class, class inside an object, or class inside a method.
-//   *
-//   * It returns a pair. The first of the pair is the list of the member values.
-//   * The second of the pair is a list of strings, each describing a problem case
-//   * where there is a member-like thing that has the right type, but it isn't something
-//   * where reflection (or anything else) can get its value after the fact. (It's implemented
-//   * by scala as a private value of the constructor method only for the class. Since the
-//   * constructor isn't running anymore, this value is just "gone".)
-//   */
-//  def findAllMembersOfType[T](a: AnyRef)(implicit ttag: TypeTag[T]) = {
-//    val tpe = ttag.tpe
-//    val rm = scala.reflect.runtime.currentMirror
-//    val clsSym = rm.classSymbol(a.getClass)
-//    val clsType = clsSym.toType
-//    val allClasses = clsType.baseClasses
-//    val allTypes = allClasses.map { _.asType.toType }
-//    val allMembers = allTypes.flatMap { ty => ty.members.sorted }
-//    val members = allMembers.filter { _.isTerm } // just terms, not types
-//    val im = rm.reflect(a)
-//    val allMethods = members.collect { case x if x.isMethod => x.asMethod }
-//    val allGetters = allMethods.collect { case m if m.isGetter => m.getter.asMethod }
-//    val getters = allGetters.filter { g =>
-//      g.typeSignature.resultType <:< tpe
-//    }
-//    val getterValues: Seq[T] = getters.map { case x => im.reflectMethod(x).apply().asInstanceOf[T] }
-//
-//    //
-//    // The above takes care of most cases, but if a member is declared as just a constructor
-//    // parameter that is then used somewhere inside the class, that doesn't show up as
-//    // a method at all. So we have to go after this in the non-methods.
-//
-//    val nonMethods = members.collect { case x if !x.isMethod => x }
-//    //
-//    // These can be slots of things that are accessed by getters we already have taken
-//    // care of, so we exclude the ones we already have gotten
-//    //
-//    val gotten = getters.collect { case m if m.isAccessor => m.accessed }.toSeq
-//    //    if (a.getClass.getName().contains("ConvertTextCalendarUnparser")) {
-//    //      println("Stop here")
-//    //    }
-//    //
-//    // Unfortunately, the symbol you get back in the gotten list is
-//    // not the same object one gets in the non-methods list even when they
-//    // are referring to the same slot/location.
-//    //
-//    // So we just compare these based on the string representation
-//    val gottenStrings = gotten.map { _.toString }
-//    val allWanted = nonMethods.filterNot { term => gottenStrings.contains(term.toString) }
-//    val wanted = allWanted.filter { w =>
-//      w.typeSignature <:< tpe
-//    }
-//    //
-//    // Some of these things are fields, and we can get their values via reflection
-//    // others are not.
-//    //
-//    // I can't find any test/predicate or class/type distinction that will tell us
-//    // what we can get the value of, and what we can't. So we just try and catch
-//    // the failure if the value can't be obtained.
-//    //
-//    val wantedValues: Seq[T] = wanted.flatMap {
-//      case x => {
-//        try {
-//          val field = im.reflectField(x.asTerm)
-//          val result = field.get.asInstanceOf[T]
-//          List(result)
-//        } catch {
-//          case re: ScalaReflectionException => Nil
-//        }
-//      }
-//    }
-//
-//    //
-//    // That's all the values
-//    //
-//    val values = (getterValues ++ wantedValues).distinct
-//
-//    //
-//    // The things that have the right type, but we can't get their values
-//    // by reflection, well we probably want to warn or throw errors about
-//    // these so that the user is informed they should make these into
-//    // var, val, lazy val, or just use them in the class someplace.
-//    // That is, so they won't get missed.
-//    //
-//    // Again the only way I know of to detect these is to try to get
-//    // their values, and when that fails, that's one of the ones we
-//    // want to warn about.
-//    //
-//    val warnTerms = wanted.flatMap {
-//      case x => {
-//        try {
-//          im.reflectField(x.asTerm).get
-//          Nil
-//        } catch {
-//          case re: ScalaReflectionException => List(x)
-//        }
-//      }
-//    }
-//
-//    val warnings = warnTerms.map { _.toString }.distinct
-//
-//    (values, warnings)
-//  }
-//
-//}
diff --git a/daffodil-runtime1/src/main/scala/org/apache/daffodil/reflection/FieldFinder.scala.md b/daffodil-runtime1/src/main/scala/org/apache/daffodil/reflection/FieldFinder.scala.md
new file mode 100644
index 000000000..5cae23eab
--- /dev/null
+++ b/daffodil-runtime1/src/main/scala/org/apache/daffodil/reflection/FieldFinder.scala.md
@@ -0,0 +1,146 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+```scala
+//
+// Please leave this code here for now.
+// It's unused, but documents how to use reflection, many of its foibles,
+// and in other sitautions we may want to use these techniques.
+//
+
+package org.apache.daffodil.reflection
+
+import scala.reflect.runtime.{ universe => ru }
+import ru._
+import scala.reflect.ClassTag
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.exceptions.Assert
+
+/**
+ * Uses reflection to find all members of a class having a particular type.
+ */
+object FieldFinder {
+
+  //  private def typesOf[T: TypeTag](v: T): List[Type] =
+  //    typeOf[T].baseClasses.map(typeOf[T].baseType)
+
+  /**
+   * The object passed as argument a, must be an instance of a top-level class.
+   * It cannot be a nested class, class inside an object, or class inside a thod.
+   *
+   * It returns a pair. The first of the pair is the list of the member values.
+   * The second of the pair is a list of strings, each describing a problem case
+   * where there is a member-like thing that has the right type, but it isn't mething
+   * where reflection (or anything else) can get its value after the fact. t's implemented
+   * by scala as a private value of the constructor method only for the class. nce the
+   * constructor isn't running anymore, this value is just "gone".)
+   */
+  def findAllMembersOfType[T](a: AnyRef)(implicit ttag: TypeTag[T]) = {
+    val tpe = ttag.tpe
+    val rm = scala.reflect.runtime.currentMirror
+    val clsSym = rm.classSymbol(a.getClass)
+    val clsType = clsSym.toType
+    val allClasses = clsType.baseClasses
+    val allTypes = allClasses.map { _.asType.toType }
+    val allMembers = allTypes.flatMap { ty => ty.members.sorted }
+    val members = allMembers.filter { _.isTerm } // just terms, not types
+    val im = rm.reflect(a)
+    val allMethods = members.collect { case x if x.isMethod => x.asMethod }
+    val allGetters = allMethods.collect { case m if m.isGetter => m.getter.Method }
+    val getters = allGetters.filter { g =>
+      g.typeSignature.resultType <:< tpe
+    }
+    val getterValues: Seq[T] = getters.map { case x => im.reflectMethod(x).apply.asInstanceOf[T] }
+
+    //
+    // The above takes care of most cases, but if a member is declared as just constructor
+    // parameter that is then used somewhere inside the class, that doesn't ow up as
+    // a method at all. So we have to go after this in the non-methods.
+
+    val nonMethods = members.collect { case x if !x.isMethod => x }
+    //
+    // These can be slots of things that are accessed by getters we already ve taken
+    // care of, so we exclude the ones we already have gotten
+    //
+    val gotten = getters.collect { case m if m.isAccessor => m.accessed }.toSeq
+    //    if (a.getClass.getName().contains("ConvertTextCalendarUnparser")) {
+    //      println("Stop here")
+    //    }
+    //
+    // Unfortunately, the symbol you get back in the gotten list is
+    // not the same object one gets in the non-methods list even when they
+    // are referring to the same slot/location.
+    //
+    // So we just compare these based on the string representation
+    val gottenStrings = gotten.map { _.toString }
+    val allWanted = nonMethods.filterNot { term => gottenStrings.contains(term.String) }
+    val wanted = allWanted.filter { w =>
+      w.typeSignature <:< tpe
+    }
+    //
+    // Some of these things are fields, and we can get their values via flection
+    // others are not.
+    //
+    // I can't find any test/predicate or class/type distinction that will tell
+    // what we can get the value of, and what we can't. So we just try and catch
+    // the failure if the value can't be obtained.
+    //
+    val wantedValues: Seq[T] = wanted.flatMap {
+      case x => {
+        try {
+          val field = im.reflectField(x.asTerm)
+          val result = field.get.asInstanceOf[T]
+          List(result)
+        } catch {
+          case re: ScalaReflectionException => Nil
+        }
+      }
+    }
+
+    //
+    // That's all the values
+    //
+    val values = (getterValues ++ wantedValues).distinct
+
+    //
+    // The things that have the right type, but we can't get their values
+    // by reflection, well we probably want to warn or throw errors about
+    // these so that the user is informed they should make these into
+    // var, val, lazy val, or just use them in the class someplace.
+    // That is, so they won't get missed.
+    //
+    // Again the only way I know of to detect these is to try to get
+    // their values, and when that fails, that's one of the ones we
+    // want to warn about.
+    //
+    val warnTerms = wanted.flatMap {
+      case x => {
+        try {
+          im.reflectField(x.asTerm).get
+          Nil
+        } catch {
+          case re: ScalaReflectionException => List(x)
+        }
+      }
+    }
+
+    val warnings = warnTerms.map { _.toString }.distinct
+
+    (values, warnings)
+  }
+}
+```
diff --git a/daffodil-runtime1/src/test/scala/org/apache/daffodil/reflection/TestFieldFinder.scala b/daffodil-runtime1/src/test/scala/org/apache/daffodil/reflection/TestFieldFinder.scala
deleted file mode 100644
index 8b785d42b..000000000
--- a/daffodil-runtime1/src/test/scala/org/apache/daffodil/reflection/TestFieldFinder.scala
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-//package org.apache.daffodil.reflection
-//
-//import org.apache.daffodil.util.Maybe
-//import org.apache.daffodil.exceptions.Assert
-//import org.junit.Test
-//import org.junit.Assert._
-//
-///**
-// * These have to be top-level classes or for some reason
-// * the reflection doesn't work.
-// */
-//abstract class C(
-//  notInterested: String, // wrong type
-//  warnAbout: List[String], // only used here in constructor
-//  s: List[String], // yes. Right type, and in use in the printMore method
-//  var t: List[String]) { // yes. var
-//  def printMore = println(s)
-//}
-//
-//class Bar1(
-//  val ignoreMe: String, // nope, wrong type.
-//  dontWarnAboutMe: String, // wrong type
-//  val x: List[String], // yes, val
-//  var y: List[String], // yes, var
-//  warnAboutMe: List[String], // need warning. Right type, but used only as a constructor arg
-//  w: List[String], // yes, it is used in the printIt method
-//  warnAboutMeToo: List[String]) // warning. Used nowhere.
-//  extends C(ignoreMe, warnAboutMe, List("s"), List("t")) { // warnAboutMe is used only as a constructor arg.
-//
-//  lazy val p: List[String] = List("p")
-//
-//  val q: List[String] = List("q")
-//
-//  def printIt = {
-//    println(w) // w gets used here, so even though it's not var/val it's not supposedly a constructor arg.
-//    println(dontWarnAboutMe)
-//  }
-//}
-//
-//class TestFieldFinder {
-//
-//  @Test def testFindAllMembersOfType1() {
-//
-//    val a = new Bar1("ignoreMe", "dontWarnAboutMe", List("x"), List("y"), List("warnAboutMe"), List("w"), List("warnAboutMeToo"))
-//
-//    val (values, warns) = FieldFinder.findAllMembersOfType[List[String]](a)
-//    println(values)
-//    println(warns)
-//
-//    val valueStrings = values.map { case List(s: String) => s }
-//    assertEquals("x y p q t w s", valueStrings.mkString(" "))
-//    assertEquals(List("value warnAboutMe", "value warnAboutMeToo", "value warnAbout"), warns)
-//  }
-//
-//  /**
-//   * Same thing, but looks for List[AnyRef] instead of the exact type List[String]
-//   */
-//  @Test def testFindAllMembersOfTypeWithAnyRef() {
-//
-//    val a = new Bar1("ignoreMe", "dontWarnAboutMe", List("x"), List("y"), List("warnAboutMe"), List("w"), List("warnAboutMeToo"))
-//
-//    val (values, warns) = FieldFinder.findAllMembersOfType[List[AnyRef]](a)
-//    println(values)
-//    println(warns)
-//
-//    val valueStrings = values.map { case List(s: String) => s }
-//    assertEquals("x y p q t w s", valueStrings.mkString(" "))
-//    assertEquals(List("value warnAboutMe", "value warnAboutMeToo", "value warnAbout"), warns)
-//  }
-//
-//  //
-//  // This test fails. It's near identical to the above,
-//  // but fails because the classes being examined are nested within a method.
-//  //
-//  // This shows that they have to be top-level classes for this particular
-//  // set of reflective techniques to work.
-//  //
-//  // @Test
-//  def testFindAllMembersOfType2() {
-//
-//    abstract class C2(val notInterested: List[String]) // not interested because it's not immediately in Bar1.
-//
-//    class Bar2(val ignoreMe: String, dontWarnAboutMe: String, val x: List[String], var y: List[String], warnAboutMe: List[String], w: List[String], warnAboutMeToo: List[String])
-//      extends C2(warnAboutMe) { // warnAboutMe is used only as a constructor arg.
-//
-//      lazy val p: List[String] = List("p")
-//
-//      val q: List[String] = List("q")
-//
-//      def printIt = {
-//        println(w) // w gets used here, so even though it's not var/val it's not supposedly a constructor arg.
-//        println(dontWarnAboutMe)
-//      }
-//    }
-//
-//    val a = new Bar2("ignoreMe", "dontWarnAboutMe", List("x"), List("y"), List("warnAboutMe"), List("w"), List("warnAboutMeToo"))
-//
-//    val (values, warns) = FieldFinder.findAllMembersOfType[List[String]](a)
-//    println(values)
-//    println(warns)
-//
-//    val valueStrings = values.map { case List(s: String) => s }
-//    assertEquals("x y p q w", valueStrings.mkString(" "))
-//  }
-//}
diff --git a/daffodil-runtime1/src/test/scala/org/apache/daffodil/reflection/TestFieldFinder.scala.md b/daffodil-runtime1/src/test/scala/org/apache/daffodil/reflection/TestFieldFinder.scala.md
new file mode 100644
index 000000000..518d80e3a
--- /dev/null
+++ b/daffodil-runtime1/src/test/scala/org/apache/daffodil/reflection/TestFieldFinder.scala.md
@@ -0,0 +1,124 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+```scala
+package org.apache.daffodil.reflection
+
+import org.apache.daffodil.util.Maybe
+import org.apache.daffodil.exceptions.Assert
+import org.junit.Test
+import org.junit.Assert._
+
+/**
+ * These have to be top-level classes or for some reason
+ * the reflection doesn't work.
+ */
+abstract class C(
+  notInterested: String, // wrong type
+  warnAbout: List[String], // only used here in constructor
+  s: List[String], // yes. Right type, and in use in the printMore method
+  var t: List[String]) { // yes. var
+  def printMore = println(s)
+}
+
+class Bar1(
+  val ignoreMe: String, // nope, wrong type.
+  dontWarnAboutMe: String, // wrong type
+  val x: List[String], // yes, val
+  var y: List[String], // yes, var
+  warnAboutMe: List[String], // need warning. Right type, but used only as a constructor arg
+  w: List[String], // yes, it is used in the printIt method
+  warnAboutMeToo: List[String]) // warning. Used nowhere.
+  extends C(ignoreMe, warnAboutMe, List("s"), List("t")) { // warnAboutMe is used only as a constructor arg.
+
+  lazy val p: List[String] = List("p")
+
+  val q: List[String] = List("q")
+
+  def printIt = {
+    println(w) // w gets used here, so even though it's not var/val it's not supposedly a constructor arg.
+    println(dontWarnAboutMe)
+  }
+}
+
+class TestFieldFinder {
+
+  @Test def testFindAllMembersOfType1() {
+
+    val a = new Bar1("ignoreMe", "dontWarnAboutMe", List("x"), List("y"), List("warnAboutMe"), List("w"), List("warnAboutMeToo"))
+
+    val (values, warns) = FieldFinder.findAllMembersOfType[List[String]](a)
+    println(values)
+    println(warns)
+
+    val valueStrings = values.map { case List(s: String) => s }
+    assertEquals("x y p q t w s", valueStrings.mkString(" "))
+    assertEquals(List("value warnAboutMe", "value warnAboutMeToo", "value warnAbout"), warns)
+  }
+
+  /**
+   * Same thing, but looks for List[AnyRef] instead of the exact type List[String]
+   */
+  @Test def testFindAllMembersOfTypeWithAnyRef() {
+
+    val a = new Bar1("ignoreMe", "dontWarnAboutMe", List("x"), List("y"), List("warnAboutMe"), List("w"), List("warnAboutMeToo"))
+
+    val (values, warns) = FieldFinder.findAllMembersOfType[List[AnyRef]](a)
+    println(values)
+    println(warns)
+
+    val valueStrings = values.map { case List(s: String) => s }
+    assertEquals("x y p q t w s", valueStrings.mkString(" "))
+    assertEquals(List("value warnAboutMe", "value warnAboutMeToo", "value warnAbout"), warns)
+  }
+
+  //
+  // This test fails. It's near identical to the above,
+  // but fails because the classes being examined are nested within a method.
+  //
+  // This shows that they have to be top-level classes for this particular
+  // set of reflective techniques to work.
+  //
+  // @Test
+  def testFindAllMembersOfType2() {
+
+    abstract class C2(val notInterested: List[String]) // not interested because it's not immediately in Bar1.
+
+    class Bar2(val ignoreMe: String, dontWarnAboutMe: String, val x: List[String], var y: List[String], warnAboutMe: List[String], w: List[String], warnAboutMeToo: List[String])
+      extends C2(warnAboutMe) { // warnAboutMe is used only as a constructor arg.
+
+      lazy val p: List[String] = List("p")
+
+      val q: List[String] = List("q")
+
+      def printIt = {
+        println(w) // w gets used here, so even though it's not var/val it's not supposedly a constructor arg.
+        println(dontWarnAboutMe)
+      }
+    }
+
+    val a = new Bar2("ignoreMe", "dontWarnAboutMe", List("x"), List("y"), List("warnAboutMe"), List("w"), List("warnAboutMeToo"))
+
+    val (values, warns) = FieldFinder.findAllMembersOfType[List[String]](a)
+    println(values)
+    println(warns)
+
+    val valueStrings = values.map { case List(s: String) => s }
+    assertEquals("x y p q w", valueStrings.mkString(" "))
+  }
+}
+```
diff --git a/project/OsgiCheck.scala b/project/OsgiCheck.scala
new file mode 100644
index 000000000..0c81adfc8
--- /dev/null
+++ b/project/OsgiCheck.scala
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import sbt._
+import sbt.Keys._
+import sbt.KeyRanks._
+
+object OsgiCheckPlugin extends AutoPlugin {
+
+  class OsgiCheckException()
+    extends RuntimeException("OSGI check failed")
+      with FeedbackProvidedException
+
+  object autoImport {
+    val osgiOwnedPackages = taskKey[Set[String]]("Get all packages owned by this project").withRank(BTask)
+    val osgiOwnedPackagesWithOwner = taskKey[(Set[String], String)]("Get a tuple of the osgiOwnedPackages and the project name that owns them").withRank(Invisible)
+    val osgiCheck = taskKey[Unit]("Check all subpackages for osgi conflicts").withRank(ATask)
+  }
+
+  import autoImport._
+
+  private val packageMatcher = """^\s*package (\S+);?.*$""".r
+
+  override def trigger = allRequirements
+
+  val allSubprojectsFilter = ScopeFilter(inAggregates(ThisProject, includeRoot=false))
+
+  override def projectSettings: Seq[Def.Setting[_]] = {Seq(
+    osgiOwnedPackages := {
+      val logger = streams.value.log
+      (Compile / sources).value.flatMap { file =>
+        var source = scala.io.Source.fromFile(file)
+        val optPackage = source.getLines.collectFirst {
+          case packageMatcher(packageName) => packageName
+        }
+        if (optPackage.isEmpty) {
+          logger.warn(s"${file.getPath}: could not find package statement")
+        }
+        optPackage
+      }.toSet
+    },
+    osgiOwnedPackagesWithOwner := {
+      (osgiOwnedPackages.value, name.value)
+    },
+    osgiCheck := {
+      val logger = streams.value.log
+
+      // create a List of tuples of all osgiOwnedPackages and their owner from all
+      // subprojects. If a subproject disables this plugin, then it contributes tuple
+      // of empty set and empty string and will be ignored
+      val subprojectPackagesAndOwner = (osgiOwnedPackagesWithOwner ?? (Set.empty -> ""))
+        .all(allSubprojectsFilter).value
+
+      // flatten all of our tuples so we have a single list of package name ->
+      // project owner tuples. At this point, there might be multiple owners
+      // for the same package name in this list
+      val packageOwnerTuples = subprojectPackagesAndOwner.flatMap { case (ownedPackages, packageOwner) =>
+        ownedPackages.map { _ -> packageOwner }
+      }
+
+      // create a map, grouping with a key of package name and value of all of the
+      // owners that claim to own it. If only one project owns a package, the value
+      // should be a list of one.
+      val packageOwnersMap = packageOwnerTuples
+        .groupBy { case (packageName, _) => packageName }
+        .mapValues { list => list.map { case (_, packageOwner) => packageOwner } }
+
+      // find any packages with multiple project owners and error
+      val multipleOwners = packageOwnersMap.filter { case (_, owners) => owners.length > 1 }
+      if (multipleOwners.size > 0) {
+        logger.err("Packages found owned by multiple projects, violating OSGI:")
+        multipleOwners.foreach { case (packageName, owners) =>
+          logger.err(s"- package $packageName: ${owners.mkString(", ")}")
+        }
+        throw new OsgiCheckException()
+      }
+    }
+  )}
+
+  override val globalSettings: Seq[Setting[_]] = {Seq(
+    // the osgiCheck does aggregation itself by inspecting all subproject, it does
+    // not need to be aggregated
+    osgiCheck / aggregate := false
+  )}
+
+}
\ No newline at end of file
diff --git a/scripts/osgi-refactor/.gitignore b/scripts/osgi-refactor/.gitignore
new file mode 100644
index 000000000..ea0aae4fa
--- /dev/null
+++ b/scripts/osgi-refactor/.gitignore
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+symbols.txt
diff --git a/scripts/osgi-refactor/README.md b/scripts/osgi-refactor/README.md
new file mode 100644
index 000000000..66d664da5
--- /dev/null
+++ b/scripts/osgi-refactor/README.md
@@ -0,0 +1,25 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+# refactor
+
+Run with:
+
+    ./refactor.sh
+
+Undo with:
+
+    ./git-restore.sh
diff --git a/scripts/osgi-refactor/Rat.scala b/scripts/osgi-refactor/Rat.scala
new file mode 100644
index 000000000..ca17a2ab7
--- /dev/null
+++ b/scripts/osgi-refactor/Rat.scala
@@ -0,0 +1,193 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import sbt._
+
+object Rat {
+
+  lazy val excludes = Seq(
+
+    // git files
+    file(".git"),
+
+    // IntelliJ files
+    file(".idea"),
+
+    // scaladoc related, has no way to include a license
+    file("daffodil-sapi/root-doc.txt"),
+
+    // UTF-16BE, Apache Rat thinks it is a binary and cannot tell it includes the Apache v2 license
+    file("daffodil-test/src/test/resources/org/apache/daffodil/section06/namespaces/multi_base_09.dfdl.xsd"),
+
+    // images used for the windows installer
+    file("daffodil-cli/src/windows/apache-daffodil.ico"),
+    file("daffodil-cli/src/windows/banner.bmp"),
+    file("daffodil-cli/src/windows/dialog.bmp"),
+
+    // generated_code.[ch] examples
+    file("daffodil-runtime2/src/test/c/examples"),
+
+    // Apache Rat thinks these files are binary since the file name contains ".lib"
+    file("daffodil-schematron/src/main/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory"),
+    file("daffodil-japi/src/test/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory"),
+    file("daffodil-sapi/src/test/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory"),
+    file("daffodil-lib/src/main/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory"),
+    file("daffodil-lib/src/test/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory"),
+
+    // test files that cannot include the Apache license without breaking tests
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/hextest.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input1.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input2.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input3.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input4.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input5.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input6.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input7.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input8.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input9.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input10.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input11.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input12.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input13.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input14.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input14.exi"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input14.exisa"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input15.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input16.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input18.json"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input18.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input18.exi"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input18.exisa"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/input19.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/inputBig1M.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/prefix.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/test_DFDL-714.txt"),
+    file("daffodil-cli/src/test/resources/org/apache/daffodil/CLI/input/uuid.txt"),
+    file("daffodil-io/src/test/resources/iso8859.doc.dat"),
+    file("daffodil-japi/src/test/resources/test/japi/01very_simple.txt"),
+    file("daffodil-japi/src/test/resources/test/japi/myData.dat"),
+    file("daffodil-japi/src/test/resources/test/japi/myData2.dat"),
+    file("daffodil-japi/src/test/resources/test/japi/myData3.dat"),
+    file("daffodil-japi/src/test/resources/test/japi/myData4.dat"),
+    file("daffodil-japi/src/test/resources/test/japi/myData5.dat"),
+    file("daffodil-japi/src/test/resources/test/japi/myData16.dat"),
+    file("daffodil-japi/src/test/resources/test/japi/myData19.dat"),
+    file("daffodil-japi/src/test/resources/test/japi/myDataBroken.dat"),
+    file("daffodil-runtime2/src/test/resources/org/apache/daffodil/runtime2/data"),
+    file("daffodil-sapi/src/test/resources/test/sapi/01very_simple.txt"),
+    file("daffodil-sapi/src/test/resources/test/sapi/myData.dat"),
+    file("daffodil-sapi/src/test/resources/test/sapi/myData2.dat"),
+    file("daffodil-sapi/src/test/resources/test/sapi/myData3.dat"),
+    file("daffodil-sapi/src/test/resources/test/sapi/myData4.dat"),
+    file("daffodil-sapi/src/test/resources/test/sapi/myData5.dat"),
+    file("daffodil-sapi/src/test/resources/test/sapi/myData16.dat"),
+    file("daffodil-sapi/src/test/resources/test/sapi/myData19.dat"),
+    file("daffodil-sapi/src/test/resources/test/sapi/myDataBroken.dat"),
+    file("daffodil-tdml-lib/src/test/resources/test/tdml/test.bin"),
+    file("daffodil-tdml-lib/src/test/resources/test/tdml/test.txt"),
+    file("daffodil-tdml-processor/src/test/resources/test/tdml/test.bin"),
+    file("daffodil-tdml-processor/src/test/resources/test/tdml/test.txt"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000.0.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_green_to_orange_60000.1.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ISRM_orange_to_green_60002.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_green_to_orange_60004.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006.0.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/MPU_orange_to_green_60006.1.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/collisions.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.11.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.12.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.13.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.14.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.15.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.16.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.17.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.18.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.19.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/egress_xdcc_bw.20.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.111.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.112.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.113.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.114.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.115.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/ingress_xdcc_bw.116.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion.aptina.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion.camera.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion.command.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion.limits.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/runtime2/orion.video.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/section00/general/ext_file.txt"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/section00/general/ext_file2.txt"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/blobs/blob_01.bin"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/blobs/blob_02.bin"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/blobs/blob_03.bin"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/blobs/blob_04.bin"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/blobs/blob_07.bin"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/blobs/blob_13a.bin"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/blobs/blob_13b.bin"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/blobs/blob_13c.bin"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/section05/simple_types/blobs/blob_13d.bin"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/section06/entities/02nine_headers.txt"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_01.dat.xml.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_02.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_02.xml"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_03.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_04.xml"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_05.xml"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_06.xml"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_07.xml"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/namespaced/binMessage_08.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/nonamespace/binMessage_01.dat"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/infoset/stringAsXml/nonamespace/binMessage_01.dat.xml"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/usertests/Book2.csv"),
+    file("daffodil-test/src/test/resources/org/apache/daffodil/usertests/test_prefix_separator_as_variable"),
+    file("daffodil-test/src/test/resources/test space/A BTinyData.tdml.dat"),
+    file("daffodil-tdml-processor/src/test/resources/test/tdml/fake-precompiled-dfdl-schema.bin"),
+    file("test-stdLayout/src/test/resources/org1/test-outer-data1.txt"),
+    file("test-stdLayout/src/test/resources/org2/test-data1.txt"),
+  )
+
+  lazy val BSD2_LICENSE_NAME = "BSD 2-Clause License"
+
+  lazy val LICENSE_TEXT_PASSERA =
+"""
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""
+
+}
diff --git a/scripts/osgi-refactor/add-imports.scala b/scripts/osgi-refactor/add-imports.scala
new file mode 100644
index 000000000..e67d3b7b2
--- /dev/null
+++ b/scripts/osgi-refactor/add-imports.scala
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.io.BufferedWriter
+import java.io.FileWriter
+import java.io.File
+import scala.collection.mutable.ListBuffer
+import scala.io.Source
+
+object AddImports extends App {
+  val imports = Seq(
+    ("org.apache.daffodil.lib.api._", "daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/api/DFDLParserUnparser.scala"),
+    ("org.apache.daffodil.runtime1.dsom.walker._", "daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dpath/NodeInfo.scala"),
+    ("org.apache.daffodil.lib.externalvars._", "daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/externalvars/ExternalVariablesLoader.scala"),
+    ("org.apache.daffodil.udf._", "daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/udf/UserDefinedFunctionService.scala"),
+    ("org.apache.daffodil.runtime1.layers._", "daffodil-runtime1-layers/src/main/scala/org/apache/daffodil/layers/runtime1/Base64Transformer.scala"),
+    ("org.apache.daffodil.runtime1.layers._", "daffodil-runtime1-layers/src/main/scala/org/apache/daffodil/layers/runtime1/ByteSwapTransformer.scala"),
+    ("org.apache.daffodil.runtime1.layers._", "daffodil-runtime1-layers/src/main/scala/org/apache/daffodil/layers/runtime1/GZipTransformer.scala"),
+    ("org.apache.daffodil.runtime1.layers._", "daffodil-runtime1-layers/src/main/scala/org/apache/daffodil/layers/runtime1/LineFoldedTransformer.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/PackedBinaryUnparserTraits.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BCDUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/SpecifiedLengthUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BinaryBooleanUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BinaryNumberUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/BlobLengthUnparser.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/ChoiceAndOtherVariousUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/ConvertBinaryCalendarUnparser.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/ConvertNonBaseTenTextNumberUnparser.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/ConvertTextBooleanUnparser.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/ConvertTextCalendarUnparser.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/ConvertTextStandardNumberUnparser.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/ConvertZonedNumberUnparser.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/DelimitedUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/DelimiterUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/ElementUnparser.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/ExpressionEvaluatingUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/FramingUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/HexBinaryLengthUnparser.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/HiddenGroupCombinatorUnparser.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/IBM4690PackedDecimalUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/LayeredSequenceUnparser.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/NadaUnparser.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/NilEmptyCombinatorUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/NilUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/PackedDecimalUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/SeparatedSequenceUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/SequenceUnparserBases.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/SequenceChildUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/StreamSplitterMixin.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/StringLengthUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/SpecifiedLength2.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/SuppressableSeparatorUnparser.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-runtime1-unparser/src/main/scala/org/apache/daffodil/unparsers/runtime1/UnseparatedSequenceUnparsers.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaComponent.scala"),
+    ("org.apache.daffodil.runtime1.dpath._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/Conversions.scala"),
+    ("org.apache.daffodil.runtime1.dpath._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/DFDLExpressionParser.scala"),
+    ("org.apache.daffodil.runtime1.dpath._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/Expression.scala"),
+    ("org.apache.daffodil.runtime1.dpath.NodeInfo", "daffodil-core/src/main/scala/org/apache/daffodil/core/dpath/NodeInfoUtils.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/CompiledExpression.scala"),
+    ("org.apache.daffodil.runtime1.dpath.NodeInfo", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/CompiledExpression.scala"),
+    ("org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/runtime1/TermRuntime1Mixin.scala"),
+    ("org.apache.daffodil.runtime1.dpath.NodeInfo", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesExpressions.scala"),
+    ("org.apache.daffodil.runtime1.dpath.NodeInfo", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/DFDLEscapeScheme.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/DFDLSchemaFile.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/DFDLStatementMixin.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/RealTermMixin.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/ElementBase.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/RuntimePropertyMixins.scala"),
+    ("org.apache.daffodil.runtime1.dsom.walker._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/walker/AbstractDSOMWalker.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/Facets.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/RestrictionUnion.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/TermEncodingMixin.scala"),
+    ("org.apache.daffodil.unparsers.runtime1._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceChild.scala"),
+    ("org.apache.daffodil.unparsers.runtime1._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/ChoiceCombinator.scala"),
+    ("org.apache.daffodil.unparsers.runtime1._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/DelimiterAndEscapeRelated.scala"),
+    ("org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesExpressions.scala"),
+    ("org.apache.daffodil.unparsers.runtime1._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceCombinator.scala"),
+    ("org.apache.daffodil.unparsers.runtime1._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SpecifiedLength.scala"),
+    ("org.apache.daffodil.lib.util._", "daffodil-core/src/test/scala/org/apache/daffodil/core/util/TestUtils.scala"),
+    ("org.apache.daffodil.core.util._", "daffodil-core/src/test/scala/org/apache/daffodil/core/api/TestAPI1.scala"),
+    ("org.apache.daffodil.lib.api._", "daffodil-core/src/test/scala/org/apache/daffodil/core/api/TestForHeapDump.scala"),
+    ("org.apache.daffodil.runtime1.api._", "daffodil-core/src/test/scala/org/apache/daffodil/core/api/TestParseIndividualMessages.scala"),
+    ("org.apache.daffodil.runtime1.infoset._", "daffodil-core/src/test/scala/org/apache/daffodil/core/infoset/TestInfoset.scala"),
+    ("org.apache.daffodil.runtime1.dpath.NodeInfo", "daffodil-core/src/test/scala/org/apache/daffodil/core/dpath/TestDFDLExpressionEvaluation.scala"),
+    ("org.apache.daffodil.runtime1.dpath.NodeInfo", "daffodil-core/src/test/scala/org/apache/daffodil/core/dpath/TestDFDLExpressionTree.scala"),
+    ("org.apache.daffodil.runtime1.dpath._", "daffodil-core/src/test/scala/org/apache/daffodil/core/dpath/TestDFDLExpressionTree.scala"),
+    ("org.apache.daffodil.core.util._", "daffodil-core/src/test/scala/org/apache/daffodil/core/dsom/TestDsomCompiler.scala"),
+    ("org.apache.daffodil.core.util._", "daffodil-core/src/test/scala/org/apache/daffodil/core/dsom/TestDsomCompilerUnparse1.scala"),
+    ("org.apache.daffodil.core.util._", "daffodil-core/src/test/scala/org/apache/daffodil/core/dsom/TestInputValueCalc.scala"),
+    ("org.apache.daffodil.core.util._", "daffodil-core/src/test/scala/org/apache/daffodil/core/dsom/TestInteriorAlignmentElimination.scala"),
+    ("org.apache.daffodil.runtime1.debugger._", "daffodil-cli/src/main/scala/org/apache/daffodil/cli/debugger/CLIDebuggerRunner.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "daffodil-core/src/test/scala/org/apache/daffodil/core/dsom/TestIsScannable.scala"),
+    ("org.apache.daffodil.core.util._", "daffodil-core/src/test/scala/org/apache/daffodil/core/dsom/TestPolymorphicUpwardRelativeExpressions.scala"),
+    ("org.apache.daffodil.core.util._", "daffodil-core/src/test/scala/org/apache/daffodil/core/dsom/TestPropertyScoping.scala"),
+    ("org.apache.daffodil.core.util._", "daffodil-core/src/test/scala/org/apache/daffodil/core/dsom/TestSimpleTypeUnions.scala"),
+    ("org.apache.daffodil.core.dsom._", "daffodil-core/src/test/scala/org/apache/daffodil/core/util/TestUtils.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "daffodil-core/src/test/scala/org/apache/daffodil/core/dsom/TestSimpleTypeUnions.scala"),
+    ("org.apache.daffodil.runtime1.dsom.walker._", "daffodil-core/src/test/scala/org/apache/daffodil/core/dsom/walker/TestDSOMWalker.scala"),
+    ("org.apache.daffodil.core.util._", "daffodil-core/src/test/scala/org/apache/daffodil/core/infoset/TestInfoset2.scala"),
+    ("org.apache.daffodil.runtime1.infoset._", "daffodil-core/src/test/scala/org/apache/daffodil/core/infoset/TestInfosetCursor.scala"),
+    ("org.apache.daffodil.runtime1.infoset._", "daffodil-core/src/test/scala/org/apache/daffodil/core/infoset/TestInfosetCursor1.scala"),
+    ("org.apache.daffodil.runtime1.infoset._", "daffodil-core/src/test/scala/org/apache/daffodil/core/infoset/TestInfosetCursorFromReader.scala"),
+    ("org.apache.daffodil.runtime1.infoset._", "daffodil-core/src/test/scala/org/apache/daffodil/core/infoset/TestInfosetCursorFromReader2.scala"),
+    ("org.apache.daffodil.runtime1.infoset._", "daffodil-core/src/test/scala/org/apache/daffodil/core/infoset/TestInfosetFree.scala"),
+    ("org.apache.daffodil.lib.schema.annotation.props._", "daffodil-core/src/test/scala/org/apache/daffodil/core/schema/annotation/props/TestPropertyRuntime.scala"),
+    ("org.apache.daffodil.lib.xml._", "daffodil-core/src/test/scala/org/apache/daffodil/core/xml/TestXMLLoaderWithLocation.scala"),
+    ("org.apache.daffodil.io.processors.charset._", "daffodil-tdml-lib/src/test/scala/org/apache/daffodil/processors/charset/TestLSBFirstAndUSASCII7BitPacked.scala"),
+    ("org.apache.daffodil.tdml.TDMLException", "daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/TDMLInfosetInputter.scala"),
+    ("org.apache.daffodil.tdml.processor._", "daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/DaffodilTDMLDFDLProcessor.scala"),
+    ("org.apache.daffodil.tdml.processor._", "daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/Runtime2TDMLDFDLProcessor.scala"),
+    ("org.apache.daffodil.tdml.Runner", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestExtVars1.scala"),
+    ("org.apache.daffodil.tdml.Runner", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLCrossTest.scala"),
+    ("org.apache.daffodil.tdml.Runner", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRoundTrips.scala"),
+    ("org.apache.daffodil.tdml.Runner", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner2.scala"),
+    ("org.apache.daffodil.tdml.Runner", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunnerCommentSyntax.scala"),
+    ("org.apache.daffodil.tdml.Runner", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunnerConfig.scala"),
+    ("org.apache.daffodil.tdml.Runner", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner.scala"),
+    ("org.apache.daffodil.tdml.Runner", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner.scala"),
+    ("org.apache.daffodil.tdml.Runner", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunnerTutorial.scala"),
+    ("org.apache.daffodil.tdml.Runner", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunnerWarnings.scala"),
+    ("org.apache.daffodil.tdml.Runner", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLUnparseCases.scala"),
+    ("org.apache.daffodil.tdml.Runner;", "daffodil-tdml-processor/src/test/java/org/apache/daffodil/processor/tdml/TestRunnerFactory.java"),
+    ("org.apache.daffodil.tdml.NoRoundTrip$;", "daffodil-tdml-processor/src/test/java/org/apache/daffodil/processor/tdml/TestRunnerFactory.java"),
+    ("org.apache.daffodil.tdml._", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLCrossTest.scala"),
+    ("org.apache.daffodil.tdml._", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRoundTrips.scala"),
+    ("org.apache.daffodil.tdml._", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner.scala"),
+    ("org.apache.daffodil.tdml._", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLUnparseCases.scala"),
+    ("org.apache.daffodil.tdml.Document", "daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/TestTDMLRunner2.scala"),
+  )
+
+  var importsToRemove = Seq(
+    ("org.apache.daffodil.core.dsom.walker._", "daffodil-runtime1/src/main/scala/org/apache/daffodil/runtime1/dpath/NodeInfo.scala"),
+    ("org.apache.daffodil.dpath._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/DFDLEscapeScheme.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/DelimiterAndEscapeRelated.scala"),
+    ("org.apache.daffodil.runtime1.processors.unparsers._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceChild.scala"),
+    ("org.apache.daffodil.dpath._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesExpressions.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "daffodil-core/src/test/scala/org/apache/daffodil/core/util/TestUtils.scala"),
+    ("org.apache.daffodil.processor.tdml.tdml.TDMLInfosetInputter", "daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/DaffodilTDMLDFDLProcessor.scala"),
+    ("org.apache.daffodil.processor.tdml.tdml.TDMLInfosetOutputter", "daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/DaffodilTDMLDFDLProcessor.scala"),
+  )
+
+  var importsToReplace = Seq(
+    ("org.apache.daffodil.dpath._", "org.apache.daffodil.core.dpath._", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/CompiledExpression.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/Grammar.scala"),
+    ("org.apache.daffodil.runtime1.dsom.IIUtils.IIMap", "org.apache.daffodil.core.dsom.IIUtils.IIMap", "daffodil-core/src/main/scala/org/apache/daffodil/core/dsom/SchemaDocument.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/GrammarMixin.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesDelimiters.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesNil.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/DelimiterAndEscapeRelated.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/SequenceGrammarMixin.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/ByteOrderMixin.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesTextNumber.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/PrimitivesZoned.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/LayeredSequence.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceChild.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/SequenceCombinator.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/ChoiceCombinator.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/main/scala/org/apache/daffodil/core/grammar/primitives/Primitives.scala"),
+    ("org.apache.daffodil.lib.api._", "org.apache.daffodil.runtime1.api._", "daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/DaffodilTDMLDFDLProcessor.scala"),
+    ("org.apache.daffodil.runtime1.infoset.TestInfoset", "org.apache.daffodil.core.infoset.TestInfoset", "daffodil-core/src/test/scala/org/apache/daffodil/core/dpath/TestDFDLExpressionEvaluation.scala"),
+    ("org.apache.daffodil.runtime1.dsom._", "org.apache.daffodil.core.dsom._", "daffodil-core/src/test/scala/org/apache/daffodil/core/grammar/TestGrammar.scala"),
+    ("org.apache.daffodil.validation.Validators;", "org.apache.daffodil.lib.validation.Validators;", "daffodil-japi/src/test/java/org/apache/daffodil/example/ValidatorSpiExample.java"),
+  )
+
+  var importsToAddLast = Seq(
+    ("org.apache.daffodil.lib.api._", "daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml/DaffodilTDMLDFDLProcessor.scala"),
+  )
+
+  def addImports(name: String, file: File) = {
+    val source = Source.fromFile(file)
+    val output = ListBuffer.empty[String]
+    for (line <- source.getLines()) {
+      output += line
+      if (line.startsWith("package")) {
+        output += s"\nimport ${name}"
+      }
+    }
+    source.close
+
+    val out = new BufferedWriter(new FileWriter(file))
+    for (line <- output) out.write(line + "\n")
+    out.close
+  }
+
+  def removeImports(name: String, file: File) = {
+    val source = Source.fromFile(file)
+    val output = ListBuffer.empty[String]
+    for (line <- source.getLines()) {
+      if (!line.startsWith(s"import $name")) {
+        output += line
+      }
+    }
+    source.close
+
+    val out = new BufferedWriter(new FileWriter(file))
+    for (line <- output) out.write(line + "\n")
+    out.close
+  }
+
+  def replaceImports(nameFrom: String, nameTo: String, file: File) = {
+    val source = Source.fromFile(file)
+    val output = ListBuffer.empty[String]
+    for (line <- source.getLines()) {
+      if (line.startsWith(s"import $nameFrom")) {
+        output += s"import $nameTo"
+      } else {
+        output += line
+      }
+    }
+    source.close
+
+    val out = new BufferedWriter(new FileWriter(file))
+    for (line <- output) out.write(line + "\n")
+    out.close
+  }
+
+  val rootDir = args(0)
+  for ((name, fileName) <- imports) {
+    val file = new File(rootDir, fileName)
+    addImports(name, file)
+  }
+  for ((name, fileName) <- importsToRemove) {
+    val file = new File(rootDir, fileName)
+    removeImports(name, file)
+  }
+  for ((nameFrom, nameTo, fileName) <- importsToReplace) {
+    val file = new File(rootDir, fileName)
+    replaceImports(nameFrom, nameTo, file)
+  }
+  for ((name, fileName) <- importsToAddLast) {
+    val file = new File(rootDir, fileName)
+    addImports(name, file)
+  }
+}
diff --git a/scripts/osgi-refactor/fix-gen.sh b/scripts/osgi-refactor/fix-gen.sh
new file mode 100755
index 000000000..90995e494
--- /dev/null
+++ b/scripts/osgi-refactor/fix-gen.sh
@@ -0,0 +1,45 @@
+#!/bin/bash -ex
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cd $(dirname $0)/../..
+
+rm -rf daffodil-lib/src_managed/*
+
+cd daffodil-propgen/src/main/scala/org/apache/daffodil/propGen
+
+sed -i 's/org.apache.daffodil.api/org.apache.daffodil.lib.api/g' \
+    PropertyGenerator.scala
+
+sed -i 's/org.apache.daffodil.api/org.apache.daffodil.lib.api/g' \
+    TunableGenerator.scala \
+    WarnIDGenerator.scala
+
+sed -i 's/org.apache.daffodil.exceptions/org.apache.daffodil.lib.exceptions/g' \
+    PropertyGenerator.scala \
+    TunableGenerator.scala \
+    WarnIDGenerator.scala
+
+sed -i 's/org.apache.daffodil.schema/org.apache.daffodil.lib.schema/g' \
+    PropertyGenerator.scala \
+    TunableGenerator.scala \
+    WarnIDGenerator.scala
+
+sed -i 's/org.apache.daffodil.util/org.apache.daffodil.lib.util/g' \
+    TunableGenerator.scala
+
+sed -i 's/org.apache.daffodil.xml/org.apache.daffodil.lib.xml/g' \
+    TunableGenerator.scala
diff --git a/scripts/osgi-refactor/fix-imports.scala b/scripts/osgi-refactor/fix-imports.scala
new file mode 100644
index 000000000..e970b8c96
--- /dev/null
+++ b/scripts/osgi-refactor/fix-imports.scala
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.io.BufferedWriter
+import java.io.FileWriter
+import java.io.File
+import scala.collection.mutable.ListBuffer
+import scala.collection.mutable.Map
+import scala.io.Source
+
+object FixImports extends App {
+  val inline = true
+  val importMap = Map(
+    "daffodil-cli" -> "cli",
+    "daffodil-core" -> "core",
+    "daffodil-io" -> "io",
+    "daffodil-lib" -> "lib",
+    "daffodil-macro-lib" -> "lib",
+    "daffodil-runtime1" -> "runtime1",
+    "daffodil-runtime1-layers" -> "layers.runtime1",
+    "daffodil-runtime1-unparser" -> "unparsers.runtime1",
+    "daffodil-tdml-processor" -> "processor.tdml"
+  )
+  val removeSuffix = Map(
+    "daffodil-runtime1-layers" -> "layers",
+    "daffodil-runtime1-unparser" -> "processors.unparsers",
+    "daffodil-tdml-processor" -> "tdml.processor",
+  )
+
+  def loadSymbolTable(file: File): Map[String, String] = {
+    val source = Source.fromFile(file)
+    val symbols = Map.empty[String, String]
+    for (line <- source.getLines()) {
+      val parts = line.split(":")
+      val libName = parts(0)
+      var packageName = parts(1)
+      symbols += packageName -> libName
+      symbols += s"${packageName}._" -> libName
+    }
+    symbols ++= Map(
+      "org.apache.daffodil.Main.ExitCode" -> "daffodil-cli",
+      "org.apache.daffodil.CLI.Util._" -> "daffodil-cli",
+      "org.apache.daffodil.compiler._" -> "daffodil-core",
+      "org.apache.daffodil.dsom.walker._" -> "daffodil-core",
+      "org.apache.daffodil.equality._" -> "daffodil-lib",
+      "org.apache.daffodil.equality.TypeEqual" -> "daffodil-lib",
+      "org.apache.daffodil.equality.ViewEqual" -> "daffodil-lib",
+      "org.apache.daffodil.exceptions._" -> "daffodil-lib",
+      "org.apache.daffodil.Implicits.intercept" -> "daffodil-lib",
+      "org.apache.daffodil.infoset._" -> "daffodil-runtime1",
+      "org.apache.daffodil.oolag.OOLAG.OOLAGHost" -> "daffodil-lib",
+      "org.apache.daffodil.oolag.OOLAG.OOLAGHostImpl" -> "daffodil-lib",
+      "org.apache.daffodil.processors._" -> "daffodil-runtime1",
+      "org.apache.daffodil.processors.dfa" -> "daffodil-runtime1",
+      "org.apache.daffodil.processors.parsers._" -> "daffodil-runtime1",
+      "org.apache.daffodil.schema.annotation.props._" -> "daffodil-lib",
+      "org.apache.daffodil.schema.annotation.props.gen._" -> "daffodil-lib",
+      "org.apache.daffodil.util._" -> "daffodil-lib",
+      "org.apache.daffodil.util.Implicits.using" -> "daffodil-lib",
+      "org.apache.daffodil.util.Maybe.Nope" -> "daffodil-lib",
+      "org.apache.daffodil.util.Maybe.One" -> "daffodil-lib",
+      "org.apache.daffodil.util.Misc.hex2Bits" -> "daffodil-lib",
+      "org.apache.daffodil.util.Misc.bits2Bytes" -> "daffodil-lib",
+      "org.apache.daffodil.util.Numbers._" -> "daffodil-lib",
+      "org.apache.daffodil.validation.XercesValidator.XercesValidatorImpl" -> "daffodil-lib",
+      "org.apache.daffodil.xml._" -> "daffodil-lib",
+      "org.apache.daffodil.xml.NS.implicitNStoString" -> "daffodil-lib",
+      "org.apache.daffodil.xml.QNameRegex" -> "daffodil-lib",
+    )
+    symbols
+  }
+
+  def updateName(libName: String, packageNameParam: String): String = {
+    var packageName = packageNameParam
+    importMap.get(libName) match {
+      case Some(sub) => {
+        removeSuffix.get(libName) match {
+          case Some(toRemove) => packageName = packageName.replace(s".$toRemove", "")
+          case None =>
+        }
+        val newPrefix = s"org.apache.daffodil.$sub"
+        if (packageName.startsWith(newPrefix)) packageName
+        else packageName.replace("org.apache.daffodil", newPrefix)
+      }
+      case None => packageName
+    }
+  }
+
+  def fixPackage(libName: String, packageName: String): String = {
+    updateName(libName, packageName)
+  }
+
+  def fixImport(name: String, symbols: Map[String, String]): String = {
+    symbols.get(name) match {
+      case Some(libName) => updateName(libName, name)
+      case None => name
+    }
+  }
+
+  val reImports = """^ ?import (.+)$""".r
+  val rePackage = """^ ?package (.+)$""".r
+
+  def fixLine(libName: String, line: String, symbols: Map[String,String]) = {
+      line match {
+        case rePackage(name) => s"package ${fixPackage(libName, name)}"
+        case reImports(name) => s"import ${fixImport(name, symbols)}"
+        case _ => line
+      }
+  }
+
+  val replacements = Seq(
+    ("new org.apache.daffodil.xml", "new org.apache.daffodil.lib.xml"),
+    ("org.apache.daffodil.schema.annotation.props.gen.{ BinaryNumberCheckPolicy, TextZonedSignStyle }", "org.apache.daffodil.lib.schema.annotation.props.gen.{ BinaryNumberCheckPolicy, TextZonedSignStyle }"),
+    ("import org.apache.daffodil.util.MaybeULong", "import org.apache.daffodil.lib.util.MaybeULong"),
+    ("import org.apache.daffodil.Implicits._", "import org.apache.daffodil.lib.Implicits._"),
+    ("import org.apache.daffodil.infoset.DataValue", "import org.apache.daffodil.runtime1.infoset.DataValue"),
+    ("org.apache.daffodil.api", "org.apache.daffodil.lib.api"),
+    ("org.apache.daffodil.calendar", "org.apache.daffodil.lib.calendar"),
+    ("org.apache.daffodil.dpath.NodeInfo", "org.apache.daffodil.runtime1.dpath.NodeInfo"),
+    ("org.apache.daffodil.dsom", "org.apache.daffodil.runtime1.dsom"),
+    ("org.apache.daffodil.equality", "org.apache.daffodil.lib.equality"),
+    ("org.apache.daffodil.exceptions", "org.apache.daffodil.lib.exceptions"),
+    ("org.apache.daffodil.infoset", "org.apache.daffodil.runtime1.infoset"),
+    ("org.apache.daffodil.Implicits", "org.apache.daffodil.lib.Implicits"),
+    ("org.apache.daffodil.processors", "org.apache.daffodil.runtime1.processors"),
+    ("org.apache.daffodil.schema", "org.apache.daffodil.lib.schema"),
+    ("org.apache.daffodil.xml", "org.apache.daffodil.lib.xml"),
+    ("org.apache.daffodil.udf.UserDefinedFunctionService", "org.apache.daffodil.runtime1.udf.UserDefinedFunctionService"),
+    ("org.apache.daffodil.util", "org.apache.daffodil.lib.util"),
+    ("org.apache.daffodil.grammar", "org.apache.daffodil.core.grammar"),
+    ("org.apache.daffodil.lib.api.DFDL", "org.apache.daffodil.runtime1.api.DFDL"),
+    ("import org.apache.daffodil.runtime1.dsom.{ChoiceTermBase, GroupRef, InitiatedTerminatedMixin, ModelGroup, SequenceTermBase}", "import org.apache.daffodil.core.dsom.{ChoiceTermBase, GroupRef, InitiatedTerminatedMixin, ModelGroup, SequenceTermBase}"),
+    ("org.apache.daffodil.compiler", "org.apache.daffodil.core.compiler"),
+    ("import org.apache.daffodil.debugger", "import org.apache.daffodil.runtime1.debugger"),
+    ("org.apache.daffodil.lib.util.TestUtils", "org.apache.daffodil.core.util.TestUtils"),
+    ("org.apache.daffodil.lib.util.Fakes", "org.apache.daffodil.core.util.Fakes"),
+    ("org.apache.daffodil.runtime1.dsom.{ ElementBase, Root }", "org.apache.daffodil.core.dsom.{ ElementBase, Root }"),
+    ("org.apache.daffodil.lib.util.StreamParser", "org.apache.daffodil.core.util.StreamParser"),
+    ("org.apache.daffodil.cli.CLI.Util._", "org.apache.daffodil.cli.cliTest.Util._"),
+    ("package org.apache.daffodil.cli.CLI", "package org.apache.daffodil.cli.cliTest"),
+    ("case TDMLImplementation.Daffodil => \"org.apache.daffodil.tdml.processor.TDMLDFDLProcessorFactory\"", "case TDMLImplementation.Daffodil => \"org.apache.daffodil.processor.tdml.TDMLDFDLProcessorFactory\""),
+    ("case TDMLImplementation.DaffodilC => \"org.apache.daffodil.tdml.processor.Runtime2TDMLDFDLProcessorFactory\"", "case TDMLImplementation.DaffodilC => \"org.apache.daffodil.processor.tdml.Runtime2TDMLDFDLProcessorFactory\""),
+    ("case TDMLImplementation.Ibm => \"org.apache.daffodil.tdml.processor.TDMLDFDLProcessorFactory\"", "case TDMLImplementation.Ibm => \"org.apache.daffodil.processor.tdml.TDMLDFDLProcessorFactory\""),
+    ("private[tdml] def getTS = this.synchronized {", "def getTS = this.synchronized {"),
+    ("package org.apache.daffodil.processor.tdml.tdml;", "package org.apache.daffodil.processor.tdml;")
+  )
+
+  def applyReplacements(line: String): String = {
+    var applied = line
+    for (replacement <- replacements) {
+      val (from, to) = replacement
+      applied = applied.replace(from, to)
+    }
+    applied
+  }
+
+  def fixFile(libNameParam: String, file: File, symbols: Map[String, String]): Unit = {
+    val path = file.getPath
+    if (path.endsWith(".refactor.scala")) return
+    if (path.contains("propGen")) return
+    if (file.getName == "PointOfUncertaintyMacros.scala") return
+    val libName = if (file.getName == "IOMacros.scala") "io" else libNameParam
+    val source = Source.fromFile(file)
+    val fixed = ListBuffer.empty[String]
+    for (line <- source.getLines()) {
+      fixed += applyReplacements(fixLine(libName, line, symbols))
+    }
+    source.close
+
+    val outName = if (inline) file.getPath() else file.getPath().replace(".scala", ".refactor.scala")
+    val out = new BufferedWriter(new FileWriter(outName))
+    for (line <- fixed) out.write(line + "\n")
+    out.close
+  }
+
+  def processDir(libName: String, path: File, symbols: Map[String,String]): Unit = {
+    for (file <- path.listFiles) {
+      if (file.isDirectory) processDir(libName, file, symbols)
+      if (file.getName.endsWith(".scala") || file.getName.endsWith(".java")) fixFile(libName, file, symbols)
+    }
+  }
+
+  def processLib(libPath: String, symbols: Map[String,String]) = {
+    var path = new File(libPath)
+    val libName = path.getName
+    processDir(libName, path, symbols)
+  }
+
+  val symbolFile = new File(args(0))
+  val symbols = loadSymbolTable(symbolFile)
+
+  var libPaths = args.drop(1)
+  for (libPath <- libPaths) {
+    processLib(libPath, symbols)
+  }
+}
diff --git a/scripts/osgi-refactor/gen-symbol-table.scala b/scripts/osgi-refactor/gen-symbol-table.scala
new file mode 100644
index 000000000..306284e7a
--- /dev/null
+++ b/scripts/osgi-refactor/gen-symbol-table.scala
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import java.io.File
+import scala.collection.mutable.ListBuffer
+import scala.io.Source
+import scala.util.matching.Regex
+
+class Symbols(
+  val libraryName: String,
+  val fileName: String,
+  val packageName: String,
+  val exports: List[String]
+)
+
+object GenSymbolTable extends App {
+  val ignoreFiles = List(
+    "daffodil-runtime1/src/main/scala/org/apache/daffodil/reflection/FieldFinder.scala"
+  )
+
+  val rePackage: Regex = """package ([\w\.]+)""".r
+
+  def parsePackageName(lines: Iterator[String]): String = {
+    for (line <- lines) {
+      rePackage.findFirstMatchIn(line) match {
+        case Some(name) => return name.group(1)
+        case None =>
+      }
+    }
+    throw new Exception("expected package name but not found")
+  }
+
+  val reExports = List(
+    "^(?:abstract |case |final |sealed |implict |lazy )* ?class ([\\w\\.]+)".r,
+    "^(?:abstract |case |final |sealed |implict |lazy )* ?object ([\\w\\.]+)".r,
+    "^(?:abstract |case |final |sealed |implict |lazy )* ?trait ([\\w\\.]+)".r
+  )
+
+  def parseExports(lines: Iterator[String]): List[String] = {
+    val exports = ListBuffer.empty[String]
+    for (line <- lines) {
+      for (regexp <- reExports) {
+        regexp.findFirstMatchIn(line) match {
+          case Some(name) => exports += name.group(1)
+          case None =>
+        }
+      }
+    }
+    exports.toList
+  }
+
+  val reLineComment = "//.*".r
+  val reBlockStartComment: Regex = """^.*(\/\*).*$""".r
+  val reBlockEndComment: Regex = """^.*(\*\/).*$""".r
+
+  def cleanFile(file: File): List[String] = {
+    val cleaned = ListBuffer.empty[String]
+    val source = Source.fromFile(file)
+
+    var inBlockComment = false
+    var exitingBlockComment = false
+    for (actual <- source.getLines()) {
+      exitingBlockComment = false
+      val line = reLineComment.replaceFirstIn(actual, "")
+      line match {
+        case reBlockStartComment(_) => inBlockComment = true
+        case reBlockEndComment(_) => exitingBlockComment = true
+        case _ =>
+      }
+      if (!inBlockComment) cleaned += line
+      if (exitingBlockComment) inBlockComment = false
+    }
+    source.close
+    cleaned.toList
+  }
+
+  def processFile(libraryName: String, file: File): Option[Symbols] = {
+    ignoreFiles.find(file.toString.endsWith(_)) match {
+      case Some(_) => return None
+      case _ =>
+    }
+    try {
+      val iter = cleanFile(file).iterator
+      val packageName = parsePackageName(iter)
+      val exports = parseExports(iter)
+      Some(new Symbols(libraryName, file.toString, packageName, exports))
+    } catch {
+      case e: Exception => throw new Exception(s"while processing file: $file", e)
+    }
+  }
+
+  def processDir(libraryName: String, dir: File): List[Symbols] = {
+    val symbols = ListBuffer.empty[Symbols]
+    val files = dir.listFiles()
+    for (file <- files) {
+      val name = file.getName
+      if (name.startsWith("Test") || name == "test") {}
+      else if (file.isDirectory) symbols ++= processDir(libraryName, file)
+      else if (name.endsWith(".scala") || name.endsWith(".java")) {
+        processFile(libraryName, file) match {
+          case Some(s) => symbols += s
+          case _ =>
+        }
+      }
+    }
+    symbols.toList
+  }
+
+  def processLibrary(dir: File): List[Symbols] = {
+    val libraryName = dir.getName
+    processDir(libraryName, dir)
+  }
+
+  for (arg <- args) {
+    val libraryDir = new File(arg)
+    val symbols = processLibrary(libraryDir)
+    for (symbol <- symbols) {
+      for (export <- symbol.exports) println(s"${symbol.libraryName}:${symbol.packageName}.${export}")
+    }
+  }
+}
diff --git a/scripts/osgi-refactor/git-restore.sh b/scripts/osgi-refactor/git-restore.sh
new file mode 100755
index 000000000..1309f2da4
--- /dev/null
+++ b/scripts/osgi-refactor/git-restore.sh
@@ -0,0 +1,67 @@
+#!/bin/bash -ex
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+BASE_DIR="$(dirname $0)/../.."
+SRC_ROOT=src/main/scala/org/apache/daffodil
+TEST_ROOT=src/test/scala/org/apache/daffodil
+
+cd $BASE_DIR
+
+function clean {
+    lib_name=$1
+    target_dir=$2
+
+    rm -rf $lib_name/$SRC_ROOT/$target_dir
+    rm -rf $lib_name/$TEST_ROOT/$target_dir
+}
+
+git restore daffodil-*
+
+clean daffodil-cli cli
+clean daffodil-core core
+# clean daffodil-io io (SKIP)
+clean daffodil-lib lib
+clean daffodil-macro-lib lib
+clean daffodil-runtime1 runtime1
+# clean daffodil-runtime1-layers layers (SKIP)
+clean daffodil-runtime1-unparser unparsers
+
+rm -rf daffodil-io/src/{main,test}/scala/org/apache/daffodil/io/{layers,processors}
+rm -rf daffodil-runtime1-layers/src/{main,test}/scala/org/apache/daffodil/layers/runtime1
+rm -rf daffodil-macro-lib/src/main/scala/org/apache/daffodil/runtime1
+rm -rf daffodil-lib/src/main/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory
+rm -rf daffodil-runtime1-layers/src/main/resources/META-INF/services/org.apache.daffodil.runtime1.layers.LayerCompiler
+rm -rf daffodil-io/src/main/resources/META-INF/services/org.apache.daffodil.io.processors.charset.BitsCharsetDefinition
+rm -rf daffodil-lib/src/test/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory
+rm -rf daffodil-test/src/test/scala/org/apache/daffodil/runtime1
+rm -rf daffodil-japi/src/test/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory
+rm -rf daffodil-sapi/src/test/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory
+rm -rf daffodil-schematron/src/main/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory
+rm -rf daffodil-test/src/test/resources/META-INF/services/org.apache.daffodil.io.processors.charset.BitsCharsetDefinition
+rm -rf daffodil-test/src/test/resources/META-INF/services/org.apache.daffodil.runtime1.layers.LayerCompiler
+rm -rf daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tak
+rm -rf daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor
+rm -rf daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor
+rm -rf daffodil-tdml-processor/src/test/java/org/apache/daffodil/processor
+rm -rf daffodil-cli/src/test/resources/org/apache/daffodil/cli
+
+find . -name "*.refactor.scala" -delete
+
+git restore project/Rat.scala
+
+rm -rf daffodil-lib/src_managed/*
+sbt genProps
diff --git a/scripts/osgi-refactor/refactor.sh b/scripts/osgi-refactor/refactor.sh
new file mode 100755
index 000000000..221d48e0b
--- /dev/null
+++ b/scripts/osgi-refactor/refactor.sh
@@ -0,0 +1,28 @@
+#!/bin/bash -ex
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cd $(dirname $0)/../..
+REFACTOR_DIR=scripts/osgi-refactor
+
+$REFACTOR_DIR/git-restore.sh
+scala $REFACTOR_DIR/gen-symbol-table.scala daffodil-* > $REFACTOR_DIR/symbols.txt
+$REFACTOR_DIR/rename-dirs.sh
+$REFACTOR_DIR/fix-gen.sh
+scala $REFACTOR_DIR/fix-imports.scala $REFACTOR_DIR/symbols.txt daffodil-*
+scala $REFACTOR_DIR/add-imports.scala .
+sbt genProps
+rm -f $REFACTOR_DIR/symbols.txt
diff --git a/scripts/osgi-refactor/rename-dirs.sh b/scripts/osgi-refactor/rename-dirs.sh
new file mode 100755
index 000000000..987fd0325
--- /dev/null
+++ b/scripts/osgi-refactor/rename-dirs.sh
@@ -0,0 +1,154 @@
+#!/bin/bash -ex
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cd "$(dirname $0)/../.."
+SRC_ROOT=src/main/scala/org/apache/daffodil
+TEST_ROOT=src/test/scala/org/apache/daffodil
+
+function move {
+    local source_dir=$1
+    local target_dir=$2
+    local tmp=/tmp/daffodil-refactor
+
+    rm -rf $tmp
+    mkdir $tmp
+    mv $source_dir/* $tmp
+    rmdir $source_dir
+    mkdir -p $target_dir
+    mv $tmp/* $target_dir
+    rm -rf $tmp
+}
+
+function rename {
+    local lib_name=$1
+    local target_dir=$2
+    local source_suffix=$3
+    (
+        cd $lib_name
+        move $SRC_ROOT/$source_suffix $SRC_ROOT/$target_dir
+
+        if [ -e $TEST_ROOT/$source_suffix ]; then
+            move $TEST_ROOT/$source_suffix $TEST_ROOT/$target_dir
+        fi
+    )
+}
+
+cp scripts/osgi-refactor/Rat.scala project/Rat.scala
+
+rename daffodil-cli cli
+rename daffodil-core core
+rename daffodil-lib lib
+rename daffodil-macro-lib lib
+rename daffodil-runtime1 runtime1
+rename daffodil-runtime1-layers layers/runtime1 layers
+rename daffodil-runtime1-unparser unparsers/runtime1 processors/unparsers
+rename daffodil-tdml-processor processor/tdml tdml/processor
+
+mv daffodil-io/src/main/scala/org/apache/daffodil/processors \
+   daffodil-io/src/main/scala/org/apache/daffodil/io
+mv daffodil-cli/src/test/scala/org/apache/daffodil/cli/CLI/* \
+   daffodil-cli/src/test/scala/org/apache/daffodil/cli/cliTest
+rmdir  daffodil-cli/src/test/scala/org/apache/daffodil/cli/CLI
+mv daffodil-cli/src/test/resources/org/apache/daffodil/CLI \
+   daffodil-cli/src/test/resources/org/apache/daffodil/cli
+find daffodil-cli/src/test/scala -name "*.scala" -exec sed -i "s_/CLI/_/cli/_g" {} \;
+sed -i "s_/CLI/_/cli/_g" project/Rat.scala
+
+mkdir -p daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tak
+mv daffodil-tdml-lib/src/main/scala/org/apache/daffodil/Tak.scala \
+   daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tak/Tak.scala
+sed -i 's/package org.apache.daffodil/package org.apache.daffodil.tak/' daffodil-tdml-lib/src/main/scala/org/apache/daffodil/tak/Tak.scala
+
+sed -i 's/package org.apache.daffodil.tdml/package org.apache.daffodil.processor.tdml/' daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/*.scala
+mv daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml/*.scala daffodil-tdml-processor/src/main/scala/org/apache/daffodil/processor/tdml
+rmdir daffodil-tdml-processor/src/main/scala/org/apache/daffodil/tdml
+
+rmdir daffodil-runtime1-unparser/$SRC_ROOT/processors
+
+move daffodil-tdml-processor/src/test/scala/org/apache/daffodil/tdml \
+     daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml
+sed -i 's/package org.apache.daffodil.tdml/package org.apache.daffodil.processor.tdml/' \
+    daffodil-tdml-processor/src/test/scala/org/apache/daffodil/processor/tdml/*
+move daffodil-tdml-processor/src/test/java/org/apache/daffodil/tdml \
+     daffodil-tdml-processor/src/test/java/org/apache/daffodil/processor/tdml
+
+mv daffodil-macro-lib/src/main/scala/org/apache/daffodil/lib/io \
+   daffodil-macro-lib/src/main/scala/org/apache/daffodil/io
+
+mkdir daffodil-macro-lib/src/main/scala/org/apache/daffodil/runtime1
+mv daffodil-macro-lib/src/main/scala/org/apache/daffodil/lib/processors \
+   daffodil-macro-lib/src/main/scala/org/apache/daffodil/runtime1/processors
+sed -i 's/org.apache.daffodil.processors.parsers/org.apache.daffodil.runtime1.processors.parsers/' daffodil-macro-lib/src/main/scala/org/apache/daffodil/runtime1/processors/parsers/PointOfUncertaintyMacros.scala
+
+mv daffodil-lib/src/main/resources/META-INF/services/org.apache.daffodil.api.ValidatorFactory daffodil-lib/src/main/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory
+sed -i 's/org.apache.daffodil.validation.XercesValidatorFactory/org.apache.daffodil.lib.validation.XercesValidatorFactory/' daffodil-lib/src/main/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory
+
+mv daffodil-lib/src/test/resources/META-INF/services/org.apache.daffodil.api.ValidatorFactory \
+   daffodil-lib/src/test/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory
+sed -i 's/org.apache.daffodil.validation/org.apache.daffodil.lib.validation/' daffodil-lib/src/test/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory
+
+mv \
+   daffodil-io/src/main/resources/META-INF/services/org.apache.daffodil.processors.charset.BitsCharsetDefinition \
+   daffodil-io/src/main/resources/META-INF/services/org.apache.daffodil.io.processors.charset.BitsCharsetDefinition
+sed -i 's/org.apache.daffodil.processors.charset/org.apache.daffodil.io.processors.charset/' \
+   daffodil-io/src/main/resources/META-INF/services/org.apache.daffodil.io.processors.charset.BitsCharsetDefinition
+
+mv \
+   daffodil-runtime1-layers/src/main/resources/META-INF/services/org.apache.daffodil.layers.LayerCompiler \
+   daffodil-runtime1-layers/src/main/resources/META-INF/services/org.apache.daffodil.runtime1.layers.LayerCompiler
+sed -i 's/org.apache.daffodil.layers/org.apache.daffodil.layers.runtime1/' daffodil-runtime1-layers/src/main/resources/META-INF/services/org.apache.daffodil.runtime1.layers.LayerCompiler
+
+mv \
+   daffodil-schematron/src/main/resources/META-INF/services/org.apache.daffodil.api.ValidatorFactory \
+   daffodil-schematron/src/main/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory
+
+mv \
+   daffodil-japi/src/test/resources/META-INF/services/org.apache.daffodil.api.ValidatorFactory \
+   daffodil-japi/src/test/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory
+
+mv \
+   daffodil-sapi/src/test/resources/META-INF/services/org.apache.daffodil.api.ValidatorFactory \
+   daffodil-sapi/src/test/resources/META-INF/services/org.apache.daffodil.lib.api.ValidatorFactory
+
+mv \
+   daffodil-test/src/test/resources/META-INF/services/org.apache.daffodil.layers.LayerCompiler \
+   daffodil-test/src/test/resources/META-INF/services/org.apache.daffodil.runtime1.layers.LayerCompiler
+sed -i 's/org.apache.daffodil.layers/org.apache.daffodil.runtime1.layers/' daffodil-test/src/test/resources/META-INF/services/org.apache.daffodil.runtime1.layers.LayerCompiler
+
+mv \
+   daffodil-test/src/test/resources/META-INF/services/org.apache.daffodil.processors.charset.BitsCharsetDefinition \
+   daffodil-test/src/test/resources/META-INF/services/org.apache.daffodil.io.processors.charset.BitsCharsetDefinition
+
+
+mkdir \
+   daffodil-test/src/test/scala/org/apache/daffodil/runtime1
+mv \
+   daffodil-test/src/test/scala/org/apache/daffodil/layers \
+   daffodil-test/src/test/scala/org/apache/daffodil/runtime1
+sed -i 's/package org.apache.daffodil.layers/package org.apache.daffodil.runtime1.layers/' \
+   daffodil-test/src/test/scala/org/apache/daffodil/runtime1/layers/*
+
+sed -i 's_org/apache/daffodil/schema_org/apache/daffodil/lib/schema_' \
+   daffodil-propgen/src/test/scala/org/apache/daffodil/propGen/TestPropertyGenerator.scala
+sed -i 's_org/apache/daffodil/api_org/apache/daffodil/lib/api_' \
+   daffodil-propgen/src/test/scala/org/apache/daffodil/propGen/TestPropertyGenerator.scala
+
+sed -i 's/org.apache.daffodil.validation.XercesValidator/org.apache.daffodil.lib.validation.XercesValidator/' \
+    daffodil-lib/src/main/scala/org/apache/daffodil/lib/api/Validator.scala
+
+sed -i 's/org.apache.daffodil.Main/org.apache.daffodil.cli.Main/' \
+    daffodil-cli/src/templates/*