/** * 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.catalog.nexus; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; import java.util.Iterator; import java.util.Set; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.camel.catalog.CollectionStringBuffer; import org.apache.camel.catalog.connector.CamelConnectorCatalog; import static org.apache.camel.catalog.CatalogHelper.loadText; /** * Nexus repository that can scan for custom Camel connectors and add to the {@link CamelConnectorCatalog}. */ public class ConnectorCatalogNexusRepository extends BaseNexusRepository { private CamelConnectorCatalog camelConnectorCatalog; public ConnectorCatalogNexusRepository() { super("connector"); } public CamelConnectorCatalog getCamelConnectorCatalog() { return camelConnectorCatalog; } /** * Sets the {@link CamelConnectorCatalog} to be used. */ public void setCamelConnectorCatalog(CamelConnectorCatalog camelConnectorCatalog) { this.camelConnectorCatalog = camelConnectorCatalog; } @Override public void start() { if (camelConnectorCatalog == null) { throw new IllegalArgumentException("CamelConnectorCatalog must be configured"); } super.start(); } @Override public void onNewArtifacts(Set<NexusArtifactDto> newArtifacts) { // now download the new artifact JARs and look inside to find more details for (NexusArtifactDto dto : newArtifacts) { try { logger.debug("Processing new artifact: {}:{}:{}", dto.getGroupId(), dto.getArtifactId(), dto.getVersion()); String url = createArtifactURL(dto); URL jarUrl = new URL(url); addCustomCamelConnectorFromArtifact(dto, jarUrl); } catch (Throwable e) { logger.warn("Error downloading connector JAR " + dto.getArtifactLink() + ". This exception is ignored. " + e.getMessage()); } } } /** * Adds the connector to the data store * * @param dto the artifact * @param name the name of connector * @param scheme the connector scheme * @param javaType the connector java type * @param description the description of connector * @param labels the labels of connector * @param connectorJson camel-connector JSon * @param connectorSchemaJson camel-connector-schema JSon * @param componentSchemaJson camel-component-schema JSon */ protected void addConnector(NexusArtifactDto dto, String name, String scheme, String javaType, String description, String labels, String connectorJson, String connectorSchemaJson, String componentSchemaJson) { String groupId = dto.getGroupId(); String artifactId = dto.getArtifactId(); String version = dto.getVersion(); camelConnectorCatalog.addConnector(groupId, artifactId, version, name, scheme, javaType, description, labels, connectorJson, connectorSchemaJson, componentSchemaJson); logger.info("Added connector: {}:{}:{}", dto.getGroupId(), dto.getArtifactId(), dto.getVersion()); } /** * Adds any discovered third party Camel connectors from the artifact. */ private void addCustomCamelConnectorFromArtifact(NexusArtifactDto dto, URL jarUrl) { try (URLClassLoader classLoader = new URLClassLoader(new URL[] {jarUrl});) { String[] json = loadConnectorJSonSchema(classLoader); if (json != null) { ObjectMapper mapper = new ObjectMapper(); JsonNode tree = mapper.readTree(json[0]); String name = tree.get("name").textValue(); String scheme = tree.get("scheme").textValue(); String javaType = tree.get("javaType").textValue(); String description = tree.get("description").textValue(); Iterator<JsonNode> it = tree.withArray("labels").iterator(); CollectionStringBuffer csb = new CollectionStringBuffer(","); while (it.hasNext()) { String text = it.next().textValue(); csb.append(text); } addConnector(dto, name, scheme, javaType, description, csb.toString(), json[0], json[1], json[2]); } } catch (IOException e) { logger.warn("Error scanning JAR for custom Camel components", e); } } private String[] loadConnectorJSonSchema(ClassLoader classLoader) { String[] answer = new String[3]; String path = "camel-connector.json"; try { InputStream is = classLoader.getResourceAsStream(path); if (is != null) { answer[0] = loadText(is); } } catch (Throwable e) { logger.warn("Error loading " + path + " file", e); } path = "camel-connector-schema.json"; try { InputStream is = classLoader.getResourceAsStream(path); if (is != null) { answer[1] = loadText(is); } } catch (Throwable e) { logger.warn("Error loading " + path + " file", e); } path = "camel-component-schema.json"; try { InputStream is = classLoader.getResourceAsStream(path); if (is != null) { answer[2] = loadText(is); } } catch (Throwable e) { logger.warn("Error loading " + path + " file", e); } return answer; } }