2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 * ============LICENSE_END=========================================================
18 package org.apache.nifi.nar;
20 import org.apache.nifi.bundle.Bundle;
21 import org.apache.nifi.bundle.BundleCoordinate;
22 import org.apache.nifi.bundle.BundleDetails;
25 import java.io.IOException;
26 import java.net.MalformedURLException;
29 import java.net.URLClassLoader;
30 import java.util.HashSet;
31 import java.util.List;
34 import java.util.jar.Manifest;
35 import java.util.stream.Collectors;
37 import com.fasterxml.jackson.core.JsonFactory;
38 import com.fasterxml.jackson.databind.ObjectMapper;
40 import java.util.jar.Attributes;
44 * Class responsible for loading JARs for DCAEProcessors into Nifi
46 public class DCAEClassLoaders {
48 public static class DCAEClassLoadersError extends RuntimeException {
49 public DCAEClassLoadersError(Throwable e) {
50 super("Error while using DCAEClassLoaders", e);
55 * Given a URL to a index.json file, fetches the file and generates a list of
56 * URLs for DCAE jars that has Processors packaged.
58 * @param indexDCAEJars
61 public static List<URL> getDCAEJarsURLs(URI indexDCAEJars) {
62 JsonFactory jf = new JsonFactory();
63 ObjectMapper om = new ObjectMapper();
66 List<Object> urls = om.readValue(jf.createParser(indexDCAEJars.toURL()), List.class);
68 return urls.stream().map(u -> {
70 Map<String, Object> foo = (Map<String, Object>) u;
71 String name = (String) foo.get("name");
72 String url = String.format("%s/%s", indexDCAEJars.toString(), name);
74 } catch (MalformedURLException e) {
75 // Hopefully you never come here...
78 }).collect(Collectors.toList());
79 } catch (Exception e) {
80 throw new RuntimeException("Error while getting jar URIs", e);
84 private static BundleDetails createBundleDetails(URLClassLoader classLoader) {
86 URL url = classLoader.findResource("META-INF/MANIFEST.MF");
87 Manifest manifest = new Manifest(url.openStream());
89 final Attributes attributes = manifest.getMainAttributes();
91 final BundleDetails.Builder builder = new BundleDetails.Builder();
92 // NOTE: Working directory cannot be null so set it to some bogus dir
93 // because we aren't really using this. Or maybe should create our own
95 builder.workingDir(new File("/tmp"));
97 final String group = attributes.getValue("Group");
98 final String id = attributes.getValue("Id");
99 final String version = attributes.getValue("Version");
100 builder.coordinate(new BundleCoordinate(group, id, version));
102 return builder.build();
103 } catch (IOException e) {
104 throw new DCAEClassLoadersError(e);
109 * From a list of URLs to remote JARs where the JARs contain DCAEProcessor classes,
110 * create a bundle for each JAR. You will never get a partial list of bundles.
115 public static Set<Bundle> createDCAEBundles(List<URL> jarURLs) {
116 Set<Bundle> bundles = new HashSet<>();
118 for (URL jarURL : jarURLs) {
119 URLClassLoader classLoader = new URLClassLoader(new URL[] {jarURL});
120 Bundle bundle = new Bundle(createBundleDetails(classLoader), classLoader);