예제 #1
0
  @Override
  public DioritePlugin loadPlugin(final File file) throws PluginException {
    try {
      final PluginClassLoader classLoader = new PluginClassLoader(file);

      final ConfigurationBuilder config = new ConfigurationBuilder();
      config.setClassLoaders(new PluginClassLoader[] {classLoader});
      config.setUrls(ClasspathHelper.forClassLoader(classLoader));

      final Reflections ref = new Reflections(config);
      final Set<Class<?>> annotated = ref.getTypesAnnotatedWith(Plugin.class);
      if (annotated.isEmpty()) {
        throw new PluginException("Plugin annotation doesn't found!");
      }
      if (annotated.size() > 1) {
        throw new PluginException("Plugin has more than one main class!");
      }

      final Class<?> mainClass = annotated.iterator().next();

      if (!DioritePlugin.class.isAssignableFrom(mainClass)) {
        throw new PluginException("Main class must extend PluginMainClass!");
      }

      final DioritePlugin dioritePlugin = (DioritePlugin) mainClass.newInstance();
      final Plugin pluginDescription = mainClass.getAnnotation(Plugin.class);

      if (ServerImpl.getInstance().getPluginManager().getPlugin(pluginDescription.name()) != null) {
        throw new PluginException("Plugin " + pluginDescription.name() + " is arleady loaded!");
      }

      dioritePlugin.init(
          classLoader,
          this,
          dioritePlugin,
          pluginDescription.name(),
          pluginDescription.version(),
          pluginDescription.author(),
          pluginDescription.description(),
          pluginDescription.website());
      System.out.println(
          "Loading "
              + pluginDescription.name()
              + " v"
              + pluginDescription.version()
              + " by "
              + pluginDescription.author()
              + " from file "
              + file.getName());
      dioritePlugin.onLoad();

      return dioritePlugin;
    } catch (final InstantiationException | IllegalAccessException | MalformedURLException e) {
      throw new PluginException("Exception while loading plugin from file " + file.getName(), e);
    }
  }
  @Programmatic
  @Override
  public <T> Set<Class<? extends T>> findSubTypesOfClasses(Class<T> type) {
    Vfs.setDefaultURLTypes(getUrlTypes());

    final Reflections reflections =
        new Reflections(
            ClasspathHelper.forClassLoader(Thread.currentThread().getContextClassLoader()),
            ClasspathHelper.forClass(Object.class),
            new SubTypesScanner(false));
    return reflections.getSubTypesOf(type);
  }
  /*
   * Scan the classpath looking for JAX-RS Application sub-classes
   */
  private static Set<Class<? extends Application>> findJaxrsApplicationClasses() {
    logger.info("Scanning classpath to find JAX-RS Application classes");

    final Collection<URL> systemPropertyURLs = ClasspathHelper.forJavaClassPath();
    final Collection<URL> classLoaderURLs = ClasspathHelper.forClassLoader();

    Set<URL> classpathURLs = new HashSet<URL>();

    copyValidClasspathEntries(systemPropertyURLs, classpathURLs);
    copyValidClasspathEntries(classLoaderURLs, classpathURLs);

    logger.debug("Classpath URLs to be scanned: " + classpathURLs);

    Reflections reflections = new Reflections(classpathURLs, new SubTypesScanner());

    return reflections.getSubTypesOf(Application.class);
  }
  private void guess(
      Map<String, DefaultCoreExtension> extensions, DefaultCoreExtensionRepository repository) {
    Set<ExtensionDependency> dependencies = new HashSet<ExtensionDependency>();

    for (DefaultCoreExtension coreExtension : extensions.values()) {
      for (ExtensionDependency dependency : coreExtension.getDependencies()) {
        dependencies.add(dependency);
      }
    }

    // Normalize and guess

    Map<String, Object[]> fileNames = new HashMap<String, Object[]>();
    Map<String, Object[]> guessedArtefacts = new HashMap<String, Object[]>();
    Set<URL> urls = ClasspathHelper.forClassLoader();

    for (URL url : urls) {
      try {
        String path = url.toURI().getPath();
        String filename = path.substring(path.lastIndexOf('/') + 1);
        String type = null;

        int extIndex = filename.lastIndexOf('.');
        if (extIndex != -1) {
          type = filename.substring(extIndex + 1);
          filename = filename.substring(0, extIndex);
        }

        int index;
        if (!filename.endsWith(SNAPSHOTSUFFIX)) {
          index = filename.lastIndexOf('-');
        } else {
          index = filename.lastIndexOf('-', filename.length() - SNAPSHOTSUFFIX.length());
        }

        if (index != -1) {
          fileNames.put(filename, new Object[] {url});

          String artefactname = filename.substring(0, index);
          String version = filename.substring(index + 1);

          guessedArtefacts.put(artefactname, new Object[] {version, url, type});
        }
      } catch (Exception e) {
        this.logger.warn("Failed to parse resource name [" + url + "]", e);
      }
    }

    // Try to resolve version no easy to find from the pom.xml
    try {
      for (DefaultCoreExtension coreExtension : extensions.values()) {
        String artifactId = getArtifactId(coreExtension);

        Object[] artefact = guessedArtefacts.get(artifactId);

        if (artefact != null) {
          if (coreExtension.getId().getVersion().getValue().charAt(0) == '$') {
            coreExtension.setId(
                new ExtensionId(coreExtension.getId().getId(), (String) artefact[0]));
            coreExtension.setGuessed(true);
          }

          if (coreExtension.getType().charAt(0) == '$') {
            coreExtension.setType((String) artefact[2]);
            coreExtension.setGuessed(true);
          }
        }
      }

      // Add dependencies that does not provide proper pom.xml resource and can't be found in the
      // classpath
      for (ExtensionDependency extensionDependency : dependencies) {
        Dependency dependency =
            (Dependency)
                extensionDependency.getProperty(MavenCoreExtensionDependency.PKEY_MAVEN_DEPENDENCY);

        if (dependency == null) {
          dependency =
              toDependency(
                  extensionDependency.getId(),
                  extensionDependency.getVersionConstraint().getValue(),
                  null);
        }

        String dependencyId = dependency.getGroupId() + ':' + dependency.getArtifactId();

        DefaultCoreExtension coreExtension = extensions.get(dependencyId);
        if (coreExtension == null) {
          String dependencyFileName = dependency.getArtifactId() + '-' + dependency.getVersion();
          if (dependency.getClassifier() != null) {
            dependencyFileName += '-' + dependency.getClassifier();
            dependencyId += ':' + dependency.getClassifier();
          }

          Object[] filenameArtifact = fileNames.get(dependencyFileName);
          Object[] guessedArtefact = guessedArtefacts.get(dependency.getArtifactId());

          if (filenameArtifact != null) {
            coreExtension =
                new DefaultCoreExtension(
                    repository,
                    (URL) filenameArtifact[0],
                    new ExtensionId(dependencyId, dependency.getVersion()),
                    packagingToType(dependency.getType()));
            coreExtension.setGuessed(true);
          } else if (guessedArtefact != null) {
            coreExtension =
                new DefaultCoreExtension(
                    repository,
                    (URL) guessedArtefact[1],
                    new ExtensionId(dependencyId, (String) guessedArtefact[0]),
                    packagingToType(dependency.getType()));
            coreExtension.setGuessed(true);
          }

          if (coreExtension != null) {
            extensions.put(dependencyId, coreExtension);
          }
        }
      }
    } catch (Exception e) {
      this.logger.warn("Failed to guess extra information about some extensions", e);
    }
  }
예제 #5
0
/** @author Nils Olsson */
public final class TestExecutor implements Executor {

  private static final Reflections reflections =
      new Reflections(
          new ConfigurationBuilder()
              .addUrls(filter(ClasspathHelper.forJavaClassPath(), ClasspathHelper.forClassLoader()))
              .addScanners(new SubTypesScanner(), new TypeAnnotationsScanner()));

  private static Collection<URL> filter(Collection<URL> classPath, Collection<URL> classLoader) {
    Reflections.log = null;
    List<URL> urls = new ArrayList<>(), filteredUrls = new ArrayList<>();
    urls.addAll(classPath);
    urls.addAll(classLoader);
    for (URL url : urls) {
      if (!filteredUrls.contains(url) && new File(url.getFile()).exists()) {
        filteredUrls.add(url);
      }
    }
    return filteredUrls;
  }

  private final Configuration configuration;
  private final MachineConfiguration machineConfiguration;
  private final Map<Context, MachineException> failures = new HashMap<>();
  private final Machine machine;
  private Result result;

  public TestExecutor(Configuration configuration) {
    this.configuration = configuration;
    this.machineConfiguration = createMachineConfiguration(AnnotationUtils.findTests(reflections));
    this.machine = createMachine(machineConfiguration);
  }

  public TestExecutor(Class<?>... tests) {
    this.configuration = new Configuration();
    this.machineConfiguration = createMachineConfiguration(Arrays.asList(tests));
    this.machine = createMachine(machineConfiguration);
  }

  public TestExecutor(Context... contexts) {
    this.configuration = new Configuration();
    this.machineConfiguration = new MachineConfiguration();
    this.machine = new SimpleMachine(contexts);
  }

  public TestExecutor(Collection<Context> contexts) {
    this.configuration = new Configuration();
    this.machineConfiguration = new MachineConfiguration();
    this.machine = new SimpleMachine(contexts);
  }

  @Override
  public Machine getMachine() {
    return machine;
  }

  private MachineConfiguration createMachineConfiguration(Collection<Class<?>> testClasses) {
    MachineConfiguration machineConfiguration = new MachineConfiguration();
    for (Class<?> testClass : testClasses) {
      GraphWalker annotation = testClass.getAnnotation(GraphWalker.class);
      if (isTestIncluded(annotation, testClass.getName())) {
        ContextConfiguration contextConfiguration = new ContextConfiguration();
        contextConfiguration.setTestClass(testClass);
        machineConfiguration.addContextConfiguration(contextConfiguration);
      }
    }
    return machineConfiguration;
  }

  private Collection<Context> createContexts(MachineConfiguration machineConfiguration) {
    Set<Context> contexts = new HashSet<>();
    for (ContextConfiguration contextConfiguration :
        machineConfiguration.getContextConfigurations()) {
      Context context = createContext(contextConfiguration.getTestClass());
      configureContext(context);
      contexts.add(context);
    }
    return contexts;
  }

  private Context createContext(Class<?> testClass) {
    try {
      return (Context) testClass.newInstance();
    } catch (Throwable e) {
      throw new TestExecutionException("Failed to create context");
    }
  }

  private void configureContext(Context context) {
    Set<Model> models = AnnotationUtils.getAnnotations(context.getClass(), Model.class);
    GraphWalker annotation = context.getClass().getAnnotation(GraphWalker.class);
    if (!models.isEmpty()) {
      Path path = Paths.get(models.iterator().next().file());
      ContextFactoryScanner.get(reflections, path).create(path, context);
    }
    if (!"".equals(annotation.value())) {
      context.setPathGenerator(GeneratorFactory.parse(annotation.value()));
    } else {
      context.setPathGenerator(PathGeneratorFactory.createPathGenerator(annotation));
    }
    if (!"".equals(annotation.start())) {
      context.setNextElement(getElement(context.getModel(), annotation.start()));
    }
  }

  private Machine createMachine(MachineConfiguration machineConfiguration) {
    Collection<Context> contexts = createContexts(machineConfiguration);
    Machine machine = new SimpleMachine(contexts);
    for (Context context : machine.getContexts()) {
      if (context instanceof Observer) {
        machine.addObserver((Observer) context);
      }
    }
    return machine;
  }

  @Override
  public MachineConfiguration getMachineConfiguration() {
    return machineConfiguration;
  }

  @Override
  public Result execute() {
    return execute(false);
  }

  @Override
  public Result execute(boolean ignoreErrors) {
    result = new Result(machine.getContexts().size());
    executeAnnotation(BeforeExecution.class, machine);
    try {
      Context context = null;
      while (machine.hasNextStep()) {
        if (null != context) {
          executeAnnotation(BeforeElement.class, context);
        }
        context = machine.getNextStep();
        executeAnnotation(AfterElement.class, context);
      }
    } catch (MachineException e) {
      failures.put(e.getContext(), e);
    }
    executeAnnotation(AfterExecution.class, machine);
    updateResult(result, machine);
    if (!ignoreErrors && !failures.isEmpty()) {
      throw new TestExecutionException("Test execution contains failures");
    }
    return result;
  }

  @Override
  public Result getResult() {
    return result;
  }

  private void updateResult(Result result, Machine machine) {
    int completed = 0, failed = 0, notExecuted = 0, incomplete = 0;
    for (Context context : machine.getContexts()) {
      switch (context.getExecutionStatus()) {
        case COMPLETED:
          {
            completed++;
          }
          break;
        case FAILED:
          {
            failed++;
          }
          break;
        case NOT_EXECUTED:
          {
            notExecuted++;
          }
          break;
        case EXECUTING:
          {
            incomplete++;
          }
      }
    }
    result.setCompletedCount(completed);
    result.setFailedCount(failed);
    result.setNotExecutedCount(notExecuted);
    result.setIncompleteCount(incomplete);
    for (MachineException exception : getFailures()) {
      result.addError(getStackTrace(exception.getCause()));
    }
  }

  private String getStackTrace(Throwable throwable) {
    StringWriter writer = new StringWriter();
    throwable.printStackTrace(new PrintWriter(writer, true));
    return writer.getBuffer().toString();
  }

  private boolean isTestIncluded(GraphWalker annotation, String name) {
    boolean belongsToGroup = false;
    for (String group : annotation.groups()) {
      for (String definedGroups : configuration.getGroups()) {
        if (SelectorUtils.match(definedGroups, group)) {
          belongsToGroup = true;
          break;
        }
      }
    }
    if (belongsToGroup) {
      for (String exclude : configuration.getExcludes()) {
        if (SelectorUtils.match(exclude, name)) {
          return false;
        }
      }
      for (String include : configuration.getIncludes()) {
        if (SelectorUtils.match(include, name)) {
          return true;
        }
      }
    }
    return false;
  }

  private Element getElement(RuntimeModel model, String name) {
    List<Element> elements = model.findElements(name);
    if (null == elements || 0 == elements.size()) {
      throw new TestExecutionException("Start element not found");
    }
    if (1 < elements.size()) {
      throw new TestExecutionException("Ambiguous start element defined");
    }
    return elements.get(0);
  }

  private void executeAnnotation(Class<? extends Annotation> annotation, Machine machine) {
    for (Context context : machine.getContexts()) {
      executeAnnotation(annotation, context);
    }
  }

  private void executeAnnotation(Class<? extends Annotation> annotation, Context context) {
    AnnotationUtils.execute(annotation, context);
  }

  @Override
  public boolean isFailure(Context context) {
    return failures.containsKey(context);
  }

  @Override
  public MachineException getFailure(Context context) {
    return failures.get(context);
  }

  @Override
  public Collection<MachineException> getFailures() {
    return failures.values();
  }

  public void reportResults(File file, Date startTime, Properties properties) {
    new XMLReportGenerator(startTime, properties).writeReport(file, this);
    if (0 < getFailures().size()) {
      throw new TestExecutionException(
          MessageFormat.format(
              "There are test failures.\n\n Please refer to {0} for the individual test results.",
              file.getAbsolutePath()));
    }
  }
}
예제 #6
0
  @Override
  public void beforeStart(final Application application) {
    final Reflections reflections =
        new Reflections(
            new ConfigurationBuilder()
                .filterInputsBy(new FilterBuilder.Exclude(FilterBuilder.prefix("com.google")))
                .addUrls(ClasspathHelper.forClassLoader(application.classloader()))
                .addScanners(new SubTypesScanner()));

    // automatic Guice module detection
    Set<Class<? extends AbstractModule>> guiceModules =
        reflections.getSubTypesOf(AbstractModule.class);
    for (Class<? extends Module> moduleClass : guiceModules) {
      try {
        if (!moduleClass.isAnonymousClass()) {
          modules.add(moduleClass.newInstance());
        }
      } catch (InstantiationException e) {
        throw Throwables.propagate(e);
      } catch (IllegalAccessException e) {
        throw Throwables.propagate(e);
      }
    }

    modules.add(
        new AbstractModule() {
          @Override
          protected void configure() {
            bind(Application.class).toInstance(application);
            bind(Reflections.class).toInstance(reflections);

            Names.bindProperties(
                this.binder(),
                fromKeys(
                    application.configuration().keys(),
                    new Function<String, String>() {
                      @Override
                      public String apply(String key) {
                        // remove after https://play.lighthouseapp.com/projects/82401/tickets/372 is
                        // fixed
                        if (key.contains("akka")) return null;

                        return application.configuration().getString(key);
                      }
                    }));

            for (Class<? extends Controller> controllerClass :
                reflections.getSubTypesOf(Controller.class)) {
              requestStaticInjection(controllerClass);
            }

            // bind all services
            Multibinder<Service> serviceBinder = Multibinder.newSetBinder(binder(), Service.class);
            for (Class<? extends Service> serviceImplClass :
                reflections.getSubTypesOf(AbstractService.class)) {
              serviceBinder.addBinding().to(serviceImplClass).asEagerSingleton();
            }
            for (Class<? extends Service> serviceImplClass :
                reflections.getSubTypesOf(AbstractIdleService.class)) {
              serviceBinder.addBinding().to(serviceImplClass).asEagerSingleton();
            }
            for (Class<? extends Service> serviceImplClass :
                reflections.getSubTypesOf(AbstractExecutionThreadService.class)) {
              serviceBinder.addBinding().to(serviceImplClass).asEagerSingleton();
            }

            // bind actor - todo use reflections for this

            // start/stop services after injection and on shutdown of the Play app
            bindListener(
                MoreMatchers.subclassesOf(Service.class),
                new TypeListener() {
                  @Override
                  public <I> void hear(TypeLiteral<I> typeLiteral, TypeEncounter<I> typeEncounter) {
                    typeEncounter.register(
                        new InjectionListener<I>() {
                          @Override
                          public void afterInjection(final I i) {
                            onStartListeners.add(
                                new OnStartListener() {
                                  @Override
                                  public void onApplicationStart(
                                      Application application, Injector injector) {
                                    Logger.info(String.format("Starting %s", i.toString()));
                                    ((Service) i).start();

                                    onStopListeners.add(
                                        new OnStopListener() {
                                          @Override
                                          public void onApplicationStop(Application application) {
                                            Logger.info(String.format("Stopping %s", i.toString()));
                                            ((Service) i).stop();
                                          }
                                        });
                                  }
                                });
                          }
                        });
                  }
                });
          }
        });
  }