/**
     * Such classes do not extend {@link TestCase} and simply use the Test annotation to denote
     * their tests.
     *
     * @param suite
     * @param suiteKlazz
     */
    private static void addJUnit4TestClass(TestSuite suite, Class<?> klazz) {
      if (!hasJUnit4AnnotateTestMethods(klazz)) {
        TestDesignerPlugin.logWarning(
            "Test Class "
                + klazz.getSimpleName()
                + " tagged for testing but has no annotated Test methods"); //$NON-NLS-1$
                                                                            // //$NON-NLS-2$
        return;
      }

      JUnit4TestAdapter testAdapter = new JUnit4TestAdapter(klazz);
      suite.addTest(testAdapter);
    }
    /**
     * @param parentSuite
     * @param bundle
     * @return
     */
    private static void collectTests(TestSuite parentSuite, Bundle bundle) {

      Enumeration<URL> entries =
          bundle.findEntries("/", "AllTests.class", true); // $NON-NLS-1$ //$NON-NLS-2$
      if (entries == null || !entries.hasMoreElements()) {
        TestDesignerPlugin.logWarning(
            "No AllTests class in bundle " + bundle.getSymbolicName()); // $NON-NLS-1$
        return;
      }

      TestSuite suite = new TestSuite(bundle.getSymbolicName());

      while (entries.hasMoreElements()) {
        URL element = entries.nextElement();

        try {
          URL url = FileLocator.toFileURL(element);
          String className = convertToClassName(url);

          TestDesignerPlugin.logInfo("Test class name: " + className); // $NON-NLS-1$

          Class<?> klazz = loadClassFromBundle(bundle, className);

          SuiteClasses suiteClasses = klazz.getAnnotation(SuiteClasses.class);
          for (Class<?> suiteKlazz : suiteClasses.value()) {
            if (TestCase.class.isAssignableFrom(suiteKlazz)) {
              addJUnit3TestClass(suite, (Class<? extends TestCase>) suiteKlazz);
            } else {
              addJUnit4TestClass(suite, suiteKlazz);
            }
          }

          parentSuite.addTest(suite);
        } catch (Exception ex) {
          TestDesignerPlugin.logException(ex);
        }
      }
    }
    public static Test suite() {

      // Turn off mockito's objenesis cache as it can return the
      // wrong Admin interface in the runtime client tests
      MockitoConfiguration.setEnableClassCache(false);

      TestSuite aggregateSuite = new TestSuite(ALL_PLUGIN_TESTS);

      BundleContext context = TestDesignerPlugin.getPlugin().getBundleContext();
      for (Bundle bundle : context.getBundles()) {
        if (!bundle.getSymbolicName().matches(BUNDLE_FILTER)) {
          continue;
        }

        collectTests(aggregateSuite, bundle);
      }

      return aggregateSuite;
    }
    /**
     * @param bundle
     * @param className
     * @return
     */
    private static Class<?> loadClassFromBundle(Bundle bundle, String className)
        throws ClassNotFoundException {
      Class<?> klazz = null;

      if (Platform.isFragment(bundle)) {
        // Need to use the bundle's host for loading the class
        Bundle[] hosts = Platform.getHosts(bundle);
        if (hosts == null) {
          TestDesignerPlugin.logWarning("Cannot test fragment as NO host!"); // $NON-NLS-1$
          return klazz;
        }

        for (Bundle host : hosts) {
          klazz = host.loadClass(className);
          if (klazz != null) {
            break;
          }
        }
      } else {
        klazz = bundle.loadClass(className);
      }

      return klazz;
    }