[java-identity-provider] 01/11: IDP-1499 New V4 Installer: Initial Commit
Rod Widdowson
rdw at steadingsoftware.com
Fri Oct 11 11:08:24 EDT 2019
This is an automated email from the git hooks/post-receive script.
rdw pushed a commit to branch master
in repository java-identity-provider.
View the commit online:
http://git.shibboleth.net/view/?p=java-identity-provider.git;a=commit;h=da6c9070e58cdbdad68a9d89cc10c995d0d22376
commit da6c9070e58cdbdad68a9d89cc10c995d0d22376
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Mon Aug 26 09:53:13 2019 +0100
IDP-1499 New V4 Installer: Initial Commit
https://issues.shibboleth.net/jira/browse/IDP-1499
Basic installer properties, some help classes and BuildWar.
---
idp-conf/src/main/resources/conf/logback.xml | 4 +-
.../src/test/resources/conf/metadata-providers.xml | 2 -
idp-distribution/src/main/resources/bin/build.xml | 4 +-
idp-installer/pom.xml | 12 ++
.../shibboleth/idp/installer/impl/BuildWar.java | 134 ++++++++++++
.../idp/installer/impl/CopyingVisitor.java | 132 ++++++++++++
.../idp/installer/impl/DeletingVisitor.java | 76 +++++++
.../idp/installer/impl/InstallerProperties.java | 227 +++++++++++++++++++++
.../java/net/shibboleth/idp/installer/Test.java | 66 ++++++
idp-installer/src/test/resources/logback-test.xml | 2 +-
10 files changed, 652 insertions(+), 7 deletions(-)
diff --git a/idp-conf/src/main/resources/conf/logback.xml b/idp-conf/src/main/resources/conf/logback.xml
index eeaecf4..f5d1078 100644
--- a/idp-conf/src/main/resources/conf/logback.xml
+++ b/idp-conf/src/main/resources/conf/logback.xml
@@ -14,7 +14,7 @@
<!-- Location and retention. -->
- <variable name="idp.logfiles" value="${idp.home}/logs}" />
+ <variable name="idp.logfiles" value="${idp.home}/logs" />
<variable name="idp.loghistory" value="${idp.loghistory:-180}" />
<!-- Much higher performance if you operate on DEBUG. -->
@@ -189,4 +189,4 @@
<appender-ref ref="${idp.warn.appender:-IDP_WARN}" />
</root>
-</configuration>
\ No newline at end of file
+</configuration>
diff --git a/idp-conf/src/test/resources/conf/metadata-providers.xml b/idp-conf/src/test/resources/conf/metadata-providers.xml
index cdd5a3a..3e687ba 100644
--- a/idp-conf/src/test/resources/conf/metadata-providers.xml
+++ b/idp-conf/src/test/resources/conf/metadata-providers.xml
@@ -24,7 +24,6 @@
<!-- Metadata Configuration -->
<!-- ========================================== -->
-
<!-- Example metadata provider. -->
<MetadataProvider id="URLMD" xsi:type="ResourceBackedMetadataProvider" maxRefreshDelay="PT5M" indexesRef="testbed.MetadataIndexes" resourceRef="exampleMetadata">
@@ -71,5 +70,4 @@
</MetadataProvider>
<MetadataProvider id="SP123MD" xsi:type="ResourceBackedMetadataProvider" maxRefreshDelay="PT5M" indexesRef="testbed.MetadataIndexes" resourceRef="exampleMetadata-sp123"/>
-
</MetadataProvider>
diff --git a/idp-distribution/src/main/resources/bin/build.xml b/idp-distribution/src/main/resources/bin/build.xml
index 279830f..b81a091 100644
--- a/idp-distribution/src/main/resources/bin/build.xml
+++ b/idp-distribution/src/main/resources/bin/build.xml
@@ -21,8 +21,8 @@
The following properties are used. If they are not specified on the command line then
they will be prompted for if needed.
- idp.src.dir (update only): Where to install from. No default
- idp.target.dir (all): where to install to. Default is basedir.
+ idp.src.dir (update only): Where to install from. Default is basedir
+ idp.target.dir (all): where to install to. Default is basedir for build-war, shibboleth-idp otherwise
idp.host.name: If we are creating certificates
idp.uri.subject.alt.name: If we are creating certificates. Defaulted
idp.sealer.password:
diff --git a/idp-installer/pom.xml b/idp-installer/pom.xml
index 7bb873d..b27c49f 100644
--- a/idp-installer/pom.xml
+++ b/idp-installer/pom.xml
@@ -42,6 +42,18 @@
</dependency>
<dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <scope>compile</scope><!-- normally runtime -->
+ </dependency>
+
+<!-- <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>compile</scope>
+ </dependency> -->
+
+ <dependency>
<groupId>${opensaml.groupId}</groupId>
<artifactId>opensaml-core</artifactId>
</dependency>
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/BuildWar.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/BuildWar.java
new file mode 100644
index 0000000..f46a6f8
--- /dev/null
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/BuildWar.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 net.shibboleth.idp.installer.impl;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.taskdefs.Copy;
+import org.apache.tools.ant.taskdefs.Jar;
+import org.apache.tools.ant.types.FileSet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/** Code to build the war file during an install or on request.<p/>
+ * This code<ul>
+ * <li>Deletes any old detritus</li>
+ * <li>Creates a directory called webapp.tmp and populates it from the dist folder</li>
+ * <li>Overwrites this from edit-webapp</li>
+ * <li>Deletes the old idp.war</li>
+ * <li>Builds a jar file called idp.war</li>
+ * <li>Deletes webapp.tmp</li>
+ * </ul>
+ */
+public final class BuildWar {
+
+ /** Log. */
+ public static final Logger LOG = LoggerFactory.getLogger(BuildWar.class);
+
+ /** And psuedo project as parent. */
+ private static final Project ANT_PROJECT = new Project();
+
+ /** private Constructor. */
+ private BuildWar() {}
+
+ /** Method to do the work of building the war.
+ * @param installerProps The environment for the work.
+ * @throws BuildException if unexpected badness occurs.
+ */
+ public static void buildWar(final InstallerProperties installerProps) throws BuildException {
+ final Path target = installerProps.getTargetDir();
+ final Path warFile = target.resolve("war").resolve("idp.war");
+
+ LOG.info("Rebuilding {}", warFile.toAbsolutePath());
+ try {
+ DeletingVisitor.deleteTree(target.resolve("webpapp"));
+ } catch (final IOException e) {
+ LOG.warn("Deleting {} failed", target.resolve("webpapp").toAbsolutePath(), e);
+ }
+ final Path webAppTmp =target.resolve("webpapp.tmp");
+ try {
+ DeletingVisitor.deleteTree(webAppTmp);
+ } catch (final IOException e) {
+ LOG.warn("Deleting {} failed", webAppTmp.toAbsolutePath(), e);
+ }
+ final Path distWebApp = target.resolve("dist").resolve("webapp");
+ final Copy initial = getCopyTask(distWebApp, webAppTmp);
+ initial.setPreserveLastModified(true);
+ initial.setFailOnError(true);
+ initial.setVerbose(LOG.isDebugEnabled());
+ LOG.info("Initial populate from {} to {}", distWebApp, webAppTmp);
+ initial.execute();
+
+ final Path editWebApp = target.resolve("edit-webapp");
+ final Copy overlay = getCopyTask(editWebApp, webAppTmp);
+ overlay.setOverwrite(true);
+ overlay.setPreserveLastModified(true);
+ overlay.setFailOnError(true);
+ overlay.setVerbose(LOG.isDebugEnabled());
+ LOG.info("Overlay from {} to {}", editWebApp, webAppTmp);
+ overlay.execute();
+
+ warFile.toFile().delete();
+ final Jar jarTask = new Jar();
+ jarTask.setDestFile(warFile.toFile());
+ jarTask.setBasedir(webAppTmp.toFile());
+ jarTask.setProject(ANT_PROJECT);
+ LOG.info("Creating war file {}", warFile);
+ jarTask.execute();
+ try {
+ DeletingVisitor.deleteTree(webAppTmp);
+ } catch (final IOException e) {
+ LOG.warn("Deleting {} failed", webAppTmp, e);
+ }
+ }
+
+ /** Copy files. We use ant rather than {@link Files#copy(Path, Path, java.nio.file.CopyOption...)}
+ * because the latter has issues with the Windows ReadOnly Attribute, and the former is tried
+ * and tested technology.
+ * @param from where to copy from
+ * @param to where to copy to
+ * @return a partially populated {@link Copy} task
+ */
+ private static Copy getCopyTask(final Path from, final Path to) {
+ final Copy result = new Copy();
+ result.setTodir(to.toFile());
+ final FileSet fromSet = new FileSet();
+ fromSet.setDir(from.toFile());
+ result.addFileset(fromSet);
+ result.setProject(ANT_PROJECT);
+ return result;
+ }
+
+ /** Program entry to build war. Calls {@link #buildWar(InstallerProperties)}.
+ * @param args input
+ */
+ public static void main(final String[] args) {
+ try {
+ LOG.error("Starting build");
+ final InstallerProperties ip = new InstallerProperties(true);
+ ip.initialize();
+ buildWar(ip);
+ } catch (final Throwable e) {
+ LOG.error("Build WebApp failed", e);
+ }
+ }
+}
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/CopyingVisitor.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/CopyingVisitor.java
new file mode 100644
index 0000000..d8ed275
--- /dev/null
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/CopyingVisitor.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 net.shibboleth.idp.installer.impl;
+
+import java.io.IOException;
+import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.BasicFileAttributes;
+
+import javax.annotation.Nonnull;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+
+/** {@link FileVisitor} which copies a directory tree.
+ * This class is based on that found in the javadoc for {@link FileVisitor}.
+ *
+ */
+public class CopyingVisitor extends SimpleFileVisitor<Path> {
+
+ /** Class logger. */
+ @Nonnull
+ private static final Logger LOG = LoggerFactory.getLogger(CopyingVisitor.class);
+
+ /** The 'to' directory.*/
+ private final Path source;
+
+ /** The 'from' directory.*/
+ private final Path target;
+
+ /** Do we overwriting or leave exiting in place. */
+ private final boolean overWrite;
+
+ /**
+ * Constructor.
+ *
+ * @param from source to copy from.
+ * @param to target to Copy to.
+ * @param replace do we replace or leave in place.
+ */
+ public CopyingVisitor(final Path from, final Path to, final boolean replace) {
+ Constraint.isTrue(!Files.exists(to) || Files.isDirectory(to), "Destination should be a directory or not exist");
+ Constraint.isTrue(Files.exists(from) && Files.isDirectory(from), "Source should be a directory and exist");
+
+ source = from;
+ target = to;
+ overWrite = replace;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FileVisitResult preVisitDirectory(final Path dir, final BasicFileAttributes attrs) throws IOException {
+ final Path targetDir = target.resolve(source.relativize(dir));
+ try {
+ if (!Files.exists(targetDir)) {
+ LOG.debug("Creating Directory {}", targetDir);
+ Files.copy(dir, targetDir);
+ } else {
+ LOG.debug("Directory {} exists already", targetDir);
+ }
+ } catch (final FileAlreadyExistsException e) {
+ if (!Files.isDirectory(targetDir)) {
+ throw e;
+ }
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
+ final Path targetFile = target.resolve(source.relativize(file));
+ if (overWrite) {
+ LOG.debug("Overwriting file {}", targetFile);
+ Files.copy(file, targetFile, StandardCopyOption.REPLACE_EXISTING);
+ } else if (!Files.exists(targetFile)) {
+ LOG.debug("Creating file {}", targetFile);
+ Files.copy(file, targetFile);
+ } else {
+ LOG.debug("File {} exists, not copied", targetFile);
+ }
+ return FileVisitResult.CONTINUE;
+ }
+
+ /**
+ * Method to copy a directory tree.
+ *
+ * @param from source to copy from.
+ * @param to target to Copy to.
+ * @throws IOException if the tree walks fails
+ */
+ public static void copyTree(final Path from, final Path to) throws IOException {
+ copyTree(from, to, false);
+ }
+
+ /**
+ * Method to copy a directory tree.
+ *
+ * @param from source to copy from.
+ * @param to target to Copy to.
+ * @param overWrite do we leave existing files in place or overwrite them?
+ * @throws IOException if the tree walks fails
+ */
+ public static void copyTree(final Path from, final Path to, final boolean overWrite) throws IOException {
+ LOG.debug("Copying From {} to {} overwrite = {}", from, to, overWrite);
+ final CopyingVisitor visitor = new CopyingVisitor(from, to, overWrite);
+ Files.walkFileTree(from, visitor);
+ }
+}
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/DeletingVisitor.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/DeletingVisitor.java
new file mode 100644
index 0000000..d53d3bd
--- /dev/null
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/DeletingVisitor.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 net.shibboleth.idp.installer.impl;
+
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+
+import javax.annotation.Nonnull;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.utilities.java.support.logic.Constraint;
+
+
+/** {@link FileVisitor} which deletes a directory tree.
+ * This class is based on that found in the javadoc for {@link FileVisitor}.
+ *
+ */
+public class DeletingVisitor extends SimpleFileVisitor<Path> {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(DeletingVisitor.class);
+
+ /** {@inheritDoc} */
+ @Override
+ public FileVisitResult postVisitDirectory(final Path dir, final IOException e) throws IOException {
+ if (e == null) {
+ log.trace("Deleting Directory {}", dir);
+ Files.delete(dir);
+ return FileVisitResult.CONTINUE;
+ }
+ // directory iteration failed
+ throw e;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
+ log.trace("Deleting file {}", file);
+ Files.delete(file);
+ return FileVisitResult.CONTINUE;
+ }
+
+ /**
+ * Method to delete a tree.
+ *
+ * @param root where to delete
+ * @throws IOException if the tree walks fails
+ */
+ public static void deleteTree(final Path root) throws IOException {
+ Constraint.isTrue(!Files.exists(root) || Files.isDirectory(root),
+ "Delete point should be a directory and must exist");
+ Files.walkFileTree(root, new DeletingVisitor());
+ }
+}
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/InstallerProperties.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/InstallerProperties.java
new file mode 100644
index 0000000..64d0ff1
--- /dev/null
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/InstallerProperties.java
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 net.shibboleth.idp.installer.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Properties;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.input.DefaultInputHandler;
+import org.apache.tools.ant.input.InputRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
+import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
+
+/** Class to describe simply parameterization and status of the installation.
+ *
+ * Mostly it interrogates the system environment, but will load a file if one
+ * is supplied (via a property name).<p/>Property names :
+ * <ul>
+ * <li> idp.src.dir (update only): Where to install from. Default is basedir. Not used for build-war</li>
+ * <li> idp.target.dir (all): where to install to. Default is basedir for build war /opt/shibboleth-idp otherwise.</li>
+ * <li> idp.host.name: If we are creating certificates</li>
+ * <li> idp.uri.subject.alt.name: If we are creating certificates. Defaulted</li>
+ * <li> idp.sealer.password:</li>
+ * <li> idp.sealer.alias:</li>
+ * <li> idp.keystore.password:</li>
+ * <li> idp.keysize: to change from the the default of 3072</li>
+ * <li> idp.scope: The scope to assert. If present this should also be present in idp.merge.properties</li>
+ * <li> idp.merge.properties: The name of a property file to merge with idp.properties. This file is only
+ * used when doing the initial create of idp.properties, and is deleted after processing</li>
+ * <ul><li> if idp.noprompt is set, then this file should contain a line setting idp.entityID. </li>
+ * <li> if idp.sealer.password is set, then this file should contain a line setting
+ * idp.sealer.storePassword and idp.sealer.keyPassword</li>
+ * <li> if idp.scope is present, then this file should contain a line setting idp.scope
+ * services.merge.properties: The name of a property file to merge with services.properties</li>
+ * <li> if idp.is.V2 is set, then this file should contain a line setting
+ * idp.service.relyingparty.resources=shibboleth.LegacyRelyingPartyResolverResources</li></ul>
+ * <li> nameid.merge.properties: The name of a property file to merge with saml-nameid.properties.
+ * If idp.is.V2 is set, then this file should contain lines enabling legacy nameid generation
+ * <li> idp.property.file: The name of a property file to fill in some or all of the above.
+ This file is deleted after processing.</li>
+ * <li> idp.no.tidy: Do not delete the two above files (debug only)</li>
+ * <li> idp.jetty.config: Copy jetty configuration from distribution (Unsupported)</li>
+ * <li> ldap.merge.properties: The name of a property file to merge with ldap.properties</li>
+ * <li> idp.conf.filemode (default "600"): The permissions to mark the files in conf with (UNIX only).</li>
+ * <li> idp.conf.credentials.filemode (default "600"): The permissions to mark the files in conf with (UNIX only).</li>
+ * <li> idp.noprompt will cause a failure rather than a prompt.</li>
+ * </ul>
+ */
+public class InstallerProperties extends AbstractInitializableComponent {
+
+ /** The base directory, inherited and shared with ant. */
+ public static final String ANT_BASE_DIR = "ant.home";
+
+ /** The name of a property file to fill in some or all of the above. This file is deleted after processing. */
+ public static final String PROPERTY_SOURCE_FILE = "idp.property.file";
+
+ /** where to install to. Default is basedir */
+ public static final String TARGET_DIR = "idp.target.dir";
+
+ /** where to install from (installs only). */
+ public static final String SOURCE_DIR = "idp.src.dir";
+
+ /** Do we cause a failure rather than a prompt. */
+ public static final String NO_PROMPT = "idp.noprompt";
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(InstallerProperties.class);
+
+ /** The base directory. */
+ @NonnullAfterInit private Path baseDir;
+
+ /** The properties driving the install. */
+ @NonnullAfterInit private Properties installerProperties;
+
+ /** The file specified in the system file idp.property.file (if present). */
+ @Nullable private File idpPropertyFile;
+
+ /** The target Directory. */
+ private Path targetDir;
+
+ /** The sourceDirectory. */
+ private Path srcDir;
+
+ /** Do we allow prompting?*/
+ private boolean noPrompt;
+
+ /** Is a source Dir needed? */
+ private final boolean needSourceDir;
+
+ /**
+ * Constructor.
+ * @param populateDone is this a war build (or a windows installer)? If no we don't need the source dir.
+ */
+ public InstallerProperties(final boolean populateDone) {
+ needSourceDir = !populateDone;
+ }
+
+ /** {@inheritDoc} */
+ protected void doInitialize() throws ComponentInitializationException {
+ installerProperties = new Properties(System.getProperties());
+ final String antBase = installerProperties.getProperty(ANT_BASE_DIR);
+ if (antBase == null) {
+ throw new ComponentInitializationException(ANT_BASE_DIR + " must be specified");
+ }
+ try {
+ baseDir = Path.of(antBase).resolve("..").toRealPath();
+ } catch (final IOException e) {
+ throw new ComponentInitializationException(e);
+ }
+ if (!Files.exists(baseDir)) {
+ log.error("Base dir {} did not exist", baseDir.toAbsolutePath());
+ throw new ComponentInitializationException(ANT_BASE_DIR + " must exist");
+ }
+ log.debug("base dir {}", baseDir);
+
+ if (installerProperties.containsKey(PROPERTY_SOURCE_FILE)) {
+ final Path file = baseDir.resolve(installerProperties.getProperty(PROPERTY_SOURCE_FILE));
+ if (!Files.exists(file)) {
+ log.error("Property file {} did not exist", file.toAbsolutePath());
+ throw new ComponentInitializationException(file + " must exist");
+ }
+ log.debug("Loading properties from {}", file.toAbsolutePath());
+
+ idpPropertyFile = file.toFile();
+ try {
+ installerProperties.load(new FileInputStream(idpPropertyFile));
+ } catch (final IOException e) {
+ log.error("Could not load {}", file.toAbsolutePath(), e);
+ throw new ComponentInitializationException(e);
+ }
+ idpPropertyFile.deleteOnExit();
+ }
+
+ String value = installerProperties.getProperty(NO_PROMPT);
+ noPrompt = value != null;
+
+ if (needSourceDir) {
+ value = getValue(SOURCE_DIR, "Source (Distribution) Directory (press <enter> to accept default):", antBase);
+ srcDir = Path.of(value);
+ log.debug("Source directory {}", srcDir.toAbsolutePath());
+ }
+ }
+
+ /** Lookup a property. If it isn't defined then ask the user (if we are allowed)
+ * @param propertyName the property to lookup.
+ * @param prompt what to say to the user
+ * @param defaultValue the default value
+ * @throws BuildException of anything goes wrong
+ * @return the value
+ */
+ protected String getValue(final String propertyName,
+ final String prompt, final String defaultValue) throws BuildException {
+ String value = installerProperties.getProperty(propertyName);
+ if (value != null) {
+ return value;
+ }
+ if (noPrompt) {
+ throw new BuildException("No value for " + propertyName + " specified");
+ }
+
+ final InputRequest request = new InputRequest("Installation Directory:");
+ request.setDefaultValue(defaultValue);
+
+ new DefaultInputHandler().handleInput(request);
+ value = request.getInput();
+ if (value == null || "".contentEquals(value)) {
+ return defaultValue;
+ }
+ return value;
+ }
+
+ /** Get where we are installing/updating/building the war.
+ * @return the target directory
+ * @throws BuildException if something goes awry.
+ */
+ @Nonnull public Path getTargetDir() throws BuildException {
+ ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
+ if (targetDir != null) {
+ return targetDir;
+ }
+ final String defTarget;
+ if (needSourceDir) {
+ // Source is not "here"
+ defTarget = "/opt/shibboleth-idp";
+ } else {
+ // build-war or Windows so "here" is also "where"
+ defTarget = baseDir.toAbsolutePath().toString();
+ }
+ final String targetValue = getValue(TARGET_DIR, "Installation Directory", defTarget);
+ targetDir = Path.of(targetValue);
+ return targetDir;
+ }
+
+ /** Where is the install coming from?
+ * @return the source directory
+ */
+ @Nullable public Path getSourceDir() {
+ return srcDir;
+ }
+}
diff --git a/idp-installer/src/test/java/net/shibboleth/idp/installer/Test.java b/idp-installer/src/test/java/net/shibboleth/idp/installer/Test.java
new file mode 100644
index 0000000..7c6e1c0
--- /dev/null
+++ b/idp-installer/src/test/java/net/shibboleth/idp/installer/Test.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 net.shibboleth.idp.installer;
+
+import java.nio.file.Path;
+import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+
+import javax.annotation.Nonnull;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.Copy;
+import org.apache.tools.ant.types.FileSet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import net.shibboleth.idp.installer.impl.CopyingVisitor;
+import net.shibboleth.idp.installer.impl.DeletingVisitor;
+import net.shibboleth.idp.installer.impl.InstallerProperties;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+
+/**
+ *
+ */
+public class Test {
+
+ /** Class logger. */
+ @Nonnull private final Logger log = LoggerFactory.getLogger(Test.class);
+
+ private static Copy getCopyTask(final Path from, final Path to) {
+ final Copy result = new Copy();
+ result.setTodir(to.toFile());
+ final FileSet fromSet = new FileSet();
+ fromSet.setDir(from.toFile());
+ result.addFileset(fromSet);
+ return result;
+ }
+
+ /**
+ * @param args
+ * @throws IOException
+ * @throws ComponentInitializationException
+ */
+ public static void main(String[] args) throws IOException, ComponentInitializationException {
+ Copy tsk = getCopyTask(Path.of("C:\\Users\\rdw\\Downloads"), Path.of("C:\\Users\\rdw\\Desktop\\fofofo"));
+ tsk.setProject(new Project());
+ tsk.execute();
+ }
+
+}
diff --git a/idp-installer/src/test/resources/logback-test.xml b/idp-installer/src/test/resources/logback-test.xml
index f3280e5..8f891b4 100644
--- a/idp-installer/src/test/resources/logback-test.xml
+++ b/idp-installer/src/test/resources/logback-test.xml
@@ -10,7 +10,7 @@
</appender>
<root>
- <level value="warn" />
+ <level value="DEBUG" />
<appender-ref ref="STDOUT" />
</root>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list