1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.common.config;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.net.URI;
25 import java.net.URISyntaxException;
26 import java.net.URL;
27 import java.util.Collections;
28 import java.util.Enumeration;
29 import java.util.Properties;
30 import java.util.SortedSet;
31 import java.util.TreeSet;
32 import java.util.jar.Attributes;
33 import java.util.jar.Attributes.Name;
34 import java.util.jar.Manifest;
35 import java.util.stream.Collectors;
36
37 import org.apache.logging.log4j.LogManager;
38 import org.apache.logging.log4j.Logger;
39 import org.mycore.common.MCRClassTools;
40
41 import com.google.common.collect.Sets;
42
43
44
45
46
47
48
49
50
51 public class MCRRuntimeComponentDetector {
52
53 private static Logger LOGGER = LogManager.getLogger(MCRRuntimeComponentDetector.class);
54
55 private static final Name ATT_POM = new Name("POM");
56
57 private static final Name ATT_MCR_APPLICATION_MODULE = new Name("MCR-Application-Module");
58
59 private static final Name ATT_MCR_ARTIFACT_ID = new Name("MCR-Artifact-Id");
60
61 private static SortedSet<MCRComponent> ALL_COMPONENTS = Collections
62 .unmodifiableSortedSet(getConfiguredComponents());
63
64 private static SortedSet<MCRComponent> MYCORE_COMPONENTS = Collections.unmodifiableSortedSet(
65 ALL_COMPONENTS.stream()
66 .filter(MCRComponent::isMyCoReComponent)
67 .collect(Collectors.toCollection(TreeSet::new)));
68
69 private static SortedSet<MCRComponent> APP_MODULES = Collections.unmodifiableSortedSet(
70 ALL_COMPONENTS.stream()
71 .filter(MCRComponent::isAppModule)
72 .collect(Collectors.toCollection(TreeSet::new)));
73
74 private static SortedSet<MCRComponent> getConfiguredComponents() {
75 try {
76 String underTesting = System.getProperty("MCRRuntimeComponentDetector.underTesting");
77 Enumeration<URL> resources = MCRClassTools.getClassLoader().getResources("META-INF/MANIFEST.MF");
78 if (!resources.hasMoreElements() && underTesting == null) {
79 LOGGER.warn("Did not find any Manifests.");
80 return Collections.emptySortedSet();
81 }
82 SortedSet<MCRComponent> components = Sets.newTreeSet();
83 while (resources.hasMoreElements()) {
84 URL manifestURL = resources.nextElement();
85 try (InputStream manifestStream = manifestURL.openStream()) {
86 Manifest manifest = new Manifest(manifestStream);
87 MCRComponent component = buildComponent(manifest, manifestURL);
88
89 if (component != null) {
90 components.add(component);
91 }
92 }
93 }
94 if (underTesting != null) {
95
96 MCRComponent component = new MCRComponent(underTesting, new Manifest());
97 components.add(component);
98 }
99 return components;
100 } catch (IOException e) {
101 LOGGER.warn("Error while detecting MyCoRe components", e);
102 return Sets.newTreeSet();
103 }
104 }
105
106 private static MCRComponent buildComponent(Manifest manifest, URL manifestURL) throws IOException {
107 Attributes mainAttributes = manifest.getMainAttributes();
108 String artifactId = mainAttributes.getValue(ATT_MCR_ARTIFACT_ID);
109 String pomPropertiesPath = mainAttributes.getValue(ATT_POM);
110 boolean usePomProperties = false;
111
112 if (artifactId == null) {
113 if (!mainAttributes.containsKey(ATT_POM)) {
114 return null;
115 }
116
117 if (pomPropertiesPath == null) {
118 return null;
119 }
120
121 try (InputStream pi = MCRClassTools.getClassLoader().getResourceAsStream(
122 pomPropertiesPath)) {
123 if (pi == null) {
124 LOGGER.warn("Manifest entry {} set to \"{}\", but resource could not be loaded.", ATT_POM,
125 pomPropertiesPath);
126 return null;
127 }
128 Properties pomProperties = new Properties();
129 pomProperties.load(pi);
130 artifactId = (String) pomProperties.get("artifactId");
131 usePomProperties = true;
132 }
133 }
134
135 if (artifactId != null && artifactId.startsWith("mycore-")
136 || mainAttributes.containsKey(ATT_MCR_APPLICATION_MODULE)) {
137 if (usePomProperties) {
138 LOGGER.warn("No Attribute \"{}\" in Manifest of {}.", ATT_MCR_ARTIFACT_ID,
139 mainAttributes.getValue(ATT_MCR_APPLICATION_MODULE));
140 LOGGER.warn("Change this in the future, pom.properties path definition is deprecated.");
141 LOGGER.info("Using artifactId in {}.", pomPropertiesPath);
142 }
143
144 return new MCRComponent(artifactId, manifest, extractJarFile(manifestURL));
145 }
146 return null;
147 }
148
149 private static File extractJarFile(URL manifestURL) {
150 try {
151 if (manifestURL.toExternalForm().startsWith("jar:")) {
152 return new File(new URI(manifestURL.getPath().replaceAll("!.*$", "")));
153 }
154 } catch (URISyntaxException e) {
155 LOGGER.error("Couldn't extract jar file path from MANIFEST.MF url.", e);
156 }
157
158 return null;
159 }
160
161
162
163
164
165
166 public static SortedSet<MCRComponent> getAllComponents() {
167 return ALL_COMPONENTS;
168 }
169
170
171
172
173
174
175 public static SortedSet<MCRComponent> getMyCoReComponents() {
176 return MYCORE_COMPONENTS;
177 }
178
179
180
181
182
183
184 public static SortedSet<MCRComponent> getApplicationModules() {
185 return APP_MODULES;
186 }
187
188 }