From: Mathieu Baudier Date: Mon, 5 Feb 2018 10:05:24 +0000 (+0100) Subject: Introduce org.argeo.maintenance X-Git-Tag: argeo-commons-2.1.71~17 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;h=2980adcfb0c8778426cd0f2176b86ba00e9697ab;p=lgpl%2Fargeo-commons.git Introduce org.argeo.maintenance Slim down CMS dependencies --- diff --git a/org.argeo.cms/bnd.bnd b/org.argeo.cms/bnd.bnd index 9d4c3bb50..3061a0e51 100644 --- a/org.argeo.cms/bnd.bnd +++ b/org.argeo.cms/bnd.bnd @@ -5,9 +5,10 @@ org.h2;resolution:=optional,\ org.postgresql;resolution:=optional,\ org.apache.jackrabbit.webdav.server,\ org.apache.jackrabbit.webdav.jcr,\ -org.eclipse.equinox.http.jetty,\ -org.springframework.context,\ -org.springframework.core.io,\ +org.springframework.context;resolution:=optional,\ +org.springframework.core.io;resolution:=optional,\ +org.springframework.*;resolution:=optional,\ +org.eclipse.gemini.blueprint.*;resolution:=optional\ org.apache.commons.httpclient.cookie;resolution:=optional,\ org.osgi.*;version=0.0.0,\ * diff --git a/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java index d2f0fe738..ccd02b5b2 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java @@ -2,6 +2,7 @@ package org.argeo.cms.auth; import java.io.IOException; import java.security.cert.X509Certificate; +import java.util.Base64; import java.util.Collection; import java.util.Map; import java.util.StringTokenizer; @@ -16,7 +17,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; @@ -154,7 +154,8 @@ public class HttpSessionLoginModule implements LoginModule { if (basic.equalsIgnoreCase("Basic")) { try { // TODO manipulate char[] - String credentials = new String(Base64.decodeBase64(st.nextToken()), "UTF-8"); + Base64.Decoder decoder = Base64.getDecoder(); + String credentials = new String(decoder.decode(st.nextToken()), "UTF-8"); // log.debug("Credentials: " + credentials); int p = credentials.indexOf(":"); if (p != -1) { @@ -170,7 +171,8 @@ public class HttpSessionLoginModule implements LoginModule { } } else if (basic.equalsIgnoreCase("Negotiate")) { String spnegoToken = st.nextToken(); - byte[] authToken = Base64.decodeBase64(spnegoToken); + Base64.Decoder decoder = Base64.getDecoder(); + byte[] authToken = decoder.decode(spnegoToken); sharedState.put(CmsAuthUtils.SHARED_STATE_SPNEGO_TOKEN, authToken); } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/backup/AbstractAtomicBackup.java b/org.argeo.cms/src/org/argeo/cms/internal/backup/AbstractAtomicBackup.java deleted file mode 100644 index d8824ba4e..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/backup/AbstractAtomicBackup.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.argeo.cms.internal.backup; - -import org.apache.commons.vfs2.FileObject; -import org.apache.commons.vfs2.FileSystemManager; -import org.apache.commons.vfs2.FileSystemOptions; -import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder; -import org.argeo.cms.CmsException; - -/** - * Simplify atomic backups implementation, especially by managing VFS. - */ -public abstract class AbstractAtomicBackup implements AtomicBackup { - private String name; - private String compression = "bz2"; - - protected abstract void writeBackup(FileObject targetFo); - - public AbstractAtomicBackup() { - } - - public AbstractAtomicBackup(String name) { - this.name = name; - } - - public void init() { - if (name == null) - throw new CmsException("Atomic backup name must be set"); - } - - public void destroy() { - - } - - @Override - public String backup(FileSystemManager fileSystemManager, - String backupsBase, BackupContext backupContext, - FileSystemOptions opts) { - if (name == null) - throw new CmsException("Atomic backup name must be set"); - - FileObject targetFo = null; - try { - if (backupsBase.startsWith("sftp:")) - SftpFileSystemConfigBuilder.getInstance() - .setStrictHostKeyChecking(opts, "no"); - if (compression == null || compression.equals("none")) - targetFo = fileSystemManager.resolveFile(backupsBase + '/' - + backupContext.getRelativeFolder() + '/' + name, opts); - else if (compression.equals("bz2")) - targetFo = fileSystemManager.resolveFile("bz2:" + backupsBase - + '/' + backupContext.getRelativeFolder() + '/' + name - + ".bz2" + "!" + name, opts); - else if (compression.equals("gz")) - targetFo = fileSystemManager.resolveFile("gz:" + backupsBase - + '/' + backupContext.getRelativeFolder() + '/' + name - + ".gz" + "!" + name, opts); - else - throw new CmsException("Unsupported compression " - + compression); - - writeBackup(targetFo); - - return targetFo.toString(); - } catch (Exception e) { - throw new CmsException("Cannot backup " + name + " to " - + targetFo, e); - } finally { - BackupUtils.closeFOQuietly(targetFo); - } - } - - public void setName(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setCompression(String compression) { - this.compression = compression; - } -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/backup/AtomicBackup.java b/org.argeo.cms/src/org/argeo/cms/internal/backup/AtomicBackup.java deleted file mode 100644 index e14344c8f..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/backup/AtomicBackup.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.argeo.cms.internal.backup; - -import org.apache.commons.vfs2.FileSystemManager; -import org.apache.commons.vfs2.FileSystemOptions; - -/** Performs the backup of a single component, typically a database dump */ -public interface AtomicBackup { - /** Name identifiying this backup */ - public String getName(); - - /** - * Retrieves the data of the component in a format that allows to restore - * the component - * - * @param backupContext - * the context of this backup - * @return the VFS URI of the generated file or directory - */ - public String backup(FileSystemManager fileSystemManager, - String backupsBase, BackupContext backupContext, - FileSystemOptions opts); -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/backup/BackupContext.java b/org.argeo.cms/src/org/argeo/cms/internal/backup/BackupContext.java deleted file mode 100644 index 14e7eb41a..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/backup/BackupContext.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.argeo.cms.internal.backup; - -import java.text.DateFormat; -import java.util.Date; - -/** - * Transient information of a given backup, centralizing common information such - * as timestamp and location. - */ -public interface BackupContext { - /** Backup date */ - public Date getTimestamp(); - - /** Formatted backup date */ - public String getTimestampAsString(); - - /** System name */ - public String getSystemName(); - - /** Local base */ - public String getRelativeFolder(); - - /** Date format */ - public DateFormat getDateFormat(); -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/backup/BackupFileSystemManager.java b/org.argeo.cms/src/org/argeo/cms/internal/backup/BackupFileSystemManager.java deleted file mode 100644 index d8d626ad5..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/backup/BackupFileSystemManager.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.argeo.cms.internal.backup; - -import org.apache.commons.vfs2.FileSystemException; -import org.apache.commons.vfs2.impl.DefaultFileSystemManager; -import org.apache.commons.vfs2.provider.bzip2.Bzip2FileProvider; -import org.apache.commons.vfs2.provider.ftp.FtpFileProvider; -import org.apache.commons.vfs2.provider.gzip.GzipFileProvider; -import org.apache.commons.vfs2.provider.local.DefaultLocalFileProvider; -import org.apache.commons.vfs2.provider.ram.RamFileProvider; -import org.apache.commons.vfs2.provider.sftp.SftpFileProvider; -import org.apache.commons.vfs2.provider.url.UrlFileProvider; -import org.argeo.cms.CmsException; - -/** - * Programatically configured VFS file system manager which can be declared as a - * bean and associated with a life cycle (methods - * {@link DefaultFileSystemManager#init()} and - * {@link DefaultFileSystemManager#close()}). Supports bz2, file, ram, gzip, - * ftp, sftp - */ -public class BackupFileSystemManager extends DefaultFileSystemManager { - - public BackupFileSystemManager() { - super(); - try { - addProvider("file", new DefaultLocalFileProvider()); - addProvider("bz2", new Bzip2FileProvider()); - addProvider("ftp", new FtpFileProvider()); - addProvider("sftp", new SftpFileProvider()); - addProvider("gzip", new GzipFileProvider()); - addProvider("ram", new RamFileProvider()); - setDefaultProvider(new UrlFileProvider()); - } catch (FileSystemException e) { - throw new CmsException("Cannot configure backup file provider", e); - } - } -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/backup/BackupPurge.java b/org.argeo.cms/src/org/argeo/cms/internal/backup/BackupPurge.java deleted file mode 100644 index 75a6b164b..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/backup/BackupPurge.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.argeo.cms.internal.backup; - -import java.text.DateFormat; - -import org.apache.commons.vfs2.FileSystemManager; -import org.apache.commons.vfs2.FileSystemOptions; - -/** Purges previous backups */ -public interface BackupPurge { - /** - * Purge the backups identified by these arguments. Although these are the - * same fields as a {@link BackupContext} we don't pass it as argument since - * we want to use this interface to purge remote backups as well (that is, - * with a different base), or outside the scope of a running backup. - */ - public void purge(FileSystemManager fileSystemManager, String base, - String name, DateFormat dateFormat, FileSystemOptions opts); -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/backup/BackupUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/backup/BackupUtils.java deleted file mode 100644 index 9a4e91c1f..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/backup/BackupUtils.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.argeo.cms.internal.backup; - -import org.apache.commons.vfs2.FileObject; - -/** Backup utilities */ -public class BackupUtils { - /** Close a file object quietly even if it is null or throws an exception. */ - public static void closeFOQuietly(FileObject fo) { - if (fo != null) { - try { - fo.close(); - } catch (Exception e) { - // silent - } - } - } - - /** Prevents instantiation */ - private BackupUtils() { - } -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/backup/MySqlBackup.java b/org.argeo.cms/src/org/argeo/cms/internal/backup/MySqlBackup.java deleted file mode 100644 index 765c56495..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/backup/MySqlBackup.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.argeo.cms.internal.backup; - -import org.apache.commons.vfs2.FileObject; - -/** Backups a MySQL database using mysqldump. */ -public class MySqlBackup extends OsCallBackup { - private String mysqldumpLocation = "/usr/bin/mysqldump"; - - private String dbUser; - private String dbPassword; - private String dbName; - - public MySqlBackup() { - } - - public MySqlBackup(String dbUser, String dbPassword, String dbName) { - this.dbUser = dbUser; - this.dbPassword = dbPassword; - this.dbName = dbName; - init(); - } - - @Override - public void init() { - if (getName() == null) - setName(dbName + ".mysql"); - super.init(); - } - - @Override - public void writeBackup(FileObject targetFo) { - if (getCommand() == null) - setCommand(mysqldumpLocation - + " --lock-tables --add-locks --add-drop-table" - + " -u ${dbUser} --password=${dbPassword} --databases ${dbName}"); - getVariables().put("dbUser", dbUser); - getVariables().put("dbPassword", dbPassword); - getVariables().put("dbName", dbName); - - super.writeBackup(targetFo); - } - - public void setDbUser(String dbUser) { - this.dbUser = dbUser; - } - - public void setDbPassword(String dbPassword) { - this.dbPassword = dbPassword; - } - - public void setDbName(String dbName) { - this.dbName = dbName; - } - - public void setMysqldumpLocation(String mysqldumpLocation) { - this.mysqldumpLocation = mysqldumpLocation; - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/backup/OpenLdapBackup.java b/org.argeo.cms/src/org/argeo/cms/internal/backup/OpenLdapBackup.java deleted file mode 100644 index 96c2f3a77..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/backup/OpenLdapBackup.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.argeo.cms.internal.backup; - -import org.apache.commons.vfs2.FileObject; -import org.argeo.cms.CmsException; - -/** Backups an OpenLDAP server using slapcat */ -public class OpenLdapBackup extends OsCallBackup { - private String slapcatLocation = "/usr/sbin/slapcat"; - private String slapdConfLocation = "/etc/openldap/slapd.conf"; - private String baseDn; - - public OpenLdapBackup() { - super(); - } - - public OpenLdapBackup(String baseDn) { - super(); - this.baseDn = baseDn; - } - - @Override - public void writeBackup(FileObject targetFo) { - if (baseDn == null) - throw new CmsException("Base DN must be set"); - - if (getCommand() == null) - setCommand(slapcatLocation - + " -f ${slapdConfLocation} -b '${baseDn}'"); - getVariables().put("slapdConfLocation", slapdConfLocation); - getVariables().put("baseDn", baseDn); - - super.writeBackup(targetFo); - } - - public void setSlapcatLocation(String slapcatLocation) { - this.slapcatLocation = slapcatLocation; - } - - public void setSlapdConfLocation(String slapdConfLocation) { - this.slapdConfLocation = slapdConfLocation; - } - - public void setBaseDn(String baseDn) { - this.baseDn = baseDn; - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/backup/OsCallBackup.java b/org.argeo.cms/src/org/argeo/cms/internal/backup/OsCallBackup.java deleted file mode 100644 index ad8ffe861..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/backup/OsCallBackup.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.argeo.cms.internal.backup; - -import java.io.ByteArrayOutputStream; -import java.util.HashMap; -import java.util.Map; - -import org.apache.commons.exec.CommandLine; -import org.apache.commons.exec.DefaultExecutor; -import org.apache.commons.exec.ExecuteException; -import org.apache.commons.exec.ExecuteStreamHandler; -import org.apache.commons.exec.Executor; -import org.apache.commons.exec.PumpStreamHandler; -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.vfs2.FileContent; -import org.apache.commons.vfs2.FileObject; -import org.argeo.cms.CmsException; - -/** - * Runs an OS command and save its standard output as a file. Typically used for - * MySQL or OpenLDAP dumps. - */ -public class OsCallBackup extends AbstractAtomicBackup { - private final static Log log = LogFactory.getLog(OsCallBackup.class); - - private String command; - private Map variables = new HashMap(); - private Executor executor = new DefaultExecutor(); - - private Map environment = new HashMap(); - - /** Name of the sudo user, root if "", not sudo if null */ - private String sudo = null; - - public OsCallBackup() { - } - - public OsCallBackup(String name) { - super(name); - } - - public OsCallBackup(String name, String command) { - super(name); - this.command = command; - } - - @Override - public void writeBackup(FileObject targetFo) { - String commandToUse = command; - - // sudo - if (sudo != null) { - if (sudo.equals("")) - commandToUse = "sudo " + commandToUse; - else - commandToUse = "sudo -u " + sudo + " " + commandToUse; - } - - CommandLine commandLine = CommandLine.parse(commandToUse, variables); - ByteArrayOutputStream errBos = new ByteArrayOutputStream(); - if (log.isTraceEnabled()) - log.trace(commandLine.toString()); - - try { - // stdout - FileContent targetContent = targetFo.getContent(); - // stderr - ExecuteStreamHandler streamHandler = new PumpStreamHandler(targetContent.getOutputStream(), errBos); - executor.setStreamHandler(streamHandler); - executor.execute(commandLine, environment); - } catch (ExecuteException e) { - byte[] err = errBos.toByteArray(); - String errStr = new String(err); - throw new CmsException("Process " + commandLine + " failed (" + e.getExitValue() + "): " + errStr, e); - } catch (Exception e) { - byte[] err = errBos.toByteArray(); - String errStr = new String(err); - throw new CmsException("Process " + commandLine + " failed: " + errStr, e); - } finally { - IOUtils.closeQuietly(errBos); - } - } - - public void setCommand(String command) { - this.command = command; - } - - protected String getCommand() { - return command; - } - - /** - * A reference to the environment variables that will be passed to the - * process. Empty by default. - */ - protected Map getEnvironment() { - return environment; - } - - protected Map getVariables() { - return variables; - } - - public void setVariables(Map variables) { - this.variables = variables; - } - - public void setExecutor(Executor executor) { - this.executor = executor; - } - - public void setSudo(String sudo) { - this.sudo = sudo; - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/backup/PostgreSqlBackup.java b/org.argeo.cms/src/org/argeo/cms/internal/backup/PostgreSqlBackup.java deleted file mode 100644 index dbc3624fb..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/backup/PostgreSqlBackup.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.argeo.cms.internal.backup; - -import org.apache.commons.vfs2.FileObject; - -/** Backups a PostgreSQL database using pg_dump. */ -public class PostgreSqlBackup extends OsCallBackup { - /** - * PostgreSQL password environment variable (see - * http://stackoverflow.com/questions - * /2893954/how-to-pass-in-password-to-pg-dump) - */ - protected final static String PGPASSWORD = "PGPASSWORD"; - - private String pgDumpLocation = "/usr/bin/pg_dump"; - - private String dbUser; - private String dbPassword; - private String dbName; - - public PostgreSqlBackup() { - super(); - } - - public PostgreSqlBackup(String dbUser, String dbPassword, String dbName) { - this.dbUser = dbUser; - this.dbPassword = dbPassword; - this.dbName = dbName; - init(); - } - - @Override - public void init() { - // disable compression since pg_dump is used with -Fc option - setCompression(null); - - if (getName() == null) - setName(dbName + ".pgdump"); - super.init(); - } - - @Override - public void writeBackup(FileObject targetFo) { - if (getCommand() == null) { - getEnvironment().put(PGPASSWORD, dbPassword); - setCommand(pgDumpLocation + " -Fc" + " -U ${dbUser} ${dbName}"); - } - getVariables().put("dbUser", dbUser); - getVariables().put("dbPassword", dbPassword); - getVariables().put("dbName", dbName); - - super.writeBackup(targetFo); - } - - public void setDbUser(String dbUser) { - this.dbUser = dbUser; - } - - public void setDbPassword(String dbPassword) { - this.dbPassword = dbPassword; - } - - public void setDbName(String dbName) { - this.dbName = dbName; - } - - public void setPgDumpLocation(String mysqldumpLocation) { - this.pgDumpLocation = mysqldumpLocation; - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/backup/SimpleBackupContext.java b/org.argeo.cms/src/org/argeo/cms/internal/backup/SimpleBackupContext.java deleted file mode 100644 index 8e9e418f0..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/backup/SimpleBackupContext.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.argeo.cms.internal.backup; - -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.apache.commons.vfs2.FileSystemManager; - -/** Simple implementation of a backup context */ -public class SimpleBackupContext implements BackupContext { - private DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmm"); - private final Date timestamp; - private final String name; - - private final FileSystemManager fileSystemManager; - - public SimpleBackupContext(FileSystemManager fileSystemManager, - String backupsBase, String name) { - this.name = name; - this.timestamp = new Date(); - this.fileSystemManager = fileSystemManager; - } - - public Date getTimestamp() { - return timestamp; - } - - public String getTimestampAsString() { - return dateFormat.format(timestamp); - } - - public String getSystemName() { - return name; - } - - public String getRelativeFolder() { - return name + '/' + getTimestampAsString(); - } - - public DateFormat getDateFormat() { - return dateFormat; - } - - public FileSystemManager getFileSystemManager() { - return fileSystemManager; - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/backup/SimpleBackupPurge.java b/org.argeo.cms/src/org/argeo/cms/internal/backup/SimpleBackupPurge.java deleted file mode 100644 index 33b5b5ebe..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/backup/SimpleBackupPurge.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.argeo.cms.internal.backup; - -import java.text.DateFormat; -import java.time.Period; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.util.Date; -import java.util.SortedMap; -import java.util.TreeMap; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.vfs2.FileObject; -import org.apache.commons.vfs2.FileSystemManager; -import org.apache.commons.vfs2.FileSystemOptions; -import org.apache.commons.vfs2.Selectors; -import org.argeo.cms.CmsException; - -/** Simple backup purge which keeps backups only for a given number of days */ -public class SimpleBackupPurge implements BackupPurge { - private final static Log log = LogFactory.getLog(SimpleBackupPurge.class); - - private Integer daysKept = 30; - - @Override - public void purge(FileSystemManager fileSystemManager, String base, String name, DateFormat dateFormat, - FileSystemOptions opts) { - try { - ZonedDateTime nowDt = ZonedDateTime.now(); - FileObject baseFo = fileSystemManager.resolveFile(base + '/' + name, opts); - - SortedMap toDelete = new TreeMap(); - int backupCount = 0; - - // make sure base dir exists - baseFo.createFolder(); - - // scan backups and list those which should be deleted - for (FileObject backupFo : baseFo.getChildren()) { - String backupName = backupFo.getName().getBaseName(); - Date backupDate = dateFormat.parse(backupName); - backupCount++; - ZonedDateTime backupDt = ZonedDateTime.ofInstant(backupDate.toInstant(), ZoneId.systemDefault()); - Period sinceThen = Period.between(backupDt.toLocalDate(), nowDt.toLocalDate()); - // new Period(backupDt, nowDt); - int days = sinceThen.getDays(); - // int days = sinceThen.getMinutes(); - if (days > daysKept) { - toDelete.put(backupDt, backupFo); - } - } - - if (toDelete.size() != 0 && toDelete.size() == backupCount) { - // all backups would be deleted - // but we want to keep at least one - ZonedDateTime lastBackupDt = toDelete.firstKey(); - FileObject keptFo = toDelete.remove(lastBackupDt); - log.warn("Backup " + keptFo + " kept although it is older than " + daysKept + " days."); - } - - // delete old backups - for (FileObject backupFo : toDelete.values()) { - backupFo.delete(Selectors.SELECT_ALL); - if (log.isDebugEnabled()) - log.debug("Deleted backup " + backupFo); - } - } catch (Exception e) { - throw new CmsException("Could not purge previous backups", e); - } - - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/backup/SvnBackup.java b/org.argeo.cms/src/org/argeo/cms/internal/backup/SvnBackup.java deleted file mode 100644 index 7367c04c6..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/backup/SvnBackup.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.argeo.cms.internal.backup; - -import java.io.File; - -import org.apache.commons.vfs2.FileObject; - -/** Backups a Subversion repository using svnadmin. */ -public class SvnBackup extends OsCallBackup { - private String svnadminLocation = "/usr/bin/svnadmin"; - - private String repoLocation; - private String repoName; - - public SvnBackup() { - } - - public SvnBackup(String repoLocation) { - this.repoLocation = repoLocation; - init(); - } - - @Override - public void init() { - // use directory as repo name - if (repoName == null) - repoName = new File(repoLocation).getName(); - - if (getName() == null) - setName(repoName + ".svndump"); - super.init(); - } - - @Override - public void writeBackup(FileObject targetFo) { - if (getCommand() == null) { - setCommand(svnadminLocation + " dump " + " ${repoLocation}"); - } - getVariables().put("repoLocation", repoLocation); - - super.writeBackup(targetFo); - } - - public void setRepoLocation(String repoLocation) { - this.repoLocation = repoLocation; - } - - public void setRepoName(String repoName) { - this.repoName = repoName; - } - - public void setSvnadminLocation(String mysqldumpLocation) { - this.svnadminLocation = mysqldumpLocation; - } - -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/backup/SystemBackup.java b/org.argeo.cms/src/org/argeo/cms/internal/backup/SystemBackup.java deleted file mode 100644 index 36d3e0b2d..000000000 --- a/org.argeo.cms/src/org/argeo/cms/internal/backup/SystemBackup.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2007-2012 Argeo GmbH - * - * 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.argeo.cms.internal.backup; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.vfs2.FileObject; -import org.apache.commons.vfs2.FileSystemException; -import org.apache.commons.vfs2.FileSystemManager; -import org.apache.commons.vfs2.FileSystemOptions; -import org.apache.commons.vfs2.Selectors; -import org.apache.commons.vfs2.UserAuthenticator; -import org.apache.commons.vfs2.impl.DefaultFileSystemConfigBuilder; -import org.argeo.cms.CmsException; -import org.argeo.util.LangUtils; - -/** - * Combines multiple backups and transfer them to a remote location. Purges - * remote and local data based on certain criteria. - */ -public class SystemBackup implements Runnable { - private final static Log log = LogFactory.getLog(SystemBackup.class); - - private FileSystemManager fileSystemManager; - private UserAuthenticator userAuthenticator = null; - - private String backupsBase; - private String systemName; - - private List atomicBackups = new ArrayList(); - private BackupPurge backupPurge = new SimpleBackupPurge(); - - private Map remoteBases = new HashMap(); - - @Override - public void run() { - if (atomicBackups.size() == 0) - throw new CmsException("No atomic backup listed"); - List failures = new ArrayList(); - - SimpleBackupContext backupContext = new SimpleBackupContext(fileSystemManager, backupsBase, systemName); - - // purge older backups - FileSystemOptions opts = new FileSystemOptions(); - try { - DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, userAuthenticator); - } catch (FileSystemException e) { - throw new CmsException("Cannot create authentication", e); - } - - try { - - backupPurge.purge(fileSystemManager, backupsBase, systemName, backupContext.getDateFormat(), opts); - } catch (Exception e) { - failures.add("Purge " + backupsBase + " failed: " + e.getMessage()); - log.error("Purge of " + backupsBase + " failed", e); - } - - // perform backup - for (AtomicBackup atomickBackup : atomicBackups) { - try { - String target = atomickBackup.backup(fileSystemManager, backupsBase, backupContext, opts); - if (log.isDebugEnabled()) - log.debug("Performed backup " + target); - } catch (Exception e) { - String msg = "Atomic backup " + atomickBackup.getName() + " failed: " - + LangUtils.chainCausesMessages(e); - failures.add(msg); - log.error(msg); - if (log.isTraceEnabled()) - log.trace("Stacktrace of atomic backup " + atomickBackup.getName() + " failure.", e); - } - } - - // dispatch to remote - for (String remoteBase : remoteBases.keySet()) { - FileObject localBaseFo = null; - FileObject remoteBaseFo = null; - UserAuthenticator auth = remoteBases.get(remoteBase); - - // authentication - FileSystemOptions remoteOpts = new FileSystemOptions(); - try { - DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(remoteOpts, auth); - backupPurge.purge(fileSystemManager, remoteBase, systemName, backupContext.getDateFormat(), remoteOpts); - } catch (Exception e) { - failures.add("Purge " + remoteBase + " failed: " + e.getMessage()); - log.error("Cannot purge " + remoteBase, e); - } - - try { - localBaseFo = fileSystemManager.resolveFile(backupsBase + '/' + backupContext.getRelativeFolder(), - opts); - remoteBaseFo = fileSystemManager.resolveFile(remoteBase + '/' + backupContext.getRelativeFolder(), - remoteOpts); - remoteBaseFo.copyFrom(localBaseFo, Selectors.SELECT_ALL); - if (log.isDebugEnabled()) - log.debug("Copied backup to " + remoteBaseFo + " from " + localBaseFo); - // } - } catch (Exception e) { - failures.add("Dispatch to " + remoteBase + " failed: " + e.getMessage()); - log.error("Cannot dispatch backups from " + backupContext.getRelativeFolder() + " to " + remoteBase, e); - } - BackupUtils.closeFOQuietly(localBaseFo); - BackupUtils.closeFOQuietly(remoteBaseFo); - } - - int failureCount = 0; - if (failures.size() > 0) { - StringBuffer buf = new StringBuffer(); - for (String failure : failures) { - buf.append('\n').append(failureCount).append(" - ").append(failure); - failureCount++; - } - throw new CmsException(failureCount + " error(s) when running the backup," - + " check the logs and the backups as soon as possible." + buf); - } - } - - public void setFileSystemManager(FileSystemManager fileSystemManager) { - this.fileSystemManager = fileSystemManager; - } - - public void setBackupsBase(String backupsBase) { - this.backupsBase = backupsBase; - } - - public void setSystemName(String name) { - this.systemName = name; - } - - public void setAtomicBackups(List atomicBackups) { - this.atomicBackups = atomicBackups; - } - - public void setBackupPurge(BackupPurge backupPurge) { - this.backupPurge = backupPurge; - } - - public void setUserAuthenticator(UserAuthenticator userAuthenticator) { - this.userAuthenticator = userAuthenticator; - } - - public void setRemoteBases(Map remoteBases) { - this.remoteBases = remoteBases; - } - - // public static void main(String args[]) { - // while (true) { - // try { - // StandardFileSystemManager fsm = new StandardFileSystemManager(); - // fsm.init(); - // - // SystemBackup systemBackup = new SystemBackup(); - // systemBackup.setSystemName("mySystem"); - // systemBackup - // .setBackupsBase("/home/mbaudier/dev/src/commons/server/runtime/org.argeo.server.core/target"); - // systemBackup.setFileSystemManager(fsm); - // - // List atomicBackups = new ArrayList(); - // - // MySqlBackup mySqlBackup = new MySqlBackup("root", "", "test"); - // atomicBackups.add(mySqlBackup); - // PostgreSqlBackup postgreSqlBackup = new PostgreSqlBackup( - // "argeo", "argeo", "gis_template"); - // atomicBackups.add(postgreSqlBackup); - // SvnBackup svnBackup = new SvnBackup( - // "/home/mbaudier/tmp/testsvnrepo"); - // atomicBackups.add(svnBackup); - // - // systemBackup.setAtomicBackups(atomicBackups); - // - // Map remoteBases = new HashMap(); - // StaticUserAuthenticator userAuthenticator = new StaticUserAuthenticator( - // null, "demo", "demo"); - // remoteBases.put("sftp://localhost/home/mbaudier/test", - // userAuthenticator); - // systemBackup.setRemoteBases(remoteBases); - // - // systemBackup.run(); - // - // fsm.close(); - // } catch (FileSystemException e) { - // // TODO Auto-generated catch block - // e.printStackTrace(); - // System.exit(1); - // } - // - // // wait - // try { - // Thread.sleep(120 * 1000); - // } catch (InterruptedException e) { - // e.printStackTrace(); - // } - // } - // } -} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/http/HttpConstants.java b/org.argeo.cms/src/org/argeo/cms/internal/http/HttpConstants.java new file mode 100644 index 000000000..5fe57b7c2 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/http/HttpConstants.java @@ -0,0 +1,21 @@ +package org.argeo.cms.internal.http; + +/** Compatible with Jetty. */ +public interface HttpConstants { + public static final String HTTP_ENABLED = "http.enabled"; + public static final String HTTP_PORT = "http.port"; + public static final String HTTP_HOST = "http.host"; + public static final String HTTPS_ENABLED = "https.enabled"; + public static final String HTTPS_HOST = "https.host"; + public static final String HTTPS_PORT = "https.port"; + public static final String SSL_KEYSTORE = "ssl.keystore"; + public static final String SSL_PASSWORD = "ssl.password"; + public static final String SSL_KEYPASSWORD = "ssl.keypassword"; + public static final String SSL_NEEDCLIENTAUTH = "ssl.needclientauth"; + public static final String SSL_WANTCLIENTAUTH = "ssl.wantclientauth"; + public static final String SSL_PROTOCOL = "ssl.protocol"; + public static final String SSL_ALGORITHM = "ssl.algorithm"; + public static final String SSL_KEYSTORETYPE = "ssl.keystoretype"; + public static final String JETTY_PROPERTY_PREFIX = "org.eclipse.equinox.http.jetty."; + +} diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/FirstInit.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/FirstInit.java index 6175e4d03..98c2483cc 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/FirstInit.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/FirstInit.java @@ -22,10 +22,10 @@ import org.apache.commons.io.FileUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.cms.CmsException; +import org.argeo.cms.internal.http.HttpConstants; import org.argeo.cms.internal.jcr.RepoConf; import org.argeo.node.NodeConstants; import org.argeo.osgi.useradmin.UserAdminConf; -import org.eclipse.equinox.http.jetty.JettyConstants; /** * Interprets framework properties in order to generate the initial deploy @@ -56,35 +56,35 @@ class FirstInit { String httpPort = getFrameworkProp("org.osgi.service.http.port"); String httpsPort = getFrameworkProp("org.osgi.service.http.port.secure"); /// TODO make it more generic - String httpHost = getFrameworkProp(JettyConstants.PROPERTY_PREFIX + JettyConstants.HTTP_HOST); - String httpsHost = getFrameworkProp(JettyConstants.PROPERTY_PREFIX + JettyConstants.HTTPS_HOST); + String httpHost = getFrameworkProp(HttpConstants.JETTY_PROPERTY_PREFIX + HttpConstants.HTTP_HOST); + String httpsHost = getFrameworkProp(HttpConstants.JETTY_PROPERTY_PREFIX + HttpConstants.HTTPS_HOST); final Hashtable props = new Hashtable(); // try { if (httpPort != null || httpsPort != null) { if (httpPort != null) { - props.put(JettyConstants.HTTP_PORT, httpPort); - props.put(JettyConstants.HTTP_ENABLED, true); + props.put(HttpConstants.HTTP_PORT, httpPort); + props.put(HttpConstants.HTTP_ENABLED, true); } if (httpsPort != null) { - props.put(JettyConstants.HTTPS_PORT, httpsPort); - props.put(JettyConstants.HTTPS_ENABLED, true); + props.put(HttpConstants.HTTPS_PORT, httpsPort); + props.put(HttpConstants.HTTPS_ENABLED, true); Path keyStorePath = KernelUtils.getOsgiInstancePath(KernelConstants.DEFAULT_KEYSTORE_PATH); String keyStorePassword = getFrameworkProp( - JettyConstants.PROPERTY_PREFIX + JettyConstants.SSL_PASSWORD); + HttpConstants.JETTY_PROPERTY_PREFIX + HttpConstants.SSL_PASSWORD); if (keyStorePassword == null) keyStorePassword = "changeit"; if (!Files.exists(keyStorePath)) createSelfSignedKeyStore(keyStorePath, keyStorePassword); - props.put(JettyConstants.SSL_KEYSTORETYPE, "PKCS12"); - props.put(JettyConstants.SSL_KEYSTORE, keyStorePath.toString()); - props.put(JettyConstants.SSL_PASSWORD, keyStorePassword); - props.put(JettyConstants.SSL_WANTCLIENTAUTH, true); + props.put(HttpConstants.SSL_KEYSTORETYPE, "PKCS12"); + props.put(HttpConstants.SSL_KEYSTORE, keyStorePath.toString()); + props.put(HttpConstants.SSL_PASSWORD, keyStorePassword); + props.put(HttpConstants.SSL_WANTCLIENTAUTH, true); } if (httpHost != null) - props.put(JettyConstants.HTTP_HOST, httpHost); + props.put(HttpConstants.HTTP_HOST, httpHost); if (httpsHost != null) - props.put(JettyConstants.HTTPS_HOST, httpHost); + props.put(HttpConstants.HTTPS_HOST, httpHost); props.put(NodeConstants.CN, NodeConstants.DEFAULT); } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java index 45f3354b8..f8bce9cf6 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java @@ -28,6 +28,9 @@ public interface KernelConstants { String DEFAULT_USERS_BASE_PATH = "/users"; String DEFAULT_GROUPS_BASE_PATH = "/groups"; + // HTTP client + String COOKIE_POLICY_BROWSER_COMPATIBILITY = "compatibility"; + // RWT / RAP // String PATH_WORKBENCH = "/ui"; // String PATH_WORKBENCH_PUBLIC = PATH_WORKBENCH + "/public"; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java index f1132a642..236585e1b 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeUserAdmin.java @@ -29,7 +29,6 @@ import javax.transaction.TransactionManager; import org.apache.commons.httpclient.auth.AuthPolicy; import org.apache.commons.httpclient.auth.CredentialsProvider; -import org.apache.commons.httpclient.cookie.CookiePolicy; import org.apache.commons.httpclient.params.DefaultHttpParams; import org.apache.commons.httpclient.params.HttpMethodParams; import org.apache.commons.httpclient.params.HttpParams; @@ -162,14 +161,12 @@ class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactor public String getName() { return "Node User Admin"; } - - @Override protected void addAbstractSystemRoles(Authorization rawAuthorization, Set sysRoles) { - if(rawAuthorization.getName()==null) { + if (rawAuthorization.getName() == null) { sysRoles.add(NodeConstants.ROLE_ANONYMOUS); - }else { + } else { sysRoles.add(NodeConstants.ROLE_USER); } } @@ -215,7 +212,7 @@ class NodeUserAdmin extends AggregatingUserAdmin implements ManagedServiceFactor // schemes.add(AuthPolicy.BASIC);// incompatible with Basic params.setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, schemes); params.setParameter(CredentialsProvider.PROVIDER, new HttpCredentialProvider()); - params.setParameter(HttpMethodParams.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY); + params.setParameter(HttpMethodParams.COOKIE_POLICY, KernelConstants.COOKIE_POLICY_BROWSER_COMPATIBILITY); // params.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY); } } diff --git a/org.argeo.maintenance/.classpath b/org.argeo.maintenance/.classpath new file mode 100644 index 000000000..eca7bdba8 --- /dev/null +++ b/org.argeo.maintenance/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.argeo.maintenance/.gitignore b/org.argeo.maintenance/.gitignore new file mode 100644 index 000000000..09e3bc9b2 --- /dev/null +++ b/org.argeo.maintenance/.gitignore @@ -0,0 +1,2 @@ +/bin/ +/target/ diff --git a/org.argeo.maintenance/.project b/org.argeo.maintenance/.project new file mode 100644 index 000000000..d1c87c7b3 --- /dev/null +++ b/org.argeo.maintenance/.project @@ -0,0 +1,28 @@ + + + org.argeo.maintenance + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/org.argeo.maintenance/META-INF/.gitignore b/org.argeo.maintenance/META-INF/.gitignore new file mode 100644 index 000000000..4854a41b9 --- /dev/null +++ b/org.argeo.maintenance/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/org.argeo.maintenance/bnd.bnd b/org.argeo.maintenance/bnd.bnd new file mode 100644 index 000000000..e69de29bb diff --git a/org.argeo.maintenance/build.properties b/org.argeo.maintenance/build.properties new file mode 100644 index 000000000..34d2e4d2d --- /dev/null +++ b/org.argeo.maintenance/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/org.argeo.maintenance/pom.xml b/org.argeo.maintenance/pom.xml new file mode 100644 index 000000000..8c4abf3be --- /dev/null +++ b/org.argeo.maintenance/pom.xml @@ -0,0 +1,26 @@ + + + 4.0.0 + + org.argeo.commons + argeo-commons + 2.1.71-SNAPSHOT + .. + + org.argeo.maintenance + Maintenance + jar + + + org.argeo.commons + org.argeo.jcr + 2.1.71-SNAPSHOT + + + org.argeo.commons + org.argeo.enterprise + 2.1.71-SNAPSHOT + + + \ No newline at end of file diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/MaintenanceException.java b/org.argeo.maintenance/src/org/argeo/maintenance/MaintenanceException.java new file mode 100644 index 000000000..dc4243edb --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/MaintenanceException.java @@ -0,0 +1,13 @@ +package org.argeo.maintenance; + +public class MaintenanceException extends RuntimeException { + private static final long serialVersionUID = -4571088120514827735L; + + public MaintenanceException(String message) { + super(message); + } + + public MaintenanceException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/AbstractAtomicBackup.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/AbstractAtomicBackup.java new file mode 100644 index 000000000..ae587ea2d --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/AbstractAtomicBackup.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.maintenance.backup.vfs; + +import org.apache.commons.vfs2.FileObject; +import org.apache.commons.vfs2.FileSystemManager; +import org.apache.commons.vfs2.FileSystemOptions; +import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder; +import org.argeo.maintenance.MaintenanceException; + +/** + * Simplify atomic backups implementation, especially by managing VFS. + */ +public abstract class AbstractAtomicBackup implements AtomicBackup { + private String name; + private String compression = "bz2"; + + protected abstract void writeBackup(FileObject targetFo); + + public AbstractAtomicBackup() { + } + + public AbstractAtomicBackup(String name) { + this.name = name; + } + + public void init() { + if (name == null) + throw new MaintenanceException("Atomic backup name must be set"); + } + + public void destroy() { + + } + + @Override + public String backup(FileSystemManager fileSystemManager, + String backupsBase, BackupContext backupContext, + FileSystemOptions opts) { + if (name == null) + throw new MaintenanceException("Atomic backup name must be set"); + + FileObject targetFo = null; + try { + if (backupsBase.startsWith("sftp:")) + SftpFileSystemConfigBuilder.getInstance() + .setStrictHostKeyChecking(opts, "no"); + if (compression == null || compression.equals("none")) + targetFo = fileSystemManager.resolveFile(backupsBase + '/' + + backupContext.getRelativeFolder() + '/' + name, opts); + else if (compression.equals("bz2")) + targetFo = fileSystemManager.resolveFile("bz2:" + backupsBase + + '/' + backupContext.getRelativeFolder() + '/' + name + + ".bz2" + "!" + name, opts); + else if (compression.equals("gz")) + targetFo = fileSystemManager.resolveFile("gz:" + backupsBase + + '/' + backupContext.getRelativeFolder() + '/' + name + + ".gz" + "!" + name, opts); + else + throw new MaintenanceException("Unsupported compression " + + compression); + + writeBackup(targetFo); + + return targetFo.toString(); + } catch (Exception e) { + throw new MaintenanceException("Cannot backup " + name + " to " + + targetFo, e); + } finally { + BackupUtils.closeFOQuietly(targetFo); + } + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setCompression(String compression) { + this.compression = compression; + } +} diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/AtomicBackup.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/AtomicBackup.java new file mode 100644 index 000000000..e8c3ded11 --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/AtomicBackup.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.maintenance.backup.vfs; + +import org.apache.commons.vfs2.FileSystemManager; +import org.apache.commons.vfs2.FileSystemOptions; + +/** Performs the backup of a single component, typically a database dump */ +public interface AtomicBackup { + /** Name identifiying this backup */ + public String getName(); + + /** + * Retrieves the data of the component in a format that allows to restore + * the component + * + * @param backupContext + * the context of this backup + * @return the VFS URI of the generated file or directory + */ + public String backup(FileSystemManager fileSystemManager, + String backupsBase, BackupContext backupContext, + FileSystemOptions opts); +} diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/BackupContext.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/BackupContext.java new file mode 100644 index 000000000..cc1391fe8 --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/BackupContext.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.maintenance.backup.vfs; + +import java.text.DateFormat; +import java.util.Date; + +/** + * Transient information of a given backup, centralizing common information such + * as timestamp and location. + */ +public interface BackupContext { + /** Backup date */ + public Date getTimestamp(); + + /** Formatted backup date */ + public String getTimestampAsString(); + + /** System name */ + public String getSystemName(); + + /** Local base */ + public String getRelativeFolder(); + + /** Date format */ + public DateFormat getDateFormat(); +} diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/BackupFileSystemManager.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/BackupFileSystemManager.java new file mode 100644 index 000000000..3053f0a91 --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/BackupFileSystemManager.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.maintenance.backup.vfs; + +import org.apache.commons.vfs2.FileSystemException; +import org.apache.commons.vfs2.impl.DefaultFileSystemManager; +import org.apache.commons.vfs2.provider.bzip2.Bzip2FileProvider; +import org.apache.commons.vfs2.provider.ftp.FtpFileProvider; +import org.apache.commons.vfs2.provider.gzip.GzipFileProvider; +import org.apache.commons.vfs2.provider.local.DefaultLocalFileProvider; +import org.apache.commons.vfs2.provider.ram.RamFileProvider; +import org.apache.commons.vfs2.provider.sftp.SftpFileProvider; +import org.apache.commons.vfs2.provider.url.UrlFileProvider; +import org.argeo.maintenance.MaintenanceException; + +/** + * Programatically configured VFS file system manager which can be declared as a + * bean and associated with a life cycle (methods + * {@link DefaultFileSystemManager#init()} and + * {@link DefaultFileSystemManager#close()}). Supports bz2, file, ram, gzip, + * ftp, sftp + */ +public class BackupFileSystemManager extends DefaultFileSystemManager { + + public BackupFileSystemManager() { + super(); + try { + addProvider("file", new DefaultLocalFileProvider()); + addProvider("bz2", new Bzip2FileProvider()); + addProvider("ftp", new FtpFileProvider()); + addProvider("sftp", new SftpFileProvider()); + addProvider("gzip", new GzipFileProvider()); + addProvider("ram", new RamFileProvider()); + setDefaultProvider(new UrlFileProvider()); + } catch (FileSystemException e) { + throw new MaintenanceException("Cannot configure backup file provider", e); + } + } +} diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/BackupPurge.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/BackupPurge.java new file mode 100644 index 000000000..face8a128 --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/BackupPurge.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.maintenance.backup.vfs; + +import java.text.DateFormat; + +import org.apache.commons.vfs2.FileSystemManager; +import org.apache.commons.vfs2.FileSystemOptions; + +/** Purges previous backups */ +public interface BackupPurge { + /** + * Purge the backups identified by these arguments. Although these are the + * same fields as a {@link BackupContext} we don't pass it as argument since + * we want to use this interface to purge remote backups as well (that is, + * with a different base), or outside the scope of a running backup. + */ + public void purge(FileSystemManager fileSystemManager, String base, + String name, DateFormat dateFormat, FileSystemOptions opts); +} diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/BackupUtils.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/BackupUtils.java new file mode 100644 index 000000000..94e8a1d49 --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/BackupUtils.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.maintenance.backup.vfs; + +import org.apache.commons.vfs2.FileObject; + +/** Backup utilities */ +public class BackupUtils { + /** Close a file object quietly even if it is null or throws an exception. */ + public static void closeFOQuietly(FileObject fo) { + if (fo != null) { + try { + fo.close(); + } catch (Exception e) { + // silent + } + } + } + + /** Prevents instantiation */ + private BackupUtils() { + } +} diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/MySqlBackup.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/MySqlBackup.java new file mode 100644 index 000000000..7ab2d6a85 --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/MySqlBackup.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.maintenance.backup.vfs; + +import org.apache.commons.vfs2.FileObject; + +/** Backups a MySQL database using mysqldump. */ +public class MySqlBackup extends OsCallBackup { + private String mysqldumpLocation = "/usr/bin/mysqldump"; + + private String dbUser; + private String dbPassword; + private String dbName; + + public MySqlBackup() { + } + + public MySqlBackup(String dbUser, String dbPassword, String dbName) { + this.dbUser = dbUser; + this.dbPassword = dbPassword; + this.dbName = dbName; + init(); + } + + @Override + public void init() { + if (getName() == null) + setName(dbName + ".mysql"); + super.init(); + } + + @Override + public void writeBackup(FileObject targetFo) { + if (getCommand() == null) + setCommand(mysqldumpLocation + + " --lock-tables --add-locks --add-drop-table" + + " -u ${dbUser} --password=${dbPassword} --databases ${dbName}"); + getVariables().put("dbUser", dbUser); + getVariables().put("dbPassword", dbPassword); + getVariables().put("dbName", dbName); + + super.writeBackup(targetFo); + } + + public void setDbUser(String dbUser) { + this.dbUser = dbUser; + } + + public void setDbPassword(String dbPassword) { + this.dbPassword = dbPassword; + } + + public void setDbName(String dbName) { + this.dbName = dbName; + } + + public void setMysqldumpLocation(String mysqldumpLocation) { + this.mysqldumpLocation = mysqldumpLocation; + } + +} diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/OpenLdapBackup.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/OpenLdapBackup.java new file mode 100644 index 000000000..415bc24d9 --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/OpenLdapBackup.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.maintenance.backup.vfs; + +import org.apache.commons.vfs2.FileObject; +import org.argeo.maintenance.MaintenanceException; + +/** Backups an OpenLDAP server using slapcat */ +public class OpenLdapBackup extends OsCallBackup { + private String slapcatLocation = "/usr/sbin/slapcat"; + private String slapdConfLocation = "/etc/openldap/slapd.conf"; + private String baseDn; + + public OpenLdapBackup() { + super(); + } + + public OpenLdapBackup(String baseDn) { + super(); + this.baseDn = baseDn; + } + + @Override + public void writeBackup(FileObject targetFo) { + if (baseDn == null) + throw new MaintenanceException("Base DN must be set"); + + if (getCommand() == null) + setCommand(slapcatLocation + + " -f ${slapdConfLocation} -b '${baseDn}'"); + getVariables().put("slapdConfLocation", slapdConfLocation); + getVariables().put("baseDn", baseDn); + + super.writeBackup(targetFo); + } + + public void setSlapcatLocation(String slapcatLocation) { + this.slapcatLocation = slapcatLocation; + } + + public void setSlapdConfLocation(String slapdConfLocation) { + this.slapdConfLocation = slapdConfLocation; + } + + public void setBaseDn(String baseDn) { + this.baseDn = baseDn; + } + +} diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/OsCallBackup.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/OsCallBackup.java new file mode 100644 index 000000000..07589d305 --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/OsCallBackup.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.maintenance.backup.vfs; + +import java.io.ByteArrayOutputStream; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.exec.CommandLine; +import org.apache.commons.exec.DefaultExecutor; +import org.apache.commons.exec.ExecuteException; +import org.apache.commons.exec.ExecuteStreamHandler; +import org.apache.commons.exec.Executor; +import org.apache.commons.exec.PumpStreamHandler; +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.vfs2.FileContent; +import org.apache.commons.vfs2.FileObject; +import org.argeo.maintenance.MaintenanceException; + +/** + * Runs an OS command and save its standard output as a file. Typically used for + * MySQL or OpenLDAP dumps. + */ +public class OsCallBackup extends AbstractAtomicBackup { + private final static Log log = LogFactory.getLog(OsCallBackup.class); + + private String command; + private Map variables = new HashMap(); + private Executor executor = new DefaultExecutor(); + + private Map environment = new HashMap(); + + /** Name of the sudo user, root if "", not sudo if null */ + private String sudo = null; + + public OsCallBackup() { + } + + public OsCallBackup(String name) { + super(name); + } + + public OsCallBackup(String name, String command) { + super(name); + this.command = command; + } + + @Override + public void writeBackup(FileObject targetFo) { + String commandToUse = command; + + // sudo + if (sudo != null) { + if (sudo.equals("")) + commandToUse = "sudo " + commandToUse; + else + commandToUse = "sudo -u " + sudo + " " + commandToUse; + } + + CommandLine commandLine = CommandLine.parse(commandToUse, variables); + ByteArrayOutputStream errBos = new ByteArrayOutputStream(); + if (log.isTraceEnabled()) + log.trace(commandLine.toString()); + + try { + // stdout + FileContent targetContent = targetFo.getContent(); + // stderr + ExecuteStreamHandler streamHandler = new PumpStreamHandler(targetContent.getOutputStream(), errBos); + executor.setStreamHandler(streamHandler); + executor.execute(commandLine, environment); + } catch (ExecuteException e) { + byte[] err = errBos.toByteArray(); + String errStr = new String(err); + throw new MaintenanceException("Process " + commandLine + " failed (" + e.getExitValue() + "): " + errStr, e); + } catch (Exception e) { + byte[] err = errBos.toByteArray(); + String errStr = new String(err); + throw new MaintenanceException("Process " + commandLine + " failed: " + errStr, e); + } finally { + IOUtils.closeQuietly(errBos); + } + } + + public void setCommand(String command) { + this.command = command; + } + + protected String getCommand() { + return command; + } + + /** + * A reference to the environment variables that will be passed to the + * process. Empty by default. + */ + protected Map getEnvironment() { + return environment; + } + + protected Map getVariables() { + return variables; + } + + public void setVariables(Map variables) { + this.variables = variables; + } + + public void setExecutor(Executor executor) { + this.executor = executor; + } + + public void setSudo(String sudo) { + this.sudo = sudo; + } + +} diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/PostgreSqlBackup.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/PostgreSqlBackup.java new file mode 100644 index 000000000..da3ea38b3 --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/PostgreSqlBackup.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.maintenance.backup.vfs; + +import org.apache.commons.vfs2.FileObject; + +/** Backups a PostgreSQL database using pg_dump. */ +public class PostgreSqlBackup extends OsCallBackup { + /** + * PostgreSQL password environment variable (see + * http://stackoverflow.com/questions + * /2893954/how-to-pass-in-password-to-pg-dump) + */ + protected final static String PGPASSWORD = "PGPASSWORD"; + + private String pgDumpLocation = "/usr/bin/pg_dump"; + + private String dbUser; + private String dbPassword; + private String dbName; + + public PostgreSqlBackup() { + super(); + } + + public PostgreSqlBackup(String dbUser, String dbPassword, String dbName) { + this.dbUser = dbUser; + this.dbPassword = dbPassword; + this.dbName = dbName; + init(); + } + + @Override + public void init() { + // disable compression since pg_dump is used with -Fc option + setCompression(null); + + if (getName() == null) + setName(dbName + ".pgdump"); + super.init(); + } + + @Override + public void writeBackup(FileObject targetFo) { + if (getCommand() == null) { + getEnvironment().put(PGPASSWORD, dbPassword); + setCommand(pgDumpLocation + " -Fc" + " -U ${dbUser} ${dbName}"); + } + getVariables().put("dbUser", dbUser); + getVariables().put("dbPassword", dbPassword); + getVariables().put("dbName", dbName); + + super.writeBackup(targetFo); + } + + public void setDbUser(String dbUser) { + this.dbUser = dbUser; + } + + public void setDbPassword(String dbPassword) { + this.dbPassword = dbPassword; + } + + public void setDbName(String dbName) { + this.dbName = dbName; + } + + public void setPgDumpLocation(String mysqldumpLocation) { + this.pgDumpLocation = mysqldumpLocation; + } + +} diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/SimpleBackupContext.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/SimpleBackupContext.java new file mode 100644 index 000000000..bef6f65cf --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/SimpleBackupContext.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.maintenance.backup.vfs; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; + +import org.apache.commons.vfs2.FileSystemManager; + +/** Simple implementation of a backup context */ +public class SimpleBackupContext implements BackupContext { + private DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmm"); + private final Date timestamp; + private final String name; + + private final FileSystemManager fileSystemManager; + + public SimpleBackupContext(FileSystemManager fileSystemManager, + String backupsBase, String name) { + this.name = name; + this.timestamp = new Date(); + this.fileSystemManager = fileSystemManager; + } + + public Date getTimestamp() { + return timestamp; + } + + public String getTimestampAsString() { + return dateFormat.format(timestamp); + } + + public String getSystemName() { + return name; + } + + public String getRelativeFolder() { + return name + '/' + getTimestampAsString(); + } + + public DateFormat getDateFormat() { + return dateFormat; + } + + public FileSystemManager getFileSystemManager() { + return fileSystemManager; + } + +} diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/SimpleBackupPurge.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/SimpleBackupPurge.java new file mode 100644 index 000000000..042070f5c --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/SimpleBackupPurge.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.maintenance.backup.vfs; + +import java.text.DateFormat; +import java.time.Period; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Date; +import java.util.SortedMap; +import java.util.TreeMap; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.vfs2.FileObject; +import org.apache.commons.vfs2.FileSystemManager; +import org.apache.commons.vfs2.FileSystemOptions; +import org.apache.commons.vfs2.Selectors; +import org.argeo.maintenance.MaintenanceException; + +/** Simple backup purge which keeps backups only for a given number of days */ +public class SimpleBackupPurge implements BackupPurge { + private final static Log log = LogFactory.getLog(SimpleBackupPurge.class); + + private Integer daysKept = 30; + + @Override + public void purge(FileSystemManager fileSystemManager, String base, String name, DateFormat dateFormat, + FileSystemOptions opts) { + try { + ZonedDateTime nowDt = ZonedDateTime.now(); + FileObject baseFo = fileSystemManager.resolveFile(base + '/' + name, opts); + + SortedMap toDelete = new TreeMap(); + int backupCount = 0; + + // make sure base dir exists + baseFo.createFolder(); + + // scan backups and list those which should be deleted + for (FileObject backupFo : baseFo.getChildren()) { + String backupName = backupFo.getName().getBaseName(); + Date backupDate = dateFormat.parse(backupName); + backupCount++; + ZonedDateTime backupDt = ZonedDateTime.ofInstant(backupDate.toInstant(), ZoneId.systemDefault()); + Period sinceThen = Period.between(backupDt.toLocalDate(), nowDt.toLocalDate()); + // new Period(backupDt, nowDt); + int days = sinceThen.getDays(); + // int days = sinceThen.getMinutes(); + if (days > daysKept) { + toDelete.put(backupDt, backupFo); + } + } + + if (toDelete.size() != 0 && toDelete.size() == backupCount) { + // all backups would be deleted + // but we want to keep at least one + ZonedDateTime lastBackupDt = toDelete.firstKey(); + FileObject keptFo = toDelete.remove(lastBackupDt); + log.warn("Backup " + keptFo + " kept although it is older than " + daysKept + " days."); + } + + // delete old backups + for (FileObject backupFo : toDelete.values()) { + backupFo.delete(Selectors.SELECT_ALL); + if (log.isDebugEnabled()) + log.debug("Deleted backup " + backupFo); + } + } catch (Exception e) { + throw new MaintenanceException("Could not purge previous backups", e); + } + + } + +} diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/SvnBackup.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/SvnBackup.java new file mode 100644 index 000000000..b725a3ee5 --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/SvnBackup.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.maintenance.backup.vfs; + +import java.io.File; + +import org.apache.commons.vfs2.FileObject; + +/** Backups a Subversion repository using svnadmin. */ +public class SvnBackup extends OsCallBackup { + private String svnadminLocation = "/usr/bin/svnadmin"; + + private String repoLocation; + private String repoName; + + public SvnBackup() { + } + + public SvnBackup(String repoLocation) { + this.repoLocation = repoLocation; + init(); + } + + @Override + public void init() { + // use directory as repo name + if (repoName == null) + repoName = new File(repoLocation).getName(); + + if (getName() == null) + setName(repoName + ".svndump"); + super.init(); + } + + @Override + public void writeBackup(FileObject targetFo) { + if (getCommand() == null) { + setCommand(svnadminLocation + " dump " + " ${repoLocation}"); + } + getVariables().put("repoLocation", repoLocation); + + super.writeBackup(targetFo); + } + + public void setRepoLocation(String repoLocation) { + this.repoLocation = repoLocation; + } + + public void setRepoName(String repoName) { + this.repoName = repoName; + } + + public void setSvnadminLocation(String mysqldumpLocation) { + this.svnadminLocation = mysqldumpLocation; + } + +} diff --git a/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/SystemBackup.java b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/SystemBackup.java new file mode 100644 index 000000000..480f6dc4c --- /dev/null +++ b/org.argeo.maintenance/src/org/argeo/maintenance/backup/vfs/SystemBackup.java @@ -0,0 +1,216 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * 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.argeo.maintenance.backup.vfs; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.vfs2.FileObject; +import org.apache.commons.vfs2.FileSystemException; +import org.apache.commons.vfs2.FileSystemManager; +import org.apache.commons.vfs2.FileSystemOptions; +import org.apache.commons.vfs2.Selectors; +import org.apache.commons.vfs2.UserAuthenticator; +import org.apache.commons.vfs2.impl.DefaultFileSystemConfigBuilder; +import org.argeo.maintenance.MaintenanceException; +import org.argeo.util.LangUtils; + +/** + * Combines multiple backups and transfer them to a remote location. Purges + * remote and local data based on certain criteria. + */ +public class SystemBackup implements Runnable { + private final static Log log = LogFactory.getLog(SystemBackup.class); + + private FileSystemManager fileSystemManager; + private UserAuthenticator userAuthenticator = null; + + private String backupsBase; + private String systemName; + + private List atomicBackups = new ArrayList(); + private BackupPurge backupPurge = new SimpleBackupPurge(); + + private Map remoteBases = new HashMap(); + + @Override + public void run() { + if (atomicBackups.size() == 0) + throw new MaintenanceException("No atomic backup listed"); + List failures = new ArrayList(); + + SimpleBackupContext backupContext = new SimpleBackupContext(fileSystemManager, backupsBase, systemName); + + // purge older backups + FileSystemOptions opts = new FileSystemOptions(); + try { + DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, userAuthenticator); + } catch (FileSystemException e) { + throw new MaintenanceException("Cannot create authentication", e); + } + + try { + + backupPurge.purge(fileSystemManager, backupsBase, systemName, backupContext.getDateFormat(), opts); + } catch (Exception e) { + failures.add("Purge " + backupsBase + " failed: " + e.getMessage()); + log.error("Purge of " + backupsBase + " failed", e); + } + + // perform backup + for (AtomicBackup atomickBackup : atomicBackups) { + try { + String target = atomickBackup.backup(fileSystemManager, backupsBase, backupContext, opts); + if (log.isDebugEnabled()) + log.debug("Performed backup " + target); + } catch (Exception e) { + String msg = "Atomic backup " + atomickBackup.getName() + " failed: " + + LangUtils.chainCausesMessages(e); + failures.add(msg); + log.error(msg); + if (log.isTraceEnabled()) + log.trace("Stacktrace of atomic backup " + atomickBackup.getName() + " failure.", e); + } + } + + // dispatch to remote + for (String remoteBase : remoteBases.keySet()) { + FileObject localBaseFo = null; + FileObject remoteBaseFo = null; + UserAuthenticator auth = remoteBases.get(remoteBase); + + // authentication + FileSystemOptions remoteOpts = new FileSystemOptions(); + try { + DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(remoteOpts, auth); + backupPurge.purge(fileSystemManager, remoteBase, systemName, backupContext.getDateFormat(), remoteOpts); + } catch (Exception e) { + failures.add("Purge " + remoteBase + " failed: " + e.getMessage()); + log.error("Cannot purge " + remoteBase, e); + } + + try { + localBaseFo = fileSystemManager.resolveFile(backupsBase + '/' + backupContext.getRelativeFolder(), + opts); + remoteBaseFo = fileSystemManager.resolveFile(remoteBase + '/' + backupContext.getRelativeFolder(), + remoteOpts); + remoteBaseFo.copyFrom(localBaseFo, Selectors.SELECT_ALL); + if (log.isDebugEnabled()) + log.debug("Copied backup to " + remoteBaseFo + " from " + localBaseFo); + // } + } catch (Exception e) { + failures.add("Dispatch to " + remoteBase + " failed: " + e.getMessage()); + log.error("Cannot dispatch backups from " + backupContext.getRelativeFolder() + " to " + remoteBase, e); + } + BackupUtils.closeFOQuietly(localBaseFo); + BackupUtils.closeFOQuietly(remoteBaseFo); + } + + int failureCount = 0; + if (failures.size() > 0) { + StringBuffer buf = new StringBuffer(); + for (String failure : failures) { + buf.append('\n').append(failureCount).append(" - ").append(failure); + failureCount++; + } + throw new MaintenanceException(failureCount + " error(s) when running the backup," + + " check the logs and the backups as soon as possible." + buf); + } + } + + public void setFileSystemManager(FileSystemManager fileSystemManager) { + this.fileSystemManager = fileSystemManager; + } + + public void setBackupsBase(String backupsBase) { + this.backupsBase = backupsBase; + } + + public void setSystemName(String name) { + this.systemName = name; + } + + public void setAtomicBackups(List atomicBackups) { + this.atomicBackups = atomicBackups; + } + + public void setBackupPurge(BackupPurge backupPurge) { + this.backupPurge = backupPurge; + } + + public void setUserAuthenticator(UserAuthenticator userAuthenticator) { + this.userAuthenticator = userAuthenticator; + } + + public void setRemoteBases(Map remoteBases) { + this.remoteBases = remoteBases; + } + + // public static void main(String args[]) { + // while (true) { + // try { + // StandardFileSystemManager fsm = new StandardFileSystemManager(); + // fsm.init(); + // + // SystemBackup systemBackup = new SystemBackup(); + // systemBackup.setSystemName("mySystem"); + // systemBackup + // .setBackupsBase("/home/mbaudier/dev/src/commons/server/runtime/org.argeo.server.core/target"); + // systemBackup.setFileSystemManager(fsm); + // + // List atomicBackups = new ArrayList(); + // + // MySqlBackup mySqlBackup = new MySqlBackup("root", "", "test"); + // atomicBackups.add(mySqlBackup); + // PostgreSqlBackup postgreSqlBackup = new PostgreSqlBackup( + // "argeo", "argeo", "gis_template"); + // atomicBackups.add(postgreSqlBackup); + // SvnBackup svnBackup = new SvnBackup( + // "/home/mbaudier/tmp/testsvnrepo"); + // atomicBackups.add(svnBackup); + // + // systemBackup.setAtomicBackups(atomicBackups); + // + // Map remoteBases = new HashMap(); + // StaticUserAuthenticator userAuthenticator = new StaticUserAuthenticator( + // null, "demo", "demo"); + // remoteBases.put("sftp://localhost/home/mbaudier/test", + // userAuthenticator); + // systemBackup.setRemoteBases(remoteBases); + // + // systemBackup.run(); + // + // fsm.close(); + // } catch (FileSystemException e) { + // // TODO Auto-generated catch block + // e.printStackTrace(); + // System.exit(1); + // } + // + // // wait + // try { + // Thread.sleep(120 * 1000); + // } catch (InterruptedException e) { + // e.printStackTrace(); + // } + // } + // } +} diff --git a/pom.xml b/pom.xml index 361161015..4da560d15 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,7 @@ org.argeo.eclipse.ui.rap org.argeo.node.api + org.argeo.maintenance org.argeo.cms org.argeo.cms.ui