blob: 4f7805962ab9dc5a5f0cd4c6edc65c25016914a1 [file] [log] [blame]
/*
* 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.karaf.profile.assembly;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import org.apache.karaf.features.internal.download.Downloader;
import org.apache.karaf.features.internal.model.Config;
import org.apache.karaf.features.internal.model.ConfigFile;
import org.apache.karaf.features.internal.model.Content;
import org.apache.karaf.features.internal.model.Feature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Installs PID configuration to <code>${karaf.etc}</code> and <code>system/</code> directory.
*/
public class ConfigInstaller {
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigInstaller.class);
private Path etcDirectory;
private List<String> pidsToExtract;
public ConfigInstaller(Path etcDirectory, List<String> pidsToExtract) {
this.etcDirectory = etcDirectory;
this.pidsToExtract = pidsToExtract;
}
public void installConfigs(Feature feature, Downloader downloader, ArtifactInstaller installer)
throws Exception {
List<Content> contents = new ArrayList<>();
contents.add(feature);
contents.addAll(feature.getConditional());
for (Content content : contents) {
// Install config files
for (Config config : content.getConfig()) {
if (config.isExternal()) {
installer.installArtifact(config.getValue().trim());
}
}
for (ConfigFile configFile : content.getConfigfile()) {
installer.installArtifact(configFile.getLocation().trim());
}
// Extract configs
Path homeDirectory = etcDirectory.getParent();
for (Config config : content.getConfig()) {
if (pidMatching(config.getName())) {
Path configFile = etcDirectory.resolve(config.getName() + ".cfg");
boolean configFileExist = Files.exists(configFile);
if (!config.isAppend() && configFileExist) {
LOGGER.info(" not changing existing config file: {}", homeDirectory.relativize(configFile));
continue;
}
if (config.isExternal()) {
downloader.download(config.getValue().trim(), provider -> {
synchronized (provider) {
if (config.isAppend()) {
byte[] data = Files.readAllBytes(provider.getFile().toPath());
LOGGER.info(" appending to config file: {}", homeDirectory.relativize(configFile));
Files.write(configFile, data, StandardOpenOption.APPEND);
} else {
LOGGER.info(" adding config file: {}", homeDirectory.relativize(configFile));
Files.copy(provider.getFile().toPath(), configFile, StandardCopyOption.REPLACE_EXISTING);
}
}
});
} else {
if (config.isAppend()) {
if (configFileExist) {
LOGGER.info(" appending to config file: {}", homeDirectory.relativize(configFile));
Files.write(configFile, config.getValue().getBytes(), StandardOpenOption.APPEND);
}
else
LOGGER.warn(" Could not append, because config file does not exist: {}", homeDirectory.relativize(configFile));
} else {
LOGGER.info(" adding config file: {}", homeDirectory.relativize(configFile));
Files.write(configFile, config.getValue().getBytes());
}
}
}
}
}
}
private boolean pidMatching(String name) {
if (pidsToExtract == null) {
return true;
}
for (String p : pidsToExtract) {
boolean negated = false;
if (p.startsWith("!")) {
negated = true;
p = p.substring(1);
}
String r = globToRegex(p);
if (Pattern.matches(r, name)) {
return !negated;
}
}
return false;
}
private String globToRegex(String pattern) {
StringBuilder sb = new StringBuilder(pattern.length());
int inGroup = 0;
int inClass = 0;
int firstIndexInClass = -1;
char[] arr = pattern.toCharArray();
for (int i = 0; i < arr.length; i++) {
char ch = arr[i];
switch (ch) {
case '\\':
if (++i >= arr.length) {
sb.append('\\');
} else {
char next = arr[i];
switch (next) {
case ',':
// escape not needed
break;
case 'Q':
case 'E':
// extra escape needed
sb.append('\\');
default:
sb.append('\\');
}
sb.append(next);
}
break;
case '*':
if (inClass == 0)
sb.append(".*");
else
sb.append('*');
break;
case '?':
if (inClass == 0)
sb.append('.');
else
sb.append('?');
break;
case '[':
inClass++;
firstIndexInClass = i + 1;
sb.append('[');
break;
case ']':
inClass--;
sb.append(']');
break;
case '.':
case '(':
case ')':
case '+':
case '|':
case '^':
case '$':
case '@':
case '%':
if (inClass == 0 || (firstIndexInClass == i && ch == '^'))
sb.append('\\');
sb.append(ch);
break;
case '!':
if (firstIndexInClass == i)
sb.append('^');
else
sb.append('!');
break;
case '{':
inGroup++;
sb.append('(');
break;
case '}':
inGroup--;
sb.append(')');
break;
case ',':
if (inGroup > 0)
sb.append('|');
else
sb.append(',');
break;
default:
sb.append(ch);
}
}
return sb.toString();
}
}