[java-identity-provider] 04/11: IDP-1499 New V4 Installer: Copy Distribution
Rod Widdowson
rdw at steadingsoftware.com
Fri Oct 11 11:08:27 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=48188349acffdf1561aff36a5b6de9c8a1c997ae
commit 48188349acffdf1561aff36a5b6de9c8a1c997ae
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Mon Oct 7 13:50:34 2019 +0100
IDP-1499 New V4 Installer: Copy Distribution
https://issues.shibboleth.net/jira/browse/IDP-1499
---
.../idp/installer/impl/CopyDistributions.java | 173 +++++++++++++++++++++
.../idp/installer/impl/InstallerSupport.java | 80 +++++++++-
idp-installer/src/main/resources/logback.xml | 17 ++
3 files changed, 267 insertions(+), 3 deletions(-)
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/CopyDistributions.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/CopyDistributions.java
new file mode 100644
index 0000000..43079f5
--- /dev/null
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/CopyDistributions.java
@@ -0,0 +1,173 @@
+/*
+ * 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 java.time.Instant;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.taskdefs.Copy;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Copy the distribution to its final location.
+ */
+public final class CopyDistributions {
+
+ /** Log. */
+ public static final Logger LOG = LoggerFactory.getLogger(CopyDistributions.class);
+
+ /** Private Constructor. */
+ private CopyDistributions() { }
+
+ /** Copy the distribution from the dstribution to its new location.
+ * @param ip what drives the install.
+ * @throws BuildException if badness occurs
+ */
+ public static void copyDistribution(final InstallerProperties ip) throws BuildException {
+ backupOld(ip);
+ deleteOld(ip);
+ copyDist(ip);
+ copyBinDocSystem(ip);
+ createUserFolders(ip);
+ }
+
+ /** Helper for the {@link #backupOld(InstallerProperties)} method.
+ * @param from where from
+ * @param to where to.
+ * @throws BuildException if badness occurs
+ */
+ private static void backup(final Path from, final Path to) throws BuildException {
+ LOG.debug("Backing up From {} to {}", from, to);
+ final Copy copy = InstallerSupport.getCopyTask(from, to);
+ copy.setFailOnError(false);
+ copy.execute();
+ }
+
+ /** Copy bin, edit-webapp, dist and doc to old-date-time.
+ * @param ip The configuration for this install
+ * @throws BuildException if badness occurs
+ */
+ protected static void backupOld(final InstallerProperties ip) throws BuildException {
+ final Path backup = ip.getTargetDir().resolve("Old-" + Instant.now().toString());
+ InstallerSupport.createDirectory(backup);
+ backup(ip.getTargetDir().resolve("edit-webapp"), backup.resolve("edit-webapp"));
+ backup(ip.getTargetDir().resolve("doc"), backup.resolve("doc"));
+ backup(ip.getTargetDir().resolve("system"), backup.resolve("system"));
+ }
+
+ /** Helper for the delete {@link #deleteOld(InstallerProperties)} method.
+ * @param what what to delete
+ */
+ private static void delete(final Path what) {
+ if (!Files.exists(what)) {
+ LOG.debug("{} doesn't exist, ignoring", what);
+ } else if (Files.isDirectory(what)) {
+ throw new BuildException("Corrupt install " + what + " is not a directory");
+ } else {
+ LOG.debug("Deleteing {} ", what);
+ try {
+ DeletingVisitor.deleteTree(what);
+ } catch (final IOException e) {
+ LOG.warn("Deleting {} failed", what, e);
+ }
+ }
+ }
+
+ /** Delete old copies of bin/lib (leaving bin for scripts), disty, doc and system.
+ * system has to be unprotected first which also means we need to create it too.
+ * @param ip The configuration for this install
+ * @throws BuildException if badness occurs
+ */
+ protected static void deleteOld(final InstallerProperties ip) {
+ delete(ip.getTargetDir().resolve("bin").resolve("lib"));
+ delete(ip.getTargetDir().resolve("dist"));
+ delete(ip.getTargetDir().resolve("doc"));
+ final Path system = ip.getTargetDir().resolve("system");
+ if (Files.exists(system)) {
+ LOG.debug("Clearing {} readonly (id Windows)", system);
+ InstallerSupport.setReadOnly(system, false);
+ }
+ delete(system);
+ }
+
+
+ /** Helper for the delete {@link #copyDist(InstallerProperties)} and
+ * {@link #copyBinDocSystem(InstallerProperties)} methods.
+ * @param srcDist the source distribution.
+ * @param dist the dist directory
+ * @param to the subfolder name
+ * @throws BuildException if badness occurs
+ */
+ private static void distCopy(final Path srcDist, final Path dist, final String to) throws BuildException {
+ final Path toPath = dist.resolve(to);
+ final Path fromPath = srcDist.resolve(to);
+ LOG.debug("Copying distribution from {} to {}", fromPath, toPath);
+ final Copy copy = InstallerSupport.getCopyTask(fromPath, toPath);
+ copy.execute();
+ }
+
+ /** Populate the dist folder.
+ * @param ip The configuration for this install
+ * @throws BuildException if badness occurs
+ */
+ protected static void copyDist(final InstallerProperties ip) {
+ final Path dist = ip.getTargetDir().resolve("dist");
+ InstallerSupport.createDirectory(dist);
+ final Path src = ip.getSourceDir().resolve("dist");
+ if (!Files.exists(src)) {
+ LOG.error("Source distribution {} not found", src);
+ throw new BuildException("Source distribution not found");
+ }
+ distCopy(src, dist, "conf");
+ distCopy(src, dist, "flows");
+ distCopy(src, dist, "messages");
+ distCopy(src, dist, "views");
+ distCopy(src, dist, "webapp");
+ }
+
+ /** Populate the per distribution (but non dist) folders.
+ * @param ip The configuration for this install
+ * @throws BuildException if badness occurs
+ */
+ protected static void copyBinDocSystem(final InstallerProperties ip) {
+ distCopy(ip.getSourceDir(), ip.getTargetDir(), "bin");
+ distCopy(ip.getSourceDir(), ip.getTargetDir(), "doc");
+ distCopy(ip.getSourceDir(), ip.getTargetDir(), "system");
+ }
+
+ /** Create (if they do not exist) the user editable folders, suitable for
+ * later population during update or install.
+ * @param ip The configuration for this install
+ * @throws BuildException if badness occurs
+ */
+ protected static void createUserFolders(final InstallerProperties ip) {
+ final Path target = ip.getTargetDir();
+ InstallerSupport.createDirectory(target.resolve("conf"));
+ InstallerSupport.createDirectory(target.resolve("credentials"));
+ InstallerSupport.createDirectory(target.resolve("flows"));
+ InstallerSupport.createDirectory(target.resolve("logs"));
+ InstallerSupport.createDirectory(target.resolve("messages"));
+ InstallerSupport.createDirectory(target.resolve("metadata"));
+ InstallerSupport.createDirectory(target.resolve("views"));
+ InstallerSupport.createDirectory(target.resolve("war"));
+ }
+}
diff --git a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/InstallerSupport.java b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/InstallerSupport.java
index 6edfd8e..e8bb479 100644
--- a/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/InstallerSupport.java
+++ b/idp-installer/src/main/java/net/shibboleth/idp/installer/impl/InstallerSupport.java
@@ -17,31 +17,57 @@
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.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Copy;
+import org.apache.tools.ant.taskdefs.optional.windows.Attrib;
import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.selectors.PresentSelector;
+import org.apache.tools.ant.types.selectors.PresentSelector.FilePresence;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/** General common names and helper functions for the installer. */
public final class InstallerSupport {
+ /** Log. */
+ public static final Logger LOG = LoggerFactory.getLogger(InstallerSupport.class);
+
/** The name of the file and the property with the current V4 installation value.*/
public static final String VERSION_NAME = "idp.installed.version";
-
+
/** A psuedo ant-project as parent. */
public static final Project ANT_PROJECT = new Project();
/** Private Constructor. */
private InstallerSupport() {}
-
+
+ /** Method to create a directory and log same.
+ * @param dir what to create
+ * @throws BuildException if bad ness occurs
+ */
+ protected static void createDirectory(final Path dir) throws BuildException{
+ if (!Files.exists(dir)) {
+ try {
+ Files.createDirectory(dir);
+ LOG.debug("Created directory {}", dir);
+ } catch (final IOException e) {
+ LOG.error("Could no create {}", dir, e);
+ throw new BuildException(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
+ * @return a partially populated {@link Copy} task
*/
protected static Copy getCopyTask(final Path from, final Path to) {
final Copy result = new Copy();
@@ -53,4 +79,52 @@ public final class InstallerSupport {
return result;
}
+ /** Populate a with all the missing files.
+ * @param from where to go from
+ * @param to where to go to
+ * @throws BuildException
+ * Based on (for instance the following ant<code>
+ <!-- flows: copy from dist if not already present -->
+ <mkdir dir="${idp.target.dir}/flows" />
+ <copy todir="${idp.target.dir}/flows">
+ <fileset dir="${idp.target.dir}/dist/flows" includes="**\/*">
+ <present present="srconly" targetdir="${idp.target.dir}/flows" />
+ </fileset >
+ </copy>
+ </code>
+ *
+ */
+ protected static void copyDirIfNotPresent(final Path from, final Path to) throws BuildException {
+ createDirectory(to);
+ final Copy copy = new Copy();
+ copy.setTodir(to.toFile());
+ final FileSet fromSet = new FileSet();
+ fromSet.setDir(from.toFile());
+ fromSet.setIncludes("**/**");
+ final PresentSelector present = new PresentSelector();
+ present.setPresent((FilePresence) FilePresence.getInstance(FilePresence.class, "srconly"));
+ present.setTargetdir(from.toFile());
+ fromSet.addPresent(present);
+ copy.addFileset(fromSet);
+ copy.setProject(ANT_PROJECT);
+ copy.execute();
+ LOG.debug("Copied not-previously existing files from {} to {}", from, to);
+
+ }
+
+ /** On Windows sets the readOnly attribute recursively.
+ * @param directory where
+ * @param readOnly what to set it as
+ */
+ protected static void setReadOnly(final Path directory, final boolean readOnly) {
+ final Attrib attrib = new Attrib();
+ attrib.setReadonly(readOnly);
+ final FileSet where = new FileSet();
+ where.setDir(directory.toFile());
+ where.setIncludes("**/**");
+ attrib.addFileset(where);
+ attrib.setProject(ANT_PROJECT);
+ attrib.execute();
+ }
+
}
diff --git a/idp-installer/src/main/resources/logback.xml b/idp-installer/src/main/resources/logback.xml
new file mode 100644
index 0000000..f52d4cc
--- /dev/null
+++ b/idp-installer/src/main/resources/logback.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Logging for the installer. Pin to Debug for now -->
+<configuration>
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+ <pattern>%level [%logger:%line] - %msg%n</pattern>
+ <charset>UTF-8</charset>
+ </encoder>
+ </appender>
+
+ <root>
+ <level value="DEBUG" />
+ <appender-ref ref="STDOUT" />
+ </root>
+
+</configuration>
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list