[MSCRIPTING-7] binding the session and servers helper in binding context
diff --git a/src/main/java/org/apache/maven/plugins/scripting/EvalMojo.java b/src/main/java/org/apache/maven/plugins/scripting/EvalMojo.java
index ec55f24..bf930d6 100644
--- a/src/main/java/org/apache/maven/plugins/scripting/EvalMojo.java
+++ b/src/main/java/org/apache/maven/plugins/scripting/EvalMojo.java
@@ -24,12 +24,16 @@
 
 import java.io.File;
 
+import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugins.annotations.Component;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
+import org.apache.maven.plugins.scripting.binding.Servers;
 import org.apache.maven.project.MavenProject;
+import org.apache.maven.settings.crypto.SettingsDecrypter;
 
 /**
  * Evaluate the specified script or scriptFile
@@ -60,18 +64,27 @@
     @Parameter
     String scriptResource;
 
+    @Component
+    private SettingsDecrypter settingsDecrypter;
+
     // script variables
     @Parameter(defaultValue = "${project}", readonly = true)
     private MavenProject project;
 
+    // script variables
+    @Parameter(defaultValue = "${session}", readonly = true)
+    private MavenSession session;
+
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
         try {
             AbstractScriptEvaluator execute = constructExecute();
 
             Bindings bindings = new SimpleBindings();
+            bindings.put("session", session);
             bindings.put("project", project);
             bindings.put("log", getLog());
+            bindings.put("servers", new Servers(session, settingsDecrypter));
 
             Object result = execute.eval(bindings, getLog());
 
diff --git a/src/main/java/org/apache/maven/plugins/scripting/binding/Servers.java b/src/main/java/org/apache/maven/plugins/scripting/binding/Servers.java
new file mode 100644
index 0000000..b2e8fd4
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/scripting/binding/Servers.java
@@ -0,0 +1,74 @@
+/*
+ * 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.maven.plugins.scripting.binding;
+
+/*
+ * 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.
+ */
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.settings.Server;
+import org.apache.maven.settings.building.SettingsProblem;
+import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
+import org.apache.maven.settings.crypto.SettingsDecrypter;
+import org.apache.maven.settings.crypto.SettingsDecryptionResult;
+
+import static java.util.stream.Collectors.joining;
+
+/**
+ * Binding which enables to work with servers (from settings.xml) and in particular decipher them transparently.
+ */
+public class Servers {
+    private final MavenSession session;
+    private final SettingsDecrypter settingsDecrypter;
+
+    public Servers(MavenSession session, SettingsDecrypter settingsDecrypter) {
+        this.session = session;
+        this.settingsDecrypter = settingsDecrypter;
+    }
+
+    public Server find(String id) {
+        final Server server = session.getSettings().getServer(id);
+        if (server == null) {
+            return null;
+        }
+        final SettingsDecryptionResult result = settingsDecrypter.decrypt(new DefaultSettingsDecryptionRequest(server));
+        if (!result.getProblems().isEmpty()) {
+            throw new IllegalStateException(
+                    result.getProblems().stream().map(SettingsProblem::toString).collect(joining("\n")));
+        }
+        final Server decrypted = result.getServer();
+        return decrypted == null ? server : decrypted;
+    }
+}
diff --git a/src/site/markdown/configure-the-script-engine.md.vm b/src/site/markdown/configure-the-script-engine.md.vm
index 1e6f322..66eac0a 100644
--- a/src/site/markdown/configure-the-script-engine.md.vm
+++ b/src/site/markdown/configure-the-script-engine.md.vm
@@ -47,4 +47,8 @@
           </dependency>
         </dependencies>
       </plugin>
-```
\ No newline at end of file
+```
+
+The binding context is provided with `log` (maven mojo logger), `project` (maven project), `session` (maven session) and `servers` which enables to find a decrypted (if needed) server from your settings.xml.
+
+To use `servers`, you simply call `servers.find(<server_id>)` and it returns null or a `Server` instance which means you can call `server.getPassword()` to access the clear password.
diff --git a/src/test/java/org/apache/maven/plugins/scripting/binding/ServersTest.java b/src/test/java/org/apache/maven/plugins/scripting/binding/ServersTest.java
new file mode 100644
index 0000000..8803c07
--- /dev/null
+++ b/src/test/java/org/apache/maven/plugins/scripting/binding/ServersTest.java
@@ -0,0 +1,167 @@
+/*
+ * 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.maven.plugins.scripting.binding;
+
+/*
+ * 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.
+ */
+
+import java.util.List;
+
+import org.apache.maven.execution.DefaultMavenExecutionRequest;
+import org.apache.maven.execution.DefaultMavenExecutionResult;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.settings.Proxy;
+import org.apache.maven.settings.Server;
+import org.apache.maven.settings.building.SettingsProblem;
+import org.apache.maven.settings.crypto.DefaultSettingsDecrypter;
+import org.apache.maven.settings.crypto.SettingsDecryptionRequest;
+import org.apache.maven.settings.crypto.SettingsDecryptionResult;
+import org.codehaus.plexus.DefaultPlexusContainer;
+import org.codehaus.plexus.PlexusContainerException;
+import org.junit.Test;
+import org.sonatype.aether.util.DefaultRepositorySystemSession;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+// sanity check, decrypter impl is mocked for simplicity
+public class ServersTest {
+    @Test
+    public void missing() throws PlexusContainerException {
+        assertNull(new Servers(newSession(emptyList()), new DefaultSettingsDecrypter()).find("test"));
+    }
+
+    @Test
+    public void clear() throws PlexusContainerException {
+        final Server server = new Server();
+        server.setId("test");
+        server.setUsername("clear");
+        server.setPassword("12345");
+        assertEquals(
+                "12345",
+                new Servers(newSession(singletonList(server)), new DefaultSettingsDecrypter() {
+                            @Override
+                            public SettingsDecryptionResult decrypt(SettingsDecryptionRequest request) {
+                                return new SettingsDecryptionResult() {
+                                    @Override
+                                    public Server getServer() {
+                                        return null;
+                                    }
+
+                                    @Override
+                                    public List<SettingsProblem> getProblems() {
+                                        return emptyList();
+                                    }
+
+                                    @Override
+                                    public List<Server> getServers() {
+                                        throw new UnsupportedOperationException();
+                                    }
+
+                                    @Override
+                                    public Proxy getProxy() {
+                                        throw new UnsupportedOperationException();
+                                    }
+
+                                    @Override
+                                    public List<Proxy> getProxies() {
+                                        throw new UnsupportedOperationException();
+                                    }
+                                };
+                            }
+                        })
+                        .find("test")
+                        .getPassword());
+    }
+
+    @Test
+    public void ciphered() throws PlexusContainerException {
+        final Server server = new Server();
+        server.setId("test");
+        server.setUsername("not-clear");
+        server.setPassword("ciphered");
+        assertEquals(
+                "12345",
+                new Servers(newSession(singletonList(server)), new DefaultSettingsDecrypter() {
+                            @Override
+                            public SettingsDecryptionResult decrypt(SettingsDecryptionRequest request) {
+                                return new SettingsDecryptionResult() {
+                                    @Override
+                                    public Server getServer() {
+                                        final Server result = new Server();
+                                        result.setId(server.getId());
+                                        result.setUsername(server.getUsername());
+                                        result.setPassword("12345");
+                                        return result;
+                                    }
+
+                                    @Override
+                                    public List<SettingsProblem> getProblems() {
+                                        return emptyList();
+                                    }
+
+                                    @Override
+                                    public List<Server> getServers() {
+                                        throw new UnsupportedOperationException();
+                                    }
+
+                                    @Override
+                                    public Proxy getProxy() {
+                                        throw new UnsupportedOperationException();
+                                    }
+
+                                    @Override
+                                    public List<Proxy> getProxies() {
+                                        throw new UnsupportedOperationException();
+                                    }
+                                };
+                            }
+                        })
+                        .find("test")
+                        .getPassword());
+    }
+
+    private MavenSession newSession(final List<Server> servers) throws PlexusContainerException {
+        final DefaultMavenExecutionRequest request = new DefaultMavenExecutionRequest();
+        request.setServers(servers);
+        return new MavenSession(
+                new DefaultPlexusContainer(),
+                new DefaultRepositorySystemSession(),
+                request,
+                new DefaultMavenExecutionResult());
+    }
+}