You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2021/12/30 12:04:25 UTC

[camel] 09/30: CAMEL-17384: Developer Console SPI

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

davsclaus pushed a commit to branch console
in repository https://gitbox.apache.org/repos/asf/camel.git

commit efa35d52edbf10c0e86ba8c0a5c5f611347ed143
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Mon Dec 27 15:07:43 2021 +0100

    CAMEL-17384: Developer Console SPI
---
 .../apache/camel/console/DevConsoleRegistry.java   | 113 ++++++++++++++
 .../impl/console/DefaultDevConsoleRegistry.java    | 163 +++++++++++++++++++++
 2 files changed, 276 insertions(+)

diff --git a/core/camel-api/src/main/java/org/apache/camel/console/DevConsoleRegistry.java b/core/camel-api/src/main/java/org/apache/camel/console/DevConsoleRegistry.java
new file mode 100644
index 0000000..03ecf79
--- /dev/null
+++ b/core/camel-api/src/main/java/org/apache/camel/console/DevConsoleRegistry.java
@@ -0,0 +1,113 @@
+/*
+ * 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.camel.console;
+
+import java.util.Collection;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.StaticService;
+import org.apache.camel.spi.IdAware;
+import org.apache.camel.util.ObjectHelper;
+
+/**
+ * A registry for dev console.
+ */
+public interface DevConsoleRegistry extends CamelContextAware, StaticService, IdAware {
+
+    /**
+     * Service factory name.
+     */
+    String NAME = "default-registry";
+
+    /**
+     * Service factory key.
+     */
+    String FACTORY = "console/" + NAME;
+
+    /**
+     * Whether dev console is enabled globally
+     */
+    boolean isEnabled();
+
+    /**
+     * Whether dev console is enabled globally
+     */
+    void setEnabled(boolean enabled);
+
+    /**
+     * Resolves {@link DevConsole by id.
+     *
+     * Will first lookup in this {@link DevConsoleRegistry} and then {@link org.apache.camel.spi.Registry}, and lastly
+     * do classpath scanning via {@link org.apache.camel.spi.annotations.ServiceFactory}.
+     *
+     * @return either {@link DevConsole}, or <tt>null</tt> if none found.
+     */
+    Object resolveById(String id);
+
+    /**
+     * Registers a {@link DevConsole}.
+     */
+    boolean register(DevConsole console);
+
+    /**
+     * Unregisters a {@link DevConsole}.
+     */
+    boolean unregister(DevConsole console);
+
+    /**
+     * A collection of dev console IDs.
+     */
+    default Collection<String> getConsoleIDs() {
+        return stream()
+                .map(DevConsole::getId)
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * Returns the dev console identified by the given <code>id</code> if available.
+     */
+    default Optional<DevConsole> getConsole(String id) {
+        return stream()
+                .filter(r -> ObjectHelper.equal(r.getId(), id))
+                .findFirst();
+    }
+
+    /**
+     * Returns an optional {@link DevConsoleRegistry}, by default no registry is present, and it must be explicit
+     * activated. Components can register/unregister dev consoles in response to life-cycle events (i.e. start/stop).
+     *
+     * This registry is not used by the camel context, but it is up to the implementation to properly use it.
+     */
+    static DevConsoleRegistry get(CamelContext context) {
+        return context.getExtension(DevConsoleRegistry.class);
+    }
+
+    /**
+     * Returns a sequential {@code Stream} with the known {@link DevConsole} as its source.
+     */
+    Stream<DevConsole> stream();
+
+    /**
+     * Loads custom dev consoles by scanning classpath.
+     */
+    void loadDevConsoles();
+
+}
diff --git a/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsoleRegistry.java b/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsoleRegistry.java
new file mode 100644
index 0000000..2fde33f
--- /dev/null
+++ b/core/camel-console/src/main/java/org/apache/camel/impl/console/DefaultDevConsoleRegistry.java
@@ -0,0 +1,163 @@
+/*
+ * 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.camel.impl.console;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.CamelContextAware;
+import org.apache.camel.DeferredContextBinding;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.console.DevConsole;
+import org.apache.camel.console.DevConsoleRegistry;
+import org.apache.camel.console.DevConsoleResolver;
+import org.apache.camel.support.service.ServiceSupport;
+import org.apache.camel.util.StopWatch;
+import org.apache.camel.util.TimeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.stream.Stream;
+
+/**
+ * Default {@link org.apache.camel.console.DevConsoleRegistry}.
+ */
+@org.apache.camel.spi.annotations.DevConsole(DevConsoleRegistry.NAME)
+@DeferredContextBinding
+public class DefaultDevConsoleRegistry extends ServiceSupport implements DevConsoleRegistry {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultDevConsoleRegistry.class);
+
+    private String id = "camel-console";
+    private CamelContext camelContext;
+    private final Set<DevConsole> consoles;
+    private boolean enabled = true;
+    private volatile boolean loadDevConsolesDone;
+
+    public DefaultDevConsoleRegistry() {
+        this(null);
+    }
+
+    public DefaultDevConsoleRegistry(CamelContext camelContext) {
+        this.consoles = new CopyOnWriteArraySet<>();
+        setCamelContext(camelContext);
+    }
+
+    @Override
+    public String getId() {
+        return id;
+    }
+
+    @Override
+    public void setId(String id) {
+        this.id = id;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    protected void doInit() throws Exception {
+        super.doInit();
+
+        for (DevConsole console : consoles) {
+            CamelContextAware.trySetCamelContext(console, camelContext);
+        }
+    }
+
+    @Override
+    public DevConsole resolveById(String id) {
+        DevConsole answer = consoles.stream().filter(h -> h.getId().equals(id)).findFirst()
+                .orElse(camelContext.getRegistry().findByTypeWithName(DevConsole.class).get(id));
+        if (answer == null) {
+            DevConsoleResolver resolver = camelContext.adapt(ExtendedCamelContext.class).getDevConsoleResolver();
+            answer = resolver.resolveDevConsole(id);
+        }
+
+        return answer;
+    }
+
+    @Override
+    public boolean register(DevConsole console) {
+        boolean result;
+        // do we have this already
+        if (getConsole(console.getId()).isPresent()) {
+            return false;
+        }
+        result = consoles.add(console);
+        if (result) {
+            CamelContextAware.trySetCamelContext(console, camelContext);
+            LOG.debug("DevConsole with id {} successfully registered", console.getId());
+        }
+        return result;
+    }
+
+    @Override
+    public boolean unregister(DevConsole console) {
+        boolean result;
+
+        result = consoles.remove(console);
+        if (result) {
+            LOG.debug("DevConsole with id {} successfully un-registered", console.getId());
+        }
+        return result;
+    }
+
+    @Override
+    public Stream<DevConsole> stream() {
+        if (enabled) {
+            return consoles.stream();
+        }
+        return Stream.empty();
+    }
+
+    @Override
+    public void loadDevConsoles() {
+        StopWatch watch = new StopWatch();
+
+        if (!loadDevConsolesDone) {
+            loadDevConsolesDone = true;
+
+            DefaultDevConsolesLoader loader = new DefaultDevConsolesLoader(camelContext);
+            Collection<DevConsole> col = loader.loadDevConsoles();
+
+            // report how many health checks we have loaded
+            if (col.size() > 0) {
+                String time = TimeUtils.printDuration(watch.taken());
+                LOG.info("Dev consoles (scanned: {}) loaded in {}", col.size(), time);
+            }
+        }
+    }
+}