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,\
*
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;
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;
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) {
}
} 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);
}
}
+++ /dev/null
-/*
- * 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;
- }
-}
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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();
-}
+++ /dev/null
-/*
- * 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);
- }
- }
-}
+++ /dev/null
-/*
- * 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);
-}
+++ /dev/null
-/*
- * 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() {
- }
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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<String, String> variables = new HashMap<String, String>();
- private Executor executor = new DefaultExecutor();
-
- private Map<String, String> environment = new HashMap<String, String>();
-
- /** 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<String, String> getEnvironment() {
- return environment;
- }
-
- protected Map<String, String> getVariables() {
- return variables;
- }
-
- public void setVariables(Map<String, String> variables) {
- this.variables = variables;
- }
-
- public void setExecutor(Executor executor) {
- this.executor = executor;
- }
-
- public void setSudo(String sudo) {
- this.sudo = sudo;
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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<ZonedDateTime, FileObject> toDelete = new TreeMap<ZonedDateTime, FileObject>();
- 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);
- }
-
- }
-
-}
+++ /dev/null
-/*
- * 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;
- }
-
-}
+++ /dev/null
-/*
- * 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<AtomicBackup> atomicBackups = new ArrayList<AtomicBackup>();
- private BackupPurge backupPurge = new SimpleBackupPurge();
-
- private Map<String, UserAuthenticator> remoteBases = new HashMap<String, UserAuthenticator>();
-
- @Override
- public void run() {
- if (atomicBackups.size() == 0)
- throw new CmsException("No atomic backup listed");
- List<String> failures = new ArrayList<String>();
-
- 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<AtomicBackup> atomicBackups) {
- this.atomicBackups = atomicBackups;
- }
-
- public void setBackupPurge(BackupPurge backupPurge) {
- this.backupPurge = backupPurge;
- }
-
- public void setUserAuthenticator(UserAuthenticator userAuthenticator) {
- this.userAuthenticator = userAuthenticator;
- }
-
- public void setRemoteBases(Map<String, UserAuthenticator> 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<AtomicBackup> atomicBackups = new ArrayList<AtomicBackup>();
- //
- // 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<String, UserAuthenticator> remoteBases = new HashMap<String,
- // UserAuthenticator>();
- // 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();
- // }
- // }
- // }
-}
--- /dev/null
+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.";
+
+}
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
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<String, Object> props = new Hashtable<String, Object>();
// 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);
}
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";
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;
public String getName() {
return "Node User Admin";
}
-
-
@Override
protected void addAbstractSystemRoles(Authorization rawAuthorization, Set<String> sysRoles) {
- if(rawAuthorization.getName()==null) {
+ if (rawAuthorization.getName() == null) {
sysRoles.add(NodeConstants.ROLE_ANONYMOUS);
- }else {
+ } else {
sysRoles.add(NodeConstants.ROLE_USER);
}
}
// 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);
}
}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
--- /dev/null
+/bin/
+/target/
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.argeo.maintenance</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+/MANIFEST.MF
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>argeo-commons</artifactId>
+ <version>2.1.71-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+ <artifactId>org.argeo.maintenance</artifactId>
+ <name>Maintenance</name>
+ <packaging>jar</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.jcr</artifactId>
+ <version>2.1.71-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.argeo.commons</groupId>
+ <artifactId>org.argeo.enterprise</artifactId>
+ <version>2.1.71-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+</project>
\ No newline at end of file
--- /dev/null
+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);
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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();
+}
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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() {
+ }
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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<String, String> variables = new HashMap<String, String>();
+ private Executor executor = new DefaultExecutor();
+
+ private Map<String, String> environment = new HashMap<String, String>();
+
+ /** 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<String, String> getEnvironment() {
+ return environment;
+ }
+
+ protected Map<String, String> getVariables() {
+ return variables;
+ }
+
+ public void setVariables(Map<String, String> variables) {
+ this.variables = variables;
+ }
+
+ public void setExecutor(Executor executor) {
+ this.executor = executor;
+ }
+
+ public void setSudo(String sudo) {
+ this.sudo = sudo;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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<ZonedDateTime, FileObject> toDelete = new TreeMap<ZonedDateTime, FileObject>();
+ 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);
+ }
+
+ }
+
+}
--- /dev/null
+/*
+ * 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;
+ }
+
+}
--- /dev/null
+/*
+ * 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<AtomicBackup> atomicBackups = new ArrayList<AtomicBackup>();
+ private BackupPurge backupPurge = new SimpleBackupPurge();
+
+ private Map<String, UserAuthenticator> remoteBases = new HashMap<String, UserAuthenticator>();
+
+ @Override
+ public void run() {
+ if (atomicBackups.size() == 0)
+ throw new MaintenanceException("No atomic backup listed");
+ List<String> failures = new ArrayList<String>();
+
+ 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<AtomicBackup> atomicBackups) {
+ this.atomicBackups = atomicBackups;
+ }
+
+ public void setBackupPurge(BackupPurge backupPurge) {
+ this.backupPurge = backupPurge;
+ }
+
+ public void setUserAuthenticator(UserAuthenticator userAuthenticator) {
+ this.userAuthenticator = userAuthenticator;
+ }
+
+ public void setRemoteBases(Map<String, UserAuthenticator> 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<AtomicBackup> atomicBackups = new ArrayList<AtomicBackup>();
+ //
+ // 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<String, UserAuthenticator> remoteBases = new HashMap<String,
+ // UserAuthenticator>();
+ // 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();
+ // }
+ // }
+ // }
+}
<module>org.argeo.eclipse.ui.rap</module>
<!-- CMS -->
<module>org.argeo.node.api</module>
+ <module>org.argeo.maintenance</module>
<module>org.argeo.cms</module>
<module>org.argeo.cms.ui</module>
<!-- CMS Workbench -->