Repository: karaf Updated Branches: refs/heads/master 3f6bca010 -> e920dde01
http://git-wip-us.apache.org/repos/asf/karaf/blob/e920dde0/profile/src/main/java/org/apache/karaf/profile/assembly/CustomSimpleDownloadTask.java ---------------------------------------------------------------------- diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/CustomSimpleDownloadTask.java b/profile/src/main/java/org/apache/karaf/profile/assembly/CustomSimpleDownloadTask.java new file mode 100644 index 0000000..94f5475 --- /dev/null +++ b/profile/src/main/java/org/apache/karaf/profile/assembly/CustomSimpleDownloadTask.java @@ -0,0 +1,161 @@ +/* + * 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.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.concurrent.ScheduledExecutorService; + +import org.apache.karaf.deployer.blueprint.BlueprintTransformer; +import org.apache.karaf.deployer.spring.SpringTransformer; +import org.apache.karaf.features.internal.download.impl.AbstractRetryableDownloadTask; +import org.apache.karaf.profile.Profile; + +public class CustomSimpleDownloadTask extends AbstractRetryableDownloadTask { + + private static final String WRAP_URI_PREFIX = "wrap"; + private static final String SPRING_URI_PREFIX = "spring"; + private static final String BLUEPRINT_URI_PREFIX = "blueprint"; + private static final String WAR_URI_PREFIX = "war"; + private static final String PROFILE_URI_PREFIX = "profile"; + + private final Profile profile; + + public CustomSimpleDownloadTask(ScheduledExecutorService executorService, Profile profile, String url) { + super(executorService, url); + this.profile = profile; + } + + @Override + protected File download() throws Exception { + URL url = createUrl(getUrl()); + Path path = Files.createTempFile("download-", null); + try (InputStream is = url.openStream()) { + Files.copy(is, path, StandardCopyOption.REPLACE_EXISTING); + } + return path.toFile(); + } + + private URL createUrl(String url) throws MalformedURLException, URISyntaxException { + URLStreamHandler handler = getUrlStreamHandler(url); + if (handler != null) { + return new URL(null, url, handler); + } else { + return new URL(url); + } + } + + private URLStreamHandler getUrlStreamHandler(String url) throws URISyntaxException { + String scheme = new URI(url).getScheme(); + switch (scheme) { + case WRAP_URI_PREFIX: + return new org.ops4j.pax.url.wrap.Handler(); + case WAR_URI_PREFIX: + return new org.ops4j.pax.url.war.Handler(); + case SPRING_URI_PREFIX: + return new SpringURLHandler(); + case BLUEPRINT_URI_PREFIX: + return new BlueprintURLHandler(); + case PROFILE_URI_PREFIX: + if (profile != null) { + return new ProfileURLHandler(); + } + default: + return null; + } + } + + public class SpringURLHandler extends URLStreamHandler { + @Override + protected URLConnection openConnection(URL u) throws IOException { + return new URLConnection(u) { + @Override + public void connect() throws IOException { + } + + @Override + public InputStream getInputStream() throws IOException { + try { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + SpringTransformer.transform(createUrl(url.getPath()), os); + os.close(); + return new ByteArrayInputStream(os.toByteArray()); + } catch (Exception e) { + throw new IOException("Error opening spring xml url", e); + } + } + }; + } + } + + public class BlueprintURLHandler extends URLStreamHandler { + @Override + protected URLConnection openConnection(URL u) throws IOException { + return new URLConnection(u) { + @Override + public void connect() throws IOException { + } + + @Override + public InputStream getInputStream() throws IOException { + try { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + BlueprintTransformer.transform(createUrl(url.getPath()), os); + os.close(); + return new ByteArrayInputStream(os.toByteArray()); + } catch (Exception e) { + throw new IOException("Error opening blueprint xml url", e); + } + } + }; + } + } + + public class ProfileURLHandler extends URLStreamHandler { + @Override + protected URLConnection openConnection(URL u) throws IOException { + return new URLConnection(u) { + @Override + public void connect() throws IOException { + } + + @Override + public InputStream getInputStream() throws IOException { + String path = url.getPath(); + byte[] data = profile.getFileConfiguration(path); + if (data == null) { + throw new FileNotFoundException(url.toExternalForm()); + } + return new ByteArrayInputStream(data); + } + }; + } + } +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e920dde0/profile/src/main/java/org/apache/karaf/profile/assembly/FakeBundleRevision.java ---------------------------------------------------------------------- diff --git a/profile/src/main/java/org/apache/karaf/profile/assembly/FakeBundleRevision.java b/profile/src/main/java/org/apache/karaf/profile/assembly/FakeBundleRevision.java new file mode 100644 index 0000000..7b797d6 --- /dev/null +++ b/profile/src/main/java/org/apache/karaf/profile/assembly/FakeBundleRevision.java @@ -0,0 +1,157 @@ +/* + * 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.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.util.Hashtable; +import java.util.List; + +import org.apache.karaf.features.internal.resolver.ResourceBuilder; +import org.apache.karaf.features.internal.resolver.ResourceImpl; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; +import org.osgi.framework.Version; +import org.osgi.framework.startlevel.BundleStartLevel; +import org.osgi.framework.wiring.BundleCapability; +import org.osgi.framework.wiring.BundleRequirement; +import org.osgi.framework.wiring.BundleRevision; +import org.osgi.framework.wiring.BundleWiring; + +/** + * Fake bundle revision implementation for resolution simulations without OSGi. + */ +public class FakeBundleRevision extends ResourceImpl implements BundleRevision, BundleStartLevel { + + private final Bundle bundle; + private int startLevel; + + public FakeBundleRevision(final Hashtable<String, String> headers, final String location, final long bundleId) throws BundleException { + ResourceBuilder.build(this, location, headers); + this.bundle = (Bundle) Proxy.newProxyInstance( + getClass().getClassLoader(), + new Class[]{Bundle.class}, + new BundleRevisionInvocationHandler(headers, location, bundleId)); + } + + @Override + public int getStartLevel() { + return startLevel; + } + + @Override + public void setStartLevel(int startLevel) { + this.startLevel = startLevel; + } + + @Override + public boolean isPersistentlyStarted() { + return true; + } + + @Override + public boolean isActivationPolicyUsed() { + return false; + } + + @Override + public String getSymbolicName() { + return bundle.getSymbolicName(); + } + + @Override + public Version getVersion() { + return bundle.getVersion(); + } + + @Override + public List<BundleCapability> getDeclaredCapabilities(String namespace) { + throw new UnsupportedOperationException(); + } + + @Override + public List<BundleRequirement> getDeclaredRequirements(String namespace) { + throw new UnsupportedOperationException(); + } + + @Override + public int getTypes() { + throw new UnsupportedOperationException(); + } + + @Override + public BundleWiring getWiring() { + throw new UnsupportedOperationException(); + } + + @Override + public Bundle getBundle() { + return bundle; + } + + private class BundleRevisionInvocationHandler implements InvocationHandler { + + private final Hashtable<String, String> headers; + private final String location; + private final long bundleId; + + public BundleRevisionInvocationHandler(Hashtable<String, String> headers, String location, long bundleId) { + this.headers = headers; + this.location = location; + this.bundleId = bundleId; + } + + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + if (method.getName().equals("hashCode")) { + return FakeBundleRevision.this.hashCode(); + } else if (method.getName().equals("equals")) { + return proxy == args[0]; + } else if (method.getName().equals("toString")) { + return bundle.getSymbolicName() + "/" + bundle.getVersion(); + } else if (method.getName().equals("adapt")) { + if (args.length == 1 && args[0] == BundleRevision.class) { + return FakeBundleRevision.this; + } else if (args.length == 1 && args[0] == BundleStartLevel.class) { + return FakeBundleRevision.this; + } + } else if (method.getName().equals("getHeaders")) { + return headers; + } else if (method.getName().equals("getBundleId")) { + return bundleId; + } else if (method.getName().equals("getLocation")) { + return location; + } else if (method.getName().equals("getSymbolicName")) { + String name = headers.get(Constants.BUNDLE_SYMBOLICNAME); + int idx = name.indexOf(';'); + if (idx > 0) { + name = name.substring(0, idx).trim(); + } + return name; + } else if (method.getName().equals("getVersion")) { + return new Version(headers.get(Constants.BUNDLE_VERSION)); + } else if (method.getName().equals("getState")) { + return Bundle.ACTIVE; + } else if (method.getName().equals("getLastModified")) { + return 0l; + } + return null; + } + } +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e920dde0/profile/src/main/java/org/apache/karaf/profile/impl/ProfileImpl.java ---------------------------------------------------------------------- diff --git a/profile/src/main/java/org/apache/karaf/profile/impl/ProfileImpl.java b/profile/src/main/java/org/apache/karaf/profile/impl/ProfileImpl.java index d2111fd..48b064e 100644 --- a/profile/src/main/java/org/apache/karaf/profile/impl/ProfileImpl.java +++ b/profile/src/main/java/org/apache/karaf/profile/impl/ProfileImpl.java @@ -40,7 +40,7 @@ final class ProfileImpl implements Profile { private static final Pattern ALLOWED_PROFILE_NAMES_PATTERN = Pattern.compile("^[A-Za-z0-9]+[\\.A-Za-z0-9_-]*$"); private final String profileId; - private final Map<String, String> attributes = new HashMap<>(); + private final Map<String, String> attributes; private final List<String> parents = new ArrayList<>(); private final Map<String, byte[]> fileConfigurations = new HashMap<>(); private final Map<String, Map<String, String>> configurations = new HashMap<>(); @@ -72,17 +72,8 @@ final class ProfileImpl implements Profile { } } - // Attributes are agent configuration with prefix 'attribute.' - Map<String, String> agentConfig = configurations.get(Profile.INTERNAL_PID); - if (agentConfig != null) { - int prefixLength = Profile.ATTRIBUTE_PREFIX.length(); - for (Entry<String, String> entry : agentConfig.entrySet()) { - String key = entry.getKey(); - if (key.startsWith(Profile.ATTRIBUTE_PREFIX)) { - attributes.put(key.substring(prefixLength), entry.getValue()); - } - } - } + // Attributes are agent configuration with prefix 'attribute.' + attributes = getPrefixedMap(ATTRIBUTE_PREFIX); } public String getId() { @@ -95,6 +86,31 @@ final class ProfileImpl implements Profile { } @Override + public Map<String, String> getConfig() { + return getPrefixedMap(CONFIG_PREFIX); + } + + @Override + public Map<String, String> getSystem() { + return getPrefixedMap(SYSTEM_PREFIX); + } + + private Map<String, String> getPrefixedMap(String prefix) { + Map<String, String> map = new HashMap<>(); + Map<String, String> agentConfig = configurations.get(Profile.INTERNAL_PID); + if (agentConfig != null) { + int prefixLength = prefix.length(); + for (Entry<String, String> entry : agentConfig.entrySet()) { + String key = entry.getKey(); + if (key.startsWith(prefix)) { + map.put(key.substring(prefixLength), entry.getValue()); + } + } + } + return map; + } + + @Override public List<String> getLibraries() { return getContainerConfigList(ConfigListType.LIBRARIES); } http://git-wip-us.apache.org/repos/asf/karaf/blob/e920dde0/profile/src/test/java/org/apache/karaf/profile/assembly/BuilderTest.java ---------------------------------------------------------------------- diff --git a/profile/src/test/java/org/apache/karaf/profile/assembly/BuilderTest.java b/profile/src/test/java/org/apache/karaf/profile/assembly/BuilderTest.java new file mode 100644 index 0000000..dc7fbcd --- /dev/null +++ b/profile/src/test/java/org/apache/karaf/profile/assembly/BuilderTest.java @@ -0,0 +1,68 @@ +/* + * 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.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.junit.Test; + +public class BuilderTest { + + @Test + public void testBuilder() throws Exception { + + Path workDir = Paths.get("target/distrib"); + recursiveDelete(workDir); + + Builder builder = Builder.newInstance() + .staticFramework() + .profilesUris("jar:mvn:org.apache.karaf.demos.profiles/registry/4.0.0-SNAPSHOT!/") + .environment("static") + .profiles("karaf", + "example-loanbroker-bank1", + "example-loanbroker-bank2", + "example-loanbroker-bank3", + "example-loanbroker-broker", + "activemq-broker") + .homeDirectory(workDir); + + try { + builder.generateAssembly(); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + private static void recursiveDelete(Path path) throws IOException { + if (Files.exists(path)) { + if (Files.isDirectory(path)) { + try (DirectoryStream<Path> children = Files.newDirectoryStream(path)) { + for (Path child : children) { + recursiveDelete(child); + } + } + } + Files.delete(path); + } + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e920dde0/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java ---------------------------------------------------------------------- diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java index e36e0ed..c4b451d 100644 --- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java +++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/InstallKarsMojo.java @@ -18,52 +18,11 @@ */ package org.apache.karaf.tooling.features; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.net.URI; -import java.net.URL; -import java.nio.file.FileSystem; -import java.nio.file.FileSystemNotFoundException; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardCopyOption; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.LinkedHashMap; -import java.util.LinkedHashSet; import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; -import java.util.UUID; - -import org.apache.felix.utils.properties.InterpolationHelper; -import org.apache.felix.utils.properties.Properties; -import org.apache.karaf.features.internal.download.impl.DownloadManagerHelper; -import org.apache.karaf.features.internal.model.Bundle; -import org.apache.karaf.features.internal.model.Conditional; -import org.apache.karaf.features.internal.model.Config; -import org.apache.karaf.features.internal.model.ConfigFile; -import org.apache.karaf.features.internal.model.Dependency; -import org.apache.karaf.features.internal.model.Feature; -import org.apache.karaf.features.internal.model.Features; -import org.apache.karaf.features.internal.model.JaxbUtil; -import org.apache.karaf.features.internal.util.MapUtils; -import org.apache.karaf.kar.internal.Kar; -import org.apache.karaf.profile.Profile; -import org.apache.karaf.profile.ProfileBuilder; -import org.apache.karaf.profile.impl.Profiles; -import org.apache.karaf.tooling.url.CustomBundleURLStreamHandlerFactory; -import org.apache.karaf.tooling.utils.InternalMavenResolver; + +import org.apache.karaf.profile.assembly.Builder; import org.apache.karaf.tooling.utils.IoUtils; import org.apache.karaf.tooling.utils.MojoSupport; import org.apache.maven.artifact.Artifact; @@ -73,7 +32,6 @@ import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; -import org.ops4j.pax.url.mvn.MavenResolver; /** * Installs kar dependencies into a server-under-construction in target/assembly @@ -182,16 +140,9 @@ public class InstallKarsMojo extends MojoSupport { // an access layer for available Aether implementation protected DependencyHelper dependencyHelper; - private static final String FEATURES_REPOSITORIES = "featuresRepositories"; - private static final String FEATURES_BOOT = "featuresBoot"; - @Override public void execute() throws MojoExecutionException, MojoFailureException { - this.dependencyHelper = DependencyHelperFactory.createDependencyHelper(this.container, this.project, this.mavenSession, getLog()); - MavenResolver resolver = new InternalMavenResolver(dependencyHelper, getLog()); - CustomBundleURLStreamHandlerFactory.install(resolver); - try { doExecute(); } @@ -201,20 +152,9 @@ public class InstallKarsMojo extends MojoSupport { catch (Exception e) { throw new MojoExecutionException("Unable to build assembly", e); } - finally { - CustomBundleURLStreamHandlerFactory.uninstall(); - } } protected void doExecute() throws Exception { - this.dependencyHelper = DependencyHelperFactory.createDependencyHelper(this.container, this.project, this.mavenSession, getLog()); - - // creating system directory - getLog().info("Creating system directory"); - systemDirectory.mkdirs(); - - IoUtils.deleteRecursive(new File(systemDirectory, "generated")); - startupRepositories = nonNullList(startupRepositories); bootRepositories = nonNullList(bootRepositories); installedRepositories = nonNullList(installedRepositories); @@ -241,576 +181,97 @@ public class InstallKarsMojo extends MojoSupport { installedRepositories.addAll(featureRepositories); } - // Build optional features and known prerequisites - Map<String, List<String>> prereqs = new HashMap<>(); - prereqs.put("blueprint:", Arrays.asList("deployer", "aries-blueprint")); - prereqs.put("spring:", Arrays.asList("deployer", "spring")); - prereqs.put("wrap:", Arrays.asList("wrap")); - prereqs.put("war:", Arrays.asList("war")); + Builder builder = Builder.newInstance(); + + // creating system directory + getLog().info("Creating work directory"); + builder.homeDirectory(workDirectory.toPath()); + IoUtils.deleteRecursive(workDirectory); + workDirectory.mkdirs(); + List<String> startupKars = new ArrayList<>(); + List<String> bootKars = new ArrayList<>(); + List<String> installedKars = new ArrayList<>(); // Loading kars and features repositories getLog().info("Loading kar and features repositories dependencies"); for (Artifact artifact : project.getDependencyArtifacts()) { + Builder.Stage stage; + switch (artifact.getScope()) { + case "compile": + stage = Builder.Stage.Startup; + break; + case "runtime": + stage = Builder.Stage.Boot; + break; + case "provided": + stage = Builder.Stage.Installed; + break; + default: + continue; + } if ("kar".equals(artifact.getType())) { - File karFile = artifact.getFile(); - getLog().info("Extracting " + artifact.toString() + " kar"); - try { - Kar kar = new Kar(karFile.toURI()); - kar.extract(systemDirectory, workDirectory); - for (URI repositoryUri : kar.getFeatureRepos()) { - switch (artifact.getScope()) { - case "compile": - startupRepositories.add(repositoryUri.getPath()); - break; - case "runtime": - bootRepositories.add(repositoryUri.getPath()); - break; - case "provided": - installedRepositories.add(repositoryUri.getPath()); - break; - } - } - } catch (Exception e) { - throw new RuntimeException("Can not install " + artifact.toString() + " kar", e); + String uri = dependencyHelper.artifactToMvn(artifact); + switch (stage) { + case Startup: startupKars.add(uri); break; + case Boot: bootKars.add(uri); break; + case Installed: installedKars.add(uri); break; } } else if ("features".equals(artifact.getClassifier())) { - String repositoryUri = dependencyHelper.artifactToMvn(artifact); - switch (artifact.getScope()) { - case "compile": - startupRepositories.add(repositoryUri); - break; - case "runtime": - bootRepositories.add(repositoryUri); - break; - case "provided": - installedRepositories.add(repositoryUri); - break; + String uri = dependencyHelper.artifactToMvn(artifact); + switch (stage) { + case Startup: startupRepositories.add(uri); break; + case Boot: bootRepositories.add(uri); break; + case Installed: installedRepositories.add(uri); break; } } else if ("jar".equals(artifact.getType()) || "bundle".equals(artifact.getType())) { - String bundleUri = dependencyHelper.artifactToMvn(artifact); - switch (artifact.getScope()) { - case "compile": - startupBundles.add(bundleUri); - break; - case "runtime": - bootBundles.add(bundleUri); - break; - case "provided": - installedBundles.add(bundleUri); - break; + String uri = dependencyHelper.artifactToMvn(artifact); + switch (stage) { + case Startup: startupBundles.add(uri); break; + case Boot: bootBundles.add(uri); break; + case Installed: installedBundles.add(uri); break; } } } - // Load profiles - Map<String, Profile> allProfiles; + builder.use24SyntaxForStartup(use24SyntaxForStartup) + .useReferenceUrls(useReferenceUrls) + .defaultAddAll(installAllFeaturesByDefault) + .ignoreDependencyFlag(ignoreDependencyFlag); if (profilesUri != null) { - URI profileURI = URI.create(profilesUri); - Path profilePath; - try { - profilePath = Paths.get(profileURI); - } catch (FileSystemNotFoundException e) { - // file system does not exist, try to create it - FileSystem fs = FileSystems.newFileSystem(profileURI, new HashMap<String, Object>(), InstallKarsMojo.class.getClassLoader()); - profilePath = fs.provider().getPath(profileURI); - } - allProfiles = Profiles.loadProfiles(profilePath); - } else { - allProfiles = new HashMap<>(); - } - // Generate profiles - Profile startupProfile = generateProfile(allProfiles, startupProfiles, startupRepositories, startupFeatures, startupBundles); - Profile bootProfile = generateProfile(allProfiles, bootProfiles, bootRepositories, bootFeatures, bootBundles); - Profile installedProfile = generateProfile(allProfiles, installedProfiles, installedRepositories, installedFeatures, installedBundles); - - // - // Compute overall profile - // - Profile overallProfile = ProfileBuilder.Factory.create(UUID.randomUUID().toString()) - .setParents(Arrays.asList(startupProfile.getId(), bootProfile.getId(), installedProfile.getId())) - .getProfile(); - Profile overallOverlay = Profiles.getOverlay(overallProfile, allProfiles); - Profile overallEffective = Profiles.getEffective(overallOverlay, false); - - Hashtable<String, String> agentProps = new Hashtable<>(overallEffective.getConfiguration("org.ops4j.pax.url.mvn")); - final Map<String, String> properties = new HashMap<>(); - properties.put("karaf.default.repository", "system"); - InterpolationHelper.performSubstitution(agentProps, new InterpolationHelper.SubstitutionCallback() { - @Override - public String getValue(String key) { - return properties.get(key); - } - }, false, false, true); - - // - // Write all configuration files - // - for (Map.Entry<String, byte[]> config : overallEffective.getFileConfigurations().entrySet()) { - Path configFile = workDirectory.toPath().resolve("etc/" + config.getKey()); - Files.createDirectories(configFile.getParent()); - Files.write(configFile, config.getValue()); - } - - // - // Compute startup - // - Profile startupOverlay = Profiles.getOverlay(startupProfile, allProfiles); - Profile startupEffective = Profiles.getEffective(startupOverlay, false); - // Load startup repositories - Map<String, Features> startupRepositories = loadRepositories(startupEffective.getRepositories()); - // Compute startup feature dependencies - Set<Feature> allStartupFeatures = new HashSet<>(); - for (Features repo : startupRepositories.values()) { - allStartupFeatures.addAll(repo.getFeature()); - } - Set<Feature> startupFeatures = new LinkedHashSet<>(); - if (startupEffective.getFeatures().isEmpty() && installAllFeaturesByDefault) { - startupFeatures.addAll(allStartupFeatures); - } else { - for (String feature : startupEffective.getFeatures()) { - addFeatures(startupFeatures, allStartupFeatures, feature); - } - } - // Compute all bundles - Map<String, Integer> allStartupBundles = new LinkedHashMap<>(); - for (Feature feature : startupFeatures) { - for (Bundle bundleInfo : feature.getBundle()) { - String bundleLocation = bundleInfo.getLocation().trim(); - int bundleStartLevel = bundleInfo.getStartLevel() == 0 ? defaultStartLevel : bundleInfo.getStartLevel(); - if (allStartupBundles.containsKey(bundleLocation)) { - bundleStartLevel = Math.min(bundleStartLevel, allStartupBundles.get(bundleLocation)); - } - allStartupBundles.put(bundleLocation, bundleStartLevel); - } - // Install config - for (Config config : feature.getConfig()) { - installConfig(config); - } - for (Conditional cond : feature.getConditional()) { - boolean doInstall = true; - for (Dependency dep : cond.getFeature()) { - if (!startupFeatures.contains(dep.getName())) { - doInstall = false; - break; - } - } - if (doInstall) { - for (Bundle bundleInfo : cond.getBundle()) { - String bundleLocation = bundleInfo.getLocation().trim(); - int bundleStartLevel = bundleInfo.getStartLevel() == 0 ? defaultStartLevel : bundleInfo.getStartLevel(); - if (allStartupBundles.containsKey(bundleLocation)) { - bundleStartLevel = Math.min(bundleStartLevel, allStartupBundles.get(bundleLocation)); - } - allStartupBundles.put(bundleLocation, bundleStartLevel); - } - } - for (Config config : cond.getConfig()) { - installConfig(config); - } - } - // Install config files - for (ConfigFile configFile : feature.getConfigfile()) { - try (InputStream is = new URL(configFile.getLocation().trim()).openStream()) { - String path = configFile.getFinalname(); - if (path.startsWith("/")) { - path = path.substring(1); - } - Path output = workDirectory.toPath().resolve(path); - Files.copy(is, output, StandardCopyOption.REPLACE_EXISTING); // TODO: be smarter about overwrites - } - } - for (Conditional cond : feature.getConditional()) { - for (ConfigFile configFile : cond.getConfigfile()) { - try (InputStream is = new URL(configFile.getLocation().trim()).openStream()) { - Path output = workDirectory.toPath().resolve(configFile.getFinalname()); - Files.copy(is, output, StandardCopyOption.REPLACE_EXISTING); // TODO: be smarter about overwrites - } - } - } - } - for (String bundleLocation : startupEffective.getBundles()) { - int bundleStartLevel = defaultStartLevel; - if (allStartupBundles.containsKey(bundleLocation)) { - bundleStartLevel = Math.min(bundleStartLevel, allStartupBundles.get(bundleLocation)); - } - allStartupBundles.put(bundleLocation, bundleStartLevel); - } - // Load startup.properties - startupPropertiesFile.getParentFile().mkdirs(); - Properties startupProperties = new Properties(startupPropertiesFile); - if (!startupPropertiesFile.exists()) { - startupProperties.setHeader(Collections.singletonList("# Bundles to be started on startup, with startlevel")); - } - // Install bundles and update startup.properties - Map<Integer, Set<String>> invertedStartupBundles = MapUtils.invert(allStartupBundles); - for (Map.Entry<Integer, Set<String>> entry : invertedStartupBundles.entrySet()) { - String startLevel = Integer.toString(entry.getKey()); - for (String location : new TreeSet<>(entry.getValue())) { - location = installStartupArtifact(location, useReferenceUrls || use24SyntaxForStartup); - if (location.startsWith("file:") && useReferenceUrls) { - location = "reference:" + location; - } - if (location.startsWith("file:") && use24SyntaxForStartup) { - location = location.substring("file:".length()); - } - startupProperties.put(location, startLevel); - } - } - // generate the startup.properties file - startupProperties.save(); - - - // - // Handle boot profiles - // - Profile bootOverlay = Profiles.getOverlay(bootProfile, allProfiles); - Profile bootEffective = Profiles.getEffective(bootOverlay, false); - // Load startup repositories - Map<String, Features> bootRepositories = loadRepositories(bootEffective.getRepositories()); - // Compute startup feature dependencies - Set<Feature> allBootFeatures = new HashSet<>(); - for (Features repo : bootRepositories.values()) { - allBootFeatures.addAll(repo.getFeature()); - } - // Install all repositories - for (String repository : bootRepositories.keySet()) { - installArtifact(repository); - } - // Generate a global feature - Map<String, Dependency> generatedDep = new HashMap<>(); - Feature generated = new Feature(); - generated.setName(UUID.randomUUID().toString()); - // Add feature dependencies - if (bootEffective.getFeatures().isEmpty()) { - if (installAllFeaturesByDefault) { - for (Features repo : bootRepositories.values()) { - for (Feature feature : repo.getFeature()) { - Dependency dep = generatedDep.get(feature.getName()); - if (dep == null) { - dep = new Dependency(); - dep.setName(feature.getName()); - generated.getFeature().add(dep); - generatedDep.put(dep.getName(), dep); - } - dep.setDependency(false); - } - } - } - } else { - for (String dependency : bootEffective.getFeatures()) { - Dependency dep = generatedDep.get(dependency); - if (dep == null) { - dep = new Dependency(); - dep.setName(dependency); - generated.getFeature().add(dep); - generatedDep.put(dep.getName(), dep); - } - dep.setDependency(false); - } - } - // Add bundles - for (String location : bootEffective.getBundles()) { - location = location.replace("profile:", "file:etc/"); - Bundle bun = new Bundle(); - bun.setLocation(location); - generated.getBundle().add(bun); - } - Features rep = new Features(); - rep.setName(UUID.randomUUID().toString()); - rep.getRepository().addAll(bootEffective.getRepositories()); - rep.getFeature().add(generated); - allBootFeatures.add(generated); - - // Compute startup feature dependencies - Set<Feature> bootFeatures = new HashSet<>(); - addFeatures(bootFeatures, allBootFeatures, generated.getName()); - for (Feature feature : bootFeatures) { - // the feature is a startup feature, updating startup.properties file - getLog().info("Feature " + feature.getName() + " is defined as a boot feature"); - // add the feature in the system folder - Set<String> locations = new HashSet<>(); - for (Bundle bundle : feature.getBundle()) { - if (!ignoreDependencyFlag || !bundle.isDependency()) { - locations.add(bundle.getLocation().trim()); - } - } - for (Conditional cond : feature.getConditional()) { - for (Bundle bundle : cond.getBundle()) { - if (!ignoreDependencyFlag || !bundle.isDependency()) { - locations.add(bundle.getLocation().trim()); - } - } - } - for (String location : locations) { - installArtifact(location); - for (Map.Entry<String, List<String>> entry : prereqs.entrySet()) { - if (location.startsWith(entry.getKey())) { - for (String prereq : entry.getValue()) { - Dependency dep = generatedDep.get(prereq); - if (dep == null) { - dep = new Dependency(); - dep.setName(prereq); - generated.getFeature().add(dep); - generatedDep.put(dep.getName(), dep); - } - dep.setPrerequisite(true); - } - } - } - } - // Install config files - for (ConfigFile configFile : feature.getConfigfile()) { - installArtifact(configFile.getLocation().trim()); - } - for (Conditional cond : feature.getConditional()) { - for (ConfigFile configFile : cond.getConfigfile()) { - installArtifact(configFile.getLocation().trim()); - } - } - } - - // If there are bundles to install, we can't use the boot features only - // so keep the generated feature - if (!generated.getBundle().isEmpty()) { - File output = new File(workDirectory, "etc/" + rep.getName() + ".xml"); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - JaxbUtil.marshal(rep, baos); - ByteArrayInputStream bais; - String repoUrl; - if (use24SyntaxForStartup) { - String str = baos.toString(); - str = str.replace("http://karaf.apache.org/xmlns/features/v1.3.0", "http://karaf.apache.org/xmlns/features/v1.2.0"); - str = str.replaceAll(" dependency=\".*?\"", ""); - str = str.replaceAll(" prerequisite=\".*?\"", ""); - for (Feature f : rep.getFeature()) { - for (Dependency d : f.getFeature()) { - if (d.isPrerequisite()) { - if (!startupEffective.getFeatures().contains(d.getName())) { - getLog().warn("Feature " + d.getName() + " is a prerequisite and should be installed as a startup feature."); } - } - } - } - bais = new ByteArrayInputStream(str.getBytes()); - repoUrl = "file:etc/" + output.getName(); - } else { - bais = new ByteArrayInputStream(baos.toByteArray()); - repoUrl = "file:${karaf.home}/etc/" + output.getName(); - } - Files.copy(bais, output.toPath()); - Properties featuresProperties = new Properties(featuresCfgFile); - featuresProperties.put(FEATURES_REPOSITORIES, repoUrl); - featuresProperties.put(FEATURES_BOOT, generated.getName()); - featuresProperties.save(); - } - else { - String boot = ""; - for (Dependency dep : generatedDep.values()) { - if (dep.isPrerequisite()) { - if (boot.isEmpty()) { - boot = "("; - } else { - boot = boot + ","; - } - boot = boot + dep.getName(); - } - } - if (!boot.isEmpty()) { - boot = boot + ")"; - } - // TODO: for dependencies, we'd need to resolve the features completely - for (Dependency dep : generatedDep.values()) { - if (!dep.isPrerequisite() && !dep.isDependency()) { - if (!boot.isEmpty()) { - boot = boot + ","; - } - boot = boot + dep.getName(); - } - } - String repos = ""; - for (String repo : new HashSet<>(rep.getRepository())) { - if (!repos.isEmpty()) { - repos = repos + ","; - } - repos = repos + repo; - } - - Properties featuresProperties = new Properties(featuresCfgFile); - featuresProperties.put(FEATURES_REPOSITORIES, repos); - featuresProperties.put(FEATURES_BOOT, boot); - featuresProperties.save(); - } - - - // - // Handle installed profiles - // - Profile installedOverlay = Profiles.getOverlay(installedProfile, allProfiles); - Profile installedEffective = Profiles.getEffective(installedOverlay, false); - - // Load startup repositories - Map<String, Features> installedRepositories = loadRepositories(installedEffective.getRepositories()); - // Install all repositories - for (String repository : installedRepositories.keySet()) { - installArtifact(repository); - } - // Compute startup feature dependencies - Set<Feature> allInstalledFeatures = new HashSet<>(); - for (Features repo : installedRepositories.values()) { - allInstalledFeatures.addAll(repo.getFeature()); - } - Set<Feature> installedFeatures = new LinkedHashSet<>(); - if (installedEffective.getFeatures().isEmpty() && installAllFeaturesByDefault) { - installedFeatures.addAll(allInstalledFeatures); - } else { - // Add boot features for search - allInstalledFeatures.addAll(allBootFeatures); - for (String feature : installedEffective.getFeatures()) { - addFeatures(installedFeatures, allInstalledFeatures, feature); - } - } - for (Feature feature : installedFeatures) { - for (Bundle bundle : feature.getBundle()) { - if (!ignoreDependencyFlag || !bundle.isDependency()) { - installArtifact(bundle.getLocation().trim()); - } - } - for (Conditional cond : feature.getConditional()) { - for (Bundle bundle : cond.getBundle()) { - if (!ignoreDependencyFlag || !bundle.isDependency()) { - installArtifact(bundle.getLocation().trim()); - } - } - } - } - for (String location : installedEffective.getBundles()) { - installArtifact(location); - } - // TODO: install config files - } - - private Map<String, Features> loadRepositories(List<String> repositories) throws Exception { - Map<String, Features> loaded = new HashMap<>(); - for (String repository : repositories) { - doLoadRepository(loaded, repository); - } - return loaded; + builder.profilesUris(profilesUri); + } + // Startup + builder.defaultStage(Builder.Stage.Startup) + .kars(toArray(startupKars)) + .repositories(startupFeatures.isEmpty() && startupProfiles.isEmpty() && installAllFeaturesByDefault, toArray(startupRepositories)) + .features(toArray(startupFeatures)) + .bundles(toArray(startupBundles)) + .profiles(toArray(startupProfiles)); + // Boot + builder.defaultStage(Builder.Stage.Boot) + .kars(toArray(bootKars)) + .repositories(bootFeatures.isEmpty() && bootProfiles.isEmpty() && installAllFeaturesByDefault, toArray(bootRepositories)) + .features(toArray(bootFeatures)) + .bundles(toArray(bootBundles)) + .profiles(toArray(bootProfiles)); + // Installed + builder.defaultStage(Builder.Stage.Installed) + .kars(toArray(installedKars)) + .repositories(installedFeatures.isEmpty() && installedProfiles.isEmpty() && installAllFeaturesByDefault, toArray(installedRepositories)) + .features(toArray(installedFeatures)) + .bundles(toArray(installedBundles)) + .profiles(toArray(installedProfiles)); + + builder.generateAssembly(); } - private void doLoadRepository(Map<String, Features> loaded, String repository) throws Exception { - if (!loaded.containsKey(repository)) { - Features featuresModel = JaxbUtil.unmarshal(repository, false); - loaded.put(repository, featuresModel); - // recursively process the inner repositories - for (String innerRepository : featuresModel.getRepository()) { - doLoadRepository(loaded, innerRepository); - } - } - } - - private Profile generateProfile(Map<String, Profile> allProfiles, List<String> profiles, List<String> repositories, List<String> features, List<String> bundles) { - Profile profile = ProfileBuilder.Factory.create(UUID.randomUUID().toString()) - .setParents(profiles) - .setRepositories(repositories) - .setFeatures(features) - .setBundles(bundles) - .getProfile(); - allProfiles.put(profile.getId(), profile); - return profile; + private String[] toArray(List<String> strings) { + return strings.toArray(new String[strings.size()]); } private List<String> nonNullList(List<String> list) { return list == null ? new ArrayList<String>() : list; } - private void addFeatures(Set<Feature> startupFeatures, Set<Feature> features, String feature) { - int nbFound = 0; - for (Feature f : features) { - String[] split = feature.split("/"); - if (split.length == 2) { - if (f.getName().equals(split[0]) && f.getVersion().equals(split[1])) { - for (Dependency dep : f.getFeature()) { - addFeatures(startupFeatures, features, dep.getName()); - } - startupFeatures.add(f); - nbFound++; - } - } else { - if (feature.equals(f.getName())) { - for (Dependency dep : f.getFeature()) { - addFeatures(startupFeatures, features, dep.getName()); - } - startupFeatures.add(f); - nbFound++; - } - } - } - if (nbFound == 0) { - throw new IllegalStateException("Could not find matching feature for " + feature); - } - } - - private String installStartupArtifact(String location, boolean asFile) throws Exception { - getLog().info("== Installing artifact " + location); - String url; - String path; - if (location.startsWith("mvn:")) { - url = location; - path = dependencyHelper.pathFromMaven(location); - if (asFile) { - location = "file:" + path ; - } - } else { - url = location.replace("profile:", "file:" + workDirectory.getAbsolutePath() + "/etc/"); - path = "generated/" + location.replaceAll("[^0-9a-zA-Z.\\-_]+", "_"); - location = "file:" + path; - } - File bundleSystemFile = new File(systemDirectory, path); - if (!bundleSystemFile.exists()) { - bundleSystemFile.getParentFile().mkdirs(); - try (InputStream is = new URL(url).openStream()) { - Files.copy(is, bundleSystemFile.toPath()); - } - } - return location; - } - - private void installArtifact(String location) throws Exception { - getLog().info("== Installing artifact " + location); - location = DownloadManagerHelper.stripUrl(location); - location = DownloadManagerHelper.removeInlinedMavenRepositoryUrl(location); - if (location.startsWith("mvn:")) { - if (location.endsWith("/")) { - // for bad formed URL (like in Camel for mustache-compiler), we remove the trailing / - location = location.substring(0, location.length() - 1); - } - File inputFile = dependencyHelper.resolveById(location, getLog()); - File targetFile = new File(systemDirectory, dependencyHelper.pathFromMaven(location)); - copy(inputFile, targetFile); - // add metadata for snapshot - Artifact artifact = dependencyHelper.mvnToArtifact(location); - if (artifact.isSnapshot()) { - File metadataTarget = new File(targetFile.getParentFile(), "maven-metadata-local.xml"); - try { - MavenUtil.generateMavenMetadata(artifact, metadataTarget); - } catch (Exception e) { - getLog().warn("Could not create maven-metadata-local.xml", e); - getLog().warn("It means that this SNAPSHOT could be overwritten by an older one present on remote repositories"); - } - } - } else { - getLog().warn("Ignoring artifact " + location); - } - } - - private void installConfig(Config config) throws Exception { - getLog().info("== Installing configuration " + config.getName()); - Path configFile = workDirectory.toPath().resolve("etc/" + config.getName()); - if (!Files.exists(configFile)) { - Files.write(configFile, config.getValue().getBytes()); - } else if (config.isAppend()) { - // TODO - } - } - } http://git-wip-us.apache.org/repos/asf/karaf/blob/e920dde0/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/VerifyFeatureResolutionMojo.java ---------------------------------------------------------------------- diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/VerifyFeatureResolutionMojo.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/VerifyFeatureResolutionMojo.java index d196c44..b3cb74a 100644 --- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/VerifyFeatureResolutionMojo.java +++ b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/features/VerifyFeatureResolutionMojo.java @@ -29,14 +29,10 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.net.URI; import java.net.URL; -import java.net.URLConnection; -import java.net.URLStreamHandler; -import java.net.URLStreamHandlerFactory; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Dictionary; import java.util.EnumSet; import java.util.Enumeration; import java.util.HashMap; @@ -81,9 +77,8 @@ import org.apache.karaf.features.internal.util.MultiException; import org.apache.karaf.tooling.url.CustomBundleURLStreamHandlerFactory; import org.apache.karaf.tooling.utils.InternalMavenResolver; import org.apache.karaf.tooling.utils.MojoSupport; -import org.apache.karaf.tooling.utils.PropertiesLoader; +import org.apache.karaf.util.config.PropertiesLoader; import org.apache.maven.artifact.Artifact; -import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Mojo; @@ -91,11 +86,6 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; import org.ops4j.pax.url.mvn.MavenResolver; -import org.ops4j.pax.url.mvn.MavenResolvers; -import org.ops4j.pax.url.mvn.ServiceConstants; -import org.ops4j.pax.url.mvn.internal.AetherBasedResolver; -import org.ops4j.pax.url.mvn.internal.Connection; -import org.ops4j.pax.url.mvn.internal.config.MavenConfigurationImpl; import org.osgi.framework.Bundle; import org.osgi.framework.BundleException; import org.osgi.framework.Constants; @@ -111,7 +101,6 @@ import org.osgi.resource.Requirement; import org.osgi.resource.Resource; import org.osgi.resource.Wire; import org.osgi.service.resolver.ResolutionException; -import shaded.org.ops4j.util.property.PropertiesPropertyResolver; import static java.util.jar.JarFile.MANIFEST_NAME; http://git-wip-us.apache.org/repos/asf/karaf/blob/e920dde0/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/utils/PropertiesLoader.java ---------------------------------------------------------------------- diff --git a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/utils/PropertiesLoader.java b/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/utils/PropertiesLoader.java deleted file mode 100644 index 6507b83..0000000 --- a/tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/utils/PropertiesLoader.java +++ /dev/null @@ -1,249 +0,0 @@ -/* - * 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.tooling.utils; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Enumeration; -import org.apache.felix.utils.properties.Properties; -import java.util.StringTokenizer; - -import static org.apache.felix.utils.properties.InterpolationHelper.substVars; - -public class PropertiesLoader { - - private static final String INCLUDES_PROPERTY = "${includes}"; // mandatory includes - - private static final String OPTIONALS_PROPERTY = "${optionals}"; // optionals include - - private static final String OVERRIDE_PREFIX = "karaf.override."; // prefix that marks that system property should override defaults. - - /** - * <p> - * Loads the configuration properties in the configuration property file - * associated with the framework installation; these properties - * are accessible to the framework and to bundles and are intended - * for configuration purposes. By default, the configuration property - * file is located in the <tt>conf/</tt> directory of the Felix - * installation directory and is called "<tt>config.properties</tt>". - * The installation directory of Felix is assumed to be the parent - * directory of the <tt>felix.jar</tt> file as found on the system class - * path property. The precise file from which to load configuration - * properties can be set by initializing the "<tt>felix.config.properties</tt>" - * system property to an arbitrary URL. - * </p> - * - * @return A <tt>Properties</tt> instance or <tt>null</tt> if there was an error. - * @throws Exception if something wrong occurs - */ - public static Properties loadConfigProperties(File file) throws Exception { - // See if the property URL was specified as a property. - URL configPropURL; - try { - configPropURL = file.toURI().toURL(); - } - catch (MalformedURLException ex) { - System.err.print("Main: " + ex); - return null; - } - - Properties configProps = loadPropertiesFile(configPropURL, false); - copySystemProperties(configProps); - configProps.substitute(); - - // Perform variable substitution for system properties. -// for (Enumeration<?> e = configProps.propertyNames(); e.hasMoreElements();) { -// String name = (String) e.nextElement(); -// configProps.setProperty(name, -// SubstHelper.substVars(configProps.getProperty(name), name, null, configProps)); -// } - - return configProps; - } - - /** - * <p> - * Loads the properties in the system property file associated with the - * framework installation into <tt>System.setProperty()</tt>. These properties - * are not directly used by the framework in anyway. By default, the system - * property file is located in the <tt>conf/</tt> directory of the Felix - * installation directory and is called "<tt>system.properties</tt>". The - * installation directory of Felix is assumed to be the parent directory of - * the <tt>felix.jar</tt> file as found on the system class path property. - * The precise file from which to load system properties can be set by - * initializing the "<tt>felix.system.properties</tt>" system property to an - * arbitrary URL. - * </p> - * - * @param karafBase the karaf base folder - * @throws IOException - */ - public static void loadSystemProperties(File file) throws IOException { - Properties props = new Properties(false); - try { - InputStream is = new FileInputStream(file); - props.load(is); - is.close(); - } catch (Exception e1) { - // Ignore - } - - for (Enumeration<?> e = props.propertyNames(); e.hasMoreElements();) { - String name = (String) e.nextElement(); - if (name.startsWith(OVERRIDE_PREFIX)) { - String overrideName = name.substring(OVERRIDE_PREFIX.length()); - String value = props.getProperty(name); - System.setProperty(overrideName, substVars(value, name, null, props)); - } else { - String value = System.getProperty(name, props.getProperty(name)); - System.setProperty(name, substVars(value, name, null, props)); - } - } - } - - public static void copySystemProperties(Properties configProps) { - for (Enumeration<?> e = System.getProperties().propertyNames(); - e.hasMoreElements();) { - String key = (String) e.nextElement(); - if (key.startsWith("felix.") || - key.startsWith("karaf.") || - key.startsWith("org.osgi.framework.")) { - configProps.setProperty(key, System.getProperty(key)); - } - } - } - - public static Properties loadPropertiesOrFail(File configFile) { - try { - URL configPropURL = configFile.toURI().toURL(); - return loadPropertiesFile(configPropURL, true); - } catch (Exception e) { - throw new RuntimeException("Error loading properties from " + configFile, e); - } - } - - public static Properties loadPropertiesFile(URL configPropURL, boolean failIfNotFound) throws Exception { - Properties configProps = new Properties(null, false); - InputStream is = null; - try { - is = configPropURL.openConnection().getInputStream(); - configProps.load(is); - is.close(); - } catch (FileNotFoundException ex) { - if (failIfNotFound) { - throw ex; - } else { - System.err.println("WARN: " + configPropURL + " is not found, so not loaded"); - } - } catch (Exception ex) { - System.err.println("Error loading config properties from " + configPropURL); - System.err.println("Main: " + ex); - return configProps; - } finally { - try { - if (is != null) { - is.close(); - } - } - catch (IOException ex2) { - // Nothing we can do. - } - } - loadIncludes(INCLUDES_PROPERTY, true, configPropURL, configProps); - loadIncludes(OPTIONALS_PROPERTY, false, configPropURL, configProps); - trimValues(configProps); - return configProps; - } - - private static void loadIncludes(String propertyName, boolean mandatory, URL configPropURL, Properties configProps) - throws MalformedURLException, Exception { - String includes = (String) configProps.get(propertyName); - if (includes != null) { - StringTokenizer st = new StringTokenizer(includes, "\" ", true); - if (st.countTokens() > 0) { - String location; - do { - location = nextLocation(st); - if (location != null) { - URL url = new URL(configPropURL, location); - Properties props = loadPropertiesFile(url, mandatory); - configProps.putAll(props); - } - } - while (location != null); - } - } - configProps.remove(propertyName); - } - - private static void trimValues(Properties configProps) { - for (String key : configProps.keySet()) { - configProps.put(key, configProps.get(key).trim()); - } - } - - private static String nextLocation(StringTokenizer st) { - String retVal = null; - - if (st.countTokens() > 0) { - String tokenList = "\" "; - StringBuffer tokBuf = new StringBuffer(10); - String tok; - boolean inQuote = false; - boolean tokStarted = false; - boolean exit = false; - while ((st.hasMoreTokens()) && (!exit)) { - tok = st.nextToken(tokenList); - if (tok.equals("\"")) { - inQuote = !inQuote; - if (inQuote) { - tokenList = "\""; - } else { - tokenList = "\" "; - } - - } else if (tok.equals(" ")) { - if (tokStarted) { - retVal = tokBuf.toString(); - tokStarted = false; - tokBuf = new StringBuffer(10); - exit = true; - } - } else { - tokStarted = true; - tokBuf.append(tok.trim()); - } - } - - // Handle case where end of token stream and - // still got data - if ((!exit) && (tokStarted)) { - retVal = tokBuf.toString(); - } - } - - return retVal; - } - -} http://git-wip-us.apache.org/repos/asf/karaf/blob/e920dde0/util/src/main/java/org/apache/karaf/util/config/PropertiesLoader.java ---------------------------------------------------------------------- diff --git a/util/src/main/java/org/apache/karaf/util/config/PropertiesLoader.java b/util/src/main/java/org/apache/karaf/util/config/PropertiesLoader.java new file mode 100644 index 0000000..609957b --- /dev/null +++ b/util/src/main/java/org/apache/karaf/util/config/PropertiesLoader.java @@ -0,0 +1,249 @@ +/* + * 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.util.config; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; +import org.apache.felix.utils.properties.Properties; +import java.util.StringTokenizer; + +import static org.apache.felix.utils.properties.InterpolationHelper.substVars; + +public class PropertiesLoader { + + private static final String INCLUDES_PROPERTY = "${includes}"; // mandatory includes + + private static final String OPTIONALS_PROPERTY = "${optionals}"; // optionals include + + private static final String OVERRIDE_PREFIX = "karaf.override."; // prefix that marks that system property should override defaults. + + /** + * <p> + * Loads the configuration properties in the configuration property file + * associated with the framework installation; these properties + * are accessible to the framework and to bundles and are intended + * for configuration purposes. By default, the configuration property + * file is located in the <tt>conf/</tt> directory of the Felix + * installation directory and is called "<tt>config.properties</tt>". + * The installation directory of Felix is assumed to be the parent + * directory of the <tt>felix.jar</tt> file as found on the system class + * path property. The precise file from which to load configuration + * properties can be set by initializing the "<tt>felix.config.properties</tt>" + * system property to an arbitrary URL. + * </p> + * + * @return A <tt>Properties</tt> instance or <tt>null</tt> if there was an error. + * @throws Exception if something wrong occurs + */ + public static Properties loadConfigProperties(File file) throws Exception { + // See if the property URL was specified as a property. + URL configPropURL; + try { + configPropURL = file.toURI().toURL(); + } + catch (MalformedURLException ex) { + System.err.print("Main: " + ex); + return null; + } + + Properties configProps = loadPropertiesFile(configPropURL, false); + copySystemProperties(configProps); + configProps.substitute(); + + // Perform variable substitution for system properties. +// for (Enumeration<?> e = configProps.propertyNames(); e.hasMoreElements();) { +// String name = (String) e.nextElement(); +// configProps.setProperty(name, +// SubstHelper.substVars(configProps.getProperty(name), name, null, configProps)); +// } + + return configProps; + } + + /** + * <p> + * Loads the properties in the system property file associated with the + * framework installation into <tt>System.setProperty()</tt>. These properties + * are not directly used by the framework in anyway. By default, the system + * property file is located in the <tt>conf/</tt> directory of the Felix + * installation directory and is called "<tt>system.properties</tt>". The + * installation directory of Felix is assumed to be the parent directory of + * the <tt>felix.jar</tt> file as found on the system class path property. + * The precise file from which to load system properties can be set by + * initializing the "<tt>felix.system.properties</tt>" system property to an + * arbitrary URL. + * </p> + * + * @param karafBase the karaf base folder + * @throws IOException + */ + public static void loadSystemProperties(File file) throws IOException { + Properties props = new Properties(false); + try { + InputStream is = new FileInputStream(file); + props.load(is); + is.close(); + } catch (Exception e1) { + // Ignore + } + + for (Enumeration<?> e = props.propertyNames(); e.hasMoreElements();) { + String name = (String) e.nextElement(); + if (name.startsWith(OVERRIDE_PREFIX)) { + String overrideName = name.substring(OVERRIDE_PREFIX.length()); + String value = props.getProperty(name); + System.setProperty(overrideName, substVars(value, name, null, props)); + } else { + String value = System.getProperty(name, props.getProperty(name)); + System.setProperty(name, substVars(value, name, null, props)); + } + } + } + + public static void copySystemProperties(Properties configProps) { + for (Enumeration<?> e = System.getProperties().propertyNames(); + e.hasMoreElements();) { + String key = (String) e.nextElement(); + if (key.startsWith("felix.") || + key.startsWith("karaf.") || + key.startsWith("org.osgi.framework.")) { + configProps.setProperty(key, System.getProperty(key)); + } + } + } + + public static Properties loadPropertiesOrFail(File configFile) { + try { + URL configPropURL = configFile.toURI().toURL(); + return loadPropertiesFile(configPropURL, true); + } catch (Exception e) { + throw new RuntimeException("Error loading properties from " + configFile, e); + } + } + + public static Properties loadPropertiesFile(URL configPropURL, boolean failIfNotFound) throws Exception { + Properties configProps = new Properties(null, false); + InputStream is = null; + try { + is = configPropURL.openConnection().getInputStream(); + configProps.load(is); + is.close(); + } catch (FileNotFoundException ex) { + if (failIfNotFound) { + throw ex; + } else { + System.err.println("WARN: " + configPropURL + " is not found, so not loaded"); + } + } catch (Exception ex) { + System.err.println("Error loading config properties from " + configPropURL); + System.err.println("Main: " + ex); + return configProps; + } finally { + try { + if (is != null) { + is.close(); + } + } + catch (IOException ex2) { + // Nothing we can do. + } + } + loadIncludes(INCLUDES_PROPERTY, true, configPropURL, configProps); + loadIncludes(OPTIONALS_PROPERTY, false, configPropURL, configProps); + trimValues(configProps); + return configProps; + } + + private static void loadIncludes(String propertyName, boolean mandatory, URL configPropURL, Properties configProps) + throws MalformedURLException, Exception { + String includes = (String) configProps.get(propertyName); + if (includes != null) { + StringTokenizer st = new StringTokenizer(includes, "\" ", true); + if (st.countTokens() > 0) { + String location; + do { + location = nextLocation(st); + if (location != null) { + URL url = new URL(configPropURL, location); + Properties props = loadPropertiesFile(url, mandatory); + configProps.putAll(props); + } + } + while (location != null); + } + } + configProps.remove(propertyName); + } + + private static void trimValues(Properties configProps) { + for (String key : configProps.keySet()) { + configProps.put(key, configProps.get(key).trim()); + } + } + + private static String nextLocation(StringTokenizer st) { + String retVal = null; + + if (st.countTokens() > 0) { + String tokenList = "\" "; + StringBuffer tokBuf = new StringBuffer(10); + String tok; + boolean inQuote = false; + boolean tokStarted = false; + boolean exit = false; + while ((st.hasMoreTokens()) && (!exit)) { + tok = st.nextToken(tokenList); + if (tok.equals("\"")) { + inQuote = !inQuote; + if (inQuote) { + tokenList = "\""; + } else { + tokenList = "\" "; + } + + } else if (tok.equals(" ")) { + if (tokStarted) { + retVal = tokBuf.toString(); + tokStarted = false; + tokBuf = new StringBuffer(10); + exit = true; + } + } else { + tokStarted = true; + tokBuf.append(tok.trim()); + } + } + + // Handle case where end of token stream and + // still got data + if ((!exit) && (tokStarted)) { + retVal = tokBuf.toString(); + } + } + + return retVal; + } + +} http://git-wip-us.apache.org/repos/asf/karaf/blob/e920dde0/util/src/main/java/org/apache/karaf/util/maven/Parser.java ---------------------------------------------------------------------- diff --git a/util/src/main/java/org/apache/karaf/util/maven/Parser.java b/util/src/main/java/org/apache/karaf/util/maven/Parser.java index 232942e..8f6920f 100644 --- a/util/src/main/java/org/apache/karaf/util/maven/Parser.java +++ b/util/src/main/java/org/apache/karaf/util/maven/Parser.java @@ -150,6 +150,19 @@ public class Parser } /** + * Returns the artifact path from the given maven uri. + * @param uri the maven uri + * @return the artifact path + * @throws MalformedURLException + */ + public static String pathFromMaven(String uri) throws MalformedURLException { + if (!uri.startsWith("mvn:")) { + return uri; + } + return new Parser(uri.substring("mvn:".length())).getArtifactPath(); + } + + /** * Parses the artifact part of the url ( without the repository). * * @param part url part without protocol and repository.
