Search in sources :

Example 1 with ProfileBuilder

use of org.apache.karaf.profile.ProfileBuilder in project karaf by apache.

the class Builder method doGenerateAssembly.

private void doGenerateAssembly() throws Exception {
    LOGGER.info("Generating Karaf assembly: " + homeDirectory);
    // 
    // Create download manager - combination of pax-url-aether and a resolver wrapper that may
    // alter the way pax-url-aether resolver works
    // 
    MavenResolver resolver = createMavenResolver();
    manager = new CustomDownloadManager(resolver, executor, null, translatedUrls);
    this.resolver = new ResolverImpl(new Slf4jResolverLog(LOGGER));
    // 
    // Unzip KARs
    // 
    LOGGER.info("Unzipping kars");
    Downloader downloader = manager.createDownloader();
    for (String kar : kars.keySet()) {
        downloader.download(kar, null);
    }
    downloader.await();
    // stage as the KAR and with the same "add all" flag as the KAR itself
    for (String karUri : kars.keySet()) {
        LOGGER.info("   processing KAR: " + karUri);
        Kar kar = new Kar(manager.getProviders().get(karUri).getFile().toURI());
        kar.extract(systemDirectory.toFile(), homeDirectory.toFile());
        RepositoryInfo info = kars.get(karUri);
        for (URI repositoryUri : kar.getFeatureRepos()) {
            LOGGER.info("      found repository: " + repositoryUri);
            repositories.put(repositoryUri.toString(), info);
        }
    }
    // 
    // Load profiles
    // 
    LOGGER.info("Loading profiles from:");
    profilesUris.forEach(p -> LOGGER.info("   " + p));
    allProfiles = loadExternalProfiles(profilesUris);
    if (allProfiles.size() > 0) {
        StringBuilder sb = new StringBuilder();
        LOGGER.info("   Found profiles: " + allProfiles.keySet().stream().collect(Collectors.joining(", ")));
    }
    // Generate initial profile to collect overrides and blacklisting instructions
    Profile initialProfile = ProfileBuilder.Factory.create("initial").setParents(new ArrayList<>(profiles.keySet())).getProfile();
    Profile initialOverlay = Profiles.getOverlay(initialProfile, allProfiles, environment);
    Profile initialEffective = Profiles.getEffective(initialOverlay, false);
    // 
    // Handle blacklist - we'll use SINGLE instance of Blacklist for all further downloads
    // 
    blacklist = processBlacklist(initialEffective);
    // 
    // Configure blacklisting and overriding features processor
    // 
    boolean needFeaturesProcessorFileCopy = false;
    String existingProcessorDefinitionURI = null;
    Path existingProcessorDefinition = etcDirectory.resolve("org.apache.karaf.features.xml");
    if (existingProcessorDefinition.toFile().isFile()) {
        existingProcessorDefinitionURI = existingProcessorDefinition.toFile().toURI().toString();
        LOGGER.info("Found existing features processor configuration: {}", homeDirectory.relativize(existingProcessorDefinition));
    }
    if (featuresProcessingLocation != null && featuresProcessingLocation.toFile().isFile() && !featuresProcessingLocation.equals(existingProcessorDefinition)) {
        if (existingProcessorDefinitionURI != null) {
            LOGGER.warn("Explicitly configured {} will be used for features processor configuration.", homeDirectory.relativize(featuresProcessingLocation));
        } else {
            LOGGER.info("Found features processor configuration: {}", homeDirectory.relativize(featuresProcessingLocation));
        }
        existingProcessorDefinitionURI = featuresProcessingLocation.toFile().toURI().toString();
        // when there are no other (configured via Maven for example) processing instructions (e.g., blacklisting)
        // we don't have to generate this file and may take original content
        needFeaturesProcessorFileCopy = true;
    }
    // now we can configure blacklisting features processor which may have already defined (in XML)
    // configuration for bundle replacements or feature overrides.
    FeaturesProcessorImpl processor = new FeaturesProcessorImpl(existingProcessorDefinitionURI, null, blacklist, new HashSet<>());
    // add overrides from initialProfile
    Set<String> overrides = processOverrides(initialEffective.getOverrides());
    processor.addOverrides(overrides);
    // 
    // Propagate feature installation from repositories
    // 
    LOGGER.info("Loading repositories");
    Map<String, Features> karRepositories = loadRepositories(manager, repositories.keySet(), false, processor);
    for (String repo : repositories.keySet()) {
        RepositoryInfo info = repositories.get(repo);
        if (info.addAll) {
            LOGGER.info("   adding all non-blacklisted features from repository: " + repo + " (stage: " + info.stage + ")");
            for (Feature feature : karRepositories.get(repo).getFeature()) {
                if (feature.isBlacklisted()) {
                    LOGGER.info("      feature {}/{} is blacklisted - skipping.", feature.getId(), feature.getVersion());
                } else {
                    features.put(feature.getId(), info.stage);
                }
            }
        }
    }
    if (generateConsistencyReport != null) {
        File directory = new File(generateConsistencyReport);
        if (directory.isDirectory()) {
            LOGGER.info("Writing bundle report");
            generateConsistencyReport(karRepositories, new File(directory, "bundle-report-full.xml"), true);
            generateConsistencyReport(karRepositories, new File(directory, "bundle-report.xml"), false);
            Files.copy(getClass().getResourceAsStream("/bundle-report.xslt"), directory.toPath().resolve("bundle-report.xslt"), StandardCopyOption.REPLACE_EXISTING);
        }
    }
    // 
    // Generate profiles. If user has configured additional profiles, they'll be used as parents
    // of the generated ones.
    // 
    Profile startupProfile = generateProfile(Stage.Startup, profiles, repositories, features, bundles);
    allProfiles.put(startupProfile.getId(), startupProfile);
    // generated startup profile should be used (together with configured startup and boot profiles) as parent
    // of the generated boot profile - similar visibility rule (boot stage requires startup stage) is applied
    // for repositories and features
    profiles.put(startupProfile.getId(), Stage.Boot);
    Profile bootProfile = generateProfile(Stage.Boot, profiles, repositories, features, bundles);
    allProfiles.put(bootProfile.getId(), bootProfile);
    Profile installedProfile = generateProfile(Stage.Installed, profiles, repositories, features, bundles);
    allProfiles.put(installedProfile.getId(), installedProfile);
    // 
    // Compute "overlay" profile - a single profile with all parent profiles included (when there's the same
    // file in both profiles, parent profile's version has lower priority)
    // 
    ProfileBuilder builder = ProfileBuilder.Factory.create(UUID.randomUUID().toString()).setParents(Arrays.asList(startupProfile.getId(), bootProfile.getId(), installedProfile.getId()));
    config.forEach((k, v) -> builder.addConfiguration(Profile.INTERNAL_PID, Profile.CONFIG_PREFIX + k, v));
    system.forEach((k, v) -> builder.addConfiguration(Profile.INTERNAL_PID, Profile.SYSTEM_PREFIX + k, v));
    // profile with all the parents configured and stage-agnostic blacklisting configuration added
    blacklistedRepositoryURIs.forEach(builder::addBlacklistedRepository);
    blacklistedFeatureIdentifiers.forEach(builder::addBlacklistedFeature);
    blacklistedBundleURIs.forEach(builder::addBlacklistedBundle);
    // final profilep
    Profile overallProfile = builder.getProfile();
    // profile with parents included and "flattened" using inheritance rules (child files overwrite parent
    // files and child PIDs are merged with parent PIDs and same properties are taken from child profiles)
    Profile overallOverlay = Profiles.getOverlay(overallProfile, allProfiles, environment);
    // profile with property placeholders resolved or left unchanged (if there's no property value available,
    // so property placeholders are preserved - like ${karaf.base})
    Profile overallEffective = Profiles.getEffective(overallOverlay, false);
    if (writeProfiles) {
        Path profiles = etcDirectory.resolve("profiles");
        LOGGER.info("Adding profiles to {}", homeDirectory.relativize(profiles));
        allProfiles.forEach((id, profile) -> {
            try {
                Profiles.writeProfile(profiles, profile);
            } catch (IOException e) {
                LOGGER.warn("Problem writing profile {}: {}", id, e.getMessage());
            }
        });
    }
    manager = new CustomDownloadManager(resolver, executor, overallEffective, translatedUrls);
    // Hashtable<String, String> profileProps = new Hashtable<>(overallEffective.getConfiguration(ORG_OPS4J_PAX_URL_MVN_PID));
    // final Map<String, String> properties = new HashMap<>();
    // properties.put("karaf.default.repository", "system");
    // InterpolationHelper.performSubstitution(profileProps, properties::get, false, false, true);
    // 
    // Write config and system properties
    // 
    LOGGER.info("Configuring etc/config.properties and etc/system.properties");
    Path configPropertiesPath = etcDirectory.resolve("config.properties");
    Properties configProperties = new Properties(configPropertiesPath.toFile());
    configProperties.putAll(overallEffective.getConfig());
    configProperties.save();
    Path systemPropertiesPath = etcDirectory.resolve("system.properties");
    Properties systemProperties = new Properties(systemPropertiesPath.toFile());
    systemProperties.putAll(overallEffective.getSystem());
    systemProperties.save();
    // 
    // Download libraries
    // 
    // TODO: handle karaf 2.x and 3.x libraries
    downloader = manager.createDownloader();
    LOGGER.info("Downloading libraries for generated profiles");
    downloadLibraries(downloader, configProperties, overallEffective.getLibraries(), "");
    LOGGER.info("Downloading additional libraries");
    downloadLibraries(downloader, configProperties, libraries, "");
    downloader.await();
    // Reformat clauses
    reformatClauses(configProperties, Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
    reformatClauses(configProperties, Constants.FRAMEWORK_BOOTDELEGATION);
    configProperties.save();
    // 
    // Write all configuration files
    // 
    LOGGER.info("Writing configurations");
    for (Map.Entry<String, byte[]> config : overallEffective.getFileConfigurations().entrySet()) {
        Path configFile = etcDirectory.resolve(config.getKey());
        if (Files.exists(configFile)) {
            LOGGER.info("   not changing existing config file: {}", homeDirectory.relativize(configFile));
        } else {
            LOGGER.info("   adding config file: {}", homeDirectory.relativize(configFile));
            Files.createDirectories(configFile.getParent());
            Files.write(configFile, config.getValue());
        }
    }
    // 'improve' configuration files.
    if (propertyEdits != null) {
        KarafPropertiesEditor editor = new KarafPropertiesEditor();
        editor.setInputEtc(etcDirectory.toFile()).setOutputEtc(etcDirectory.toFile()).setEdits(propertyEdits);
        editor.run();
    }
    if (processor.hasInstructions()) {
        Path featuresProcessingXml = etcDirectory.resolve("org.apache.karaf.features.xml");
        if (hasOwnInstructions() || overrides.size() > 0) {
            // just generate new etc/org.apache.karaf.features.xml file (with external config + builder config)
            try (FileOutputStream fos = new FileOutputStream(featuresProcessingXml.toFile())) {
                LOGGER.info("Generating features processor configuration: {}", homeDirectory.relativize(featuresProcessingXml));
                processor.writeInstructions(fos);
            }
        } else if (needFeaturesProcessorFileCopy) {
            // we may simply copy configured features processor XML configuration
            LOGGER.info("Copying features processor configuration: {} -> {}", homeDirectory.relativize(featuresProcessingLocation), homeDirectory.relativize(featuresProcessingXml));
            Files.copy(featuresProcessingLocation, featuresProcessingXml, StandardCopyOption.REPLACE_EXISTING);
        }
    }
    // 
    // Startup stage
    // 
    Profile startupEffective = startupStage(startupProfile, processor);
    // 
    // Boot stage
    // 
    Set<Feature> allBootFeatures = bootStage(bootProfile, startupEffective, processor);
    // 
    // Installed stage
    // 
    installStage(installedProfile, allBootFeatures, processor);
}
Also used : ArrayList(java.util.ArrayList) Downloader(org.apache.karaf.features.internal.download.Downloader) ResolverImpl(org.apache.felix.resolver.ResolverImpl) Properties(org.apache.felix.utils.properties.Properties) URI(java.net.URI) Feature(org.apache.karaf.features.internal.model.Feature) ProfileBuilder(org.apache.karaf.profile.ProfileBuilder) Profile(org.apache.karaf.profile.Profile) FeaturesProcessorImpl(org.apache.karaf.features.internal.service.FeaturesProcessorImpl) MavenResolver(org.ops4j.pax.url.mvn.MavenResolver) Features(org.apache.karaf.features.internal.model.Features) Path(java.nio.file.Path) IOException(java.io.IOException) FileOutputStream(java.io.FileOutputStream) KarafPropertiesEditor(org.apache.karaf.tools.utils.KarafPropertiesEditor) Kar(org.apache.karaf.kar.internal.Kar) ConfigFile(org.apache.karaf.features.internal.model.ConfigFile) File(java.io.File) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) TreeMap(java.util.TreeMap)

Example 2 with ProfileBuilder

use of org.apache.karaf.profile.ProfileBuilder in project karaf by apache.

the class Profiles method loadProfiles.

/**
 * Loads profiles from given directory path. A profile is represented as directory with <code>.profile</code>
 * extension. Subdirectories constitute part of {@link Profile#getId} - directory separators are changed to
 * <code>-</code>.
 * For example, profile contained in directory <code>mq/broker/standalone.profile</code> will have
 * id = <code>mq-broker-standalone</code>.
 */
public static Map<String, Profile> loadProfiles(final Path root) throws IOException {
    final Map<String, Profile> profiles = new HashMap<>();
    Files.walkFileTree(root, new SimpleFileVisitor<Path>() {

        ProfileBuilder builder;

        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
            Path fileName = dir.getFileName();
            if (fileName != null && (fileName.toString().endsWith(PROFILE_FOLDER_SUFFIX) || fileName.toString().endsWith(PROFILE_FOLDER_SUFFIX + "/"))) {
                String profileId = root.relativize(dir).toString();
                if (profileId.endsWith("/")) {
                    profileId = profileId.substring(0, profileId.length() - 1);
                }
                profileId = profileId.replaceAll(root.getFileSystem().getSeparator(), "-");
                profileId = profileId.substring(0, profileId.length() - PROFILE_FOLDER_SUFFIX.length());
                builder = ProfileBuilder.Factory.create(profileId);
            }
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
            if (exc != null) {
                throw exc;
            }
            if (builder != null) {
                Profile profile = builder.getProfile();
                profiles.put(profile.getId(), profile);
                builder = null;
            }
            return FileVisitResult.CONTINUE;
        }

        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
            if (builder != null) {
                String pid = file.getFileName().toString();
                byte[] data = Files.readAllBytes(file);
                builder.addFileConfiguration(pid, data);
            }
            return FileVisitResult.CONTINUE;
        }
    });
    return profiles;
}
Also used : Path(java.nio.file.Path) HashMap(java.util.HashMap) FileVisitResult(java.nio.file.FileVisitResult) IOException(java.io.IOException) ProfileBuilder(org.apache.karaf.profile.ProfileBuilder) Profile(org.apache.karaf.profile.Profile) BasicFileAttributes(java.nio.file.attribute.BasicFileAttributes)

Example 3 with ProfileBuilder

use of org.apache.karaf.profile.ProfileBuilder in project karaf by apache.

the class Profiles method getOverlay.

/**
 * <p>Gets an <em>overlay</em> profile for given <code>profile</code>, where passed in map of additional profiles
 * is searched for possible parent profiles of given <code>profile</code>.</p>
 * <p><code>environment</code> may be used to select different <em>variants</em> of profile configuration files.
 * For example, if <code>environment</code> is specified, configuration for <code>my.pid</code> PID will be read
 * from <code>my.pid.cfg#&lt;environment&gt;</code>.</p>
 * @param profile
 * @param profiles
 * @param environment
 * @return
 */
public static Profile getOverlay(Profile profile, Map<String, Profile> profiles, String environment) {
    assertNotNull(profile, "profile is null");
    assertNotNull(profile, "profiles is null");
    if (profile.isOverlay()) {
        return profile;
    } else {
        String profileId = profile.getId();
        ProfileBuilder builder = ProfileBuilder.Factory.create(profileId);
        new OverlayOptionsProvider(profiles, profile, environment).addOptions(builder);
        return builder.getProfile();
    }
}
Also used : ProfileBuilder(org.apache.karaf.profile.ProfileBuilder)

Example 4 with ProfileBuilder

use of org.apache.karaf.profile.ProfileBuilder in project karaf by apache.

the class ProfilesTest method testProfilesApi.

@Test
public void testProfilesApi() throws IOException {
    ProfileBuilder builder = ProfileBuilder.Factory.create("my-simple-profile");
    builder.addParents(Collections.emptyList());
    builder.addAttribute("attr1", "val1");
    builder.addBundle("mvn:commons-everything/commons-everything/42");
    builder.addBlacklistedBundle("mvn:commons-banned/commons-banned/[42,52)");
    builder.addConfiguration("my.pid", "a1", "v1${profile:my.pid2/a2}");
    builder.addConfiguration("my.pid", "a2", "v1${profile:my.pid2/a3}");
    builder.addFeature("feature1");
    builder.addBlacklistedFeature("f34tu4e");
    builder.addFileConfiguration("my.pid2.txt", "hello!".getBytes("UTF-8"));
    builder.addFileConfiguration("my.pid2.cfg", "a2=v2".getBytes("UTF-8"));
    builder.addRepository("mvn:my/repository/1/xml/features");
    builder.addBlacklistedRepository("mvn:my/repository/[0,1)/xml/features");
    builder.setOptionals(Arrays.asList("mvn:g/a/1", "mvn:g/a/2"));
    builder.setOverrides(Arrays.asList("mvn:g/a/4", "mvn:g/a/3"));
    Profile profile = builder.getProfile();
    LOG.info("Profile: {}", profile.toString());
    LOG.info("Config: {}", profile.getConfig());
    LOG.info("Libraries: {}", profile.getLibraries());
    LOG.info("System: {}", profile.getSystem());
    LOG.info("Configurations: {}", profile.getConfigurations());
    LOG.info("ConfigurationFileNames: {}", profile.getConfigurationFileNames());
    LOG.info("FileConfigurations: {}", profile.getFileConfigurations().keySet());
    Profile effectiveProfile1 = Profiles.getEffective(profile, false);
    Profile effectiveProfile2 = Profiles.getEffective(profile, true);
    Map<String, Profile> profiles = new HashMap<>();
    profiles.put("x", profile);
    Profile overlayProfile = Profiles.getOverlay(profile, profiles);
    Profiles.writeProfile(Paths.get("target/p-" + UUID.randomUUID().toString()), profile);
    Profiles.writeProfile(Paths.get("target/ep1-" + UUID.randomUUID().toString()), effectiveProfile1);
    Profiles.writeProfile(Paths.get("target/ep2-" + UUID.randomUUID().toString()), effectiveProfile2);
    Profiles.writeProfile(Paths.get("target/op-" + UUID.randomUUID().toString()), overlayProfile);
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ProfileBuilder(org.apache.karaf.profile.ProfileBuilder) Profile(org.apache.karaf.profile.Profile) Test(org.junit.Test)

Example 5 with ProfileBuilder

use of org.apache.karaf.profile.ProfileBuilder in project karaf by apache.

the class ProfileEdit method editProfile.

private void editProfile(Profile profile) throws Exception {
    boolean editInLine = false;
    ProfileBuilder builder = ProfileBuilder.Factory.createFrom(profile);
    if (delete || remove) {
        editInLine = true;
    }
    if (features != null && features.length > 0) {
        editInLine = true;
        handleFeatures(builder, features, profile);
    }
    if (repositories != null && repositories.length > 0) {
        editInLine = true;
        handleFeatureRepositories(builder, repositories, profile);
    }
    if (libs != null && libs.length > 0) {
        editInLine = true;
        handleLibraries(builder, libs, profile, "lib", ProfileConstants.LIB_PREFIX);
    }
    if (endorsed != null && endorsed.length > 0) {
        editInLine = true;
        handleLibraries(builder, endorsed, profile, "endorsed lib", ProfileConstants.ENDORSED_PREFIX);
    }
    if (extension != null && extension.length > 0) {
        editInLine = true;
        handleLibraries(builder, extension, profile, "extension lib", ProfileConstants.EXT_PREFIX);
    }
    if (bundles != null && bundles.length > 0) {
        editInLine = true;
        handleBundles(builder, bundles, profile);
    }
    if (overrides != null && overrides.length > 0) {
        editInLine = true;
        handleOverrides(builder, overrides, profile);
    }
    if (pidProperties != null && pidProperties.length > 0) {
        editInLine = handlePid(builder, pidProperties, profile);
    }
    if (systemProperties != null && systemProperties.length > 0) {
        editInLine = true;
        handleSystemProperties(builder, systemProperties, profile);
    }
    if (configProperties != null && configProperties.length > 0) {
        editInLine = true;
        handleConfigProperties(builder, configProperties, profile);
    }
    if (!editInLine) {
        if (resource == null) {
            resource = Profile.INTERNAL_PID + Profile.PROPERTIES_SUFFIX;
        }
        // then open the resource in the editor.
        if (pidProperties != null && pidProperties.length == 1) {
            resource = pidProperties[0] + Profile.PROPERTIES_SUFFIX;
        }
        openInEditor(profile, resource);
    }
    profileService.updateProfile(builder.getProfile());
}
Also used : ProfileBuilder(org.apache.karaf.profile.ProfileBuilder)

Aggregations

ProfileBuilder (org.apache.karaf.profile.ProfileBuilder)6 HashMap (java.util.HashMap)4 IOException (java.io.IOException)3 Profile (org.apache.karaf.profile.Profile)3 Path (java.nio.file.Path)2 LinkedHashMap (java.util.LinkedHashMap)2 Map (java.util.Map)2 ByteArrayInputStream (java.io.ByteArrayInputStream)1 File (java.io.File)1 FileOutputStream (java.io.FileOutputStream)1 URI (java.net.URI)1 FileVisitResult (java.nio.file.FileVisitResult)1 BasicFileAttributes (java.nio.file.attribute.BasicFileAttributes)1 ArrayList (java.util.ArrayList)1 TreeMap (java.util.TreeMap)1 ResolverImpl (org.apache.felix.resolver.ResolverImpl)1 Properties (org.apache.felix.utils.properties.Properties)1 TypedProperties (org.apache.felix.utils.properties.TypedProperties)1 Downloader (org.apache.karaf.features.internal.download.Downloader)1 ConfigFile (org.apache.karaf.features.internal.model.ConfigFile)1