Search in sources :

Example 1 with Artifact

use of org.jboss.fuse.patch.management.Artifact in project fuse-karaf by jboss-fuse.

the class KarafFeaturesPropertiesFileResolver method uris.

/**
 * Returns a map of groupId/artifactId -> artifact
 * @param uriStringsFromPatch
 * @return
 */
private Map<String, Artifact> uris(List<String> uriStringsFromPatch) {
    Map<String, Artifact> result = new LinkedHashMap<>();
    for (String uri : uriStringsFromPatch) {
        Artifact a = Utils.mvnurlToArtifact(uri, true);
        if (a == null) {
            continue;
        }
        String ga = String.format("%s/%s", a.getGroupId(), a.getArtifactId());
        result.put(ga, a);
    }
    return result;
}
Also used : Artifact(org.jboss.fuse.patch.management.Artifact) LinkedHashMap(java.util.LinkedHashMap)

Example 2 with Artifact

use of org.jboss.fuse.patch.management.Artifact in project fuse-karaf by jboss-fuse.

the class GitPatchManagementServiceImpl method updateOverrides.

/**
 * <p>Updates existing <code>etc/org.apache.karaf.features.xml</code> after installing single {@link PatchKind#NON_ROLLUP}
 * patch. Both bundle and feature replacements are taken into account.</p>
 * @param workTree
 * @param patches
 */
private void updateOverrides(File workTree, List<PatchData> patches) throws IOException {
    File overrides = new File(workTree, "etc/" + featureProcessing);
    File versions = new File(workTree, "etc/" + featureProcessingVersions);
    // we need two different versions to detect whether the version is externalized in etc/versions.properties
    FeaturesProcessing fp1;
    FeaturesProcessing fp2;
    if (overrides.isFile()) {
        fp1 = InternalUtils.loadFeatureProcessing(overrides, versions);
        fp2 = InternalUtils.loadFeatureProcessing(overrides, null);
    } else {
        fp1 = fp2 = new FeaturesProcessing();
    }
    List<BundleReplacements.OverrideBundle> br1 = fp1.getBundleReplacements().getOverrideBundles();
    List<BundleReplacements.OverrideBundle> br2 = fp2.getBundleReplacements().getOverrideBundles();
    org.apache.felix.utils.properties.Properties props = null;
    boolean propertyChanged = false;
    if (versions.isFile()) {
        props = new org.apache.felix.utils.properties.Properties(versions);
    }
    for (PatchData patchData : patches) {
        for (String bundle : patchData.getBundles()) {
            Artifact artifact = mvnurlToArtifact(bundle, true);
            if (artifact == null) {
                continue;
            }
            // Compute patch bundle version and range
            Version oVer = Utils.getOsgiVersion(artifact.getVersion());
            String vr = patchData.getVersionRange(bundle);
            if (vr != null && !vr.isEmpty()) {
                artifact.setVersion(vr);
            } else {
                Version v1 = new Version(oVer.getMajor(), oVer.getMinor(), 0);
                Version v2 = new Version(oVer.getMajor(), oVer.getMinor() + 1, 0);
                artifact.setVersion(new VersionRange(VersionRange.LEFT_CLOSED, v1, v2, VersionRange.RIGHT_OPEN).toString());
            }
            // features processing file may contain e.g.,:
            // <bundle originalUri="mvn:org.jboss.fuse/fuse-zen/[1,2)/war"
            // replacement="mvn:org.jboss.fuse/fuse-zen/${version.test2}/war" mode="maven" />
            // patch descriptor contains e.g.,:
            // bundle.0 = mvn:org.jboss.fuse/fuse-zen/1.2.0/war
            // bundle.0.range = [1.1,1.2)
            // 
            // we will always match by replacement attribute, ignoring originalUri - the patch descriptor must be
            // prepared correctly
            int idx = 0;
            BundleReplacements.OverrideBundle existing = null;
            // we'll examine model with resolved property placeholders, but modify the other one
            for (BundleReplacements.OverrideBundle override : br1) {
                LocationPattern lp = new LocationPattern(artifact.getCanonicalUri());
                if (lp.matches(override.getReplacement())) {
                    // we've found existing override in current etc/org.apache.karaf.features.xml
                    existing = br2.get(idx);
                    break;
                }
                idx++;
            }
            if (existing == null) {
                existing = new BundleReplacements.OverrideBundle();
                br2.add(existing);
            }
            // either update existing override or configure a new one
            existing.setMode(BundleReplacements.BundleOverrideMode.MAVEN);
            existing.setOriginalUri(artifact.getCanonicalUri());
            String replacement = existing.getReplacement();
            if (replacement != null && replacement.contains("${")) {
                // assume that we have existing replacement="mvn:org.jboss.fuse/fuse-zen/${version.test2}/war"
                // so we can't change the replacement and instead we have to update properties
                String property = null;
                String value = null;
                if (replacement.startsWith("mvn:")) {
                    LocationPattern existingReplacement = new LocationPattern(replacement);
                    property = existingReplacement.getVersionString().substring(existingReplacement.getVersionString().indexOf("${") + 2);
                    if (property.contains("}")) {
                        // it should...
                        property = property.substring(0, property.indexOf("}"));
                    }
                    LocationPattern newReplacement = new LocationPattern(bundle);
                    value = newReplacement.getVersionString();
                } else {
                // non-mvn? then we can't determine the version from non-mvn: URI...
                }
                // we are not changing replacement - we'll have to update properties
                if (props != null && property != null) {
                    props.setProperty(property, value);
                    propertyChanged = true;
                }
            } else {
                existing.setReplacement(bundle);
            }
        }
        // feature overrides
        File featureOverridesLocation = new File(patchData.getPatchDirectory(), "org.apache.karaf.features.xml");
        if (featureOverridesLocation.isFile()) {
            FeaturesProcessing featureOverrides = InternalUtils.loadFeatureProcessing(featureOverridesLocation, null);
            Map<String, FeatureReplacements.OverrideFeature> patchedFeatures = new LinkedHashMap<>();
            List<FeatureReplacements.OverrideFeature> mergedOverrides = new LinkedList<>();
            featureOverrides.getFeatureReplacements().getReplacements().forEach(of -> patchedFeatures.put(of.getFeature().getId(), of));
            fp2.getFeatureReplacements().getReplacements().forEach(of -> {
                FeatureReplacements.OverrideFeature override = patchedFeatures.remove(of.getFeature().getId());
                mergedOverrides.add(override == null ? of : override);
            });
            // add remaining
            mergedOverrides.addAll(patchedFeatures.values());
            fp2.getFeatureReplacements().getReplacements().clear();
            fp2.getFeatureReplacements().getReplacements().addAll(mergedOverrides);
        }
    }
    if (propertyChanged) {
        props.save();
    }
    InternalUtils.saveFeatureProcessing(fp2, overrides, versions);
}
Also used : BundleReplacements(org.apache.karaf.features.internal.model.processing.BundleReplacements) VersionRange(org.osgi.framework.VersionRange) FeatureReplacements(org.apache.karaf.features.internal.model.processing.FeatureReplacements) FeaturesProcessing(org.apache.karaf.features.internal.model.processing.FeaturesProcessing) LinkedHashMap(java.util.LinkedHashMap) Version(org.osgi.framework.Version) PatchData(org.jboss.fuse.patch.management.PatchData) Artifact(org.jboss.fuse.patch.management.Artifact) LinkedList(java.util.LinkedList) LocationPattern(org.apache.karaf.features.LocationPattern) ZipFile(org.apache.commons.compress.archivers.zip.ZipFile) File(java.io.File)

Example 3 with Artifact

use of org.jboss.fuse.patch.management.Artifact in project fuse-karaf by jboss-fuse.

the class GitPatchManagementServiceImpl method trackPatch.

/**
 * <p>This method turns static information about a patch into managed patch - i.e., patch added to git
 * repository.</p>
 *
 * <p>Such patch has its own branch ready to be merged (when patch is installed). Before installation we can verify
 * the patch,
 * examine the content, check the differences, conflicts and perform simulation (merge to temporary branch created
 * from main patch branch)</p>
 *
 * <p>The strategy is as follows:<ul>
 *     <li><em>main patch branch</em> in git repository tracks all changes (from baselines, patch-management
 *     system, patches and user changes)</li>
 *     <li>Initially there are 3 commits: baseline, patch-management bundle installation in etc/startup.properties,
 *     initial user changes</li>
 *     <li>We always <strong>tag the baseline commit</strong></li>
 *     <li>User changes may be applied each time Framework is restarted</li>
 *     <li>When we add a patch, we create <em>named branch</em> from the <strong>latest baseline</strong></li>
 *     <li>When we install a patch, we <strong>merge</strong> the patch branch with the <em>main patch branch</em>
 *     (that may contain additional user changes)</li>
 *     <li>When patch ZIP contains new baseline distribution, after merging patch branch, we tag the merge commit
 *     in <em>main patch branch</em> branch as new baseline</li>
 *     <li>Branches for new patches will then be created from new baseline commit</li>
 * </ul></p>
 * @param patchData
 * @return
 */
@Override
public Patch trackPatch(PatchData patchData) throws PatchException {
    try {
        awaitInitialization();
    } catch (InterruptedException e) {
        throw new PatchException("Patch management system is not ready yet");
    }
    Git fork = null;
    try {
        Git mainRepository = gitPatchRepository.findOrCreateMainGitRepository();
        // prepare single fork for all the below operations
        fork = gitPatchRepository.cloneRepository(mainRepository, true);
        // 1. find current baseline
        RevTag latestBaseline = gitPatchRepository.findCurrentBaseline(fork);
        if (latestBaseline == null) {
            throw new PatchException("Can't find baseline distribution tracked in patch management. Is patch management initialized?");
        }
        // the commit from the patch should be available from main patch branch
        RevCommit commit = new RevWalk(fork.getRepository()).parseCommit(latestBaseline.getObject());
        // create dedicated branch for this patch. We'll immediately add patch content there so we can examine the
        // changes from the latest baseline
        gitPatchRepository.checkout(fork).setCreateBranch(true).setName("patch-" + patchData.getId()).setStartPoint(commit).call();
        // copy patch resources (but not maven artifacts from system/ or repository/) to working copy
        if (patchData.getPatchDirectory() != null) {
            boolean removeTargetDir = patchData.isRollupPatch();
            copyManagedDirectories(patchData.getPatchDirectory(), fork.getRepository().getWorkTree(), removeTargetDir, false, false);
        }
        // add the changes
        fork.add().addFilepattern(".").call();
        // remove the deletes
        for (String missing : fork.status().call().getMissing()) {
            fork.rm().addFilepattern(missing).call();
        }
        // record information about other "patches" included in added patch (e.g., Fuse patch
        // may contain patches to instance:create based containers in standalone mode)
        StringWriter sw = new StringWriter();
        sw.append("# tags for patches included in \"").append(patchData.getId()).append("\"\n");
        for (String bundle : patchData.getBundles()) {
            // containers that want to patch:install patches added in root containers
            if (bundle.contains("mvn:org.apache.karaf.instance/org.apache.karaf.instance.core/")) {
                Artifact a = Utils.mvnurlToArtifact(bundle, true);
                if (a != null) {
                    sw.append(String.format(EnvType.STANDALONE_CHILD.getBaselineTagFormat(), a.getVersion())).append("\n");
                }
                break;
            }
        }
        FileUtils.write(new File(fork.getRepository().getWorkTree(), "patch-info.txt"), sw.toString(), "UTF-8");
        fork.add().addFilepattern(".").call();
        // commit the changes (patch vs. baseline) to patch branch
        gitPatchRepository.prepareCommit(fork, String.format("[PATCH] Tracking patch %s", patchData.getId())).call();
        // push the patch branch
        gitPatchRepository.push(fork, "patch-" + patchData.getId());
        // for instance:create child containers
        trackBaselinesForChildContainers(fork);
        return new Patch(patchData, gitPatchRepository.getManagedPatch(patchData.getId()));
    } catch (IOException | GitAPIException e) {
        throw new PatchException(e.getMessage(), e);
    } finally {
        if (fork != null) {
            gitPatchRepository.closeRepository(fork, true);
        }
    }
}
Also used : RevTag(org.eclipse.jgit.revwalk.RevTag) IOException(java.io.IOException) RevWalk(org.eclipse.jgit.revwalk.RevWalk) Artifact(org.jboss.fuse.patch.management.Artifact) GitAPIException(org.eclipse.jgit.api.errors.GitAPIException) Git(org.eclipse.jgit.api.Git) StringWriter(java.io.StringWriter) PatchException(org.jboss.fuse.patch.management.PatchException) ZipFile(org.apache.commons.compress.archivers.zip.ZipFile) File(java.io.File) Patch(org.jboss.fuse.patch.management.Patch) ManagedPatch(org.jboss.fuse.patch.management.ManagedPatch) RevCommit(org.eclipse.jgit.revwalk.RevCommit)

Example 4 with Artifact

use of org.jboss.fuse.patch.management.Artifact in project fuse-karaf by jboss-fuse.

the class GitPatchManagementServiceImpl method gatherOverrides.

/**
 * Returns list of bundle updates (maven coordinates) from HF/P patch that should be preserved during
 * installation of R patch
 * @param hfPatchId ID of patch that was detected to be HF patch installed previously (before R patch just being installed)
 * @param patch R patch which is currently being installed
 * @return an artificial {@link PatchData} with a list of maven URIs for bundles that are newer in previous P-patches than the ones in currently installed R-patch
 */
private PatchData gatherOverrides(String hfPatchId, Patch patch) {
    Patch hf = loadPatch(new PatchDetailsRequest(hfPatchId));
    List<String> bundles = new LinkedList<>();
    Map<String, String> ranges = new LinkedHashMap<>();
    if (hf != null && hf.getPatchData() != null) {
        for (String bundle : hf.getPatchData().getBundles()) {
            bundles.add(bundle);
            String versionRange = hf.getPatchData().getVersionRange(bundle);
            if (versionRange != null && !versionRange.trim().equals("")) {
                ranges.put(bundle, versionRange);
            }
        }
        // leave only these artifacts that are in newer version than in R patch being installed
        if (patch != null && patch.getPatchData() != null) {
            Map<String, Artifact> cache = new HashMap<>();
            for (String bu : patch.getPatchData().getBundles()) {
                Artifact rPatchArtifact = Utils.mvnurlToArtifact(bu, true);
                if (rPatchArtifact != null) {
                    cache.put(String.format("%s:%s", rPatchArtifact.getGroupId(), rPatchArtifact.getArtifactId()), rPatchArtifact);
                }
            }
            for (String bu : hf.getPatchData().getBundles()) {
                Artifact hfPatchArtifact = Utils.mvnurlToArtifact(bu, true);
                if (hfPatchArtifact != null) {
                    String key = String.format("%s:%s", hfPatchArtifact.getGroupId(), hfPatchArtifact.getArtifactId());
                    if (cache.containsKey(key)) {
                        Version hfVersion = Utils.getOsgiVersion(hfPatchArtifact.getVersion());
                        Version rVersion = Utils.getOsgiVersion(cache.get(key).getVersion());
                        if (rVersion.compareTo(hfVersion) >= 0) {
                            bundles.remove(bu);
                            ranges.remove(bu);
                        }
                    }
                }
            }
        }
    }
    return new PatchData(null, null, bundles, null, ranges, null, null);
}
Also used : PatchData(org.jboss.fuse.patch.management.PatchData) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) Version(org.osgi.framework.Version) Patch(org.jboss.fuse.patch.management.Patch) ManagedPatch(org.jboss.fuse.patch.management.ManagedPatch) PatchDetailsRequest(org.jboss.fuse.patch.management.PatchDetailsRequest) LinkedList(java.util.LinkedList) Artifact(org.jboss.fuse.patch.management.Artifact) LinkedHashMap(java.util.LinkedHashMap)

Example 5 with Artifact

use of org.jboss.fuse.patch.management.Artifact in project fuse-karaf by jboss-fuse.

the class GitPatchManagementServiceImpl method determineVersion.

/**
 * Return version of product used, but probably based on different karafHome
 * @param home
 * @return
 */
private String determineVersion(File home) {
    if (env == EnvType.STANDALONE) {
        File versions = new File(home, "etc/version.properties");
        if (versions.exists() && versions.isFile()) {
            Properties props = new Properties();
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(versions);
                props.load(fis);
                return props.getProperty("version");
            } catch (IOException e) {
                Activator.log(LogService.LOG_ERROR, null, e.getMessage(), e, true);
                return null;
            } finally {
                Utils.closeQuietly(fis);
            }
        } else {
            Activator.log2(LogService.LOG_ERROR, "Can't find etc/version.properties");
        }
    } else {
        // for child container we have to be more careful and not examine root container's etc/version.properties!
        File startup = new File(home, "etc/startup.properties");
        if (startup.exists() && startup.isFile()) {
            Properties props = new Properties();
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(startup);
                props.load(fis);
                for (String key : props.stringPropertyNames()) {
                    if (key.contains("org.apache.karaf.features/org.apache.karaf.features.core/")) {
                        Artifact artifact = Utils.mvnurlToArtifact(key, true);
                        if (artifact != null) {
                            return artifact.getVersion();
                        }
                    }
                }
            } catch (IOException e) {
                Activator.log(LogService.LOG_ERROR, null, e.getMessage(), e, true);
                return null;
            } finally {
                Utils.closeQuietly(fis);
            }
        } else {
            Activator.log2(LogService.LOG_ERROR, "Can't find etc/startup.properties file in child container");
        }
    }
    return null;
}
Also used : IOException(java.io.IOException) Properties(java.util.Properties) ZipFile(org.apache.commons.compress.archivers.zip.ZipFile) File(java.io.File) FileInputStream(java.io.FileInputStream) Artifact(org.jboss.fuse.patch.management.Artifact)

Aggregations

Artifact (org.jboss.fuse.patch.management.Artifact)9 File (java.io.File)6 LinkedHashMap (java.util.LinkedHashMap)4 LinkedList (java.util.LinkedList)4 Version (org.osgi.framework.Version)4 IOException (java.io.IOException)3 HashMap (java.util.HashMap)3 Properties (java.util.Properties)3 ZipFile (org.apache.commons.compress.archivers.zip.ZipFile)3 Patch (org.jboss.fuse.patch.management.Patch)3 PatchData (org.jboss.fuse.patch.management.PatchData)3 Bundle (org.osgi.framework.Bundle)3 FileInputStream (java.io.FileInputStream)2 JarFile (java.util.jar.JarFile)2 Git (org.eclipse.jgit.api.Git)2 BundleUpdate (org.jboss.fuse.patch.management.BundleUpdate)2 ManagedPatch (org.jboss.fuse.patch.management.ManagedPatch)2 BundleStartLevel (org.osgi.framework.startlevel.BundleStartLevel)2 FileOutputStream (java.io.FileOutputStream)1 FileReader (java.io.FileReader)1