[gnome-builder/wip/gtk4-port] plugins/maven: port maven plugin to C



commit 710048a6211dbea8ba02daf9d335bb6b31ebbe7c
Author: Christian Hergert <chergert redhat com>
Date:   Thu Jun 9 10:34:34 2022 -0700

    plugins/maven: port maven plugin to C
    
    This will require the new IdeRunCommand infrastructure to land for running
    instead of build targets before it's possible to run, like many of the
    other build systems that were ported.

 .../maven/gbp-maven-build-system-discovery.c       |  47 ++++
 .../maven/gbp-maven-build-system-discovery.h       |  31 +++
 src/plugins/maven/gbp-maven-build-system.c         | 166 ++++++++++++
 src/plugins/maven/gbp-maven-build-system.h         |  33 +++
 src/plugins/maven/gbp-maven-pipeline-addin.c       | 123 +++++++++
 src/plugins/maven/gbp-maven-pipeline-addin.h       |  31 +++
 src/plugins/maven/gbp-maven-run-command-provider.c | 143 ++++++++++
 src/plugins/maven/gbp-maven-run-command-provider.h |  31 +++
 src/plugins/maven/gbp-maven-test-provider.c        | 297 +++++++++++++++++++++
 src/plugins/maven/gbp-maven-test-provider.h        |  31 +++
 src/plugins/maven/gbp-maven-test.c                 |  72 +++++
 src/plugins/maven/gbp-maven-test.h                 |  34 +++
 src/plugins/maven/maven-plugin.c                   |  53 ++++
 src/plugins/maven/maven.gresource.xml              |   6 +
 src/plugins/maven/maven.plugin                     |   9 +-
 src/plugins/maven/meson.build                      |  24 +-
 16 files changed, 1118 insertions(+), 13 deletions(-)
---
diff --git a/src/plugins/maven/gbp-maven-build-system-discovery.c 
b/src/plugins/maven/gbp-maven-build-system-discovery.c
new file mode 100644
index 000000000..57f2ea69a
--- /dev/null
+++ b/src/plugins/maven/gbp-maven-build-system-discovery.c
@@ -0,0 +1,47 @@
+/* gbp-maven-build-system-discovery.c
+ *
+ * Copyright 2016-2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-maven-build-system-discovery"
+
+#include "config.h"
+
+#include "gbp-maven-build-system-discovery.h"
+
+struct _GbpMavenBuildSystemDiscovery
+{
+  IdeSimpleBuildSystemDiscovery parent_instance;
+};
+
+G_DEFINE_FINAL_TYPE (GbpMavenBuildSystemDiscovery, gbp_maven_build_system_discovery, 
IDE_TYPE_SIMPLE_BUILD_SYSTEM_DISCOVERY)
+
+static void
+gbp_maven_build_system_discovery_class_init (GbpMavenBuildSystemDiscoveryClass *klass)
+{
+}
+
+static void
+gbp_maven_build_system_discovery_init (GbpMavenBuildSystemDiscovery *self)
+{
+  g_object_set (self,
+                "glob", "pom.xml",
+                "hint", "maven",
+                "priority", 2000,
+                NULL);
+}
diff --git a/src/plugins/maven/gbp-maven-build-system-discovery.h 
b/src/plugins/maven/gbp-maven-build-system-discovery.h
new file mode 100644
index 000000000..904bf65f6
--- /dev/null
+++ b/src/plugins/maven/gbp-maven-build-system-discovery.h
@@ -0,0 +1,31 @@
+/* gbp-maven-build-system-discovery.h
+ *
+ * Copyright 2016-2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-foundry.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_MAVEN_BUILD_SYSTEM_DISCOVERY (gbp_maven_build_system_discovery_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpMavenBuildSystemDiscovery, gbp_maven_build_system_discovery, GBP, 
MAVEN_BUILD_SYSTEM_DISCOVERY, IdeSimpleBuildSystemDiscovery)
+
+G_END_DECLS
diff --git a/src/plugins/maven/gbp-maven-build-system.c b/src/plugins/maven/gbp-maven-build-system.c
new file mode 100644
index 000000000..14d2e7c4e
--- /dev/null
+++ b/src/plugins/maven/gbp-maven-build-system.c
@@ -0,0 +1,166 @@
+/* gbp-maven-build-system.c
+ *
+ * Copyright 2016-2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-maven-build-system"
+
+#include "config.h"
+
+#include "gbp-maven-build-system.h"
+
+struct _GbpMavenBuildSystem
+{
+  IdeObject  parent_instance;
+  GFile     *project_file;
+};
+
+enum {
+  PROP_0,
+  PROP_PROJECT_FILE,
+  N_PROPS
+};
+
+static char *
+gbp_maven_build_system_get_id (IdeBuildSystem *build_system)
+{
+  return g_strdup ("maven");
+}
+
+static char *
+gbp_maven_build_system_get_display_name (IdeBuildSystem *build_system)
+{
+  return g_strdup ("Maven");
+}
+
+static int
+gbp_maven_build_system_get_priority (IdeBuildSystem *build_system)
+{
+  return 2000;
+}
+
+static void
+build_system_iface_init (IdeBuildSystemInterface *iface)
+{
+  iface->get_id = gbp_maven_build_system_get_id;
+  iface->get_display_name = gbp_maven_build_system_get_display_name;
+  iface->get_priority = gbp_maven_build_system_get_priority;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpMavenBuildSystem, gbp_maven_build_system, IDE_TYPE_OBJECT,
+                               G_IMPLEMENT_INTERFACE (IDE_TYPE_BUILD_SYSTEM, build_system_iface_init))
+
+static GParamSpec *properties [N_PROPS];
+
+static void
+gbp_maven_build_system_dispose (GObject *object)
+{
+  GbpMavenBuildSystem *self = (GbpMavenBuildSystem *)object;
+
+  g_clear_object (&self->project_file);
+
+  G_OBJECT_CLASS (gbp_maven_build_system_parent_class)->dispose (object);
+}
+
+static void
+gbp_maven_build_system_get_property (GObject    *object,
+                                     guint       prop_id,
+                                     GValue     *value,
+                                     GParamSpec *pspec)
+{
+  GbpMavenBuildSystem *self = GBP_MAVEN_BUILD_SYSTEM (object);
+
+  switch (prop_id)
+    {
+    case PROP_PROJECT_FILE:
+      g_value_set_object (value, self->project_file);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gbp_maven_build_system_set_property (GObject      *object,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec)
+{
+  GbpMavenBuildSystem *self = GBP_MAVEN_BUILD_SYSTEM (object);
+
+  switch (prop_id)
+    {
+    case PROP_PROJECT_FILE:
+      g_set_object (&self->project_file, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
+}
+
+static void
+gbp_maven_build_system_class_init (GbpMavenBuildSystemClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = gbp_maven_build_system_dispose;
+  object_class->get_property = gbp_maven_build_system_get_property;
+  object_class->set_property = gbp_maven_build_system_set_property;
+
+  properties [PROP_PROJECT_FILE] =
+    g_param_spec_object ("project-file",
+                         "Project File",
+                         "The project file (Maven.toml)",
+                         G_TYPE_FILE,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, N_PROPS, properties);
+}
+
+static void
+gbp_maven_build_system_init (GbpMavenBuildSystem *self)
+{
+}
+
+char *
+gbp_maven_build_system_get_project_dir (GbpMavenBuildSystem *self)
+{
+  g_autoptr(GFile) workdir = NULL;
+  g_autofree char *base = NULL;
+  IdeContext *context;
+
+  g_return_val_if_fail (GBP_IS_MAVEN_BUILD_SYSTEM (self), NULL);
+
+  context = ide_object_get_context (IDE_OBJECT (self));
+  workdir = ide_context_ref_workdir (context);
+
+  if (self->project_file == NULL)
+    return g_strdup (g_file_peek_path (workdir));
+
+  base = g_file_get_basename (self->project_file);
+
+  if (strcasecmp (base, "pom.xml") != 0)
+    {
+      g_autoptr(GFile) parent = g_file_get_parent (self->project_file);
+      return g_file_get_path (parent);
+    }
+
+  return g_file_get_path (self->project_file);
+}
diff --git a/src/plugins/maven/gbp-maven-build-system.h b/src/plugins/maven/gbp-maven-build-system.h
new file mode 100644
index 000000000..03fd0e92a
--- /dev/null
+++ b/src/plugins/maven/gbp-maven-build-system.h
@@ -0,0 +1,33 @@
+/* gbp-maven-build-system.h
+ *
+ * Copyright 2016-2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-foundry.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_MAVEN_BUILD_SYSTEM (gbp_maven_build_system_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpMavenBuildSystem, gbp_maven_build_system, GBP, MAVEN_BUILD_SYSTEM, IdeObject)
+
+char *gbp_maven_build_system_get_project_dir (GbpMavenBuildSystem *self);
+
+G_END_DECLS
diff --git a/src/plugins/maven/gbp-maven-pipeline-addin.c b/src/plugins/maven/gbp-maven-pipeline-addin.c
new file mode 100644
index 000000000..926490113
--- /dev/null
+++ b/src/plugins/maven/gbp-maven-pipeline-addin.c
@@ -0,0 +1,123 @@
+/* gbp-maven-pipeline-addin.c
+ *
+ * Copyright 2018 danigm <danigm wadobo com>
+ * Copyright 2018 Alberto Fanjul <albfan gnome org>
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-maven-pipeline-addin"
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <libide-foundry.h>
+
+#include "gbp-maven-build-system.h"
+#include "gbp-maven-pipeline-addin.h"
+
+struct _GbpMavenPipelineAddin
+{
+  IdeObject parent_instance;
+};
+
+static void
+query_cb (IdePipelineStage *stage,
+          IdePipeline      *pipeline,
+          GPtrArray        *targets,
+          GCancellable     *cancellable,
+          gpointer          user_data)
+{
+  g_assert (IDE_IS_PIPELINE_STAGE (stage));
+  g_assert (IDE_IS_PIPELINE (pipeline));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  /* Always defer to maven to check if build is needed */
+  ide_pipeline_stage_set_completed (stage, FALSE);
+}
+
+static void
+gbp_maven_pipeline_addin_load (IdePipelineAddin *addin,
+                               IdePipeline      *pipeline)
+{
+  g_autoptr(IdeSubprocessLauncher) build_launcher = NULL;
+  g_autoptr(IdeSubprocessLauncher) clean_launcher = NULL;
+  g_autoptr(IdeSubprocessLauncher) install_launcher = NULL;
+  g_autoptr(IdePipelineStage) build_stage = NULL;
+  g_autoptr(IdePipelineStage) install_stage = NULL;
+  IdeBuildSystem *build_system;
+  const char *srcdir;
+  IdeContext *context;
+  guint id;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_MAVEN_PIPELINE_ADDIN (addin));
+  g_assert (IDE_IS_PIPELINE (pipeline));
+
+  context = ide_object_get_context (IDE_OBJECT (addin));
+  build_system = ide_build_system_from_context (context);
+  srcdir = ide_pipeline_get_srcdir (pipeline);
+
+  if (!GBP_IS_MAVEN_BUILD_SYSTEM (build_system))
+    IDE_EXIT;
+
+  build_launcher = ide_pipeline_create_launcher (pipeline, NULL);
+  ide_subprocess_launcher_set_cwd (build_launcher, srcdir);
+  ide_subprocess_launcher_push_args (build_launcher, IDE_STRV_INIT ("mvn", "compile"));
+
+  clean_launcher = ide_pipeline_create_launcher (pipeline, NULL);
+  ide_subprocess_launcher_set_cwd (clean_launcher, srcdir);
+  ide_subprocess_launcher_push_args (clean_launcher, IDE_STRV_INIT ("mvn", "clean"));
+
+  build_stage = ide_pipeline_stage_launcher_new (context, build_launcher);
+  ide_pipeline_stage_set_name (build_stage, _("Building project"));
+  ide_pipeline_stage_launcher_set_clean_launcher (IDE_PIPELINE_STAGE_LAUNCHER (build_stage), clean_launcher);
+  g_signal_connect (build_stage, "query", G_CALLBACK (query_cb), NULL);
+  id = ide_pipeline_attach (pipeline, IDE_PIPELINE_PHASE_BUILD, 0, build_stage);
+  ide_pipeline_addin_track (addin, id);
+
+  install_launcher = ide_pipeline_create_launcher (pipeline, NULL);
+  ide_subprocess_launcher_set_cwd (install_launcher, srcdir);
+  ide_subprocess_launcher_push_args (install_launcher, IDE_STRV_INIT ("mvn", "install", 
"-Dmaven.test.skip=true"));
+  install_stage = ide_pipeline_stage_launcher_new (context, install_launcher);
+  ide_pipeline_stage_set_name (install_stage, _("Installing project"));
+  id = ide_pipeline_attach (pipeline, IDE_PIPELINE_PHASE_INSTALL, 0, install_stage);
+  ide_pipeline_addin_track (addin, id);
+
+  IDE_EXIT;
+}
+
+static void
+pipeline_addin_iface_init (IdePipelineAddinInterface *iface)
+{
+  iface->load = gbp_maven_pipeline_addin_load;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpMavenPipelineAddin, gbp_maven_pipeline_addin, IDE_TYPE_OBJECT,
+                               G_IMPLEMENT_INTERFACE (IDE_TYPE_PIPELINE_ADDIN, pipeline_addin_iface_init))
+
+static void
+gbp_maven_pipeline_addin_class_init (GbpMavenPipelineAddinClass *klass)
+{
+}
+
+static void
+gbp_maven_pipeline_addin_init (GbpMavenPipelineAddin *self)
+{
+}
diff --git a/src/plugins/maven/gbp-maven-pipeline-addin.h b/src/plugins/maven/gbp-maven-pipeline-addin.h
new file mode 100644
index 000000000..12d60afac
--- /dev/null
+++ b/src/plugins/maven/gbp-maven-pipeline-addin.h
@@ -0,0 +1,31 @@
+/* gbp-maven-pipeline-addin.h
+ *
+ * Copyright 2016-2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-core.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_MAVEN_PIPELINE_ADDIN (gbp_maven_pipeline_addin_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpMavenPipelineAddin, gbp_maven_pipeline_addin, GBP, MAVEN_PIPELINE_ADDIN, IdeObject)
+
+G_END_DECLS
diff --git a/src/plugins/maven/gbp-maven-run-command-provider.c 
b/src/plugins/maven/gbp-maven-run-command-provider.c
new file mode 100644
index 000000000..a2bea14dd
--- /dev/null
+++ b/src/plugins/maven/gbp-maven-run-command-provider.c
@@ -0,0 +1,143 @@
+/* gbp-maven-run-command-provider.c
+ *
+ * Copyright 2016-2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-maven-run-command-provider"
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include <libide-foundry.h>
+#include <libide-threading.h>
+
+#include "gbp-maven-build-system.h"
+#include "gbp-maven-run-command-provider.h"
+
+struct _GbpMavenRunCommandProvider
+{
+  IdeObject parent_instance;
+};
+
+static void
+gbp_maven_run_command_provider_list_commands_async (IdeRunCommandProvider *provider,
+                                                    GCancellable          *cancellable,
+                                                    GAsyncReadyCallback    callback,
+                                                    gpointer               user_data)
+{
+  GbpMavenRunCommandProvider *self = (GbpMavenRunCommandProvider *)provider;
+  g_autoptr(IdeRunCommand) run_command = NULL;
+  g_autoptr(GStrvBuilder) builder = NULL;
+  g_autoptr(GListStore) store = NULL;
+  g_autoptr(IdeTask) task = NULL;
+  g_autofree char *project_dir = NULL;
+  IdeConfigManager *config_manager;
+  IdeBuildSystem *build_system;
+  g_auto(GStrv) run_argv = NULL;
+  g_auto(GStrv) args = NULL;
+  const char *run_opts;
+  IdeContext *context;
+  IdeConfig *config;
+  int run_argc;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_MAVEN_RUN_COMMAND_PROVIDER (self));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = ide_task_new (self, cancellable, callback, user_data);
+  ide_task_set_source_tag (task, gbp_maven_run_command_provider_list_commands_async);
+
+  context = ide_object_get_context (IDE_OBJECT (self));
+  build_system = ide_build_system_from_context (context);
+  config_manager = ide_config_manager_from_context (context);
+  config = ide_config_manager_get_current (config_manager);
+  run_opts = ide_config_get_run_opts (config);
+
+  if (!GBP_IS_MAVEN_BUILD_SYSTEM (build_system))
+    {
+      ide_task_return_new_error (task,
+                                 G_IO_ERROR,
+                                 G_IO_ERROR_NOT_SUPPORTED,
+                                 "Not a maven build system");
+      IDE_EXIT;
+    }
+
+  project_dir = gbp_maven_build_system_get_project_dir (GBP_MAVEN_BUILD_SYSTEM (build_system));
+
+  run_command = ide_run_command_new ();
+  ide_run_command_set_id (run_command, "maven:run");
+  ide_run_command_set_priority (run_command, -500);
+  ide_run_command_set_display_name (run_command, _("Maven Run"));
+  ide_run_command_set_cwd (run_command, project_dir);
+
+  /*
+   * This requires an argument -Dexec.mainClass="my.package.MainClass"
+   * Use run-opts in your config/manifest/etc.
+   */
+  builder = g_strv_builder_new ();
+  g_strv_builder_add_many (builder, "mvn", "exec:java", NULL);
+  if (g_shell_parse_argv (run_opts, &run_argc, &run_argv, NULL))
+    g_strv_builder_addv (builder, (const char **)run_argv);
+  args = g_strv_builder_end (builder);
+  ide_run_command_set_argv (run_command, (const char * const *)args);
+
+  store = g_list_store_new (IDE_TYPE_RUN_COMMAND);
+  g_list_store_append (store, run_command);
+  ide_task_return_pointer (task, g_steal_pointer (&store), g_object_unref);
+
+  IDE_EXIT;
+}
+
+static GListModel *
+gbp_maven_run_command_provider_list_commands_finish (IdeRunCommandProvider  *provider,
+                                                     GAsyncResult           *result,
+                                                     GError                **error)
+{
+  GListModel *ret;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_MAVEN_RUN_COMMAND_PROVIDER (provider));
+  g_assert (IDE_IS_TASK (result));
+
+  ret = ide_task_propagate_pointer (IDE_TASK (result), error);
+
+  IDE_RETURN (ret);
+}
+
+static void
+run_command_provider_iface_init (IdeRunCommandProviderInterface *iface)
+{
+  iface->list_commands_async = gbp_maven_run_command_provider_list_commands_async;
+  iface->list_commands_finish = gbp_maven_run_command_provider_list_commands_finish;
+}
+
+G_DEFINE_FINAL_TYPE_WITH_CODE (GbpMavenRunCommandProvider, gbp_maven_run_command_provider, IDE_TYPE_OBJECT,
+                               G_IMPLEMENT_INTERFACE (IDE_TYPE_RUN_COMMAND_PROVIDER, 
run_command_provider_iface_init))
+
+static void
+gbp_maven_run_command_provider_class_init (GbpMavenRunCommandProviderClass *klass)
+{
+}
+
+static void
+gbp_maven_run_command_provider_init (GbpMavenRunCommandProvider *self)
+{
+}
diff --git a/src/plugins/maven/gbp-maven-run-command-provider.h 
b/src/plugins/maven/gbp-maven-run-command-provider.h
new file mode 100644
index 000000000..22a06b4c0
--- /dev/null
+++ b/src/plugins/maven/gbp-maven-run-command-provider.h
@@ -0,0 +1,31 @@
+/* gbp-maven-run-command-provider.h
+ *
+ * Copyright 2016-2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-core.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_MAVEN_RUN_COMMAND_PROVIDER (gbp_maven_run_command_provider_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpMavenRunCommandProvider, gbp_maven_run_command_provider, GBP, 
MAVEN_RUN_COMMAND_PROVIDER, IdeObject)
+
+G_END_DECLS
diff --git a/src/plugins/maven/gbp-maven-test-provider.c b/src/plugins/maven/gbp-maven-test-provider.c
new file mode 100644
index 000000000..399f518b8
--- /dev/null
+++ b/src/plugins/maven/gbp-maven-test-provider.c
@@ -0,0 +1,297 @@
+/* gbp-maven-test-provider.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-maven-test-provider"
+
+#include "config.h"
+
+#include <libide-foundry.h>
+#include <libide-io.h>
+#include <libide-threading.h>
+
+#include "gbp-maven-build-system.h"
+#include "gbp-maven-test.h"
+#include "gbp-maven-test-provider.h"
+
+struct _GbpMavenTestProvider
+{
+  IdeTestProvider parent_instance;
+};
+
+G_DEFINE_FINAL_TYPE (GbpMavenTestProvider, gbp_maven_test_provider, IDE_TYPE_TEST_PROVIDER)
+
+static void
+gbp_maven_test_provider_add (GbpMavenTestProvider *self,
+                             GFile                *file,
+                             const char           *test_name)
+{
+  g_autoptr(GbpMavenTest) test = NULL;
+  g_autofree char *class_name = NULL;
+  g_autofree char *full_name = NULL;
+  g_autofree char *id = NULL;
+  char *dot;
+
+  g_assert (GBP_IS_MAVEN_TEST_PROVIDER (self));
+  g_assert (G_IS_FILE (file));
+  g_assert (test_name != NULL);
+
+  class_name = g_file_get_basename (file);
+  if ((dot = strrchr (class_name, '.')))
+    *dot = 0;
+
+  full_name = g_strconcat (class_name, "#", test_name, NULL);
+  id = g_strconcat ("maven:%s", full_name, NULL);
+  test = gbp_maven_test_new (full_name);
+
+  ide_test_set_id (IDE_TEST (test), id);
+  ide_test_set_group (IDE_TEST (test), class_name);
+  ide_test_set_display_name (IDE_TEST (test), test_name);
+
+  ide_test_provider_add (IDE_TEST_PROVIDER (self), IDE_TEST (test));
+}
+
+static void
+find_test_files_cb (GObject      *object,
+                    GAsyncResult *result,
+                    gpointer      user_data)
+{
+  GFile *basedir = (GFile *)object;
+  g_autoptr(GbpMavenTestProvider) self = user_data;
+  g_autoptr(GPtrArray) files = NULL;
+  g_autoptr(GError) error = NULL;
+
+  IDE_ENTRY;
+
+  g_assert (G_IS_FILE (basedir));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (GBP_IS_MAVEN_TEST_PROVIDER (self));
+
+  if (!(files = ide_g_file_find_finish (basedir, result, &error)))
+    {
+      g_debug ("Failed to find test files: %s", error->message);
+      IDE_GOTO (failure);
+    }
+
+  ide_test_provider_clear (IDE_TEST_PROVIDER (self));
+
+  for (guint i = 0; i < files->len; i++)
+    {
+      GFile *file = g_ptr_array_index (files, i);
+      g_autofree char *contents = NULL;
+      IdeLineReader reader;
+      char *line;
+      gsize line_len;
+      gsize len;
+
+      if (!g_file_load_contents (file, NULL, &contents, &len, NULL, NULL))
+        continue;
+
+      /* Obviously this isn't a great way to find tests, but it
+       * does allow for skipping any sort of introspection. Mostly
+       * just copying what the python plugin did.
+       */
+      ide_line_reader_init (&reader, contents, len);
+      while ((line = ide_line_reader_next (&reader, &line_len)))
+        {
+          char *name;
+          char *paren;
+
+          line[line_len] = 0;
+
+          if (!(name = strstr (line, "public void")))
+            continue;
+
+          if (!(paren = strchr (name, '(')))
+            continue;
+
+          *paren = 0;
+          name += strlen ("public void");
+          g_strstrip (name);
+
+          gbp_maven_test_provider_add (self, file, name);
+        }
+    }
+
+failure:
+  ide_test_provider_set_loading (IDE_TEST_PROVIDER (self), FALSE);
+
+  IDE_EXIT;
+}
+
+static void
+gbp_maven_test_provider_reload (IdeTestProvider *provider)
+{
+  g_autofree char *project_dir = NULL;
+  g_autoptr(GFile) testdir = NULL;
+  IdeBuildSystem *build_system;
+  IdeContext *context;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_MAVEN_TEST_PROVIDER (provider));
+
+  context = ide_object_get_context (IDE_OBJECT (provider));
+  build_system = ide_build_system_from_context (context);
+
+  if (!GBP_IS_MAVEN_BUILD_SYSTEM (build_system))
+    IDE_EXIT;
+
+  if (ide_test_provider_get_loading (provider))
+    IDE_EXIT;
+
+  ide_test_provider_set_loading (provider, TRUE);
+
+  project_dir = gbp_maven_build_system_get_project_dir (GBP_MAVEN_BUILD_SYSTEM (build_system));
+  testdir = g_file_new_build_filename (project_dir, "src", "test", "java", NULL);
+
+  ide_g_file_find_with_depth_async (testdir, "*.java", 5,
+                                    NULL,
+                                    find_test_files_cb,
+                                    g_object_ref (provider));
+
+  IDE_EXIT;
+}
+
+static void
+gbp_maven_test_provider_run_cb (GObject      *object,
+                                GAsyncResult *result,
+                                gpointer      user_data)
+{
+  IdeRunner *runner = (IdeRunner *)object;
+  g_autoptr(IdeTask) task = user_data;
+  g_autoptr(GError) error = NULL;
+  IdeTest *test;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_RUNNER (runner));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (IDE_IS_TASK (task));
+
+  test = ide_task_get_task_data (task);
+
+  if (!ide_runner_run_finish (runner, result, &error))
+    {
+      ide_test_set_status (test, IDE_TEST_STATUS_FAILED);
+      ide_task_return_error (task, g_steal_pointer (&error));
+    }
+  else
+    {
+      ide_test_set_status (test, IDE_TEST_STATUS_SUCCESS);
+      ide_task_return_boolean (task, TRUE);
+    }
+
+  IDE_EXIT;
+}
+
+static void
+gbp_maven_test_provider_run_async (IdeTestProvider     *provider,
+                                   IdeTest             *test,
+                                   IdePipeline         *pipeline,
+                                   VtePty              *pty,
+                                   GCancellable        *cancellable,
+                                   GAsyncReadyCallback  callback,
+                                   gpointer             user_data)
+{
+  g_autoptr(IdeRunner) runner = NULL;
+  g_autoptr(IdeTask) task = NULL;
+  g_autofree char *d_test = NULL;
+  const char *suite_name;
+  IdeRuntime *runtime;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_MAVEN_TEST_PROVIDER (provider));
+  g_assert (GBP_IS_MAVEN_TEST (test));
+  g_assert (IDE_IS_PIPELINE (pipeline));
+  g_assert (!pty || VTE_IS_PTY (pty));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = ide_task_new (provider, cancellable, callback, user_data);
+  ide_task_set_source_tag (task, gbp_maven_test_provider_run_async);
+  ide_task_set_task_data (task, g_object_ref (test), g_object_unref);
+
+  suite_name = gbp_maven_test_get_suite_name (GBP_MAVEN_TEST (test));
+
+  if (!(runtime = ide_pipeline_get_runtime (pipeline)) ||
+      !(runner = ide_runtime_create_runner (runtime, NULL)))
+    IDE_GOTO (failure);
+
+  if (pty != NULL)
+    ide_runner_set_pty (runner, pty);
+
+  ide_runner_set_cwd (runner, ide_pipeline_get_srcdir (pipeline));
+
+  /*
+   * http://maven.apache.org/surefire/maven-surefire-plugin/examples/single-test.html
+   * it has to be junit 4.x
+   */
+  d_test = g_strconcat ("-Dtest=", suite_name, NULL);
+  ide_runner_push_args (runner, IDE_STRV_INIT ("mvn", d_test, "test"));
+
+  ide_test_set_status (test, IDE_TEST_STATUS_RUNNING);
+  ide_runner_run_async (runner,
+                        cancellable,
+                        gbp_maven_test_provider_run_cb,
+                        g_steal_pointer (&task));
+
+  IDE_EXIT;
+
+failure:
+  ide_task_return_new_error (task,
+                             G_IO_ERROR,
+                             G_IO_ERROR_FAILED,
+                             "Failed to run test: %s",
+                             gbp_maven_test_get_suite_name (GBP_MAVEN_TEST (test)));
+
+  IDE_EXIT;
+}
+
+static gboolean
+gbp_maven_test_provider_run_finish (IdeTestProvider  *provider,
+                                    GAsyncResult     *result,
+                                    GError          **error)
+{
+  gboolean ret;
+
+  IDE_ENTRY;
+
+  g_assert (GBP_IS_MAVEN_TEST_PROVIDER (provider));
+  g_assert (G_IS_ASYNC_RESULT (result));
+
+  ret = ide_task_propagate_boolean (IDE_TASK (result), error);
+
+  IDE_RETURN (ret);
+}
+
+static void
+gbp_maven_test_provider_class_init (GbpMavenTestProviderClass *klass)
+{
+  IdeTestProviderClass *test_provider_class = IDE_TEST_PROVIDER_CLASS (klass);
+
+  test_provider_class->reload = gbp_maven_test_provider_reload;
+  test_provider_class->run_async = gbp_maven_test_provider_run_async;
+  test_provider_class->run_finish = gbp_maven_test_provider_run_finish;
+}
+
+static void
+gbp_maven_test_provider_init (GbpMavenTestProvider *self)
+{
+}
diff --git a/src/plugins/maven/gbp-maven-test-provider.h b/src/plugins/maven/gbp-maven-test-provider.h
new file mode 100644
index 000000000..1b7e13ea5
--- /dev/null
+++ b/src/plugins/maven/gbp-maven-test-provider.h
@@ -0,0 +1,31 @@
+/* gbp-maven-test-provider.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-core.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_MAVEN_TEST_PROVIDER (gbp_maven_test_provider_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpMavenTestProvider, gbp_maven_test_provider, GBP, MAVEN_TEST_PROVIDER, 
IdeTestProvider)
+
+G_END_DECLS
diff --git a/src/plugins/maven/gbp-maven-test.c b/src/plugins/maven/gbp-maven-test.c
new file mode 100644
index 000000000..ab10b7a5b
--- /dev/null
+++ b/src/plugins/maven/gbp-maven-test.c
@@ -0,0 +1,72 @@
+/* gbp-maven-test.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-maven-test"
+
+#include "config.h"
+
+#include "gbp-maven-test.h"
+
+struct _GbpMavenTest
+{
+  IdeTest parent_instance;
+  char *suite_name;
+};
+
+G_DEFINE_FINAL_TYPE (GbpMavenTest, gbp_maven_test, IDE_TYPE_TEST)
+
+static void
+gbp_maven_test_finalize (GObject *object)
+{
+  GbpMavenTest *self = (GbpMavenTest *)object;
+
+  g_clear_pointer (&self->suite_name, g_free);
+
+  G_OBJECT_CLASS (gbp_maven_test_parent_class)->finalize (object);
+}
+
+static void
+gbp_maven_test_class_init (GbpMavenTestClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gbp_maven_test_finalize;
+}
+
+static void
+gbp_maven_test_init (GbpMavenTest *self)
+{
+}
+
+GbpMavenTest *
+gbp_maven_test_new (const char *suite_name)
+{
+  GbpMavenTest *self = g_object_new (GBP_TYPE_MAVEN_TEST, NULL);
+  self->suite_name = g_strdup (suite_name);
+  return self;
+}
+
+const char *
+gbp_maven_test_get_suite_name (GbpMavenTest *self)
+{
+  g_return_val_if_fail (GBP_IS_MAVEN_TEST (self), NULL);
+
+  return self->suite_name;
+}
diff --git a/src/plugins/maven/gbp-maven-test.h b/src/plugins/maven/gbp-maven-test.h
new file mode 100644
index 000000000..da45a8164
--- /dev/null
+++ b/src/plugins/maven/gbp-maven-test.h
@@ -0,0 +1,34 @@
+/* gbp-maven-test.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-foundry.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_MAVEN_TEST (gbp_maven_test_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpMavenTest, gbp_maven_test, GBP, MAVEN_TEST, IdeTest)
+
+GbpMavenTest *gbp_maven_test_new            (const char    *suite_name);
+const char    *gbp_maven_test_get_suite_name (GbpMavenTest *self);
+
+G_END_DECLS
diff --git a/src/plugins/maven/maven-plugin.c b/src/plugins/maven/maven-plugin.c
new file mode 100644
index 000000000..b9524d4d0
--- /dev/null
+++ b/src/plugins/maven/maven-plugin.c
@@ -0,0 +1,53 @@
+/* maven-plugin.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "maven-plugin"
+
+#include "config.h"
+
+#include <libpeas/peas.h>
+
+#include <libide-foundry.h>
+
+#include "gbp-maven-build-system.h"
+#include "gbp-maven-build-system-discovery.h"
+#include "gbp-maven-pipeline-addin.h"
+#include "gbp-maven-run-command-provider.h"
+#include "gbp-maven-test-provider.h"
+
+_IDE_EXTERN void
+_gbp_maven_register_types (PeasObjectModule *module)
+{
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_BUILD_SYSTEM,
+                                              GBP_TYPE_MAVEN_BUILD_SYSTEM);
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_BUILD_SYSTEM_DISCOVERY,
+                                              GBP_TYPE_MAVEN_BUILD_SYSTEM_DISCOVERY);
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_PIPELINE_ADDIN,
+                                              GBP_TYPE_MAVEN_PIPELINE_ADDIN);
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_RUN_COMMAND_PROVIDER,
+                                              GBP_TYPE_MAVEN_RUN_COMMAND_PROVIDER);
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_TEST_PROVIDER,
+                                              GBP_TYPE_MAVEN_TEST_PROVIDER);
+}
diff --git a/src/plugins/maven/maven.gresource.xml b/src/plugins/maven/maven.gresource.xml
new file mode 100644
index 000000000..6352fd3a5
--- /dev/null
+++ b/src/plugins/maven/maven.gresource.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+  <gresource prefix="/plugins/maven">
+    <file>maven.plugin</file>
+  </gresource>
+</gresources>
diff --git a/src/plugins/maven/maven.plugin b/src/plugins/maven/maven.plugin
index b03ef7327..8c4aa6f44 100644
--- a/src/plugins/maven/maven.plugin
+++ b/src/plugins/maven/maven.plugin
@@ -1,12 +1,11 @@
 [Plugin]
 Authors=Alberto Fanjul Alonso <albfan gnome org>
 Builtin=true
-Copyright=Copyright © 2018 Alberto Fanjul Alonso
-Description=Provides integration with the Maven build tool
-Loader=python3
-Module=maven_plugin
+Copyright=Copyright © 2018 Alberto Fanjul Alonso, Copyright © 2022 Christian Hergert
+Description=Provides integration with the Maven build system
+Embedded=_gbp_maven_register_types
+Module=maven
 Name=Maven
 X-Category=buildsystems
-X-Builder-ABI=@PACKAGE_ABI@
 X-Project-File-Filter-Name=Maven (pom.xml)
 X-Project-File-Filter-Pattern=pom.xml
diff --git a/src/plugins/maven/meson.build b/src/plugins/maven/meson.build
index fc1a059d8..de050bf10 100644
--- a/src/plugins/maven/meson.build
+++ b/src/plugins/maven/meson.build
@@ -1,13 +1,21 @@
 if get_option('plugin_maven')
 
-install_data('maven_plugin.py', install_dir: plugindir)
-
-configure_file(
-          input: 'maven.plugin',
-         output: 'maven.plugin',
-  configuration: config_h,
-        install: true,
-    install_dir: plugindir,
+plugins_sources += files([
+  'maven-plugin.c',
+  'gbp-maven-build-system-discovery.c',
+  'gbp-maven-build-system.c',
+  'gbp-maven-pipeline-addin.c',
+  'gbp-maven-run-command-provider.c',
+  'gbp-maven-test.c',
+  'gbp-maven-test-provider.c',
+])
+
+plugin_maven_resources = gnome.compile_resources(
+  'maven-resources',
+  'maven.gresource.xml',
+  c_name: 'gbp_maven',
 )
 
+plugins_sources += plugin_maven_resources
+
 endif


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]