com.yahoo.config.model.application.provider.Bundle Maven / Gradle / Ivy
The newest version!
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.config.model.application.provider;
import com.yahoo.collections.Tuple2;
import com.yahoo.vespa.config.util.ConfigUtils;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Objects;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
/**
* A Bundle represents an OSGi bundle inside the model, and provides utilities
* for accessing resources within that bundle.
*
* @author Tony Vaagenes, Ulf Lilleengen
* @since 5.1
*/
public class Bundle {
private static final Logger log = Logger.getLogger(Bundle.class.getName());
private static final String DEFPATH = "configdefinitions/"; // path inside jar file
private final File bundleFile;
private final JarFile jarFile;
private final List defEntries;
public Bundle(JarFile jarFile, File bundleFile) {
this.jarFile = jarFile;
this.bundleFile = bundleFile;
defEntries = List.copyOf(findDefEntries());
}
public static List getBundles(File bundleDir) {
try {
List bundles = new ArrayList<>();
for (File bundleFile : getBundleFiles(bundleDir)) {
JarFile jarFile;
try {
jarFile = new JarFile(bundleFile);
} catch (ZipException e) {
throw new IllegalArgumentException("Error opening jar file '" + bundleFile.getName() +
"'. Please check that this is a valid jar file");
}
bundles.add(new Bundle(jarFile, bundleFile));
}
return bundles;
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
private static List getBundleFiles(File bundleDir) {
if (!bundleDir.isDirectory()) {
return new ArrayList<>();
}
return List.of(Objects.requireNonNull(bundleDir.listFiles((dir, name) -> name.endsWith(".jar"))));
}
public List getDefEntries() {
return defEntries;
}
/**
* Returns a list of all .def-file entries in this Component.
* @return A list of .def-file entries.
*/
private List findDefEntries() {
List defEntries = new ArrayList<>();
ZipEntry defDir = jarFile.getEntry(DEFPATH);
if ((defDir == null) || !defDir.isDirectory())
return defEntries;
for (Enumeration entries = jarFile.entries(); entries.hasMoreElements();) {
JarEntry entry = entries.nextElement();
String name = entry.getName();
if (name.endsWith(".def")) {
if (name.matches("^" + DEFPATH + ".*\\.def$")) {
defEntries.add(new DefEntry(this, entry));
} else {
log.info("Config definition file '" + name + "' in component '" + jarFile.getName() +
"' will not be used. Files must reside in the '" + DEFPATH +
"' directory in the .jar file");
}
}
}
return defEntries;
}
public File getFile() {
return bundleFile;
}
/**
* Represents a def-file inside a Component. Immutable.
*/
public static final class DefEntry {
private final Bundle bundle;
private final ZipEntry zipEntry;
public final String defName; // Without version number and suffix.
public final String defNamespace;
public final String contents;
/**
* @param bundle The bundle this def entry belongs to.
* @param zipEntry The ZipEntry representing the def-file.
*/
public DefEntry(Bundle bundle, ZipEntry zipEntry) {
this.bundle = bundle;
this.zipEntry = zipEntry;
String entryName = zipEntry.getName();
Tuple2 nameAndNamespace = ConfigUtils.getNameAndNamespaceFromString(entryName.substring(DEFPATH.length(), entryName.indexOf(".def")));
defName = nameAndNamespace.first;
defNamespace = getNamespace();
if (defNamespace.isEmpty())
throw new IllegalArgumentException("Config definition '" + defName + "' is missing a package (or namespace)");
contents = getContents();
}
/**
* Returns the namespace of the .def-file, as given by the "namespace=" statement inside the given entry.
* @return The namespace string, or "" (empty string) if no namespace exists
*/
private String getNamespace() {
return ConfigUtils.getDefNamespace(getReader());
}
private String getContents() {
StringBuilder ret = new StringBuilder();
BufferedReader reader = new BufferedReader(getReader());
try {
String str = reader.readLine();
while (str != null){
ret.append(str);
str = reader.readLine();
if (str != null) {
ret.append("\n");
}
}
reader.close();
} catch (IOException e) {
throw new IllegalArgumentException("Failed reading contents of def-file '" + defName +
".def in component " + bundle.jarFile.getName(),e);
}
return ret.toString();
}
public Reader getReader() {
if (zipEntry == null) {
return new StringReader("");
}
try {
return new InputStreamReader(bundle.jarFile.getInputStream(zipEntry), StandardCharsets.UTF_8);
} catch (IOException e) {
throw new IllegalArgumentException("IOException", e);
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy