Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions assemblies/features/framework/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,11 @@
<groupId>org.apache.karaf.features</groupId>
<artifactId>org.apache.karaf.features.core</artifactId>
</dependency>
<dependency>
<groupId>org.apache.karaf.maven</groupId>
<artifactId>org.apache.karaf.maven.resolver.paxurl</artifactId>
<version>${project.version}</version>
</dependency>

</dependencies>

Expand Down
2 changes: 2 additions & 0 deletions assemblies/features/framework/src/main/feature/feature.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<bundle start-level="11">mvn:org.apache.felix/org.apache.felix.configurator/${felix.configurator.version}</bundle>
<bundle start-level="11">mvn:org.apache.karaf.config/org.apache.karaf.config.core/${project.version}</bundle>
<!-- features service -->
<bundle start-level="14">mvn:org.apache.karaf.maven/org.apache.karaf.maven.resolver.paxurl/${project.version}</bundle>
<bundle start-level="15">mvn:org.apache.karaf.features/org.apache.karaf.features.core/${project.version}</bundle>
<bundle dependency="true" start-level="14">mvn:jakarta.xml.bind/jakarta.xml.bind-api/${spec.jaxb-api.version}</bundle>
<bundle dependency="true" start-level="14">mvn:org.glassfish.jaxb/jaxb-runtime/${spec.jaxb.version}</bundle>
Expand Down Expand Up @@ -76,6 +77,7 @@
<!-- file install -->
<bundle start-level="12">mvn:org.apache.felix/org.apache.felix.fileinstall/${felix.fileinstall.version}</bundle>
<!-- features service -->
<bundle start-level="14">mvn:org.apache.karaf.maven/org.apache.karaf.maven.resolver.paxurl/${project.version}</bundle>
<bundle start-level="15">mvn:org.apache.karaf.features/org.apache.karaf.features.core/${project.version}</bundle>
<bundle dependency="true" start-level="14">mvn:jakarta.xml.bind/jakarta.xml.bind-api/${spec.jaxb-api.version}</bundle>
<bundle dependency="true" start-level="14">mvn:org.glassfish.jaxb/jaxb-runtime/${spec.jaxb.version}</bundle>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import org.apache.karaf.shell.api.action.lifecycle.Reference;
import org.apache.karaf.shell.api.action.lifecycle.Service;
import org.apache.karaf.shell.support.completers.FileCompleter;
import org.ops4j.pax.url.mvn.MavenResolver;
import org.apache.karaf.features.spi.MavenResolver;

/**
* Simple {@link FeaturesCommandSupport} implementation that allows a user in
Expand Down
28 changes: 1 addition & 27 deletions features/core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -129,24 +129,6 @@
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.ops4j.pax.url</groupId>
<artifactId>pax-url-aether</artifactId>
</dependency>

<dependency>
<groupId>org.ops4j.base</groupId>
<artifactId>ops4j-base-util-property</artifactId>
</dependency>
<dependency>
<groupId>org.ops4j.base</groupId>
<artifactId>ops4j-base-util-collections</artifactId>
</dependency>
<dependency>
<groupId>org.ops4j.pax.swissbox</groupId>
<artifactId>pax-swissbox-property</artifactId>
</dependency>

<dependency>
<groupId>jakarta.activation</groupId>
<artifactId>jakarta.activation-api</artifactId>
Expand All @@ -158,12 +140,6 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.ops4j.pax.tinybundles</groupId>
<artifactId>tinybundles</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
Expand Down Expand Up @@ -214,6 +190,7 @@
<instructions>
<Export-Package>
org.apache.karaf.features,
org.apache.karaf.features.spi,
org.apache.karaf.features.management,
org.apache.karaf.features.management.codec;-noimport:=true,
org.osgi.service.repository,
Expand Down Expand Up @@ -248,9 +225,6 @@
org.apache.karaf.util.xml,
org.eclipse.equinox.internal.region.*;-split-package:=merge-first,
org.apache.felix.resolver.*,
org.ops4j.pax.swissbox.*,
org.ops4j.util.*,
org.ops4j.lang.*,
com.fasterxml.jackson*
</Private-Package>
<Embed-Dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import java.util.concurrent.ScheduledExecutorService;

import org.apache.karaf.features.internal.download.impl.MavenDownloadManager;
import org.ops4j.pax.url.mvn.MavenResolver;
import org.apache.karaf.features.spi.MavenResolver;

public final class DownloadManagers {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/*
* 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.features.internal.download.impl;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.apache.karaf.features.spi.MavenResolver;
import org.apache.karaf.util.maven.Parser;

/**
* Resolves Maven coordinates from the Karaf distribution's local system repository only.
*/
public class LocalMavenResolver implements MavenResolver {

private final Path systemRepository;

public LocalMavenResolver(Path systemRepository) {
this.systemRepository = systemRepository.toAbsolutePath().normalize();
}

/**
* Create a resolver for the repository configured by the running Karaf distribution.
*
* @return a resolver rooted at {@code karaf.home/karaf.default.repository}.
*/
public static LocalMavenResolver forKarafSystem() {
Path home = Paths.get(System.getProperty("karaf.home", "karaf"));
Path repository = Paths.get(System.getProperty("karaf.default.repository", "system"));
if (!repository.isAbsolute()) {
repository = home.resolve(repository);
}
return new LocalMavenResolver(repository);
}

@Override
public File resolve(String url) throws IOException {
if (url == null || !url.startsWith("mvn:")) {
throw new MalformedURLException("Expected a mvn: URI: " + url);
}
String artifactPath = Parser.pathFromMaven(url);
Path artifact = systemRepository.resolve(artifactPath).normalize();
if (!artifact.startsWith(systemRepository)) {
throw new IOException("Maven artifact path is outside the Karaf system repository: " + url);
}
if (!artifact.toFile().isFile()) {
throw new FileNotFoundException("Maven artifact " + url + " was not found in the Karaf system repository "
+ systemRepository);
}
return artifact.toFile();
}

@Override
public File resolve(String url, Exception previousException) throws IOException {
return resolve(url);
}

@Override
public RetryChance isRetryableException(Exception exception) {
return RetryChance.NEVER;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import org.apache.karaf.features.internal.download.Downloader;
import org.apache.karaf.features.internal.download.StreamProvider;
import org.apache.karaf.features.internal.util.MultiException;
import org.ops4j.pax.url.mvn.MavenResolver;
import org.apache.karaf.features.spi.MavenResolver;

public class MavenDownloadManager implements DownloadManager {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import java.util.Objects;

import org.apache.karaf.util.maven.Parser;
import org.ops4j.pax.url.mvn.MavenResolver;
import org.apache.karaf.features.spi.MavenResolver;

public class MavenDownloadTask extends AbstractRetryableDownloadTask {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
import org.apache.karaf.features.internal.service.StateStorage;
import org.apache.karaf.features.internal.util.SystemExitManager;
import org.apache.karaf.util.ThreadUtils;
import org.apache.karaf.features.spi.MavenResolverFactory;
import org.apache.karaf.util.tracker.BaseActivator;
import org.apache.karaf.util.tracker.annotation.ProvideService;
import org.apache.karaf.util.tracker.annotation.RequireService;
Expand All @@ -76,15 +77,13 @@
import org.osgi.service.cm.ManagedService;
import org.osgi.service.repository.Repository;
import org.osgi.service.resolver.Resolver;
import org.osgi.service.url.URLStreamHandlerService;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import org.slf4j.LoggerFactory;

@Services(
requires = {
@RequireService(ConfigurationAdmin.class),
@RequireService(value = URLStreamHandlerService.class, filter = "(url.handler.protocol=mvn)")
@RequireService(ConfigurationAdmin.class)
},
provides = {
@ProvideService(FeaturesService.class),
Expand All @@ -102,6 +101,8 @@ public class Activator extends BaseActivator {
private static final String STATE_FILE = "state.json";

private ServiceTracker<FeaturesListener, FeaturesListener> featuresListenerTracker;
private ServiceTracker<MavenResolverFactory, MavenResolverFactory> mavenResolverFactoryTracker;
private volatile MavenResolverFactory mavenResolverFactory;
private FeaturesServiceImpl featuresService;
private SimpleFeaturesServiceImpl simpleFeaturesService;
private StandardManageableRegionDigraph digraphMBean;
Expand All @@ -118,6 +119,32 @@ public Activator() {
protected void doOpen() throws Exception {
super.doOpen();

// Keep the Maven resolver optional so this service can start without Pax URL.
mavenResolverFactoryTracker = new ServiceTracker<>(bundleContext, MavenResolverFactory.class,
new ServiceTrackerCustomizer<MavenResolverFactory, MavenResolverFactory>() {
@Override
public MavenResolverFactory addingService(ServiceReference<MavenResolverFactory> reference) {
MavenResolverFactory factory = bundleContext.getService(reference);
setMavenResolverFactory(factory);
return factory;
}

@Override
public void modifiedService(ServiceReference<MavenResolverFactory> reference,
MavenResolverFactory factory) {
}

@Override
public void removedService(ServiceReference<MavenResolverFactory> reference,
MavenResolverFactory factory) {
if (mavenResolverFactory == factory) {
setMavenResolverFactory(null);
}
bundleContext.ungetService(reference);
}
});
mavenResolverFactoryTracker.open();

Properties configuration = new Properties();
File configFile = new File(System.getProperty("karaf.etc"), FEATURES_SERVICE_CONFIG_FILE);
if (configFile.isFile() && configFile.canRead()) {
Expand Down Expand Up @@ -159,9 +186,8 @@ protected void doStart() throws Exception {
new LinkedBlockingQueue<>(),
ThreadUtils.namedThreadFactory("resolver"));
Resolver resolver = new ResolverImpl(new Slf4jResolverLog(LoggerFactory.getLogger(ResolverImpl.class)), executorService);
URLStreamHandlerService mvnUrlHandler = getTrackedService(URLStreamHandlerService.class);

if (configurationAdmin == null || mvnUrlHandler == null) {
if (configurationAdmin == null) {
return;
}

Expand Down Expand Up @@ -200,6 +226,7 @@ protected void doStart() throws Exception {
configurationAdmin,
installSupport,
cfg);
simpleFeaturesService.setMavenResolverFactory(mavenResolverFactory);
try {
EventAdminListener eventAdminListener = new EventAdminListener(bundleContext);
simpleFeaturesService.registerListener(eventAdminListener);
Expand All @@ -216,6 +243,7 @@ protected void doStart() throws Exception {
installSupport,
globalRepository,
cfg);
featuresService.setMavenResolverFactory(mavenResolverFactory);
try {
EventAdminListener eventAdminListener = new EventAdminListener(bundleContext);
featuresService.registerListener(eventAdminListener);
Expand Down Expand Up @@ -394,4 +422,23 @@ protected void doStop() {
}
}

@Override
protected void doClose() {
if (mavenResolverFactoryTracker != null) {
mavenResolverFactoryTracker.close();
mavenResolverFactoryTracker = null;
}
super.doClose();
}

private void setMavenResolverFactory(MavenResolverFactory factory) {
mavenResolverFactory = factory;
if (featuresService != null) {
featuresService.setMavenResolverFactory(factory);
}
if (simpleFeaturesService != null) {
simpleFeaturesService.setMavenResolverFactory(factory);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,8 @@
import org.apache.karaf.features.internal.model.processing.FeaturesProcessing;
import org.apache.karaf.features.internal.model.processing.ObjectFactory;
import org.apache.karaf.util.xml.IndentingXMLEventWriter;
import org.ops4j.pax.swissbox.property.BundleContextPropertyResolver;
import org.ops4j.util.property.DictionaryPropertyResolver;
import org.ops4j.util.property.PropertyResolver;
import org.apache.karaf.features.internal.util.PropertyResolver;
import org.apache.karaf.features.internal.util.PropertySubstitutor;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkUtil;
Expand Down Expand Up @@ -106,9 +105,9 @@ public FeaturesProcessing read(InputStream stream, Properties versions) throws E
Unmarshaller unmarshaller = FEATURES_PROCESSING_CONTEXT.createUnmarshaller();
UnmarshallerHandler handler = unmarshaller.getUnmarshallerHandler();

// BundleContextPropertyResolver gives access to e.g., ${karaf.base}
final PropertyResolver resolver = bundleContext == null ? new DictionaryPropertyResolver(versions)
: new DictionaryPropertyResolver(versions, new BundleContextPropertyResolver(bundleContext));
// the bundle context resolver gives access to e.g., ${karaf.base}
final PropertyResolver resolver = bundleContext == null ? PropertyResolver.forDictionary(versions)
: PropertyResolver.forDictionary(versions, PropertyResolver.forBundleContext(bundleContext));

// indirect unmarshaling with property resolution inside XML attribute values and CDATA
SAXParserFactory spf = SAXParserFactory.newInstance();
Expand Down Expand Up @@ -314,7 +313,7 @@ private void flushBuffer(boolean resolve) throws SAXException {
}

private String resolve(String value) {
String resolved = org.ops4j.util.collections.PropertyResolver.resolve(properties, value);
String resolved = PropertySubstitutor.substitute(properties, value);
if (resolved.contains("${")) {
// there are still unresolved properties - just log warning
LOG.warn("Value {} has unresolved properties, please check configuration.", value);
Expand Down
Loading
Loading