You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gg...@apache.org on 2017/06/21 13:32:24 UTC
[1/6] karaf git commit: [KARAF-5008] Clean up org.apache.maven.*
dependencies (align to 3.0.3 for now) [Forced Update!]
Repository: karaf
Updated Branches:
refs/heads/master-maven-commands e517bad1a -> 6a6766303 (forced update)
[KARAF-5008] Clean up org.apache.maven.* dependencies (align to 3.0.3 for now)
[KARAF-5008] Clean up org.apache.maven.wagon.* dependencies (align to 2.10 for now)
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/60e25fa1
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/60e25fa1
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/60e25fa1
Branch: refs/heads/master-maven-commands
Commit: 60e25fa18392343f8697b46b35530d5da9e4199d
Parents: 83d4135
Author: Grzegorz Grzybek <gr...@gmail.com>
Authored: Fri Mar 10 12:03:27 2017 +0100
Committer: Grzegorz Grzybek <gr...@gmail.com>
Committed: Wed Jun 21 15:31:41 2017 +0200
----------------------------------------------------------------------
pom.xml | 40 +++++++++++++++++++-----
tooling/karaf-maven-plugin/pom.xml | 7 +----
tooling/karaf-services-maven-plugin/pom.xml | 7 +----
3 files changed, 35 insertions(+), 19 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/60e25fa1/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 7cf0e15..a7367d2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -252,7 +252,8 @@
<jline.version>3.3.0</jline.version>
<jsw.version>3.2.3</jsw.version>
<log4j.version>1.2.17</log4j.version>
- <maven.version>2.0.9</maven.version>
+ <maven.version>3.0.3</maven.version>
+ <maven.wagon.version>2.10</maven.wagon.version>
<org.osgi.service.jdbc.version>1.0.0</org.osgi.service.jdbc.version>
<org.osgi.service.jpa.version>1.0.0</org.osgi.service.jpa.version>
<osgi.version>6.0.0</osgi.version>
@@ -1062,10 +1063,40 @@
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
- <artifactId>maven-project</artifactId>
+ <artifactId>maven-compat</artifactId>
<version>${maven.version}</version>
</dependency>
<dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-artifact</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.shared</groupId>
+ <artifactId>maven-dependency-tree</artifactId>
+ <version>2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-provider-api</artifactId>
+ <version>${maven.wagon.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-http</artifactId>
+ <version>${maven.wagon.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.wagon</groupId>
+ <artifactId>wagon-http-lightweight</artifactId>
+ <version>${maven.wagon.version}</version>
+ </dependency>
+ <dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>${xerces.version}</version>
@@ -1177,11 +1208,6 @@
<version>${jline.version}</version>
</dependency>
<dependency>
- <groupId>org.apache.maven.artifact</groupId>
- <artifactId>maven-artifact</artifactId>
- <version>3.0-alpha-1</version>
- </dependency>
- <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
http://git-wip-us.apache.org/repos/asf/karaf/blob/60e25fa1/tooling/karaf-maven-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/tooling/karaf-maven-plugin/pom.xml b/tooling/karaf-maven-plugin/pom.xml
index d88899b..ffcc052 100644
--- a/tooling/karaf-maven-plugin/pom.xml
+++ b/tooling/karaf-maven-plugin/pom.xml
@@ -42,7 +42,6 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
- <version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.sonatype.aether</groupId>
@@ -67,17 +66,14 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
- <version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
- <version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
- <version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
@@ -87,7 +83,6 @@
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-http</artifactId>
- <version>2.10</version>
</dependency>
<dependency>
<groupId>org.apache.karaf</groupId>
@@ -105,7 +100,7 @@
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-filtering</artifactId>
- <version>1.0-beta-4</version>
+ <version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
http://git-wip-us.apache.org/repos/asf/karaf/blob/60e25fa1/tooling/karaf-services-maven-plugin/pom.xml
----------------------------------------------------------------------
diff --git a/tooling/karaf-services-maven-plugin/pom.xml b/tooling/karaf-services-maven-plugin/pom.xml
index 728999f..4dbaa56 100644
--- a/tooling/karaf-services-maven-plugin/pom.xml
+++ b/tooling/karaf-services-maven-plugin/pom.xml
@@ -41,7 +41,6 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
- <version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
@@ -71,22 +70,18 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId>
- <version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
- <version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId>
- <version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-http-lightweight</artifactId>
- <version>2.6</version>
</dependency>
<dependency>
<groupId>org.sonatype.plexus</groupId>
@@ -120,7 +115,7 @@
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-filtering</artifactId>
- <version>1.0-beta-4</version>
+ <version>3.1.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.plexus</groupId>
[4/6] karaf git commit: [KARAF-5008] maven:repository-change and
maven:repository-remove commands
Posted by gg...@apache.org.
[KARAF-5008] maven:repository-change and maven:repository-remove commands
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/32d5c7b7
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/32d5c7b7
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/32d5c7b7
Branch: refs/heads/master-maven-commands
Commit: 32d5c7b769b570824cc50917a78c103ddbfa1e6c
Parents: ede23ba
Author: Grzegorz Grzybek <gr...@gmail.com>
Authored: Wed Jun 21 13:36:40 2017 +0200
Committer: Grzegorz Grzybek <gr...@gmail.com>
Committed: Wed Jun 21 15:31:54 2017 +0200
----------------------------------------------------------------------
.../command/MavenConfigurationSupport.java | 38 +++-
.../maven/command/RepositoryAddCommand.java | 109 ++--------
.../maven/command/RepositoryChangeCommand.java | 197 +++++++++++++++++++
.../command/RepositoryEditCommandSupport.java | 148 +++++++++++++-
.../maven/command/RepositoryRemoveCommand.java | 59 +++++-
.../karaf/maven/core/MavenRepositoryURL.java | 46 ++++-
6 files changed, 484 insertions(+), 113 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/32d5c7b7/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java b/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
index b64e583..c028530 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
@@ -17,6 +17,7 @@
package org.apache.karaf.maven.command;
import java.io.File;
+import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
@@ -54,6 +55,8 @@ import org.apache.maven.settings.building.SettingsProblem;
import org.apache.maven.settings.crypto.DefaultSettingsDecrypter;
import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
import org.apache.maven.settings.crypto.SettingsDecryptionResult;
+import org.apache.maven.settings.io.xpp3.SettingsXpp3Writer;
+import org.ops4j.pax.url.mvn.ServiceConstants;
import org.osgi.framework.BundleContext;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
@@ -170,8 +173,8 @@ public abstract class MavenConfigurationSupport implements Action {
/**
* Performs command action on <strong>existing</strong> <code>org.ops4j.pax.url.mvn</code>
* PID configuration
- * @param prefix
- * @param config
+ * @param prefix prefix for properties inside <code>org.ops4j.pax.url.mvn</code> PID
+ * @param config <code>org.ops4j.pax.url.mvn</code> PID configuration taken from {@link ConfigurationAdmin}
*/
abstract protected void doAction(String prefix, Dictionary<String, Object> config) throws Exception;
@@ -491,17 +494,19 @@ public abstract class MavenConfigurationSupport implements Action {
if (repo.getReleases() != null) {
if (!repo.getReleases().isEnabled()) {
- builder.append("@noreleases");
+ builder.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_DISALLOW_RELEASES);
}
- addPolicy(builder, repo.getReleases().getUpdatePolicy(), "releasesUpdate");
+ SourceAnd<String> up = updatePolicy(repo.getReleases().getUpdatePolicy());
+ addPolicy(builder, "".equals(up.val()) ? "never" : up.val(), ServiceConstants.OPTION_RELEASES_UPDATE);
// not used in pax-url-aether
//addPolicy(builder, repo.getReleases().getChecksumPolicy(), "releasesChecksum");
}
if (repo.getSnapshots() != null) {
if (repo.getSnapshots().isEnabled()) {
- builder.append("@snapshots");
+ builder.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_ALLOW_SNAPSHOTS);
}
- addPolicy(builder, repo.getSnapshots().getUpdatePolicy(), "snapshotsUpdate");
+ SourceAnd<String> up = updatePolicy(repo.getSnapshots().getUpdatePolicy());
+ addPolicy(builder, "".equals(up.val()) ? "never" : up.val(), ServiceConstants.OPTION_SNAPSHOTS_UPDATE);
// not used in pax-url-aether
//addPolicy(builder, repo.getSnapshots().getChecksumPolicy(), "snapshotsChecksum");
}
@@ -682,6 +687,27 @@ public abstract class MavenConfigurationSupport implements Action {
}
/**
+ * Stores changed {@link org.apache.maven.settings.Settings} in new settings.xml file and updates
+ * <code>org.ops4j.pax.url.mvn.settings</code> property. Does <string>not</string> update
+ * {@link org.osgi.service.cm.ConfigurationAdmin} config.
+ * @param prefix
+ * @param config
+ */
+ protected void updateSettings(String prefix, Dictionary<String, Object> config) throws IOException {
+ File dataDir = context.getDataFile(".");
+ if (!dataDir.isDirectory()) {
+ throw new RuntimeException("Can't access data directory for " + context.getBundle().getSymbolicName() + " bundle");
+ }
+ File newSettingsFile = nextSequenceFile(dataDir, RE_SETTINGS, PATTERN_SETTINGS);
+ config.put(prefix + PROPERTY_SETTINGS_FILE, newSettingsFile.getCanonicalPath());
+
+ try (FileWriter fw = new FileWriter(newSettingsFile)) {
+ new SettingsXpp3Writer().write(fw, mavenSettings);
+ }
+ System.out.println("New settings stored in \"" + newSettingsFile.getCanonicalPath() + "\"");
+ }
+
+ /**
* Handy class containing value and information about its origin. <code>valid</code> may be used to indicate
* if the value is correct. It may be implicit, but the interpretation of <code>valid </code> is not defined.
* @param <T>
http://git-wip-us.apache.org/repos/asf/karaf/blob/32d5c7b7/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryAddCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryAddCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryAddCommand.java
index 11034d3..1001ade 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryAddCommand.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryAddCommand.java
@@ -16,26 +16,17 @@
*/
package org.apache.karaf.maven.command;
-import java.io.File;
-import java.io.FileWriter;
-import java.net.MalformedURLException;
-import java.net.URL;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.LinkedList;
import java.util.List;
-import java.util.Objects;
import java.util.Optional;
-import java.util.stream.Collectors;
-import org.apache.felix.utils.properties.InterpolationHelper;
import org.apache.karaf.maven.core.MavenRepositoryURL;
import org.apache.karaf.shell.api.action.Argument;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Option;
import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.maven.settings.Server;
-import org.apache.maven.settings.io.xpp3.SettingsXpp3Writer;
import org.ops4j.pax.url.mvn.ServiceConstants;
import org.osgi.service.cm.Configuration;
@@ -58,36 +49,27 @@ public class RepositoryAddCommand extends RepositoryEditCommandSupport {
@Option(name = "-cp", aliases = { "--checksum-policy" }, description = "Checksum policy for repository (ignore, warn (default), fail)", required = false, multiValued = false)
String checksumPolicy = "warn";
- @Argument(description = "Repository URI. It may be file:// based, http(s):// based, may use other known protocol or even property placeholders (like ${karaf.base})")
- String uri;
-
@Option(name = "-u", aliases = { "--username" }, description = "Username for remote repository", required = false, multiValued = false)
String username;
@Option(name = "-p", aliases = { "--password" }, description = "Password for remote repository (may be encrypted, see \"maven:password -ep\")", required = false, multiValued = false)
String password;
- @Override
- protected void edit(String prefix, Dictionary<String, Object> config) throws Exception {
- MavenRepositoryURL[] repositories = repositories(config, !defaultRepository);
+ @Argument(description = "Repository URI. It may be file:// based, http(s):// based, may use other known protocol or even property placeholders (like ${karaf.base})")
+ String uri;
- MavenRepositoryURL[] repositoriesFromPidProperty = Arrays.stream(repositories)
- .filter((repo) -> repo.getFrom() == MavenRepositoryURL.FROM.PID)
- .toArray(MavenRepositoryURL[]::new);
+ @Override
+ protected void edit(String prefix, Dictionary<String, Object> config,
+ MavenRepositoryURL[] allRepos, MavenRepositoryURL[] pidRepos, MavenRepositoryURL[] settingsRepos) throws Exception {
- if (idx > repositoriesFromPidProperty.length) {
+ if (idx > pidRepos.length) {
// TOCONSIDER: should we allow to add repository to settings.xml too?
System.err.printf("List of %s repositories has %d elements. Can't insert at position %s.\n",
- (defaultRepository ? "default" : "remote"), repositories.length, id);
+ (defaultRepository ? "default" : "remote"), pidRepos.length, id);
return;
}
- if (id == null || "".equals(id.trim())) {
- System.err.println("Please specify ID of repository");
- return;
- }
-
- Optional<MavenRepositoryURL> first = Arrays.stream(repositories)
+ Optional<MavenRepositoryURL> first = Arrays.stream(allRepos)
.filter((repo) -> id.equals(repo.getId())).findAny();
if (first.isPresent()) {
System.err.printf("Repository with ID \"%s\" is already configured for URL %s\n", id, first.get().getURL());
@@ -106,34 +88,8 @@ public class RepositoryAddCommand extends RepositoryEditCommandSupport {
return;
}
- if (uri == null || "".equals(uri.trim())) {
- System.err.println("Please specify repository location");
- return;
- }
- String urlResolved = InterpolationHelper.substVars(uri, "uri", null, null, context);
- URL url = null;
- try {
- url = new URL(urlResolved);
- urlResolved = url.toString();
-
- if ("file".equals(url.getProtocol()) && new File(url.toURI()).isDirectory()) {
- System.err.println("Location \"" + urlResolved + "\" is not accessible");
- return;
- }
- } catch (MalformedURLException e) {
- // a directory?
- File location = new File(urlResolved);
- if (!location.exists() || !location.isDirectory()) {
- System.err.println("Location \"" + urlResolved + "\" is not accessible");
- return;
- } else {
- url = location.toURI().toURL();
- urlResolved = url.toString();
- }
- }
-
- if (defaultRepository && !"file".equals(url.getProtocol())) {
- System.err.println("Default repositories should be locally accessible (use file:// protocol or normal directory path)");
+ SourceAnd<String> urlResolved = validateRepositoryURL(uri, defaultRepository);
+ if (!urlResolved.valid) {
return;
}
@@ -152,43 +108,15 @@ public class RepositoryAddCommand extends RepositoryEditCommandSupport {
}
// credentials for remote repository can be stored only in settings.xml
-
if (!defaultRepository && hasCredentials) {
- if (!confirm("Maven settings will be updated and org.ops4j.pax.url.mvn.settings property will change. Continue? (y/N) ")) {
+ if (!updateCredentials(force, id, username, password, prefix, config)) {
return;
}
-
- File dataDir = context.getDataFile(".");
- if (!dataDir.isDirectory()) {
- System.err.println("Can't access data directory for " + context.getBundle().getSymbolicName() + " bundle");
- return;
- }
-
- Optional<Server> existingServer = mavenSettings.getServers().stream()
- .filter((s) -> id.equals(s.getId())).findAny();
- Server server = null;
- if (existingServer.isPresent()) {
- server = existingServer.get();
- } else {
- server = new Server();
- server.setId(id);
- mavenSettings.getServers().add(server);
- }
- server.setUsername(username);
- server.setPassword(password);
-
- // prepare configadmin configuration update
- File newSettingsFile = nextSequenceFile(dataDir, RE_SETTINGS, PATTERN_SETTINGS);
- config.put(prefix + PROPERTY_SETTINGS_FILE, newSettingsFile.getCanonicalPath());
-
- try (FileWriter fw = new FileWriter(newSettingsFile)) {
- new SettingsXpp3Writer().write(fw, mavenSettings);
- }
- System.out.println("New settings stored in \"" + newSettingsFile.getCanonicalPath() + "\"");
+ updateSettings(prefix, config);
}
StringBuilder sb = new StringBuilder();
- sb.append(urlResolved);
+ sb.append(urlResolved.val());
sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_ID + "=" + id);
if (snapshots) {
sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_ALLOW_SNAPSHOTS);
@@ -200,21 +128,14 @@ public class RepositoryAddCommand extends RepositoryEditCommandSupport {
sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_CHECKSUM + "=" + checksumPolicy);
MavenRepositoryURL newRepository = new MavenRepositoryURL(sb.toString());
- List<MavenRepositoryURL> newRepos = new LinkedList<>(Arrays.asList(repositoriesFromPidProperty));
+ List<MavenRepositoryURL> newRepos = new LinkedList<>(Arrays.asList(pidRepos));
if (idx >= 0) {
newRepos.add(idx, newRepository);
} else {
newRepos.add(newRepository);
}
- String newList = newRepos.stream().map(MavenRepositoryURL::asRepositorySpec)
- .collect(Collectors.joining(","));
-
- if (defaultRepository) {
- config.put(prefix + PROPERTY_DEFAULT_REPOSITORIES, newList);
- } else {
- config.put(prefix + PROPERTY_REPOSITORIES, newList);
- }
+ updatePidRepositories(prefix, config, defaultRepository, newRepos, settingsRepos.length > 0);
Configuration cmConfig = cm.getConfiguration(PID);
cmConfig.update(config);
http://git-wip-us.apache.org/repos/asf/karaf/blob/32d5c7b7/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryChangeCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryChangeCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryChangeCommand.java
new file mode 100644
index 0000000..e85876a
--- /dev/null
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryChangeCommand.java
@@ -0,0 +1,197 @@
+/*
+ * 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.maven.command;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.karaf.maven.core.MavenRepositoryURL;
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.maven.settings.Profile;
+import org.apache.maven.settings.Repository;
+import org.apache.maven.settings.RepositoryPolicy;
+import org.osgi.service.cm.Configuration;
+
+@Command(scope = "maven", name = "repository-change", description = "Changes configuration of Maven repository")
+@Service
+public class RepositoryChangeCommand extends RepositoryEditCommandSupport {
+
+ @Option(name = "-s", aliases = { "--snapshots" }, description = "Enable SNAPSHOT handling in the repository", required = false, multiValued = false)
+ boolean snapshots = false;
+
+ @Option(name = "-nr", aliases = { "--no-releases" }, description = "Disable release handling in this repository", required = false, multiValued = false)
+ boolean noReleases = false;
+
+ @Option(name = "-up", aliases = { "--update-policy" }, description = "Update policy for repository (never, daily (default), interval:N, always)", required = false, multiValued = false)
+ String updatePolicy;
+
+ @Option(name = "-cp", aliases = { "--checksum-policy" }, description = "Checksum policy for repository (ignore, warn (default), fail)", required = false, multiValued = false)
+ String checksumPolicy;
+
+ @Option(name = "-u", aliases = { "--username" }, description = "Username for remote repository", required = false, multiValued = false)
+ String username;
+
+ @Option(name = "-p", aliases = { "--password" }, description = "Password for remote repository (may be encrypted, see \"maven:password -ep\")", required = false, multiValued = false)
+ String password;
+
+ @Argument(description = "Repository URI. It may be file:// based, http(s):// based, may use other known protocol or even property placeholders (like ${karaf.base})", required = false)
+ String uri;
+
+ @Override
+ protected void edit(String prefix, Dictionary<String, Object> config,
+ MavenRepositoryURL[] allRepos, MavenRepositoryURL[] pidRepos, MavenRepositoryURL[] settingsRepos) throws Exception {
+
+ Optional<MavenRepositoryURL> first = Arrays.stream(allRepos)
+ .filter((repo) -> id.equals(repo.getId())).findFirst();
+ if (!first.isPresent()) {
+ System.err.printf("Can't find %s repository with ID \"%s\"\n", (defaultRepository ? "default" : "remote"), id);
+ return;
+ }
+
+ MavenRepositoryURL changedRepository = first.get();
+
+ changedRepository.setSnapshotsEnabled(snapshots);
+ changedRepository.setReleasesEnabled(!noReleases);
+
+ if (updatePolicy != null) {
+ SourceAnd<String> up = updatePolicy(updatePolicy);
+ if (!up.valid) {
+ System.err.println("Unknown value of update policy: \"" + updatePolicy + "\"");
+ return;
+ }
+ changedRepository.setReleasesUpdatePolicy(up.val());
+ changedRepository.setSnapshotsUpdatePolicy(up.val());
+ }
+
+ if (checksumPolicy != null) {
+ SourceAnd<String> cp = checksumPolicy(checksumPolicy);
+ if (!cp.valid) {
+ System.err.println("Unknown value of checksum policy: \"" + checksumPolicy + "\"");
+ return;
+ }
+ changedRepository.setReleasesChecksumPolicy(cp.val());
+ changedRepository.setSnapshotsChecksumPolicy(cp.val());
+ }
+
+ if (uri != null) {
+ SourceAnd<String> urlResolved = validateRepositoryURL(uri, defaultRepository);
+ if (!urlResolved.valid) {
+ return;
+ }
+ changedRepository.setURL(new URL(urlResolved.val()));
+ }
+
+ boolean hasUsername = username != null && !"".equals(username.trim());
+ boolean hasPassword = password != null && !"".equals(password.trim());
+ boolean hasCredentials = hasUsername && hasPassword;
+
+ if ((hasUsername && !hasPassword) || (!hasUsername && hasPassword)) {
+ System.err.println("Please specify both username and password");
+ return;
+ }
+
+ if (defaultRepository && hasCredentials) {
+ System.out.println("User credentials won't be used for default repository");
+ // no return
+ }
+
+ boolean credentialsUpdated = false;
+ // credentials for remote repository can be stored only in settings.xml
+ if (!defaultRepository && hasCredentials) {
+ if (!updateCredentials(force, id, username, password, prefix, config)) {
+ return;
+ }
+ credentialsUpdated = true;
+ }
+
+ if (!defaultRepository && changedRepository.getFrom() == MavenRepositoryURL.FROM.SETTINGS) {
+ // find <repository> in any active profile to change it
+ for (Profile profile : mavenSettings.getProfiles()) {
+ Optional<Repository> repository = profile.getRepositories().stream().filter((r) -> id.equals(r.getId())).findFirst();
+ if (repository.isPresent()) {
+ // I can't imagine it's not...
+ Repository r = repository.get();
+ r.setUrl(changedRepository.getURL().toString());
+ if (!changedRepository.isSnapshotsEnabled()) {
+ r.setSnapshots(new RepositoryPolicy());
+ r.getSnapshots().setEnabled(false);
+ } else {
+ RepositoryPolicy rp = r.getSnapshots() == null ? new RepositoryPolicy() : r.getSnapshots();
+ rp.setEnabled(true);
+ if (checksumPolicy != null) {
+ rp.setChecksumPolicy(changedRepository.getSnapshotsChecksumPolicy());
+ } else if (rp.getChecksumPolicy() == null) {
+ rp.setChecksumPolicy("warn");
+ }
+ if (updatePolicy != null) {
+ rp.setUpdatePolicy(changedRepository.getSnapshotsUpdatePolicy());
+ } else if (rp.getUpdatePolicy() == null) {
+ rp.setUpdatePolicy("daily");
+ }
+ r.setSnapshots(rp);
+ }
+ if (!changedRepository.isReleasesEnabled()) {
+ r.setReleases(new RepositoryPolicy());
+ r.getReleases().setEnabled(false);
+ } else {
+ RepositoryPolicy rp = r.getReleases() == null ? new RepositoryPolicy() : r.getReleases();
+ rp.setEnabled(true);
+ if (checksumPolicy != null) {
+ rp.setChecksumPolicy(changedRepository.getReleasesChecksumPolicy());
+ } else if (rp.getChecksumPolicy() == null) {
+ rp.setChecksumPolicy("warn");
+ }
+ if (updatePolicy != null) {
+ rp.setUpdatePolicy(changedRepository.getReleasesUpdatePolicy());
+ } else if (rp.getUpdatePolicy() == null) {
+ rp.setUpdatePolicy("daily");
+ }
+ r.setReleases(rp);
+ }
+ updateSettings(prefix, config);
+ break;
+ }
+ }
+ } else if (changedRepository.getFrom() == MavenRepositoryURL.FROM.PID) {
+ List<MavenRepositoryURL> newRepos = new LinkedList<>();
+ for (MavenRepositoryURL repo : pidRepos) {
+ MavenRepositoryURL _r = repo;
+ if (id.equals(repo.getId())) {
+ _r = changedRepository;
+ }
+ newRepos.add(_r);
+ }
+ updatePidRepositories(prefix, config, defaultRepository, newRepos, settingsRepos.length > 0);
+ if (credentialsUpdated) {
+ updateSettings(prefix, config);
+ }
+ }
+
+ Configuration cmConfig = cm.getConfiguration(PID);
+ cmConfig.update(config);
+
+ success = true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/32d5c7b7/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
index 9f403c1..32dcc8f 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
@@ -16,10 +16,21 @@
*/
package org.apache.karaf.maven.command;
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Arrays;
import java.util.Dictionary;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.apache.felix.utils.properties.InterpolationHelper;
import org.apache.karaf.maven.core.MavenRepositoryURL;
import org.apache.karaf.shell.api.action.Option;
+import org.apache.maven.settings.Server;
public abstract class RepositoryEditCommandSupport extends MavenSecuritySupport {
@@ -29,21 +40,150 @@ public abstract class RepositoryEditCommandSupport extends MavenSecuritySupport
@Option(name = "-d", aliases = { "--default" }, description = "Edit default repository instead of remote one", required = false, multiValued = false)
boolean defaultRepository = false;
+ @Option(name = "-f", aliases = { "--force" }, description = "Do not ask for confirmation", required = false, multiValued = false)
+ boolean force = false;
+
boolean success = false;
@Override
public final void doAction(String prefix, Dictionary<String, Object> config) throws Exception {
- edit(prefix, config);
+ if (id == null || "".equals(id.trim())) {
+ System.err.println("Please specify ID of repository");
+ return;
+ }
+
+ MavenRepositoryURL[] repositories = repositories(config, !defaultRepository);
+
+ MavenRepositoryURL[] repositoriesFromPidProperty = Arrays.stream(repositories)
+ .filter((repo) -> repo.getFrom() == MavenRepositoryURL.FROM.PID)
+ .toArray(MavenRepositoryURL[]::new);
+
+ MavenRepositoryURL[] repositoriesFromSettings = Arrays.stream(repositories)
+ .filter((repo) -> repo.getFrom() == MavenRepositoryURL.FROM.SETTINGS)
+ .toArray(MavenRepositoryURL[]::new);
+
+ edit(prefix, config, repositories, repositoriesFromPidProperty, repositoriesFromSettings);
if (success) {
if (showPasswords) {
- session.execute("maven:repository-list -x");
+ session.execute("maven:repository-list -v -x");
} else {
- session.execute("maven:repository-list");
+ session.execute("maven:repository-list -v");
}
}
}
- protected abstract void edit(String prefix, Dictionary<String, Object> config) throws Exception;
+ /**
+ * Peform action on repository (add, remove, change)
+ * @param prefix property prefix for <code>org.ops4j.pax.url.mvn</code> PID
+ * @param config
+ * @param allRepos
+ * @param pidRepos
+ * @param settingsRepos
+ * @throws Exception
+ */
+ protected abstract void edit(String prefix, Dictionary<String, Object> config,
+ MavenRepositoryURL[] allRepos, MavenRepositoryURL[] pidRepos, MavenRepositoryURL[] settingsRepos) throws Exception;
+
+ /**
+ * Stores new repository list in relevant <code>org.ops4j.pax.url.mvn</code> PID property
+ * @param prefix
+ * @param config
+ * @param defaultRepository default (<code>true</code>) or remote repositories?
+ * @param newRepos new list of repositories
+ * @param hasSettingsRepositories whether we have repositories stored in <code>settings.xml</code> as well
+ */
+ protected void updatePidRepositories(String prefix, Dictionary<String, Object> config, boolean defaultRepository,
+ List<MavenRepositoryURL> newRepos, boolean hasSettingsRepositories) {
+ String newList = newRepos.stream().map(MavenRepositoryURL::asRepositorySpec)
+ .collect(Collectors.joining(","));
+
+ if (defaultRepository) {
+ config.put(prefix + PROPERTY_DEFAULT_REPOSITORIES, newList);
+ } else {
+ if (hasSettingsRepositories) {
+ newList = "+" + newList;
+ }
+ config.put(prefix + PROPERTY_REPOSITORIES, newList);
+ }
+ }
+
+ /**
+ * Stores credential information in settings, without persisting them
+ * @param force
+ * @param id
+ * @param username
+ * @param password
+ * @param prefix
+ * @param config
+ */
+ protected boolean updateCredentials(boolean force, String id, String username, String password,
+ String prefix, Dictionary<String, Object> config) throws IOException {
+ if (!force && !confirm("Maven settings will be updated and org.ops4j.pax.url.mvn.settings property will change. Continue? (y/N) ")) {
+ return false;
+ }
+
+ Optional<Server> existingServer = mavenSettings.getServers().stream()
+ .filter((s) -> id.equals(s.getId())).findAny();
+ Server server = null;
+ if (existingServer.isPresent()) {
+ server = existingServer.get();
+ } else {
+ server = new Server();
+ server.setId(id);
+ mavenSettings.getServers().add(server);
+ }
+ server.setUsername(username);
+ server.setPassword(password);
+
+ return true;
+ }
+
+ /**
+ * Takes passed-in repository URI and performs basic validation
+ * @param uri
+ * @param defaultRepository
+ * @return
+ */
+ protected SourceAnd<String> validateRepositoryURL(String uri, boolean defaultRepository) throws URISyntaxException, MalformedURLException {
+ SourceAnd<String> result = new SourceAnd<String>();
+ result.valid = false;
+
+ if (uri == null || "".equals(uri.trim())) {
+ System.err.println("Please specify repository location");
+ return result;
+ }
+ String urlResolved = InterpolationHelper.substVars(uri, "uri", null, null, context);
+ URL url = null;
+ try {
+ url = new URL(urlResolved);
+ urlResolved = url.toString();
+
+ if ("file".equals(url.getProtocol()) && new File(url.toURI()).isDirectory()) {
+ System.err.println("Location \"" + urlResolved + "\" is not accessible");
+ return result;
+ }
+ } catch (MalformedURLException e) {
+ // a directory?
+ File location = new File(urlResolved);
+ if (!location.exists() || !location.isDirectory()) {
+ System.err.println("Location \"" + urlResolved + "\" is not accessible");
+ return result;
+ } else {
+ url = location.toURI().toURL();
+ urlResolved = url.toString();
+ }
+ }
+
+ if (defaultRepository && !"file".equals(url.getProtocol())) {
+ System.err.println("Default repositories should be locally accessible (use file:// protocol or normal directory path)");
+ return result;
+ }
+
+ result.valid = true;
+ result.value = urlResolved;
+
+ return result;
+ }
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/32d5c7b7/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryRemoveCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryRemoveCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryRemoveCommand.java
index eaf62e5..28c0716 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryRemoveCommand.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryRemoveCommand.java
@@ -16,18 +16,75 @@
*/
package org.apache.karaf.maven.command;
+import java.util.Arrays;
import java.util.Dictionary;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.apache.karaf.maven.core.MavenRepositoryURL;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.maven.settings.Profile;
+import org.apache.maven.settings.Repository;
+import org.apache.maven.settings.Server;
+import org.osgi.service.cm.Configuration;
@Command(scope = "maven", name = "repository-remove", description = "Removes Maven repository")
@Service
public class RepositoryRemoveCommand extends RepositoryEditCommandSupport {
@Override
- protected void edit(String prefix, Dictionary<String, Object> config) throws Exception {
+ protected void edit(String prefix, Dictionary<String, Object> config,
+ MavenRepositoryURL[] allRepos, MavenRepositoryURL[] pidRepos, MavenRepositoryURL[] settingsRepos) throws Exception {
+ Optional<MavenRepositoryURL> first = Arrays.stream(allRepos)
+ .filter((repo) -> id.equals(repo.getId())).findAny();
+ if (!first.isPresent()) {
+ System.err.printf("Can't find %s repository with ID \"%s\"\n", (defaultRepository ? "default" : "remote"), id);
+ return;
+ }
+
+ if (force || confirm(String.format("Are you sure to remove repository with ID \"%s\" for URL %s? (y/N) ", id, first.get().getURL()))) {
+ if (!defaultRepository && first.get().getFrom() == MavenRepositoryURL.FROM.SETTINGS) {
+ // remove <server> (credentials) if available
+ List<Server> newServers = mavenSettings.getServers().stream()
+ .filter((s) -> !id.equals(s.getId())).collect(Collectors.toList());
+ mavenSettings.setServers(newServers);
+
+ // find <repository> in any active profile and remove it
+ for (Profile profile : mavenSettings.getProfiles()) {
+ if (profile.getRepositories().stream().anyMatch((r) -> id.equals(r.getId()))) {
+ List<Repository> newRepos = profile.getRepositories().stream()
+ .filter((r) -> !id.equals(r.getId())).collect(Collectors.toList());
+ profile.setRepositories(newRepos);
+ System.out.printf("Repository with ID \"%s\" was removed from profile \"%s\"\n", id, profile.getId());
+ break;
+ }
+ }
+
+ updateSettings(prefix, config);
+ } else if (first.get().getFrom() == MavenRepositoryURL.FROM.PID) {
+ List<MavenRepositoryURL> newRepos = Arrays.stream(pidRepos).filter((r) -> !id.equals(r.getId())).collect(Collectors.toList());
+
+ updatePidRepositories(prefix, config, defaultRepository, newRepos, settingsRepos.length > 0);
+
+ // if there are credentials for this repository, we have to remove them from settings.xml
+ if (mavenSettings.getServers().stream().anyMatch((s) -> id.equals(s.getId()))) {
+ // remove <server> (credentials) if available
+ List<Server> newServers = mavenSettings.getServers().stream()
+ .filter((s) -> !id.equals(s.getId())).collect(Collectors.toList());
+ mavenSettings.setServers(newServers);
+
+ updateSettings(prefix, config);
+ }
+ }
+
+ Configuration cmConfig = cm.getConfiguration(PID);
+ cmConfig.update(config);
+
+ success = true;
+ }
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/32d5c7b7/maven/core/src/main/java/org/apache/karaf/maven/core/MavenRepositoryURL.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/core/MavenRepositoryURL.java b/maven/core/src/main/java/org/apache/karaf/maven/core/MavenRepositoryURL.java
index 1c422c8..7bc5a73 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/core/MavenRepositoryURL.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/core/MavenRepositoryURL.java
@@ -61,7 +61,7 @@ public class MavenRepositoryURL
/**
* Repository URL.
*/
- private final URL m_repositoryURL;
+ private URL m_repositoryURL;
/**
* Repository file (only if URL is a file URL).
*/
@@ -69,27 +69,27 @@ public class MavenRepositoryURL
/**
* True if the repository contains snapshots.
*/
- private final boolean m_snapshotsEnabled;
+ private boolean m_snapshotsEnabled;
/**
* True if the repository contains releases.
*/
- private final boolean m_releasesEnabled;
+ private boolean m_releasesEnabled;
/**
* Repository update policy
*/
- private final String m_releasesUpdatePolicy;
+ private String m_releasesUpdatePolicy;
/**
* Repository update policy
*/
- private final String m_snapshotsUpdatePolicy;
+ private String m_snapshotsUpdatePolicy;
/**
* Repository checksum policy
*/
- private final String m_releasesChecksumPolicy;
+ private String m_releasesChecksumPolicy;
/**
* Repository checksum policy
*/
- private final String m_snapshotsChecksumPolicy;
+ private String m_snapshotsChecksumPolicy;
private final boolean m_multi;
/**
@@ -288,6 +288,10 @@ public class MavenRepositoryURL
return m_repositoryURL;
}
+ public void setURL(URL url) {
+ this.m_repositoryURL = url;
+ }
+
/**
* Getter.
*
@@ -308,6 +312,11 @@ public class MavenRepositoryURL
return m_releasesEnabled;
}
+ public void setReleasesEnabled(boolean enabled)
+ {
+ m_releasesEnabled = enabled;
+ }
+
/**
* Getter.
*
@@ -318,6 +327,11 @@ public class MavenRepositoryURL
return m_snapshotsEnabled;
}
+ public void setSnapshotsEnabled(boolean enabled)
+ {
+ m_snapshotsEnabled = enabled;
+ }
+
public String getReleasesUpdatePolicy() {
return m_releasesUpdatePolicy;
}
@@ -334,6 +348,22 @@ public class MavenRepositoryURL
return m_snapshotsChecksumPolicy;
}
+ public void setReleasesUpdatePolicy(String policy) {
+ m_releasesUpdatePolicy = policy;
+ }
+
+ public void setSnapshotsUpdatePolicy(String policy) {
+ m_snapshotsUpdatePolicy = policy;
+ }
+
+ public void setReleasesChecksumPolicy(String policy) {
+ m_releasesChecksumPolicy = policy;
+ }
+
+ public void setSnapshotsChecksumPolicy(String policy) {
+ m_snapshotsChecksumPolicy = policy;
+ }
+
public FROM getFrom() {
return m_from;
}
@@ -402,7 +432,7 @@ public class MavenRepositoryURL
}
}
if (m_snapshotsEnabled && m_releasesEnabled) {
- // compact snapshots & release update & checksum policies?
+ // compact snapshots & release update & checksum policies
if (m_releasesUpdatePolicy != null && Objects.equals(m_releasesUpdatePolicy, m_snapshotsUpdatePolicy)) {
sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_UPDATE + "=" + m_releasesUpdatePolicy);
}
[6/6] karaf git commit: [KARAF-5008] maven:password command
Posted by gg...@apache.org.
[KARAF-5008] maven:password command
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/ecc21a3c
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/ecc21a3c
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/ecc21a3c
Branch: refs/heads/master-maven-commands
Commit: ecc21a3c45063ce1c88f7306f4e62865d24260d2
Parents: 750fd14
Author: Grzegorz Grzybek <gr...@gmail.com>
Authored: Tue Jun 20 12:17:46 2017 +0200
Committer: Grzegorz Grzybek <gr...@gmail.com>
Committed: Wed Jun 21 15:31:54 2017 +0200
----------------------------------------------------------------------
maven/core/pom.xml | 6 ++
.../karaf/maven/command/HttpProxyCommand.java | 2 +-
.../command/MavenConfigurationSupport.java | 60 ++++++++++-
.../maven/command/MavenSecuritySupport.java | 31 ++++++
.../karaf/maven/command/PasswordCommand.java | 103 +++++++++++++++++++
.../command/RepositoryEditCommandSupport.java | 2 +-
.../maven/command/RepositoryListCommand.java | 2 +-
.../karaf/maven/command/SummaryCommand.java | 2 +-
.../org/apache/karaf/maven/SettingsTest.java | 2 +
.../command/MavenConfigurationSupportTest.java | 60 +++++++++++
maven/core/src/test/resources/log4j.properties | 34 ++++++
11 files changed, 295 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/pom.xml
----------------------------------------------------------------------
diff --git a/maven/core/pom.xml b/maven/core/pom.xml
index db2f2a7..a2a724f 100644
--- a/maven/core/pom.xml
+++ b/maven/core/pom.xml
@@ -66,6 +66,12 @@
<artifactId>maven-embedder</artifactId>
<version>3.0.3</version>
</dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
index 6f8b794..129aca5 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
@@ -27,7 +27,7 @@ import org.apache.maven.settings.Proxy;
@Command(scope = "maven", name = "http-proxy", description = "Manage HTTP proxy configuration for Maven remote repositories")
@Service
-public class HttpProxyCommand extends MavenConfigurationSupport {
+public class HttpProxyCommand extends MavenSecuritySupport {
@Option(name = "--add", description = "Adds HTTP proxy configuration to Maven settings", required = false, multiValued = false)
boolean add;
http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java b/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
index 4c3416a..0588afd 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
@@ -17,10 +17,13 @@
package org.apache.karaf.maven.command;
import java.io.File;
+import java.io.IOException;
import java.lang.reflect.Field;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Date;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.LinkedHashSet;
@@ -28,10 +31,11 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.TreeSet;
+import java.util.regex.Pattern;
import org.apache.karaf.maven.core.MavenRepositoryURL;
import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Option;
import org.apache.karaf.shell.api.action.lifecycle.Reference;
import org.apache.karaf.shell.api.console.Session;
import org.apache.karaf.shell.support.table.Row;
@@ -72,6 +76,12 @@ public abstract class MavenConfigurationSupport implements Action {
protected static final String PATTERN_PID_PROPERTY = "Explicit %s PID configuration (%s)";
+ protected static final String PATTERN_SECURITY_SETTINGS = "maven-security-settings-%d.xml";
+ protected static final Pattern RE_SECURITY_SETTINGS = Pattern.compile("maven-security-settings-(\\d+)\\.xml");
+ protected static final String PATTERN_SETTINGS = "maven-settings-%d.xml";
+ protected static final Pattern RE_SETTINGS = Pattern.compile("maven-settings-(\\d+)\\.xml");
+ private static final int MAX_SEQUENCE_SIZE = 10;
+
protected static final String PROPERTY_LOCAL_REPOSITORY = "localRepository";
protected static final String PROPERTY_DEFAULT_REPOSITORIES = "defaultRepositories";
protected static final String PROPERTY_REPOSITORIES = "repositories";
@@ -122,9 +132,6 @@ public abstract class MavenConfigurationSupport implements Action {
@Reference
protected Session session;
- @Option(name = "-x", aliases = { "--show-passwords" }, description = "Do not hide passwords related to Maven encryption", required = false, multiValued = false)
- boolean showPasswords;
-
@Override
final public Object execute() throws Exception {
Configuration c = cm.getConfiguration(PID);
@@ -144,7 +151,7 @@ public abstract class MavenConfigurationSupport implements Action {
localRepository = localRepository((String) c.getProperties().get(PID + "." + PROPERTY_LOCAL_REPOSITORY));
- if (showPasswords) {
+ if (showPasswords()) {
decryptSettings();
}
@@ -558,6 +565,49 @@ public abstract class MavenConfigurationSupport implements Action {
}
}
+ /**
+ * Asks for confirmation (user has to press <code>y</code>) after presenting a prompt
+ * @param prompt
+ * @return
+ */
+ protected boolean confirm(String prompt) throws IOException {
+ String response = session.readLine(prompt, null);
+ return "y".equals(response);
+ }
+
+ /**
+ * Returns new {@link File} that's part of fixed-size sequence. Keeps the sequence bounded.
+ * @param dataDir
+ * @param pattern
+ * @param fileNameFormat
+ * @return
+ */
+ protected File nextSequenceFile(File dataDir, Pattern pattern, String fileNameFormat) {
+ File[] files = dataDir.listFiles((dir, name) -> pattern.matcher(name).matches());
+ File result = null;
+ if (files != null && files.length > 0) {
+ List<String> names = new ArrayList<>(Arrays.stream(files).map(File::getName)
+ .collect(TreeSet<String>::new, TreeSet::add, TreeSet::addAll));
+
+ names.add(String.format(fileNameFormat, new Date().getTime()));
+
+ while (names.size() > MAX_SEQUENCE_SIZE) {
+ String name = names.remove(0);
+ new File(dataDir, name).delete();
+ }
+ result = new File(dataDir, names.get(names.size() - 1));
+ }
+ if (result == null) {
+ result = new File(dataDir, String.format(fileNameFormat, new Date().getTime()));
+ }
+
+ return result;
+ }
+
+ protected boolean showPasswords() {
+ return false;
+ }
+
protected static class SourceAnd<T> {
String source;
T value;
http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/main/java/org/apache/karaf/maven/command/MavenSecuritySupport.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/MavenSecuritySupport.java b/maven/core/src/main/java/org/apache/karaf/maven/command/MavenSecuritySupport.java
new file mode 100644
index 0000000..6c46c9d
--- /dev/null
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/MavenSecuritySupport.java
@@ -0,0 +1,31 @@
+/*
+ * 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.maven.command;
+
+import org.apache.karaf.shell.api.action.Option;
+
+public abstract class MavenSecuritySupport extends MavenConfigurationSupport {
+
+ @Option(name = "-x", aliases = { "--show-passwords" }, description = "Do not hide passwords related to Maven encryption", required = false, multiValued = false)
+ boolean showPasswords;
+
+ @Override
+ protected boolean showPasswords() {
+ return showPasswords;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/main/java/org/apache/karaf/maven/command/PasswordCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/PasswordCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/PasswordCommand.java
new file mode 100644
index 0000000..ed44b35
--- /dev/null
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/PasswordCommand.java
@@ -0,0 +1,103 @@
+/*
+ * 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.maven.command;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.util.Dictionary;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.osgi.service.cm.Configuration;
+import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
+import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;
+import org.sonatype.plexus.components.sec.dispatcher.model.io.xpp3.SecurityConfigurationXpp3Writer;
+
+@Command(scope = "maven", name = "password", description = "Manage passwords for remote repositories and proxies")
+@Service
+public class PasswordCommand extends MavenConfigurationSupport {
+
+ @Option(name = "-ep", aliases = { "--encrypt-password" }, description = "Encrypts passwords to use for remote repositories and proxies, see \"mvn -ep\"", required = false, multiValued = false)
+ boolean ep;
+
+ @Option(name = "-emp", aliases = { "--encrypt-master-password" }, description = "Encrypts master password used to encrypt/decrypt other passwords, see \"mvn -emp\"", required = false, multiValued = false)
+ boolean emp;
+
+ @Option(name = "-p", aliases = { "--persist" }, description = "", required = false, multiValued = false)
+ boolean persist;
+
+ @Override
+ public void doAction(String prefix, Dictionary<String, Object> config) throws Exception {
+ if (ep && emp) {
+ System.err.println("Please specify only one of --encrypt-password and --encrypt-master-password");
+ return;
+ }
+
+ if (ep && persist) {
+ System.err.println("Ordinary passwords are not persisted - use the encrypted password in either <proxy> or <server>");
+ return;
+ }
+
+ if (ep) {
+ // encrypt password using master password
+ if (masterPassword == null) {
+ System.err.println("Master password is not available");
+ return;
+ }
+ String password = session.readLine("Password to encrypt: ", '*');
+ System.out.println("Encrypted password: " + cipher.encryptAndDecorate(password, masterPassword));
+ return;
+ }
+
+ if (emp) {
+ if (persist && !confirm("Maven security settings will be stored in new file. This file will be used in org.ops4j.pax.url.mvn.security property. Continue? (y/N) ")) {
+ return;
+ }
+
+ // encrypt master password using DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION
+ String password = session.readLine("Master password to encrypt: ", '*');
+ String encryptedPassword = cipher.encryptAndDecorate(password, DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION);
+ System.out.println("Encrypted master password: " + encryptedPassword);
+ if (persist) {
+ SettingsSecurity settingsSecurity = new SettingsSecurity();
+ settingsSecurity.setMaster(encryptedPassword);
+ File dataDir = context.getDataFile(".");
+ if (!dataDir.isDirectory()) {
+ System.err.println("Can't access data directory for " + context.getBundle().getSymbolicName() + " bundle");
+ }
+ File newSecuritySettingsFile = nextSequenceFile(dataDir, RE_SECURITY_SETTINGS, PATTERN_SECURITY_SETTINGS);
+ try (FileWriter fw = new FileWriter(newSecuritySettingsFile)) {
+ new SecurityConfigurationXpp3Writer().write(fw, settingsSecurity);
+ }
+
+ System.out.println("New security settings stored in \"" + newSecuritySettingsFile.getCanonicalPath() + "\"");
+
+ Configuration cmConfig = cm.getConfiguration(PID);
+ config.put(prefix + PROPERTY_SECURITY_FILE, newSecuritySettingsFile.getCanonicalPath());
+ cmConfig.update(config);
+ }
+ return;
+ }
+ }
+
+ @Override
+ protected boolean showPasswords() {
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
index 0179b02..12700d0 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
@@ -21,7 +21,7 @@ import java.util.Dictionary;
import org.apache.karaf.maven.core.MavenRepositoryURL;
import org.apache.karaf.shell.api.action.Option;
-public abstract class RepositoryEditCommandSupport extends MavenConfigurationSupport {
+public abstract class RepositoryEditCommandSupport extends MavenSecuritySupport {
@Override
public void doAction(String prefix, Dictionary<String, Object> config) throws Exception {
http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryListCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryListCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryListCommand.java
index 90c7c26..ddc2ea5 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryListCommand.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryListCommand.java
@@ -28,7 +28,7 @@ import org.apache.maven.settings.Server;
@Command(scope = "maven", name = "repository-list", description = "Maven repository summary.")
@Service
-public class RepositoryListCommand extends MavenConfigurationSupport {
+public class RepositoryListCommand extends MavenSecuritySupport {
@Option(name = "-v", aliases = { "--verbose" }, description = "Show additional information (policies, source)", required = false, multiValued = false)
boolean verbose;
http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
index 1678239..3f7e91a 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
@@ -28,7 +28,7 @@ import org.apache.maven.settings.Proxy;
@Command(scope = "maven", name = "summary", description = "Maven configuration summary.")
@Service
-public class SummaryCommand extends MavenConfigurationSupport {
+public class SummaryCommand extends MavenSecuritySupport {
@Option(name = "-p", aliases = { "--property-ids" }, description = "Use PID property identifiers instead of their names", required = false, multiValued = false)
boolean propertyIds;
http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
----------------------------------------------------------------------
diff --git a/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java b/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
index b0d9110..3ecaf30 100644
--- a/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
+++ b/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
@@ -53,9 +53,11 @@ public class SettingsTest {
// non-master password ('mvn -ep admin')
DefaultPlexusCipher plexusCipher = new DefaultPlexusCipher();
System.out.println(plexusCipher.decrypt("{EhjazkVpkMoHjAgaUKX+UxeXn9lsJGHst2uFKmhNZ8U=}", "admin"));
+ System.out.println(plexusCipher.decrypt("{oWE12FbirwYHNit93TAMA+OC/GJge2r9FuzI8kOuHlA=}", "settings.security"));
// master password (`mvn -emp admin`)
PBECipher cipher = new PBECipher();
+ System.out.println(cipher.decrypt64("EhjazkVpkMoHjAgaUKX+UxeXn9lsJGHst2uFKmhNZ8U=","admin"));
System.out.println(cipher.decrypt64("oWE12FbirwYHNit93TAMA+OC/GJge2r9FuzI8kOuHlA=","settings.security"));
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/test/java/org/apache/karaf/maven/command/MavenConfigurationSupportTest.java
----------------------------------------------------------------------
diff --git a/maven/core/src/test/java/org/apache/karaf/maven/command/MavenConfigurationSupportTest.java b/maven/core/src/test/java/org/apache/karaf/maven/command/MavenConfigurationSupportTest.java
new file mode 100644
index 0000000..16ffc3f
--- /dev/null
+++ b/maven/core/src/test/java/org/apache/karaf/maven/command/MavenConfigurationSupportTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.maven.command;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Dictionary;
+import java.util.regex.Pattern;
+
+import org.junit.Test;
+import shaded.org.apache.commons.io.FileUtils;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class MavenConfigurationSupportTest {
+
+ @Test
+ public void sequenceFiles() throws IOException {
+ File dataDir = new File("target/data");
+ FileUtils.deleteDirectory(dataDir);
+ dataDir.mkdirs();
+
+ MavenConfigurationSupport support = new MavenConfigurationSupport() {
+ @Override
+ protected void doAction(String prefix, Dictionary<String, Object> config) throws Exception { }
+ };
+
+ File newFile = support.nextSequenceFile(dataDir, Pattern.compile("file-(\\d+).txt"), "file-%04d.txt");
+ assertThat(newFile.getName(), equalTo("file-0001.txt"));
+
+ try (FileWriter fw = new FileWriter(new File(dataDir, "file-abcd.txt"))) {
+ fw.write("~");
+ }
+ newFile = support.nextSequenceFile(dataDir, Pattern.compile("file-(\\d+).txt"), "file-%04d.txt");
+ assertThat(newFile.getName(), equalTo("file-0001.txt"));
+
+ try (FileWriter fw = new FileWriter(new File(dataDir, "file-0004.txt"))) {
+ fw.write("~");
+ }
+ newFile = support.nextSequenceFile(dataDir, Pattern.compile("file-(\\d+).txt"), "file-%04d.txt");
+ assertThat(newFile.getName(), equalTo("file-0005.txt"));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/ecc21a3c/maven/core/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/maven/core/src/test/resources/log4j.properties b/maven/core/src/test/resources/log4j.properties
new file mode 100644
index 0000000..e1cbdd1
--- /dev/null
+++ b/maven/core/src/test/resources/log4j.properties
@@ -0,0 +1,34 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+#
+# The logging properties used during tests..
+#
+log4j.rootLogger=DEBUG, console, file
+
+# Console will only display warnnings
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{ISO8601} | %-5.5p | %-16.16t | %-32.32c{1} | %-32.32C %4L | %m%n
+#log4j.appender.console.threshold=WARN
+
+# File appender will contain all info messages
+log4j.appender.file=org.apache.log4j.FileAppender
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=%d | %-5p | %m | %c | %t%n
+log4j.appender.file.file=target/test.log
+log4j.appender.file.append=true
[3/6] karaf git commit: [KARAF-5008] maven:repository-add command
Posted by gg...@apache.org.
[KARAF-5008] maven:repository-add command
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/ede23baa
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/ede23baa
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/ede23baa
Branch: refs/heads/master-maven-commands
Commit: ede23baa73e76256db60187b4cbc5916aafa1231
Parents: ecc21a3
Author: Grzegorz Grzybek <gr...@gmail.com>
Authored: Wed Jun 21 09:33:51 2017 +0200
Committer: Grzegorz Grzybek <gr...@gmail.com>
Committed: Wed Jun 21 15:31:54 2017 +0200
----------------------------------------------------------------------
maven/core/pom.xml | 6 +
.../command/MavenConfigurationSupport.java | 81 +++++++-
.../karaf/maven/command/PasswordCommand.java | 2 +
.../maven/command/RepositoryAddCommand.java | 196 ++++++++++++++++++-
.../command/RepositoryEditCommandSupport.java | 22 ++-
.../maven/command/RepositoryRemoveCommand.java | 4 +-
.../karaf/maven/command/SummaryCommand.java | 51 -----
.../karaf/maven/core/MavenRepositoryURL.java | 47 +++++
.../org/apache/karaf/maven/SettingsTest.java | 2 +
.../command/MavenConfigurationSupportTest.java | 8 +-
.../maven/core/MavenRepositoryURLTest.java | 64 ++++++
11 files changed, 420 insertions(+), 63 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/ede23baa/maven/core/pom.xml
----------------------------------------------------------------------
diff --git a/maven/core/pom.xml b/maven/core/pom.xml
index a2a724f..403835e 100644
--- a/maven/core/pom.xml
+++ b/maven/core/pom.xml
@@ -66,6 +66,11 @@
<artifactId>maven-embedder</artifactId>
<version>3.0.3</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.utils</artifactId>
+ <scope>provided</scope>
+ </dependency>
<dependency>
<groupId>org.slf4j</groupId>
@@ -111,6 +116,7 @@
*,
</Import-Package>
<Private-Package>
+ org.apache.felix.utils.properties;-split-package:=merge-first,
org.apache.karaf.maven.command,
org.apache.karaf.maven.core,
org.apache.maven.settings.*;-split-package:=merge-first,
http://git-wip-us.apache.org/repos/asf/karaf/blob/ede23baa/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java b/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
index 0588afd..b64e583 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
@@ -460,7 +460,7 @@ public abstract class MavenConfigurationSupport implements Action {
String[] repositories = listOfValues((String) config.get(property));
if (remote) {
- if (repositories.length == 0 || repositories.length > 0 && repositories[0].charAt(0) == '+') {
+ if (repositories.length == 0 || repositories[0].charAt(0) == '+') {
if (repositories.length > 0) {
repositories[0] = repositories[0].substring(1);
}
@@ -604,13 +604,92 @@ public abstract class MavenConfigurationSupport implements Action {
return result;
}
+ /**
+ * This method controls whether passwords are tried to be decrypted.
+ * @return
+ */
protected boolean showPasswords() {
return false;
}
+ /**
+ * Parses update policy value and returns {@link SourceAnd}<code><String></code> about the value
+ * @param policy
+ * @return
+ */
+ protected SourceAnd<String> updatePolicy(String policy) {
+ SourceAnd<String> result = new SourceAnd<>();
+ result.value = policy;
+
+ if (policy == null || "".equals(policy.trim())) {
+ result.value = "";
+ result.valid = false;
+ result.source = "Implicit \"never\", but doesn't override repository-specific value";
+ return result;
+ }
+
+ result.source = String.format(PATTERN_PID_PROPERTY, PID, PID + "." + PROPERTY_GLOBAL_UPDATE_POLICY);
+ if ("always".equals(policy) || "never".equals(policy) || "daily".equals(policy)) {
+ // ok
+ result.valid = true;
+ } else if (policy.startsWith("interval")) {
+ int minutes = 1440;
+ try {
+ String n = policy.substring("interval".length() + 1);
+ minutes = Integer.parseInt(n);
+ result.valid = true;
+ } catch (Exception e) {
+ result.valid = false;
+ result.value = "interval:1440";
+ result.source = "Implicit \"interval:1440\" (error parsing \"" + policy + "\")";
+ }
+ } else {
+ result.valid = false;
+ result.value = "never";
+ result.source = "Implicit \"never\" (unknown value \"" + policy + "\")";
+ }
+
+ return result;
+ }
+
+ /**
+ * Parses checksum policy value and returns {@link SourceAnd}<code><String></code> about the value
+ * @param policy
+ * @return
+ */
+ protected SourceAnd<String> checksumPolicy(String policy) {
+ SourceAnd<String> result = new SourceAnd<>();
+ result.value = policy;
+
+ if (policy == null || "".equals(policy.trim())) {
+ result.valid = false;
+ result.value = "warn";
+ result.source = "Default \"warn\"";
+ return result;
+ }
+
+ result.source = String.format(PATTERN_PID_PROPERTY, PID, PID + "." + PROPERTY_GLOBAL_CHECKSUM_POLICY);
+ if ("ignore".equals(policy) || "warn".equals(policy) || "fail".equals(policy)) {
+ // ok
+ result.valid = true;
+ } else {
+ result.valid = false;
+ result.value = "warn";
+ result.source = "Implicit \"warn\" (unknown value \"" + policy + "\")";
+ }
+
+ return result;
+ }
+
+ /**
+ * Handy class containing value and information about its origin. <code>valid</code> may be used to indicate
+ * if the value is correct. It may be implicit, but the interpretation of <code>valid </code> is not defined.
+ * @param <T>
+ */
protected static class SourceAnd<T> {
String source;
T value;
+ boolean valid;
public SourceAnd() {
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/ede23baa/maven/core/src/main/java/org/apache/karaf/maven/command/PasswordCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/PasswordCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/PasswordCommand.java
index ed44b35..4243212 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/PasswordCommand.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/PasswordCommand.java
@@ -61,6 +61,7 @@ public class PasswordCommand extends MavenConfigurationSupport {
}
String password = session.readLine("Password to encrypt: ", '*');
System.out.println("Encrypted password: " + cipher.encryptAndDecorate(password, masterPassword));
+ System.out.println("You can use this encrypted password when defining repositories and proxies");
return;
}
@@ -79,6 +80,7 @@ public class PasswordCommand extends MavenConfigurationSupport {
File dataDir = context.getDataFile(".");
if (!dataDir.isDirectory()) {
System.err.println("Can't access data directory for " + context.getBundle().getSymbolicName() + " bundle");
+ return;
}
File newSecuritySettingsFile = nextSequenceFile(dataDir, RE_SECURITY_SETTINGS, PATTERN_SECURITY_SETTINGS);
try (FileWriter fw = new FileWriter(newSecuritySettingsFile)) {
http://git-wip-us.apache.org/repos/asf/karaf/blob/ede23baa/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryAddCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryAddCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryAddCommand.java
index 13bcbdb..11034d3 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryAddCommand.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryAddCommand.java
@@ -16,20 +16,210 @@
*/
package org.apache.karaf.maven.command;
+import java.io.File;
+import java.io.FileWriter;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.apache.felix.utils.properties.InterpolationHelper;
+import org.apache.karaf.maven.core.MavenRepositoryURL;
+import org.apache.karaf.shell.api.action.Argument;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Option;
import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.maven.settings.Server;
+import org.apache.maven.settings.io.xpp3.SettingsXpp3Writer;
+import org.ops4j.pax.url.mvn.ServiceConstants;
+import org.osgi.service.cm.Configuration;
@Command(scope = "maven", name = "repository-add", description = "Adds Maven repository")
@Service
public class RepositoryAddCommand extends RepositoryEditCommandSupport {
- @Option(name = "-x", aliases = { "--show-passwords" }, description = "Do not hide passwords related to Maven encryption", required = false, multiValued = false)
- boolean showPasswords;
+ @Option(name = "-idx", description = "Index at which new repository is to be inserted (0-based) (defaults to last - repository will be appended)", required = false, multiValued = false)
+ int idx = -1;
+
+ @Option(name = "-s", aliases = { "--snapshots" }, description = "Enable SNAPSHOT handling in the repository", required = false, multiValued = false)
+ boolean snapshots = false;
+
+ @Option(name = "-nr", aliases = { "--no-releases" }, description = "Disable release handling in this repository", required = false, multiValued = false)
+ boolean noReleases = false;
+
+ @Option(name = "-up", aliases = { "--update-policy" }, description = "Update policy for repository (never, daily (default), interval:N, always)", required = false, multiValued = false)
+ String updatePolicy = "daily";
+
+ @Option(name = "-cp", aliases = { "--checksum-policy" }, description = "Checksum policy for repository (ignore, warn (default), fail)", required = false, multiValued = false)
+ String checksumPolicy = "warn";
+
+ @Argument(description = "Repository URI. It may be file:// based, http(s):// based, may use other known protocol or even property placeholders (like ${karaf.base})")
+ String uri;
+
+ @Option(name = "-u", aliases = { "--username" }, description = "Username for remote repository", required = false, multiValued = false)
+ String username;
+
+ @Option(name = "-p", aliases = { "--password" }, description = "Password for remote repository (may be encrypted, see \"maven:password -ep\")", required = false, multiValued = false)
+ String password;
@Override
- protected void edit() {
+ protected void edit(String prefix, Dictionary<String, Object> config) throws Exception {
+ MavenRepositoryURL[] repositories = repositories(config, !defaultRepository);
+
+ MavenRepositoryURL[] repositoriesFromPidProperty = Arrays.stream(repositories)
+ .filter((repo) -> repo.getFrom() == MavenRepositoryURL.FROM.PID)
+ .toArray(MavenRepositoryURL[]::new);
+
+ if (idx > repositoriesFromPidProperty.length) {
+ // TOCONSIDER: should we allow to add repository to settings.xml too?
+ System.err.printf("List of %s repositories has %d elements. Can't insert at position %s.\n",
+ (defaultRepository ? "default" : "remote"), repositories.length, id);
+ return;
+ }
+
+ if (id == null || "".equals(id.trim())) {
+ System.err.println("Please specify ID of repository");
+ return;
+ }
+
+ Optional<MavenRepositoryURL> first = Arrays.stream(repositories)
+ .filter((repo) -> id.equals(repo.getId())).findAny();
+ if (first.isPresent()) {
+ System.err.printf("Repository with ID \"%s\" is already configured for URL %s\n", id, first.get().getURL());
+ return;
+ }
+
+ SourceAnd<String> up = updatePolicy(updatePolicy);
+ if (!up.valid) {
+ System.err.println("Unknown value of update policy: \"" + updatePolicy + "\"");
+ return;
+ }
+
+ SourceAnd<String> cp = checksumPolicy(checksumPolicy);
+ if (!cp.valid) {
+ System.err.println("Unknown value of checksum policy: \"" + checksumPolicy + "\"");
+ return;
+ }
+
+ if (uri == null || "".equals(uri.trim())) {
+ System.err.println("Please specify repository location");
+ return;
+ }
+ String urlResolved = InterpolationHelper.substVars(uri, "uri", null, null, context);
+ URL url = null;
+ try {
+ url = new URL(urlResolved);
+ urlResolved = url.toString();
+
+ if ("file".equals(url.getProtocol()) && new File(url.toURI()).isDirectory()) {
+ System.err.println("Location \"" + urlResolved + "\" is not accessible");
+ return;
+ }
+ } catch (MalformedURLException e) {
+ // a directory?
+ File location = new File(urlResolved);
+ if (!location.exists() || !location.isDirectory()) {
+ System.err.println("Location \"" + urlResolved + "\" is not accessible");
+ return;
+ } else {
+ url = location.toURI().toURL();
+ urlResolved = url.toString();
+ }
+ }
+
+ if (defaultRepository && !"file".equals(url.getProtocol())) {
+ System.err.println("Default repositories should be locally accessible (use file:// protocol or normal directory path)");
+ return;
+ }
+
+ boolean hasUsername = username != null && !"".equals(username.trim());
+ boolean hasPassword = password != null && !"".equals(password.trim());
+ boolean hasCredentials = hasUsername && hasPassword;
+
+ if ((hasUsername && !hasPassword) || (!hasUsername && hasPassword)) {
+ System.err.println("Please specify both username and password");
+ return;
+ }
+
+ if (defaultRepository && hasCredentials) {
+ System.out.println("User credentials won't be used for default repository");
+ // no return
+ }
+
+ // credentials for remote repository can be stored only in settings.xml
+
+ if (!defaultRepository && hasCredentials) {
+ if (!confirm("Maven settings will be updated and org.ops4j.pax.url.mvn.settings property will change. Continue? (y/N) ")) {
+ return;
+ }
+
+ File dataDir = context.getDataFile(".");
+ if (!dataDir.isDirectory()) {
+ System.err.println("Can't access data directory for " + context.getBundle().getSymbolicName() + " bundle");
+ return;
+ }
+
+ Optional<Server> existingServer = mavenSettings.getServers().stream()
+ .filter((s) -> id.equals(s.getId())).findAny();
+ Server server = null;
+ if (existingServer.isPresent()) {
+ server = existingServer.get();
+ } else {
+ server = new Server();
+ server.setId(id);
+ mavenSettings.getServers().add(server);
+ }
+ server.setUsername(username);
+ server.setPassword(password);
+
+ // prepare configadmin configuration update
+ File newSettingsFile = nextSequenceFile(dataDir, RE_SETTINGS, PATTERN_SETTINGS);
+ config.put(prefix + PROPERTY_SETTINGS_FILE, newSettingsFile.getCanonicalPath());
+
+ try (FileWriter fw = new FileWriter(newSettingsFile)) {
+ new SettingsXpp3Writer().write(fw, mavenSettings);
+ }
+ System.out.println("New settings stored in \"" + newSettingsFile.getCanonicalPath() + "\"");
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(urlResolved);
+ sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_ID + "=" + id);
+ if (snapshots) {
+ sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_ALLOW_SNAPSHOTS);
+ }
+ if (noReleases) {
+ sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_DISALLOW_RELEASES);
+ }
+ sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_UPDATE + "=" + updatePolicy);
+ sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_CHECKSUM + "=" + checksumPolicy);
+
+ MavenRepositoryURL newRepository = new MavenRepositoryURL(sb.toString());
+ List<MavenRepositoryURL> newRepos = new LinkedList<>(Arrays.asList(repositoriesFromPidProperty));
+ if (idx >= 0) {
+ newRepos.add(idx, newRepository);
+ } else {
+ newRepos.add(newRepository);
+ }
+
+ String newList = newRepos.stream().map(MavenRepositoryURL::asRepositorySpec)
+ .collect(Collectors.joining(","));
+
+ if (defaultRepository) {
+ config.put(prefix + PROPERTY_DEFAULT_REPOSITORIES, newList);
+ } else {
+ config.put(prefix + PROPERTY_REPOSITORIES, newList);
+ }
+
+ Configuration cmConfig = cm.getConfiguration(PID);
+ cmConfig.update(config);
+ success = true;
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/ede23baa/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
index 12700d0..9f403c1 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
@@ -23,13 +23,27 @@ import org.apache.karaf.shell.api.action.Option;
public abstract class RepositoryEditCommandSupport extends MavenSecuritySupport {
+ @Option(name = "-id", description = "Identifier of repository", required = true, multiValued = false)
+ String id;
+
+ @Option(name = "-d", aliases = { "--default" }, description = "Edit default repository instead of remote one", required = false, multiValued = false)
+ boolean defaultRepository = false;
+
+ boolean success = false;
+
@Override
- public void doAction(String prefix, Dictionary<String, Object> config) throws Exception {
- edit();
+ public final void doAction(String prefix, Dictionary<String, Object> config) throws Exception {
+ edit(prefix, config);
- session.execute("maven:repository-list");
+ if (success) {
+ if (showPasswords) {
+ session.execute("maven:repository-list -x");
+ } else {
+ session.execute("maven:repository-list");
+ }
+ }
}
- protected abstract void edit();
+ protected abstract void edit(String prefix, Dictionary<String, Object> config) throws Exception;
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/ede23baa/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryRemoveCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryRemoveCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryRemoveCommand.java
index 46f82c8..eaf62e5 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryRemoveCommand.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryRemoveCommand.java
@@ -16,6 +16,8 @@
*/
package org.apache.karaf.maven.command;
+import java.util.Dictionary;
+
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.lifecycle.Service;
@@ -24,7 +26,7 @@ import org.apache.karaf.shell.api.action.lifecycle.Service;
public class RepositoryRemoveCommand extends RepositoryEditCommandSupport {
@Override
- protected void edit() {
+ protected void edit(String prefix, Dictionary<String, Object> config) throws Exception {
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/ede23baa/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
index 3f7e91a..c4e4c03 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
@@ -185,55 +185,4 @@ public class SummaryCommand extends MavenSecuritySupport {
}
}
- private SourceAnd<String> updatePolicy(String cmProperty) {
- SourceAnd<String> result = new SourceAnd<>();
- result.value = cmProperty;
-
- if (cmProperty == null || "".equals(cmProperty.trim())) {
- result.value = "";
- result.source = "Implicit \"never\", but doesn't override repository-specific value";
- return result;
- }
-
- result.source = String.format(PATTERN_PID_PROPERTY, PID, PID + "." + PROPERTY_GLOBAL_UPDATE_POLICY);
- if ("always".equals(cmProperty) || "never".equals(cmProperty) || "daily".equals(cmProperty)) {
- // ok
- } else if (cmProperty.startsWith("interval")) {
- int minutes = 1440;
- try {
- String n = cmProperty.substring("interval".length() + 1);
- minutes = Integer.parseInt(n);
- } catch (Exception e) {
- result.value = "interval:1440";
- result.source = "Implicit \"interval:1440\" (error parsing \"" + cmProperty + "\")";
- }
- } else {
- result.value = "never";
- result.source = "Implicit \"never\" (unknown value \"" + cmProperty + "\")";
- }
-
- return result;
- }
-
- private SourceAnd<String> checksumPolicy(String cmProperty) {
- SourceAnd<String> result = new SourceAnd<>();
- result.value = cmProperty;
-
- if (cmProperty == null || "".equals(cmProperty.trim())) {
- result.value = "warn";
- result.source = "Default \"warn\"";
- return result;
- }
-
- result.source = String.format(PATTERN_PID_PROPERTY, PID, PID + "." + PROPERTY_GLOBAL_CHECKSUM_POLICY);
- if ("ignore".equals(cmProperty) || "warn".equals(cmProperty) || "fail".equals(cmProperty)) {
- // ok
- } else {
- result.value = "warn";
- result.source = "Implicit \"warn\" (unknown value \"" + cmProperty + "\")";
- }
-
- return result;
- }
-
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/ede23baa/maven/core/src/main/java/org/apache/karaf/maven/core/MavenRepositoryURL.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/core/MavenRepositoryURL.java b/maven/core/src/main/java/org/apache/karaf/maven/core/MavenRepositoryURL.java
index 630976b..1c422c8 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/core/MavenRepositoryURL.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/core/MavenRepositoryURL.java
@@ -22,6 +22,7 @@ import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.util.Objects;
import org.ops4j.pax.url.mvn.ServiceConstants;
import org.slf4j.Logger;
@@ -367,6 +368,52 @@ public class MavenRepositoryURL
.toString();
}
+ public String asRepositorySpec() {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append(m_repositoryURL.toString());
+ if (m_id != null) {
+ sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_ID + "=" + m_id);
+ }
+ if (!m_releasesEnabled) {
+ sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_DISALLOW_RELEASES);
+ }
+ if (m_snapshotsEnabled) {
+ sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_ALLOW_SNAPSHOTS);
+ }
+ if (m_releasesEnabled) {
+ if (!m_snapshotsEnabled) {
+ if (m_releasesUpdatePolicy != null) {
+ sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_RELEASES_UPDATE + "=" + m_releasesUpdatePolicy);
+ }
+ if (m_releasesChecksumPolicy != null) {
+ sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_RELEASES_CHECKSUM + "=" + m_releasesChecksumPolicy);
+ }
+ }
+ }
+ if (m_snapshotsEnabled) {
+ if (!m_releasesEnabled) {
+ if (m_snapshotsUpdatePolicy != null) {
+ sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_SNAPSHOTS_UPDATE + "=" + m_snapshotsUpdatePolicy);
+ }
+ if (m_snapshotsChecksumPolicy != null) {
+ sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_SNAPSHOTS_CHECKSUM + "=" + m_snapshotsChecksumPolicy);
+ }
+ }
+ }
+ if (m_snapshotsEnabled && m_releasesEnabled) {
+ // compact snapshots & release update & checksum policies?
+ if (m_releasesUpdatePolicy != null && Objects.equals(m_releasesUpdatePolicy, m_snapshotsUpdatePolicy)) {
+ sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_UPDATE + "=" + m_releasesUpdatePolicy);
+ }
+ if (m_releasesChecksumPolicy != null && Objects.equals(m_releasesChecksumPolicy, m_snapshotsChecksumPolicy)) {
+ sb.append(ServiceConstants.SEPARATOR_OPTIONS + ServiceConstants.OPTION_CHECKSUM + "=" + m_releasesChecksumPolicy);
+ }
+ }
+
+ return sb.toString();
+ }
+
public static enum FROM {
PID("PID configuration"),
SETTINGS("Maven XML settings"),
http://git-wip-us.apache.org/repos/asf/karaf/blob/ede23baa/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
----------------------------------------------------------------------
diff --git a/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java b/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
index 3ecaf30..901efc3 100644
--- a/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
+++ b/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
@@ -32,6 +32,8 @@ public class SettingsTest {
Settings settings = new Settings();
Server s = new Server();
s.setId("id");
+ s.setUsername("admin");
+ s.setPassword("admin");
settings.getServers().add(s);
new DefaultSettingsWriter().write(System.out, null, settings);
http://git-wip-us.apache.org/repos/asf/karaf/blob/ede23baa/maven/core/src/test/java/org/apache/karaf/maven/command/MavenConfigurationSupportTest.java
----------------------------------------------------------------------
diff --git a/maven/core/src/test/java/org/apache/karaf/maven/command/MavenConfigurationSupportTest.java b/maven/core/src/test/java/org/apache/karaf/maven/command/MavenConfigurationSupportTest.java
index 16ffc3f..991ace1 100644
--- a/maven/core/src/test/java/org/apache/karaf/maven/command/MavenConfigurationSupportTest.java
+++ b/maven/core/src/test/java/org/apache/karaf/maven/command/MavenConfigurationSupportTest.java
@@ -22,11 +22,13 @@ import java.io.IOException;
import java.util.Dictionary;
import java.util.regex.Pattern;
+import org.hamcrest.CoreMatchers;
import org.junit.Test;
import shaded.org.apache.commons.io.FileUtils;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertTrue;
public class MavenConfigurationSupportTest {
@@ -42,19 +44,19 @@ public class MavenConfigurationSupportTest {
};
File newFile = support.nextSequenceFile(dataDir, Pattern.compile("file-(\\d+).txt"), "file-%04d.txt");
- assertThat(newFile.getName(), equalTo("file-0001.txt"));
+ assertTrue(Pattern.compile("^file-\\d+\\.txt$").matcher(newFile.getName()).matches());
try (FileWriter fw = new FileWriter(new File(dataDir, "file-abcd.txt"))) {
fw.write("~");
}
newFile = support.nextSequenceFile(dataDir, Pattern.compile("file-(\\d+).txt"), "file-%04d.txt");
- assertThat(newFile.getName(), equalTo("file-0001.txt"));
+ assertTrue(Pattern.compile("^file-\\d+\\.txt$").matcher(newFile.getName()).matches());
try (FileWriter fw = new FileWriter(new File(dataDir, "file-0004.txt"))) {
fw.write("~");
}
newFile = support.nextSequenceFile(dataDir, Pattern.compile("file-(\\d+).txt"), "file-%04d.txt");
- assertThat(newFile.getName(), equalTo("file-0005.txt"));
+ assertTrue(Pattern.compile("^file-\\d+\\.txt$").matcher(newFile.getName()).matches());
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/ede23baa/maven/core/src/test/java/org/apache/karaf/maven/core/MavenRepositoryURLTest.java
----------------------------------------------------------------------
diff --git a/maven/core/src/test/java/org/apache/karaf/maven/core/MavenRepositoryURLTest.java b/maven/core/src/test/java/org/apache/karaf/maven/core/MavenRepositoryURLTest.java
new file mode 100644
index 0000000..d460e0e
--- /dev/null
+++ b/maven/core/src/test/java/org/apache/karaf/maven/core/MavenRepositoryURLTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.maven.core;
+
+import java.net.MalformedURLException;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+public class MavenRepositoryURLTest {
+
+ @Test
+ public void uris() throws MalformedURLException {
+ String uri1, uri2;
+ MavenRepositoryURL mavenURI;
+
+ uri1 = "http://localhost/@id=id1@snapshots@update=interval:42@_from=" + MavenRepositoryURL.FROM.SETTINGS;
+ uri2 = "http://localhost/@id=id1@snapshots@update=interval:42";
+ mavenURI = new MavenRepositoryURL(uri1);
+ assertThat(mavenURI.asRepositorySpec(), equalTo(uri2));
+
+ uri1 = "http://localhost/@id=id1@snapshots@checksum=fail@_from=" + MavenRepositoryURL.FROM.SETTINGS;
+ uri2 = "http://localhost/@id=id1@snapshots@checksum=fail";
+ mavenURI = new MavenRepositoryURL(uri1);
+ assertThat(mavenURI.asRepositorySpec(), equalTo(uri2));
+
+ uri1 = "http://localhost/@id=id1@snapshots@noreleases@update=interval:42@_from=" + MavenRepositoryURL.FROM.SETTINGS;
+ uri2 = "http://localhost/@id=id1@noreleases@snapshots@snapshotsUpdate=interval:42";
+ mavenURI = new MavenRepositoryURL(uri1);
+ assertThat(mavenURI.asRepositorySpec(), equalTo(uri2));
+
+ uri1 = "http://localhost/@id=id1@update=interval:42@_from=" + MavenRepositoryURL.FROM.SETTINGS;
+ uri2 = "http://localhost/@id=id1@releasesUpdate=interval:42";
+ mavenURI = new MavenRepositoryURL(uri1);
+ assertThat(mavenURI.asRepositorySpec(), equalTo(uri2));
+
+ uri1 = "http://localhost/@id=id1@snapshots@noreleases@checksum=fail@_from=" + MavenRepositoryURL.FROM.SETTINGS;
+ uri2 = "http://localhost/@id=id1@noreleases@snapshots@snapshotsChecksum=fail";
+ mavenURI = new MavenRepositoryURL(uri1);
+ assertThat(mavenURI.asRepositorySpec(), equalTo(uri2));
+
+ uri1 = "http://localhost/@id=id1@checksum=fail@_from=" + MavenRepositoryURL.FROM.SETTINGS;
+ uri2 = "http://localhost/@id=id1@releasesChecksum=fail";
+ mavenURI = new MavenRepositoryURL(uri1);
+ assertThat(mavenURI.asRepositorySpec(), equalTo(uri2));
+ }
+
+}
[2/6] karaf git commit: [KARAF-5008] Initial "maven/core" module and
first maven:summary command
Posted by gg...@apache.org.
[KARAF-5008] Initial "maven/core" module and first maven:summary command
[KARAF-5008] maven:summary - update and checksum policy information
[KARAF-5008] Additional maven:summary details and settings-security.xml handling
[KARAF-5008] maven:summary for repositories, defaultRepositories and proxies
[KARAF-5008] maven:http-proxy command to list proxies + optional password decryption
[KARAF-5008] org.apache.karaf.maven.SettingsTest#encryptMavenPassword
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/750fd144
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/750fd144
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/750fd144
Branch: refs/heads/master-maven-commands
Commit: 750fd144a1e4c30a743e736af516114b13acd224
Parents: 60e25fa
Author: Grzegorz Grzybek <gr...@gmail.com>
Authored: Mon Mar 13 15:42:53 2017 +0100
Committer: Grzegorz Grzybek <gr...@gmail.com>
Committed: Wed Jun 21 15:31:52 2017 +0200
----------------------------------------------------------------------
maven/core/pom.xml | 129 +++++
.../karaf/maven/command/HttpProxyCommand.java | 84 +++
.../command/MavenConfigurationSupport.java | 578 +++++++++++++++++++
.../maven/command/RepositoryAddCommand.java | 35 ++
.../command/RepositoryEditCommandSupport.java | 35 ++
.../maven/command/RepositoryListCommand.java | 127 ++++
.../maven/command/RepositoryRemoveCommand.java | 31 +
.../karaf/maven/command/SummaryCommand.java | 239 ++++++++
.../karaf/maven/core/MavenRepositoryURL.java | 386 +++++++++++++
.../src/main/resources/OSGI-INF/bundle.info | 36 ++
.../org/apache/karaf/maven/SettingsTest.java | 62 ++
.../src/test/resources/reference-settings.xml | 82 +++
maven/pom.xml | 40 ++
pom.xml | 11 +
14 files changed, 1875 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/750fd144/maven/core/pom.xml
----------------------------------------------------------------------
diff --git a/maven/core/pom.xml b/maven/core/pom.xml
new file mode 100644
index 0000000..db2f2a7
--- /dev/null
+++ b/maven/core/pom.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <!--
+
+ 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.
+ -->
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.karaf</groupId>
+ <artifactId>karaf</artifactId>
+ <version>4.2.0-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.apache.karaf.maven</groupId>
+ <artifactId>org.apache.karaf.maven.core</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Karaf :: Maven :: Core</name>
+ <description>This bundle provides services and commands for Maven diagnostics.</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.ops4j.pax.url</groupId>
+ <artifactId>pax-url-aether</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-settings</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-settings-builder</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-embedder</artifactId>
+ <version>3.0.3</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <resources>
+ <resource>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>${project.basedir}/src/main/resources</directory>
+ <filtering>true</filtering>
+ <includes>
+ <include>**/*.info</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-services-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.apache.karaf.maven
+ </Export-Package>
+ <Import-Package>
+ !org.apache.maven*,
+ !org.codehaus.plexus*,
+ !org.sonatype.aether*,
+ !org.sonatype.guice*,
+ *,
+ </Import-Package>
+ <Private-Package>
+ org.apache.karaf.maven.command,
+ org.apache.karaf.maven.core,
+ org.apache.maven.settings.*;-split-package:=merge-first,
+ org.apache.maven.execution;-split-package:=merge-first,
+ org.apache.maven.model;-split-package:=merge-first,
+ org.codehaus.plexus.component.annotations,
+ org.sonatype.plexus.components.sec.dispatcher*,
+ org.sonatype.plexus.components.cipher,
+ org.codehaus.plexus.interpolation,
+ org.codehaus.plexus.logging,
+ org.codehaus.plexus.util,
+ org.codehaus.plexus.util.xml,
+ org.codehaus.plexus.util.xml.pull,
+ org.codehaus.plexus.interpolation.os,
+ </Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
http://git-wip-us.apache.org/repos/asf/karaf/blob/750fd144/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
new file mode 100644
index 0000000..6f8b794
--- /dev/null
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
@@ -0,0 +1,84 @@
+/*
+ * 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.maven.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.Row;
+import org.apache.karaf.shell.support.table.ShellTable;
+import org.apache.maven.settings.Proxy;
+
+@Command(scope = "maven", name = "http-proxy", description = "Manage HTTP proxy configuration for Maven remote repositories")
+@Service
+public class HttpProxyCommand extends MavenConfigurationSupport {
+
+ @Option(name = "--add", description = "Adds HTTP proxy configuration to Maven settings", required = false, multiValued = false)
+ boolean add;
+
+ @Option(name = "--remove", description = "Removes HTTP proxy configuration from Maven settings", required = false, multiValued = false)
+ boolean remove;
+
+ @Override
+ public void doAction(String prefix, Dictionary<String, Object> config) throws Exception {
+ if (add && remove) {
+ System.err.println("Please specify only one of --add and --remove");
+ return;
+ }
+
+ if (add) {
+ // add
+ }
+
+ if (remove) {
+ // remove
+ }
+
+ // list (also after --add or --remove)
+ System.out.println();
+ if (mavenSettings != null && mavenSettings.getProxies() != null && mavenSettings.getProxies().size() > 0) {
+ ShellTable table = new ShellTable();
+ table.column("ID");
+ table.column("Host");
+ table.column("Port");
+ table.column("Username");
+ if (showPasswords) {
+ table.column("Password");
+ }
+ for (Proxy proxy : mavenSettings.getProxies()) {
+ Row row = table.addRow();
+ row.addContent(proxy.getId(), proxy.getHost(), proxy.getPort());
+ row.addContent(proxy.getUsername() != null ? proxy.getUsername() : "");
+ if (showPasswords) {
+ addPasswordInfo(row, proxyPasswords, proxy.getId(), proxy.getPassword());
+ }
+ }
+ table.print(System.out);
+ } else {
+ System.out.print("No HTTP proxies configured");
+ if (settings != null && settings.value != null) {
+ System.out.print(" in " + settings.value);
+ }
+ System.out.println();
+ }
+
+ System.out.println();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/750fd144/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java b/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
new file mode 100644
index 0000000..4c3416a
--- /dev/null
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/MavenConfigurationSupport.java
@@ -0,0 +1,578 @@
+/*
+ * 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.maven.command;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.karaf.maven.core.MavenRepositoryURL;
+import org.apache.karaf.shell.api.action.Action;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.support.table.Row;
+import org.apache.maven.settings.Profile;
+import org.apache.maven.settings.Proxy;
+import org.apache.maven.settings.Repository;
+import org.apache.maven.settings.Server;
+import org.apache.maven.settings.Settings;
+import org.apache.maven.settings.building.DefaultSettingsBuilder;
+import org.apache.maven.settings.building.DefaultSettingsBuilderFactory;
+import org.apache.maven.settings.building.DefaultSettingsBuildingRequest;
+import org.apache.maven.settings.building.SettingsBuildingException;
+import org.apache.maven.settings.building.SettingsBuildingRequest;
+import org.apache.maven.settings.building.SettingsBuildingResult;
+import org.apache.maven.settings.building.SettingsProblem;
+import org.apache.maven.settings.crypto.DefaultSettingsDecrypter;
+import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
+import org.apache.maven.settings.crypto.SettingsDecryptionResult;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
+import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
+import org.sonatype.plexus.components.sec.dispatcher.SecUtil;
+import org.sonatype.plexus.components.sec.dispatcher.model.SettingsSecurity;
+
+/**
+ * <p>Base class for <code>maven:</code> commands.</p>
+ * <p>Important: even if it duplicates some code from pax-url-aether, this should be treated as verification code of
+ * how pax-url-aether should interact with <code>org.ops4j.pax.url.mvn</code> PID configuration.</p>
+ */
+public abstract class MavenConfigurationSupport implements Action {
+
+ public static Logger LOG = LoggerFactory.getLogger(MavenConfigurationSupport.class);
+ protected static final String PID = "org.ops4j.pax.url.mvn";
+
+ protected static final String PATTERN_PID_PROPERTY = "Explicit %s PID configuration (%s)";
+
+ protected static final String PROPERTY_LOCAL_REPOSITORY = "localRepository";
+ protected static final String PROPERTY_DEFAULT_REPOSITORIES = "defaultRepositories";
+ protected static final String PROPERTY_REPOSITORIES = "repositories";
+ protected static final String PROPERTY_SETTINGS_FILE = "settings";
+ protected static final String PROPERTY_SECURITY_FILE = "security";
+ protected static final String PROPERTY_GLOBAL_UPDATE_POLICY = "globalUpdatePolicy";
+ protected static final String PROPERTY_GLOBAL_CHECKSUM_POLICY = "globalChecksumPolicy";
+ protected static final String PROPERTY_UPDATE_RELEASES = "updateReleases";
+ protected static final String REQUIRE_CONFIG_ADMIN_CONFIG = "requireConfigAdminConfig";
+ protected static final String PROPERTY_USE_FALLBACK_REPOSITORIES = "useFallbackRepositories";
+ protected static final String PROPERTY_OFFLINE = "offline";
+ protected static final String PROPERTY_CERTIFICATE_CHECK = "certificateCheck";
+
+ // TODO timeout options {
+ protected static final String PROPERTY_TIMEOUT = "timeout";
+ protected static final String PROPERTY_SOCKET_SO_TIMEOUT = "socket.readTimeout";
+ protected static final String PROPERTY_SOCKET_SO_KEEPALIVE = "socket.keepAlive";
+ protected static final String PROPERTY_SOCKET_SO_LINGER = "socket.linger";
+ protected static final String PROPERTY_SOCKET_SO_REUSEADDRESS = "socket.reuseAddress";
+ protected static final String PROPERTY_SOCKET_TCP_NODELAY = "socket.tcpNoDelay";
+ protected static final String PROPERTY_SOCKET_CONNECTION_TIMEOUT = "socket.connectionTimeout";
+ protected static final String PROPERTY_CONNECTION_BUFFER_SIZE = "connection.bufferSize";
+ protected static final String PROPERTY_CONNECTION_RETRY_COUNT = "connection.retryCount";
+ // }
+
+ protected SourceAnd<File> localRepository;
+ protected SourceAnd<File> settings;
+ protected Settings mavenSettings;
+ protected SourceAnd<File> securitySettings;
+ protected SettingsSecurity mavenSecuritySettings;
+
+ protected Map<String, Server> servers = new HashMap<>();
+ protected Map<String, String> serverPasswords = new HashMap<>();
+ protected Map<String, String> proxyPasswords = new HashMap<>();
+
+ protected List<String> warnings = new LinkedList<>();
+
+ private static final String masterMasterPassword = DefaultSecDispatcher.SYSTEM_PROPERTY_SEC_LOCATION;
+ protected String masterPassword;
+ protected DefaultPlexusCipher cipher;
+
+ @Reference
+ protected ConfigurationAdmin cm;
+
+ @Reference
+ protected BundleContext context;
+
+ @Reference
+ protected Session session;
+
+ @Option(name = "-x", aliases = { "--show-passwords" }, description = "Do not hide passwords related to Maven encryption", required = false, multiValued = false)
+ boolean showPasswords;
+
+ @Override
+ final public Object execute() throws Exception {
+ Configuration c = cm.getConfiguration(PID);
+
+ if (c != null && c.getProperties() != null) {
+ try {
+ cipher = new DefaultPlexusCipher();
+ securitySettings = securitySettings((String) c.getProperties().get(PID + "." + PROPERTY_SECURITY_FILE));
+ if (securitySettings != null && securitySettings.value != null) {
+ mavenSecuritySettings = readSecuritySettings(securitySettings.value);
+ }
+
+ settings = settings((String) c.getProperties().get(PID + "." + PROPERTY_SETTINGS_FILE));
+ if (settings != null && settings.value != null) {
+ mavenSettings = readSettings(settings.value);
+ }
+
+ localRepository = localRepository((String) c.getProperties().get(PID + "." + PROPERTY_LOCAL_REPOSITORY));
+
+ if (showPasswords) {
+ decryptSettings();
+ }
+
+ doAction(PID + ".", c.getProperties());
+ } catch (Exception e) {
+ System.err.println(e.getMessage());
+ LOG.error(e.getMessage(), e);
+ }
+ } else {
+ System.err.printf("Can't access \"%s\" configuration\n", PID);
+ }
+
+ return null;
+ }
+
+ /**
+ * Performs command action on <strong>existing</strong> <code>org.ops4j.pax.url.mvn</code>
+ * PID configuration
+ * @param prefix
+ * @param config
+ */
+ abstract protected void doAction(String prefix, Dictionary<String, Object> config) throws Exception;
+
+ /**
+ * Gets effective location of <code>settings.xml</code> file - according to pax-url-aether rules
+ * @param cmProperty property obtained from Config Admin
+ * @return
+ */
+ protected SourceAnd<File> settings(String cmProperty) {
+ SourceAnd<File> result = new SourceAnd<>();
+ URL locationUrl = null;
+ String probableErrorMessage = null;
+
+ // 1. PID + ".settings"
+ if (cmProperty != null && !"".equals(cmProperty.trim())) {
+ result.source = String.format(PATTERN_PID_PROPERTY, PID, PID + "." + PROPERTY_SETTINGS_FILE);
+ try {
+ locationUrl = new URL(cmProperty);
+ probableErrorMessage = String.format("%s configured in %s.%s is not accessible",
+ locationUrl, PID, PROPERTY_SETTINGS_FILE);
+ } catch (MalformedURLException e) {
+ File file = new File(cmProperty);
+ if (file.isFile()) {
+ result.value = file;
+ return result;
+ }
+ }
+ }
+
+ if (locationUrl == null) {
+ // 2. System.getProperty("user.home") + "/.m2/settings.xml"
+ File file = new File(System.getProperty("user.home") + "/.m2/settings.xml");
+ if (file.isFile()) {
+ result.value = file;
+ result.source = "Implicit ${user.home}/.m2/settings.xml";
+ return result;
+ }
+
+ // 3. System.getProperty("maven.home") + "/conf/settings.xml"
+ file = new File(System.getProperty("maven.home") + "/conf/settings.xml");
+ if (file.isFile()) {
+ result.value = file;
+ result.source = "Implicit ${maven.home}/conf/settings.xml";
+ return result;
+ }
+
+ // 4. System.getenv("M2_HOME") + "/conf/settings.xml"
+ file = new File(System.getenv("M2_HOME") + "/conf/settings.xml");
+ if (file.isFile()) {
+ result.value = file;
+ result.source = "Implicit $M2_HOME/conf/settings.xml";
+ return result;
+ }
+ } else {
+ File file = new File(locationUrl.getPath());
+ result.value = file;
+ if (!file.isFile()) {
+ result.source = probableErrorMessage;
+ }
+ return result;
+ }
+
+ // 5. new org.apache.maven.settings.Settings()
+ result.value = null;
+ result.source = "No implicit settings.xml location is available";
+ return result;
+ }
+
+ /**
+ * Gets effective location of <code>settings-security.xml</code> file - according to pax-url-aether rules
+ * @param cmProperty property obtained from Config Admin
+ * @return
+ */
+ protected SourceAnd<File> securitySettings(String cmProperty) {
+ SourceAnd<File> result = new SourceAnd<>();
+ URL locationUrl = null;
+ String probableErrorMessage = null;
+
+ // 1. PID + ".security"
+ if (cmProperty != null && !"".equals(cmProperty.trim())) {
+ result.source = String.format(PATTERN_PID_PROPERTY, PID, PID + "." + PROPERTY_SECURITY_FILE);
+ try {
+ locationUrl = new URL(cmProperty);
+ probableErrorMessage = String.format("%s configured in %s.%s is not accessible",
+ locationUrl, PID, PROPERTY_SECURITY_FILE);
+ } catch (MalformedURLException e) {
+ File file = new File(cmProperty);
+ if (file.isFile()) {
+ result.value = file;
+ return result;
+ }
+ }
+ }
+
+ // 2. System.getProperty("user.home") + "/.m2/settings-security.xml"
+ if (locationUrl == null) {
+ File file = new File(System.getProperty("user.home") + "/.m2/settings-security.xml");
+ if (file.isFile()) {
+ result.value = file;
+ result.source = "Implicit ${user.home}/.m2/settings-security.xml";
+ return result;
+ }
+ } else {
+ File file = new File(locationUrl.getPath());
+ result.value = file;
+ if (!file.isFile()) {
+ result.source = probableErrorMessage;
+ }
+ }
+
+ result.value = null;
+ result.source = "No implicit settings-security.xml location is available";
+ return result;
+ }
+
+ /**
+ * Gets effective location of <em>local repository</em> - according to pax-url-aether rules
+ * @param cmProperty property obtained from Config Admin
+ * @return
+ */
+ protected SourceAnd<File> localRepository(String cmProperty) {
+ SourceAnd<File> result = new SourceAnd<>();
+ URL locationUrl = null;
+ String probableErrorMessage = null;
+
+ // 1. PID + ".localRepository"
+ if (cmProperty != null && !"".equals(cmProperty.trim())) {
+ result.source = String.format(PATTERN_PID_PROPERTY, PID, PID + "." + PROPERTY_LOCAL_REPOSITORY);
+ try {
+ locationUrl = new URL(cmProperty);
+ probableErrorMessage = String.format("%s configured in %s.%s is not accessible",
+ locationUrl, PID, PROPERTY_LOCAL_REPOSITORY);
+ } catch (MalformedURLException e) {
+ File file = new File(cmProperty);
+ if (file.isDirectory()) {
+ result.value = file;
+ return result;
+ }
+ }
+ }
+
+ // 2. from settings.xml
+ if (locationUrl == null && mavenSettings != null && mavenSettings.getLocalRepository() != null) {
+ result.source = String.format("Explicit <localRepository> in %s", settings.value);
+ try {
+ locationUrl = new URL(mavenSettings.getLocalRepository());
+ probableErrorMessage = String.format("%s configured in %s is not accessible",
+ mavenSettings.getLocalRepository(), settings.value);
+ } catch (MalformedURLException e) {
+ File file = new File(mavenSettings.getLocalRepository());
+ if (file.isDirectory()) {
+ result.value = file;
+ return result;
+ }
+ }
+ }
+
+ // 3. System.getProperty("user.home") + "/.m2/repository";
+ if (locationUrl == null) {
+ File file = new File(System.getProperty("user.home") + "/.m2/repository");
+ result.value = file; // whether it exists or not
+ if (file.isDirectory()) {
+ result.source = "Implicit ${user.home}/.m2/repository";
+ } else {
+ result.source = "Implicit ${user.home}/.m2/repository (not accessible)";
+ }
+ return result;
+ }
+
+ File file = new File(locationUrl.getPath());
+ result.value = file;
+ if (!file.isDirectory()) {
+ result.source = probableErrorMessage;
+ }
+ return result;
+ }
+
+ /**
+ * Reads on demand <code>settings.xml</code> file - without password decryption. Also
+ * collects declared servers by ID.
+ * @param settingsFile
+ */
+ protected synchronized Settings readSettings(File settingsFile) throws SettingsBuildingException {
+ if (!settingsFile.isFile() || !settingsFile.canRead()) {
+ return null;
+ }
+
+ try {
+ DefaultSettingsBuilderFactory factory = new DefaultSettingsBuilderFactory();
+ DefaultSettingsBuilder builder = factory.newInstance();
+ SettingsBuildingRequest request = new DefaultSettingsBuildingRequest();
+ request.setUserSettingsFile(settingsFile);
+
+ SettingsBuildingResult result = builder.build(request);
+ if (result.getProblems().size() > 0) {
+ for (SettingsProblem problem : result.getProblems()) {
+ System.err.println(problem);
+ }
+ return null;
+ } else {
+ Settings settings = result.getEffectiveSettings();
+ if (settings.getServers() != null) {
+ for (Server server : settings.getServers()) {
+ servers.put(server.getId(), server);
+ }
+ }
+ return settings;
+ }
+ } catch (Throwable e) {
+ System.err.println(e.getMessage());
+ LOG.error(e.getMessage(), e);
+ throw e;
+ }
+ }
+
+ /**
+ * Re-reads on demand <code>settings-security.xml</code> file
+ * @param securitySettingsFile
+ */
+ protected synchronized SettingsSecurity readSecuritySettings(File securitySettingsFile) throws Exception {
+ if (!securitySettingsFile.isFile() || !securitySettingsFile.canRead()) {
+ return null;
+ }
+
+ try {
+ return SecUtil.read(securitySettingsFile.getAbsolutePath(), true);
+ } catch (Throwable e) {
+ System.err.println(e.getMessage());
+ LOG.error(e.getMessage(), e);
+ throw e;
+ }
+ }
+
+ /**
+ * <p>Decrypts passwords inside correctly read <code>settings.xml</code>. Also tries to decrypt master password.</p>
+ * <p>Not called implicitly for each action invocation.</p>
+ */
+ private void decryptSettings() throws Exception {
+ if (mavenSecuritySettings != null && mavenSettings != null) {
+ masterPassword = cipher.decryptDecorated(mavenSecuritySettings.getMaster(), masterMasterPassword);
+ DefaultSecDispatcher dispatcher = new DefaultSecDispatcher();
+ DefaultSettingsDecrypter decrypter = new DefaultSettingsDecrypter();
+ try {
+ dispatcher.setConfigurationFile(securitySettings.value.getAbsolutePath());
+ Field f = dispatcher.getClass().getDeclaredField("_cipher");
+ f.setAccessible(true);
+ f.set(dispatcher, cipher);
+
+ f = decrypter.getClass().getDeclaredField("securityDispatcher");
+ f.setAccessible(true);
+ f.set(decrypter, dispatcher);
+
+ DefaultSettingsDecryptionRequest req = new DefaultSettingsDecryptionRequest(mavenSettings);
+ SettingsDecryptionResult res = decrypter.decrypt(req);
+ if (res.getProblems() != null && res.getProblems().size() > 0) {
+ for (SettingsProblem sp : res.getProblems()) {
+ System.err.println(sp);
+ }
+ }
+
+ for (Proxy proxy : res.getProxies()) {
+ if (!cipher.isEncryptedString(proxy.getPassword())) {
+ proxyPasswords.put(proxy.getId(), proxy.getPassword());
+ }
+ }
+ for (Server server : res.getServers()) {
+ if (!cipher.isEncryptedString(server.getPassword())) {
+ serverPasswords.put(server.getId(), server.getPassword());
+ }
+ }
+ } catch (Throwable t) {
+ LOG.warn("Can't decrypt " + securitySettings.value, t);
+ }
+ }
+ }
+
+ /**
+ * Returns list of configured remote (<code>remote=true</code>) or default (<code>remote=false</code>)
+ * repositories.
+ * @param remote
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ protected MavenRepositoryURL[] repositories(Dictionary<String, Object> config, boolean remote) throws Exception {
+ String property = remote ? PID + "." + PROPERTY_REPOSITORIES : PID + "." + PROPERTY_DEFAULT_REPOSITORIES;
+ String[] repositories = listOfValues((String) config.get(property));
+
+ if (remote) {
+ if (repositories.length == 0 || repositories.length > 0 && repositories[0].charAt(0) == '+') {
+ if (repositories.length > 0) {
+ repositories[0] = repositories[0].substring(1);
+ }
+
+ List<String> newRepositories = new LinkedList<>();
+ newRepositories.addAll(Arrays.asList(repositories));
+
+ // append all repositories from all active profiles from available settings.xml
+ if (mavenSettings != null) {
+ // see org.ops4j.pax.url.mvn.internal.config.MavenConfigurationImpl.getRepositories()
+ Set<String> activeProfiles = new LinkedHashSet<>(mavenSettings.getActiveProfiles());
+ Map<String, Profile> profiles = (Map<String, Profile>)mavenSettings.getProfilesAsMap();
+ profiles.values().stream()
+ .filter((profile) -> profile.getActivation() != null && profile.getActivation().isActiveByDefault())
+ .map(Profile::getId)
+ .forEach(activeProfiles::add);
+
+ for (String activeProfile : activeProfiles) {
+ Profile profile = profiles.get(activeProfile);
+ if (profile == null) {
+ continue;
+ }
+ for (Repository repo : profile.getRepositories()) {
+ StringBuilder builder = new StringBuilder();
+ builder.append(repo.getUrl());
+ builder.append("@id=").append(repo.getId());
+ builder.append("@_from=").append(MavenRepositoryURL.FROM.SETTINGS);
+
+ if (repo.getReleases() != null) {
+ if (!repo.getReleases().isEnabled()) {
+ builder.append("@noreleases");
+ }
+ addPolicy(builder, repo.getReleases().getUpdatePolicy(), "releasesUpdate");
+ // not used in pax-url-aether
+ //addPolicy(builder, repo.getReleases().getChecksumPolicy(), "releasesChecksum");
+ }
+ if (repo.getSnapshots() != null) {
+ if (repo.getSnapshots().isEnabled()) {
+ builder.append("@snapshots");
+ }
+ addPolicy(builder, repo.getSnapshots().getUpdatePolicy(), "snapshotsUpdate");
+ // not used in pax-url-aether
+ //addPolicy(builder, repo.getSnapshots().getChecksumPolicy(), "snapshotsChecksum");
+ }
+ newRepositories.add(builder.toString());
+ }
+ }
+ }
+
+ repositories = newRepositories.toArray(new String[newRepositories.size()]);
+ }
+ }
+
+ List<MavenRepositoryURL> result = new LinkedList<>();
+ for (String repo : repositories) {
+ result.add(new MavenRepositoryURL(repo));
+ }
+ return result.toArray(new MavenRepositoryURL[result.size()]);
+ }
+
+ private void addPolicy(StringBuilder builder, String policy, String option) {
+ if (policy != null && !policy.isEmpty()) {
+ builder.append("@");
+ builder.append(option);
+ builder.append("=");
+ builder.append(policy);
+ }
+ }
+
+ /**
+ * Splits comma separated list of values into String array
+ * @param list
+ * @return
+ */
+ protected String[] listOfValues(String list) {
+ if (list == null) {
+ return new String[0];
+ }
+
+ String[] values = list.split("\\s*,\\s*");
+ return Arrays.stream(values)
+ .filter((value) -> (value != null && !"".equals(value.trim())))
+ .toArray(String[]::new);
+ }
+
+ /**
+ * Adds information used by proxy/server
+ * @param row {@link org.apache.karaf.shell.support.table.ShellTable}'s row to add information to
+ * @param id2Password mapping of ids (servers/proxies to decrypted passwords)
+ * @param id ID of proxy or server from <code>settings.xml</code>
+ * @param password password to use if decryption failed
+ */
+ protected void addPasswordInfo(Row row, Map<String, String> id2Password, String id, String password) {
+ if (id2Password.containsKey(id)) {
+ row.addContent(id2Password.get(id));
+ } else {
+ if (cipher.isEncryptedString(password)) {
+ row.addContent(password + " (can't decrypt)");
+ } else {
+ row.addContent(password == null ? "" : password);
+ }
+ }
+ }
+
+ protected static class SourceAnd<T> {
+ String source;
+ T value;
+
+ public SourceAnd() {
+ }
+
+ public SourceAnd(String source, T value) {
+ this.source = source;
+ this.value = value;
+ }
+
+ public String val() {
+ return value == null ? "" : value.toString();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/750fd144/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryAddCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryAddCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryAddCommand.java
new file mode 100644
index 0000000..13bcbdb
--- /dev/null
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryAddCommand.java
@@ -0,0 +1,35 @@
+/*
+ * 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.maven.command;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "maven", name = "repository-add", description = "Adds Maven repository")
+@Service
+public class RepositoryAddCommand extends RepositoryEditCommandSupport {
+
+ @Option(name = "-x", aliases = { "--show-passwords" }, description = "Do not hide passwords related to Maven encryption", required = false, multiValued = false)
+ boolean showPasswords;
+
+ @Override
+ protected void edit() {
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/750fd144/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
new file mode 100644
index 0000000..0179b02
--- /dev/null
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryEditCommandSupport.java
@@ -0,0 +1,35 @@
+/*
+ * 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.maven.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.maven.core.MavenRepositoryURL;
+import org.apache.karaf.shell.api.action.Option;
+
+public abstract class RepositoryEditCommandSupport extends MavenConfigurationSupport {
+
+ @Override
+ public void doAction(String prefix, Dictionary<String, Object> config) throws Exception {
+ edit();
+
+ session.execute("maven:repository-list");
+ }
+
+ protected abstract void edit();
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/750fd144/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryListCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryListCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryListCommand.java
new file mode 100644
index 0000000..90c7c26
--- /dev/null
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryListCommand.java
@@ -0,0 +1,127 @@
+/*
+ * 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.maven.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.maven.core.MavenRepositoryURL;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.Row;
+import org.apache.karaf.shell.support.table.ShellTable;
+import org.apache.maven.settings.Server;
+
+@Command(scope = "maven", name = "repository-list", description = "Maven repository summary.")
+@Service
+public class RepositoryListCommand extends MavenConfigurationSupport {
+
+ @Option(name = "-v", aliases = { "--verbose" }, description = "Show additional information (policies, source)", required = false, multiValued = false)
+ boolean verbose;
+
+ @Override
+ public void doAction(String prefix, Dictionary<String, Object> config) throws Exception {
+ ShellTable table = new ShellTable();
+ table.column("ID");
+ table.column("URL");
+ if (verbose) {
+ table.column("Releases");
+ table.column("Snapshots");
+ table.column("Defined in");
+ }
+ if (showPasswords) {
+ table.column("Username");
+ table.column("Password");
+ }
+
+ System.out.println();
+ System.out.println("== Remote repositories");
+ MavenRepositoryURL[] repositories = repositories(config, true);
+ for (MavenRepositoryURL repoURL : repositories) {
+ Row row = table.addRow();
+ row.addContent(repoURL.getId(), repoURL.getURL());
+ if (verbose) {
+ row.addContent(repositoryKindInfo(repoURL, false),
+ repositoryKindInfo(repoURL, true),
+ repoURL.getFrom());
+ }
+ if (showPasswords) {
+ if (servers.containsKey(repoURL.getId())) {
+ Server server = servers.get(repoURL.getId());
+ row.addContent(server.getUsername() == null ? "" : server.getUsername());
+ addPasswordInfo(row, serverPasswords, repoURL.getId(), server.getPassword());
+ } else {
+ row.addContent("", "");
+ }
+ }
+ }
+
+ table.print(System.out);
+
+ table = new ShellTable();
+ table.column("ID");
+ table.column("URL");
+ if (verbose) {
+ table.column("Releases");
+ table.column("Snapshots");
+ }
+
+ System.out.println();
+ System.out.println("== Default repositories");
+ repositories = repositories(config, false);
+ for (MavenRepositoryURL repoURL : repositories) {
+ Row row = table.addRow();
+ row.addContent(repoURL.getId(),
+ repoURL.getURL());
+ if (verbose) {
+ row.addContent(repositoryKindInfo(repoURL, false),
+ repositoryKindInfo(repoURL, true),
+ repoURL.getFrom());
+ }
+ }
+
+ table.print(System.out);
+ System.out.println();
+ }
+
+ /**
+ * Information about release/snapshot handing for give repository URL
+ * @param repoURL
+ * @param snapshots
+ * @return
+ */
+ private Object repositoryKindInfo(MavenRepositoryURL repoURL, boolean snapshots) {
+ if (snapshots) {
+ if (repoURL.isSnapshotsEnabled()) {
+ String snapshotsUpdatePolicy = repoURL.getSnapshotsUpdatePolicy();
+ return String.format("yes (%s)",
+ snapshotsUpdatePolicy == null || "".equals(snapshotsUpdatePolicy.trim()) ? "daily" : snapshotsUpdatePolicy
+ );
+ }
+ } else {
+ if (repoURL.isReleasesEnabled()) {
+ String releasesUpdatePolicy = repoURL.getReleasesUpdatePolicy();
+ return String.format("yes (%s)",
+ releasesUpdatePolicy == null || "".equals(releasesUpdatePolicy.trim()) ? "daily" : releasesUpdatePolicy
+ );
+ }
+ }
+
+ return "no";
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/750fd144/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryRemoveCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryRemoveCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryRemoveCommand.java
new file mode 100644
index 0000000..46f82c8
--- /dev/null
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/RepositoryRemoveCommand.java
@@ -0,0 +1,31 @@
+/*
+ * 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.maven.command;
+
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+
+@Command(scope = "maven", name = "repository-remove", description = "Removes Maven repository")
+@Service
+public class RepositoryRemoveCommand extends RepositoryEditCommandSupport {
+
+ @Override
+ protected void edit() {
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/750fd144/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
new file mode 100644
index 0000000..1678239
--- /dev/null
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/SummaryCommand.java
@@ -0,0 +1,239 @@
+/*
+ * 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.maven.command;
+
+import java.util.Dictionary;
+
+import org.apache.karaf.maven.core.MavenRepositoryURL;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.Row;
+import org.apache.karaf.shell.support.table.ShellTable;
+import org.apache.maven.settings.Proxy;
+
+@Command(scope = "maven", name = "summary", description = "Maven configuration summary.")
+@Service
+public class SummaryCommand extends MavenConfigurationSupport {
+
+ @Option(name = "-p", aliases = { "--property-ids" }, description = "Use PID property identifiers instead of their names", required = false, multiValued = false)
+ boolean propertyIds;
+
+ @Option(name = "-s", aliases = { "--source" }, description = "Adds information about where the value is configured", required = false, multiValued = false)
+ boolean source;
+
+ @Option(name = "-d", aliases = { "--description" }, description = "Adds description of Maven configuration options", required = false, multiValued = false)
+ boolean description;
+
+ @Override
+ protected void doAction(String prefix, Dictionary<String, Object> config) throws Exception {
+ ShellTable table = new ShellTable();
+ table.column("Option");
+ table.column("Value");
+ if (source) {
+ table.column("Source");
+ }
+ if (description) {
+ table.column("Description");
+ }
+
+ addRow(table, propertyIds ? PROPERTY_LOCAL_REPOSITORY : "Local repository", localRepository,
+ "Maven repository to store artifacts resolved in *remote repositories*");
+
+ addRow(table, propertyIds ? PROPERTY_SETTINGS_FILE : "Settings file", settings,
+ "Settings file that may contain configuration of additional repositories, http proxies and mirrors");
+
+ addRow(table, propertyIds ? PROPERTY_SECURITY_FILE : "Security settings file", securitySettings,
+ "Settings file that contain (or relocates to) master Maven password");
+
+ if (showPasswords) {
+ addRow(table, propertyIds ? "<master>" : "Master password", new SourceAnd<String>(securitySettings.source, masterPassword),
+ "Master password used to decrypt proxy and server passwords");
+ }
+
+ // for default update/checksum policies specified at repository URI level, see
+ // org.ops4j.pax.url.mvn.internal.AetherBasedResolver.addRepo()
+
+ // see org.eclipse.aether.internal.impl.DefaultUpdatePolicyAnalyzer#isUpdatedRequired()
+ SourceAnd<String> updatePolicy = updatePolicy((String) config.get(prefix + PROPERTY_GLOBAL_UPDATE_POLICY));
+ addRow(table, propertyIds ? PROPERTY_GLOBAL_UPDATE_POLICY : "Global update policy", updatePolicy,
+ "Overrides update policy specified at repository level (if specified)");
+
+ // see org.eclipse.aether.internal.impl.DefaultChecksumPolicyProvider#newChecksumPolicy()
+ SourceAnd<String> checksumPolicy = checksumPolicy((String) config.get(prefix + PROPERTY_GLOBAL_CHECKSUM_POLICY));
+ addRow(table, propertyIds ? PROPERTY_GLOBAL_CHECKSUM_POLICY : "Global checksum policy", checksumPolicy,
+ "Checksum policy for all repositories");
+
+ String updateReleasesProperty = (String) config.get(prefix + PROPERTY_UPDATE_RELEASES);
+ boolean updateReleases = false;
+ String sourceInfo = String.format(PATTERN_PID_PROPERTY, PID, prefix + PROPERTY_UPDATE_RELEASES);
+ if (updateReleasesProperty == null) {
+ sourceInfo = "Default \"false\"";
+ } else {
+ updateReleases = "true".equals(updateReleasesProperty);
+ }
+ addRow(table, propertyIds ? PROPERTY_UPDATE_RELEASES : "Update releases", new SourceAnd<Boolean>(sourceInfo, updateReleases),
+ "Whether to download non-SNAPSHOT artifacts according to update policy");
+
+ // see org.ops4j.pax.url.mvn.internal.config.MavenConfigurationImpl.isValid()
+ // ANY non null value (even "false"!) means that we require configadmin
+ String requireConfigAdminProperty = context.getProperty(prefix + REQUIRE_CONFIG_ADMIN_CONFIG);
+ boolean requireConfigAdmin = requireConfigAdminProperty != null;
+ sourceInfo = "Default \"false\"";
+ if (requireConfigAdmin) {
+ sourceInfo = "BundleContext property (" + prefix + REQUIRE_CONFIG_ADMIN_CONFIG + ")";
+ }
+ addRow(table, propertyIds ? REQUIRE_CONFIG_ADMIN_CONFIG : "Require Config Admin", new SourceAnd<Boolean>(sourceInfo, requireConfigAdmin),
+ "Whether MavenResolver service is registered ONLY with proper " + PID + " PID configuration");
+
+ // see org.ops4j.pax.url.mvn.internal.config.MavenConfigurationImpl.buildSettings()
+ String useFallbackRepositoriesProperty = (String) config.get(prefix + PROPERTY_USE_FALLBACK_REPOSITORIES);
+ boolean useFallbackRepositories = Boolean.parseBoolean(useFallbackRepositoriesProperty);
+ sourceInfo = "Default \"false\"";
+ if (useFallbackRepositoriesProperty != null) {
+ sourceInfo = String.format(PATTERN_PID_PROPERTY, PID, prefix + PROPERTY_USE_FALLBACK_REPOSITORIES);
+ }
+ addRow(table, propertyIds ? PROPERTY_USE_FALLBACK_REPOSITORIES : "Use fallback repository", new SourceAnd<Boolean>(sourceInfo, useFallbackRepositories),
+ "Whether Maven Central is used as implicit, additional remote repository");
+
+ // see org.ops4j.pax.url.mvn.internal.config.MavenConfigurationImpl.enableProxy()
+ // "proxySupport" and "proxies" are not used in "new" MavenResolver
+
+ // see org.eclipse.aether.internal.impl.DefaultOfflineController#checkOffline()
+ String offlineProperty = (String) config.get(prefix + PROPERTY_OFFLINE);
+ boolean offline = Boolean.parseBoolean(offlineProperty);
+ sourceInfo = "Default \"false\"";
+ if (offlineProperty != null) {
+ sourceInfo = String.format(PATTERN_PID_PROPERTY, PID, prefix + PROPERTY_OFFLINE);
+ }
+ addRow(table, propertyIds ? PROPERTY_OFFLINE : "Offline mode", new SourceAnd<Boolean>(sourceInfo, offline),
+ "Disables access to external remote repositories (file:// based ones are still used)");
+
+ // see org.ops4j.pax.url.mvn.internal.HttpClients.createConnManager()
+ String certificateCheckProperty = (String) config.get(prefix + PROPERTY_CERTIFICATE_CHECK);
+ boolean certificateCheck = Boolean.parseBoolean(certificateCheckProperty);
+ sourceInfo = "Default \"false\"";
+ if (certificateCheckProperty != null) {
+ sourceInfo = String.format(PATTERN_PID_PROPERTY, PID, prefix + PROPERTY_CERTIFICATE_CHECK);
+ }
+ addRow(table, propertyIds ? PROPERTY_CERTIFICATE_CHECK : "SSL/TLS certificate check", new SourceAnd<Boolean>(sourceInfo, certificateCheck),
+ "Turns on server certificate validation for HTTPS remote repositories");
+
+ // repositories (short list)
+ MavenRepositoryURL[] remoteRepositories = repositories(config, true);
+ boolean first = true;
+ for (MavenRepositoryURL url : remoteRepositories) {
+ addRow(table, first ? (propertyIds ? PROPERTY_REPOSITORIES : "Remote repositories") : "", new SourceAnd<String>(url.getFrom().getSource(), url.getURL().toString()),
+ first ? "Remote repositories where artifacts are being resolved if not found locally" : "");
+ first = false;
+ }
+
+ // default repositories (short list)
+ MavenRepositoryURL[] defaultRepositories = repositories(config, false);
+ first = true;
+ for (MavenRepositoryURL url : defaultRepositories) {
+ addRow(table, first ? (propertyIds ? PROPERTY_DEFAULT_REPOSITORIES : "Default repositories") : "", new SourceAnd<String>(url.getFrom().getSource(), url.getURL().toString()),
+ first ? "Repositories where artifacts are looked up before trying remote resolution" : "");
+ first = false;
+ }
+
+ // proxies (short list)
+ if (mavenSettings != null && mavenSettings.getProxies() != null) {
+ first = true;
+ for (Proxy proxy : mavenSettings.getProxies()) {
+ String value = String.format("%s:%s", proxy.getHost(), proxy.getPort());
+ addRow(table, first ? (propertyIds ? "<proxies>" : "HTTP proxies") : "", new SourceAnd<String>(MavenRepositoryURL.FROM.SETTINGS.getSource(), value),
+ first ? "Maven HTTP proxies" : "");
+ first = false;
+ }
+ }
+
+ System.out.println();
+ table.print(System.out);
+ System.out.println();
+ }
+
+ /**
+ * Helper to add row to {@link ShellTable}
+ * @param table
+ * @param label
+ * @param value
+ * @param descriptionText
+ */
+ private <T> void addRow(ShellTable table, String label, SourceAnd<T> value, String descriptionText) {
+ Row row = table.addRow();
+ row.addContent(label, value.val());
+ if (source) {
+ row.addContent(value.source);
+ }
+ if (description) {
+ row.addContent(descriptionText);
+ }
+ }
+
+ private SourceAnd<String> updatePolicy(String cmProperty) {
+ SourceAnd<String> result = new SourceAnd<>();
+ result.value = cmProperty;
+
+ if (cmProperty == null || "".equals(cmProperty.trim())) {
+ result.value = "";
+ result.source = "Implicit \"never\", but doesn't override repository-specific value";
+ return result;
+ }
+
+ result.source = String.format(PATTERN_PID_PROPERTY, PID, PID + "." + PROPERTY_GLOBAL_UPDATE_POLICY);
+ if ("always".equals(cmProperty) || "never".equals(cmProperty) || "daily".equals(cmProperty)) {
+ // ok
+ } else if (cmProperty.startsWith("interval")) {
+ int minutes = 1440;
+ try {
+ String n = cmProperty.substring("interval".length() + 1);
+ minutes = Integer.parseInt(n);
+ } catch (Exception e) {
+ result.value = "interval:1440";
+ result.source = "Implicit \"interval:1440\" (error parsing \"" + cmProperty + "\")";
+ }
+ } else {
+ result.value = "never";
+ result.source = "Implicit \"never\" (unknown value \"" + cmProperty + "\")";
+ }
+
+ return result;
+ }
+
+ private SourceAnd<String> checksumPolicy(String cmProperty) {
+ SourceAnd<String> result = new SourceAnd<>();
+ result.value = cmProperty;
+
+ if (cmProperty == null || "".equals(cmProperty.trim())) {
+ result.value = "warn";
+ result.source = "Default \"warn\"";
+ return result;
+ }
+
+ result.source = String.format(PATTERN_PID_PROPERTY, PID, PID + "." + PROPERTY_GLOBAL_CHECKSUM_POLICY);
+ if ("ignore".equals(cmProperty) || "warn".equals(cmProperty) || "fail".equals(cmProperty)) {
+ // ok
+ } else {
+ result.value = "warn";
+ result.source = "Implicit \"warn\" (unknown value \"" + cmProperty + "\")";
+ }
+
+ return result;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/750fd144/maven/core/src/main/java/org/apache/karaf/maven/core/MavenRepositoryURL.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/core/MavenRepositoryURL.java b/maven/core/src/main/java/org/apache/karaf/maven/core/MavenRepositoryURL.java
new file mode 100644
index 0000000..630976b
--- /dev/null
+++ b/maven/core/src/main/java/org/apache/karaf/maven/core/MavenRepositoryURL.java
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2008 Alin Dreghiciu.
+ *
+ * Licensed 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.maven.core;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import org.ops4j.pax.url.mvn.ServiceConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An URL of Maven repository that knows if it contains SNAPSHOT versions and/or releases.
+ *
+ * @author Alin Dreghiciu
+ * @author Guillaume Nodet
+ * @since 0.2.1, February 07, 2008
+ *
+ * @see org.ops4j.pax.url.mvn.internal.config.MavenRepositoryURL
+ */
+public class MavenRepositoryURL
+{
+ /*
+ * String OPTION_ALLOW_SNAPSHOTS = "snapshots";
+ * String OPTION_DISALLOW_RELEASES = "noreleases";
+ * String OPTION_MULTI = "multi";
+ * String OPTION_ID = "id";
+ * String OPTION_UPDATE = "update";
+ * String OPTION_RELEASES_UPDATE = "releasesUpdate";
+ * String OPTION_SNAPSHOTS_UPDATE = "snapshotsUpdate";
+ * String OPTION_CHECKSUM = "checksum";
+ * String OPTION_RELEASES_CHECKSUM = "releasesChecksum";
+ * String OPTION_SNAPSHOTS_CHECKSUM = "snapshotsChecksum";
+ */
+
+ private static final Logger LOG = LoggerFactory.getLogger( MavenRepositoryURL.class );
+
+ /**
+ * Repository Id.
+ */
+ private final String m_id;
+ /**
+ * Repository URL.
+ */
+ private final URL m_repositoryURL;
+ /**
+ * Repository file (only if URL is a file URL).
+ */
+ private final File m_file;
+ /**
+ * True if the repository contains snapshots.
+ */
+ private final boolean m_snapshotsEnabled;
+ /**
+ * True if the repository contains releases.
+ */
+ private final boolean m_releasesEnabled;
+ /**
+ * Repository update policy
+ */
+ private final String m_releasesUpdatePolicy;
+ /**
+ * Repository update policy
+ */
+ private final String m_snapshotsUpdatePolicy;
+ /**
+ * Repository checksum policy
+ */
+ private final String m_releasesChecksumPolicy;
+ /**
+ * Repository checksum policy
+ */
+ private final String m_snapshotsChecksumPolicy;
+
+ private final boolean m_multi;
+ /**
+ * Where the repository was defined (PID or settings.xml)
+ */
+ private final FROM m_from;
+
+ /**
+ * Creates a maven repository URL bases on a string spec. The path can be marked with @snapshots and/or @noreleases
+ * (not case sensitive).
+ *
+ * @param repositorySpec url spec of repository
+ *
+ * @throws MalformedURLException if spec contains a malformed maven repository url
+ */
+ public MavenRepositoryURL( final String repositorySpec )
+ throws MalformedURLException
+ {
+ final String[] segments = repositorySpec.split( ServiceConstants.SEPARATOR_OPTIONS );
+ final StringBuilder urlBuilder = new StringBuilder();
+ boolean snapshotEnabled = false;
+ boolean releasesEnabled = true;
+ boolean multi = false;
+
+ String name = null;
+ String update = null;
+ String updateReleases = null;
+ String updateSnapshots = null;
+ String checksum = null;
+ String checksumReleases = null;
+ String checksumSnapshots = null;
+ FROM from = null;
+
+ for( int i = 0; i < segments.length; i++ )
+ {
+ String segment = segments[i].trim();
+ if( segment.equalsIgnoreCase( ServiceConstants.OPTION_ALLOW_SNAPSHOTS ) )
+ {
+ snapshotEnabled = true;
+ }
+ else if( segment.equalsIgnoreCase( ServiceConstants.OPTION_DISALLOW_RELEASES ) )
+ {
+ releasesEnabled = false;
+ }
+ else if( segment.equalsIgnoreCase( ServiceConstants.OPTION_MULTI ) )
+ {
+ multi = true;
+ }
+ else if( segment.startsWith( ServiceConstants.OPTION_ID + "=" ) )
+ {
+ try {
+ name = segments[ i ].split( "=" )[1].trim();
+ } catch (Exception e) {
+ LOG.warn( "Problem with segment " + segments[i] + " in " + repositorySpec );
+ }
+ }
+ else if( segment.startsWith( ServiceConstants.OPTION_RELEASES_UPDATE + "=" ) )
+ {
+ try {
+ updateReleases = segments[ i ].split( "=" )[1].trim();
+ } catch (Exception e) {
+ LOG.warn( "Problem with segment " + segments[i] + " in " + repositorySpec );
+ }
+ }
+ else if( segment.startsWith( ServiceConstants.OPTION_SNAPSHOTS_UPDATE + "=" ) )
+ {
+ try {
+ updateSnapshots = segments[ i ].split( "=" )[1].trim();
+ } catch (Exception e) {
+ LOG.warn( "Problem with segment " + segments[i] + " in " + repositorySpec );
+ }
+ }
+ else if( segment.startsWith( ServiceConstants.OPTION_UPDATE + "=" ) )
+ {
+ try {
+ update = segments[ i ].split( "=" )[1].trim();
+ } catch (Exception e) {
+ LOG.warn( "Problem with segment " + segments[i] + " in " + repositorySpec );
+ }
+ }
+ else if( segment.startsWith( ServiceConstants.OPTION_RELEASES_CHECKSUM + "=" ) )
+ {
+ try {
+ checksumReleases = segments[ i ].split( "=" )[1].trim();
+ } catch (Exception e) {
+ LOG.warn( "Problem with segment " + segments[i] + " in " + repositorySpec );
+ }
+ }
+ else if( segment.startsWith( ServiceConstants.OPTION_SNAPSHOTS_CHECKSUM + "=" ) )
+ {
+ try {
+ checksumSnapshots = segments[ i ].split( "=" )[1].trim();
+ } catch (Exception e) {
+ LOG.warn( "Problem with segment " + segments[i] + " in " + repositorySpec );
+ }
+ }
+ else if( segment.startsWith( ServiceConstants.OPTION_CHECKSUM + "=" ) )
+ {
+ try {
+ checksum = segments[ i ].split( "=" )[1].trim();
+ } catch (Exception e) {
+ LOG.warn( "Problem with segment " + segments[i] + " in " + repositorySpec );
+ }
+ }
+ else if( segment.startsWith( "_from=" ) )
+ {
+ try {
+ from = FROM.valueOf( segments[ i ].split( "=" )[1].trim() );
+ } catch (Exception ignored) {
+ }
+ }
+ else
+ {
+ if( i > 0 )
+ {
+ urlBuilder.append( ServiceConstants.SEPARATOR_OPTIONS );
+ }
+ urlBuilder.append( segments[ i ] );
+ }
+ }
+ String spec = buildSpec( urlBuilder );
+ m_repositoryURL = new URL( spec );
+ m_snapshotsEnabled = snapshotEnabled;
+ m_releasesEnabled = releasesEnabled;
+ m_multi = multi;
+ if (name == null) {
+ String warn = "Repository spec " + spec + " does not contain an identifier. This is deprecated & discouraged & just evil.";
+ LOG.warn( warn );
+ name = "repo_" + spec.hashCode();
+ }
+ m_id = name;
+ m_releasesUpdatePolicy = updateReleases != null ? updateReleases : update;
+ m_snapshotsUpdatePolicy = updateSnapshots != null ? updateSnapshots : update;
+ m_releasesChecksumPolicy = checksumReleases != null ? checksumReleases : checksum;
+ m_snapshotsChecksumPolicy = checksumSnapshots != null ? checksumSnapshots : checksum;
+
+ m_from = from != null ? from : FROM.PID;
+
+ if( m_repositoryURL.getProtocol().equals( "file" ) )
+ {
+ try
+ {
+ // You must transform to URI to decode the path (manage a path with a space or non
+ // us character)
+ // like D:/documents%20and%20Settings/SESA170017/.m2/repository
+ // the path can be store in path part or in scheme specific part (if is relatif
+ // path)
+ // the anti-slash character is not a valid character for uri.
+ spec = spec.replaceAll( "\\\\", "/" );
+ spec = spec.replaceAll( " ", "%20" );
+ URI uri = new URI( spec );
+ String path = uri.getPath();
+ if( path == null )
+ path = uri.getSchemeSpecificPart();
+ m_file = new File( path );
+
+ }
+ catch ( URISyntaxException e )
+ {
+ throw new MalformedURLException( e.getMessage() );
+ }
+ }
+ else
+ {
+ m_file = null;
+ }
+ }
+
+ private String buildSpec( StringBuilder urlBuilder )
+ {
+ String spec = urlBuilder.toString().trim();
+ if( !spec.endsWith( "\\" ) && !spec.endsWith( "/" ) )
+ {
+ spec = spec + "/";
+ }
+ return spec;
+ }
+
+ /**
+ * Getter.
+ *
+ * @return repository id
+ */
+ public String getId()
+ {
+ return m_id;
+ }
+
+ /**
+ * Getter.
+ *
+ * @return repository URL
+ */
+ public URL getURL()
+ {
+ return m_repositoryURL;
+ }
+
+ /**
+ * Getter.
+ *
+ * @return repository file
+ */
+ public File getFile()
+ {
+ return m_file;
+ }
+
+ /**
+ * Getter.
+ *
+ * @return true if the repository contains releases
+ */
+ public boolean isReleasesEnabled()
+ {
+ return m_releasesEnabled;
+ }
+
+ /**
+ * Getter.
+ *
+ * @return true if the repository contains snapshots
+ */
+ public boolean isSnapshotsEnabled()
+ {
+ return m_snapshotsEnabled;
+ }
+
+ public String getReleasesUpdatePolicy() {
+ return m_releasesUpdatePolicy;
+ }
+
+ public String getSnapshotsUpdatePolicy() {
+ return m_snapshotsUpdatePolicy;
+ }
+
+ public String getReleasesChecksumPolicy() {
+ return m_releasesChecksumPolicy;
+ }
+
+ public String getSnapshotsChecksumPolicy() {
+ return m_snapshotsChecksumPolicy;
+ }
+
+ public FROM getFrom() {
+ return m_from;
+ }
+
+ /**
+ * Getter.
+ *
+ * @return true if the repository is a parent path of repos
+ */
+ public boolean isMulti()
+ {
+ return m_multi;
+ }
+
+ /**
+ * Getter.
+ *
+ * @return if the repository is a file based repository.
+ */
+ public boolean isFileRepository()
+ {
+ return m_file != null;
+ }
+
+ @Override
+ public String toString()
+ {
+ return new StringBuilder()
+ .append( m_repositoryURL.toString() )
+ .append( ",releases=" ).append( m_releasesEnabled )
+ .append( ",snapshots=" ).append( m_snapshotsEnabled )
+ .toString();
+ }
+
+ public static enum FROM {
+ PID("PID configuration"),
+ SETTINGS("Maven XML settings"),
+ FALLBACK("Fallback repository");
+
+ private String source;
+
+ FROM(String source) {
+ this.source = source;
+ }
+
+ public String getSource() {
+ return source;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/750fd144/maven/core/src/main/resources/OSGI-INF/bundle.info
----------------------------------------------------------------------
diff --git a/maven/core/src/main/resources/OSGI-INF/bundle.info b/maven/core/src/main/resources/OSGI-INF/bundle.info
new file mode 100644
index 0000000..509e13b
--- /dev/null
+++ b/maven/core/src/main/resources/OSGI-INF/bundle.info
@@ -0,0 +1,36 @@
+#
+#
+# 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.
+#
+#
+h1. Synopsis
+
+ ${project.name}
+
+ ${project.description}
+
+ Maven URL:
+ [mvn:${project.groupId}/${project.artifactId}/${project.version}]
+
+h1. Description
+
+ This bundle is the core implementation of Maven diagnostics support and exposes commands
+ to change and examine Maven configuration managed by pax-url-aether bundle and org.ops4j.pax.url.mvn PID.
+
+h1. Commands
+
+ The bundle contains the following commands:
+\${command-list|maven|indent=8,list,cyan}
http://git-wip-us.apache.org/repos/asf/karaf/blob/750fd144/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
----------------------------------------------------------------------
diff --git a/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java b/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
new file mode 100644
index 0000000..b0d9110
--- /dev/null
+++ b/maven/core/src/test/java/org/apache/karaf/maven/SettingsTest.java
@@ -0,0 +1,62 @@
+/*
+ * 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.maven;
+
+import java.io.IOException;
+
+import org.apache.maven.settings.Server;
+import org.apache.maven.settings.Settings;
+import org.apache.maven.settings.io.DefaultSettingsWriter;
+import org.junit.Test;
+import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
+import org.sonatype.plexus.components.cipher.PBECipher;
+
+public class SettingsTest {
+
+ @Test
+ public void readAndWriteSettings() throws IOException {
+ Settings settings = new Settings();
+ Server s = new Server();
+ s.setId("id");
+ settings.getServers().add(s);
+
+ new DefaultSettingsWriter().write(System.out, null, settings);
+ }
+
+ @Test
+ public void encryptMavenPassword() throws Exception {
+ // non-master password ('mvn -ep admin')
+ DefaultPlexusCipher plexusCipher = new DefaultPlexusCipher();
+ System.out.println(plexusCipher.encrypt("admin", "admin"));
+
+ // master password (`mvn -emp admin`)
+ PBECipher cipher = new PBECipher();
+ System.out.println(cipher.encrypt64("admin","settings.security"));
+ }
+
+ @Test
+ public void decryptMavenPassword() throws Exception {
+ // non-master password ('mvn -ep admin')
+ DefaultPlexusCipher plexusCipher = new DefaultPlexusCipher();
+ System.out.println(plexusCipher.decrypt("{EhjazkVpkMoHjAgaUKX+UxeXn9lsJGHst2uFKmhNZ8U=}", "admin"));
+
+ // master password (`mvn -emp admin`)
+ PBECipher cipher = new PBECipher();
+ System.out.println(cipher.decrypt64("oWE12FbirwYHNit93TAMA+OC/GJge2r9FuzI8kOuHlA=","settings.security"));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/750fd144/maven/core/src/test/resources/reference-settings.xml
----------------------------------------------------------------------
diff --git a/maven/core/src/test/resources/reference-settings.xml b/maven/core/src/test/resources/reference-settings.xml
new file mode 100644
index 0000000..25b58fb
--- /dev/null
+++ b/maven/core/src/test/resources/reference-settings.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
+
+ <localRepository>file:///</localRepository>
+
+ <proxies>
+ <proxy>
+ <id>id1</id>
+ <host>localhost</host>
+ <port>3128</port>
+ <protocol>http</protocol>
+ <username>username</username>
+ <password>password</password>
+ </proxy>
+ </proxies>
+
+ <servers>
+ <server>
+ <id>id</id>
+ <username>username</username>
+ <password>password</password>
+ </server>
+ </servers>
+
+ <profiles>
+ <profile>
+ <id>profile1</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <repositories>
+ <repository>
+ <id>id1</id>
+ <url>http://localhost/maven-repository/releases</url>
+ <releases>
+ <enabled>true</enabled>
+ <updatePolicy>never</updatePolicy>
+ <checksumPolicy>warn</checksumPolicy>
+ </releases>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ <repository>
+ <id>id2</id>
+ <url>http://localhost/maven-repository/snapshots</url>
+ <releases>
+ <enabled>false</enabled>
+ </releases>
+ <snapshots>
+ <enabled>true</enabled>
+ <updatePolicy>always</updatePolicy>
+ <checksumPolicy>warn</checksumPolicy>
+ </snapshots>
+ </repository>
+ </repositories>
+ </profile>
+ </profiles>
+
+ <activeProfiles>
+ <activeProfile>profile1</activeProfile>
+ </activeProfiles>
+
+</settings>
http://git-wip-us.apache.org/repos/asf/karaf/blob/750fd144/maven/pom.xml
----------------------------------------------------------------------
diff --git a/maven/pom.xml b/maven/pom.xml
new file mode 100644
index 0000000..95a3983
--- /dev/null
+++ b/maven/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+ <!--
+
+ 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.
+ -->
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.karaf</groupId>
+ <artifactId>karaf</artifactId>
+ <version>4.2.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <groupId>org.apache.karaf.maven</groupId>
+ <artifactId>maven-parent</artifactId>
+ <packaging>pom</packaging>
+ <name>Apache Karaf :: Maven</name>
+
+ <modules>
+ <module>core</module>
+ </modules>
+
+</project>
http://git-wip-us.apache.org/repos/asf/karaf/blob/750fd144/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index a7367d2..2767cb1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -65,6 +65,7 @@
<module>jdbc</module>
<module>jms</module>
<module>jpa</module>
+ <module>maven</module>
<module>services</module>
<module>subsystem</module>
<module>profile</module>
@@ -1077,6 +1078,16 @@
<version>${maven.version}</version>
</dependency>
<dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-settings</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-settings-builder</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-dependency-tree</artifactId>
<version>2.2</version>
[5/6] karaf git commit: [KARAF-5008] maven:http-proxy and
maven:http-proxy-list commands
Posted by gg...@apache.org.
[KARAF-5008] maven:http-proxy and maven:http-proxy-list commands
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/6a676630
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/6a676630
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/6a676630
Branch: refs/heads/master-maven-commands
Commit: 6a6766303030ac9437ba3920d98a4abea1edb605
Parents: 32d5c7b
Author: Grzegorz Grzybek <gr...@gmail.com>
Authored: Wed Jun 21 15:26:45 2017 +0200
Committer: Grzegorz Grzybek <gr...@gmail.com>
Committed: Wed Jun 21 15:31:54 2017 +0200
----------------------------------------------------------------------
.../karaf/maven/command/HttpProxyCommand.java | 126 ++++++++++++++-----
.../maven/command/HttpProxyListCommand.java | 70 +++++++++++
.../src/test/resources/reference-settings.xml | 1 +
3 files changed, 168 insertions(+), 29 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/6a676630/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
index 129aca5..d7a3bfa 100644
--- a/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyCommand.java
@@ -17,13 +17,17 @@
package org.apache.karaf.maven.command;
import java.util.Dictionary;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.apache.karaf.shell.api.action.Argument;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Option;
import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.table.Row;
-import org.apache.karaf.shell.support.table.ShellTable;
import org.apache.maven.settings.Proxy;
+import org.osgi.service.cm.Configuration;
@Command(scope = "maven", name = "http-proxy", description = "Manage HTTP proxy configuration for Maven remote repositories")
@Service
@@ -32,53 +36,117 @@ public class HttpProxyCommand extends MavenSecuritySupport {
@Option(name = "--add", description = "Adds HTTP proxy configuration to Maven settings", required = false, multiValued = false)
boolean add;
+ @Option(name = "--change", description = "Changes HTTP proxy configuration in Maven settings", required = false, multiValued = false)
+ boolean change;
+
@Option(name = "--remove", description = "Removes HTTP proxy configuration from Maven settings", required = false, multiValued = false)
boolean remove;
+ @Option(name = "-id", description = "Identifier of HTTP proxy", required = true, multiValued = false)
+ String id;
+
+ @Option(name = "-f", aliases = { "--force" }, description = "Do not ask for confirmation", required = false, multiValued = false)
+ boolean force = false;
+
+ @Option(name = "-u", aliases = { "--username" }, description = "Username for remote repository", required = false, multiValued = false)
+ String username;
+
+ @Option(name = "-p", aliases = { "--password" }, description = "Password for remote repository (may be encrypted, see \"maven:password -ep\")", required = false, multiValued = false)
+ String password;
+
+ @Option(name = "-n", aliases = { "--non-proxy-hosts" }, description = "Non-proxied hosts (in the format '192.168.*|localhost|...')", required = false, multiValued = false)
+ String nonProxyHosts;
+
+ @Argument(description = "host:port of HTTP proxy", required = false, multiValued = false)
+ String hostPort;
+
@Override
public void doAction(String prefix, Dictionary<String, Object> config) throws Exception {
- if (add && remove) {
- System.err.println("Please specify only one of --add and --remove");
+ if (add && (change || remove) || change && remove) {
+ System.err.println("Please specify only one of --add/--change/--remove");
return;
}
+ if (id == null || "".equals(id.trim())) {
+ System.err.println("Please specify ID of HTTP proxy");
+ return;
+ }
+
+ if (mavenSettings.getProxies() == null) {
+ mavenSettings.setProxies(new LinkedList<>());
+ }
+ Optional<Proxy> existingProxy = mavenSettings.getProxies().stream()
+ .filter((p) -> id.equals(p.getId())).findAny();
+
if (add) {
- // add
+ if (hostPort == null || "".equals(hostPort.trim())) {
+ System.err.println("Please specify host:port of new HTTP proxy");
+ return;
+ }
+ if (existingProxy.isPresent()) {
+ System.err.printf("HTTP proxy with ID \"%s\" is already configured\n", id);
+ return;
+ }
+ } else if (!existingProxy.isPresent()) {
+ System.err.printf("Can't find HTTP proxy with ID \"%s\"\n", id);
+ return;
}
- if (remove) {
+ boolean hasUsername = username != null && !"".equals(username.trim());
+ boolean hasPassword = password != null && !"".equals(password.trim());
+ boolean hasCredentials = hasUsername && hasPassword;
+
+ if ((hasUsername && !hasPassword) || (!hasUsername && hasPassword)) {
+ System.err.println("Please specify both username and password");
+ return;
+ }
+
+ Proxy proxy = null;
+ if (add) {
+ proxy = new Proxy();
+ proxy.setId(id);
+ mavenSettings.getProxies().add(proxy);
+ } else if (change) {
+ proxy = existingProxy.get(); // should be there
+ } else /*if (remove)*/ {
// remove
+ List<Proxy> newProxies = mavenSettings.getProxies().stream()
+ .filter((p) -> !id.equals(p.getId())).collect(Collectors.toList());
+ mavenSettings.setProxies(newProxies);
}
- // list (also after --add or --remove)
- System.out.println();
- if (mavenSettings != null && mavenSettings.getProxies() != null && mavenSettings.getProxies().size() > 0) {
- ShellTable table = new ShellTable();
- table.column("ID");
- table.column("Host");
- table.column("Port");
- table.column("Username");
- if (showPasswords) {
- table.column("Password");
+ if (add || change) {
+ proxy.setActive(true);
+ proxy.setProtocol("http");
+ if (nonProxyHosts != null && !"".equals(nonProxyHosts.trim())) {
+ proxy.setNonProxyHosts(nonProxyHosts);
}
- for (Proxy proxy : mavenSettings.getProxies()) {
- Row row = table.addRow();
- row.addContent(proxy.getId(), proxy.getHost(), proxy.getPort());
- row.addContent(proxy.getUsername() != null ? proxy.getUsername() : "");
- if (showPasswords) {
- addPasswordInfo(row, proxyPasswords, proxy.getId(), proxy.getPassword());
+ if (hostPort != null && !"".equals(hostPort.trim())) {
+ if (hostPort.contains(":")) {
+ proxy.setHost(hostPort.substring(0, hostPort.indexOf(':')));
+ proxy.setPort(Integer.parseInt(hostPort.substring(hostPort.indexOf(':') + 1)));
+ } else {
+ proxy.setHost(hostPort);
+ proxy.setPort(3128);
}
}
- table.print(System.out);
- } else {
- System.out.print("No HTTP proxies configured");
- if (settings != null && settings.value != null) {
- System.out.print(" in " + settings.value);
+ if (hasCredentials) {
+ proxy.setUsername(username);
+ proxy.setPassword(password);
}
- System.out.println();
}
- System.out.println();
+ updateSettings(prefix, config);
+
+ Configuration cmConfig = cm.getConfiguration(PID);
+ cmConfig.update(config);
+
+ // list (also after --add or --remove)
+ if (showPasswords) {
+ session.execute("maven:http-proxy-list -x");
+ } else {
+ session.execute("maven:http-proxy-list");
+ }
}
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/6a676630/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyListCommand.java
----------------------------------------------------------------------
diff --git a/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyListCommand.java b/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyListCommand.java
new file mode 100644
index 0000000..799b0da
--- /dev/null
+++ b/maven/core/src/main/java/org/apache/karaf/maven/command/HttpProxyListCommand.java
@@ -0,0 +1,70 @@
+/*
+ * 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.maven.command;
+
+import java.util.Dictionary;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+import org.apache.karaf.shell.api.action.Argument;
+import org.apache.karaf.shell.api.action.Command;
+import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.support.table.Row;
+import org.apache.karaf.shell.support.table.ShellTable;
+import org.apache.maven.settings.Proxy;
+
+@Command(scope = "maven", name = "http-proxy-list", description = "Lists HTTP proxy configurations for Maven remote repositories")
+@Service
+public class HttpProxyListCommand extends MavenSecuritySupport {
+
+ @Override
+ public void doAction(String prefix, Dictionary<String, Object> config) throws Exception {
+ System.out.println();
+ if (mavenSettings != null && mavenSettings.getProxies() != null && mavenSettings.getProxies().size() > 0) {
+ ShellTable table = new ShellTable();
+ table.column("ID");
+ table.column("Host");
+ table.column("Port");
+ table.column("Non-proxy hosts");
+ table.column("Username");
+ if (showPasswords) {
+ table.column("Password");
+ }
+ for (Proxy _p : mavenSettings.getProxies()) {
+ Row row = table.addRow();
+ row.addContent(_p.getId(), _p.getHost(), _p.getPort(), _p.getNonProxyHosts());
+ row.addContent(_p.getUsername() != null ? _p.getUsername() : "");
+ if (showPasswords) {
+ addPasswordInfo(row, proxyPasswords, _p.getId(), _p.getPassword());
+ }
+ }
+ table.print(System.out);
+ } else {
+ System.out.print("No HTTP proxies configured");
+ if (settings != null && settings.value != null) {
+ System.out.print(" in " + settings.value);
+ }
+ System.out.println();
+ }
+
+ System.out.println();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/6a676630/maven/core/src/test/resources/reference-settings.xml
----------------------------------------------------------------------
diff --git a/maven/core/src/test/resources/reference-settings.xml b/maven/core/src/test/resources/reference-settings.xml
index 25b58fb..979ab11 100644
--- a/maven/core/src/test/resources/reference-settings.xml
+++ b/maven/core/src/test/resources/reference-settings.xml
@@ -29,6 +29,7 @@
<protocol>http</protocol>
<username>username</username>
<password>password</password>
+ <nonProxyHosts></nonProxyHosts>
</proxy>
</proxies>