--- /dev/null
+Import-Package: org.argeo.jcr,\
+com.sun.jndi.ldap;resolution:=optional,\
+org.springframework.ldap.core.support,\
+org.springframework.security,\
+*
\ No newline at end of file
</parent>
<artifactId>org.argeo.security.auth.ldap</artifactId>
<name>Commons Security Auth LDAP</name>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Import-Package>
- *,
- org.argeo.jcr,
- com.sun.jndi.ldap;resolution:=optional,
- org.springframework.ldap.core.support,
- org.springframework.security
- </Import-Package>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
</project>
\ No newline at end of file
--- /dev/null
+Import-Package: org.argeo.jcr,*
\ No newline at end of file
</parent>
<artifactId>org.argeo.security.dao.cli</artifactId>
<name>Commons Security DAO CLI</name>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Import-Package>
- *,
- org.argeo.jcr,
- </Import-Package>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
</project>
\ No newline at end of file
</parent>
<artifactId>org.argeo.security.dao.jackrabbit</artifactId>
<name>Commons Security DAO Jackrabbit</name>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
</project>
\ No newline at end of file
--- /dev/null
+Import-Package: org.argeo.jcr,\
+com.sun.jndi.ldap;resolution:=optional,\
+org.springframework.ldap.core.support,\
+org.springframework.security,\
+*
\ No newline at end of file
</parent>
<artifactId>org.argeo.security.dao.ldap</artifactId>
<name>Commons Security DAO LDAP</name>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Import-Package>
- *,
- org.argeo.jcr,
- com.sun.jndi.ldap;resolution:=optional,
- org.springframework.ldap.core.support,
- org.springframework.security
- </Import-Package>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
</project>
\ No newline at end of file
--- /dev/null
+Import-Package: org.argeo.jcr,*
\ No newline at end of file
</parent>
<artifactId>org.argeo.security.dao.os</artifactId>
<name>Commons Security DAO OS</name>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
- <configuration>
- <instructions>
- <Import-Package>
- *,
- org.argeo.jcr,
- </Import-Package>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="src" output="target/classes" path="src/main/java"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>>>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="output" path="target/classes"/>
+ <classpathentry kind="src" path="src" />
+ <classpathentry kind="con"
+ path="org.eclipse.pde.core.requiredPlugins" />
+ <classpathentry kind="con"
+ path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" />
+ <classpathentry kind="output" path="bin" />
</classpath>
--- /dev/null
+Import-Package: javax.servlet,\
+org.springframework.web.context,\
+*
\ No newline at end of file
-source.. = src/main/java/
+source.. = src/
additional.bundles = slf4j.api,\
slf4j.org.apache.commons.logging,\
slf4j.log4j,\
</parent>
<artifactId>org.argeo.server.core</artifactId>
<name>Commons Server Core</name>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-source-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>org.apache.felix</groupId>
- <artifactId>maven-bundle-plugin</artifactId>
-
- <configuration>
- <instructions>
- <Export-Package>
- org.argeo.server.*
- </Export-Package>
- <Import-Package>
- javax.servlet,
- org.springframework.web.context,
- *
- </Import-Package>
- </instructions>
- </configuration>
- </plugin>
- </plugins>
- </build>
<dependencies>
<dependency>
<groupId>org.argeo.commons</groupId>
+++ /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.server;
-
-
-/** Answer to an execution of a remote service which performed changes. */
-public class BooleanAnswer {
- private Boolean value = Boolean.TRUE;
-
- /** Canonical constructor */
- public BooleanAnswer(Boolean status) {
- this.value = status;
- }
-
- /** Empty constructor */
- public BooleanAnswer() {
- }
-
- public Boolean getValue() {
- return value;
- }
-
-}
+++ /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.server;
-
-import java.io.Reader;
-
-public interface Deserializer {
- public <T> T deserialize(Reader reader, Class<T> clss);
-}
+++ /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.server;
-
-import java.beans.PropertyEditorSupport;
-import java.io.StringReader;
-
-import org.apache.commons.io.IOUtils;
-
-public class DeserializingEditor extends PropertyEditorSupport {
- private final Deserializer deserializer;
- private final Class<?> targetClass;
-
- public DeserializingEditor(Deserializer deserializer, Class<?> targetClass) {
- super();
- this.deserializer = deserializer;
- this.targetClass = targetClass;
- }
-
- @Override
- public void setAsText(String text) throws IllegalArgumentException {
- StringReader reader = new StringReader(text);
- try {
- setValue(deserializer.deserialize(reader, targetClass));
- } finally {
- IOUtils.closeQuietly(reader);
- }
- }
-
-}
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.server;\r
-\r
-/**\r
- * Answer to a request to a remote service that sends back only one primitive\r
- */\r
-public class PrimitiveAnswer {\r
-\r
- private Object primitive;\r
-\r
- /** Canonical constructor */\r
- public PrimitiveAnswer(Object primitive) {\r
- this.primitive = primitive;\r
- }\r
-\r
- public Object getValue() {\r
- return primitive;\r
- }\r
-\r
-}\r
+++ /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.server;
-
-import java.io.Writer;
-
-public interface Serializer {
- /** Will be removed soon. Use {@link #serialize(Object, Writer)} instead. */
- @Deprecated
- public void serialize(Writer writer, Object obj);
-
- public void serialize(Object obj, Writer writer);
-}
+++ /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.server;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-import org.apache.commons.io.IOUtils;
-import org.argeo.ArgeoException;
-
-/** Answer to an execution of a remote service which performed changes. */
-public class ServerAnswer {
- public final static String OK = "OK";
- public final static String ERROR = "ERROR";
-
- private String status = OK;
- private String message = "";
-
- // TODO: add an exception field
-
- /** Canonical constructor */
- public ServerAnswer(String status, String message) {
- setStatus(status);
- if (message == null)
- throw new ArgeoException("Message cannot be null");
- this.message = message;
- }
-
- /** Empty constructor */
- public ServerAnswer() {
- }
-
- public String getStatus() {
- return status;
- }
-
- public void setStatus(String status) {
- if (status == null || (!status.equals(OK) && !status.equals(ERROR)))
- throw new ArgeoException("Bad status format: " + status);
- this.status = status;
- }
-
- public String getMessage() {
- return message;
- }
-
- public void setMessage(String message) {
- this.message = message;
- }
-
- public Boolean isOk() {
- return status.equals(OK);
- }
-
- public Boolean isError() {
- return status.equals(ERROR);
- }
-
- public static ServerAnswer error(String message) {
- return new ServerAnswer(ERROR, message);
- }
-
- public static ServerAnswer error(Throwable e) {
- StringWriter writer = new StringWriter();
- try {
- e.printStackTrace(new PrintWriter(writer));
- return new ServerAnswer(ERROR, writer.toString());
- } finally {
- IOUtils.closeQuietly(writer);
- }
- }
-
- public static ServerAnswer ok(String message) {
- return new ServerAnswer(OK, message);
- }
-
- @Override
- public String toString() {
- return "ServerAnswer{status:" + status + ", message:" + message + "}";
- }
-
-}
+++ /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.server;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-public interface ServerSerializer {
- public void serialize(Object obj, HttpServletRequest request,
- HttpServletResponse response);
-}
+++ /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.server.backup;
-
-import org.apache.commons.vfs.FileObject;
-import org.apache.commons.vfs.FileSystemManager;
-import org.apache.commons.vfs.FileSystemOptions;
-import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder;
-import org.argeo.ArgeoException;
-
-/**
- * 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 ArgeoException("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 ArgeoException("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 ArgeoException("Unsupported compression "
- + compression);
-
- writeBackup(targetFo);
-
- return targetFo.toString();
- } catch (Exception e) {
- throw new ArgeoException("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.server.backup;
-
-import org.apache.commons.vfs.FileSystemManager;
-import org.apache.commons.vfs.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.server.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.server.backup;
-
-import org.apache.commons.vfs.FileSystemException;
-import org.apache.commons.vfs.impl.DefaultFileSystemManager;
-import org.apache.commons.vfs.provider.bzip2.Bzip2FileProvider;
-import org.apache.commons.vfs.provider.ftp.FtpFileProvider;
-import org.apache.commons.vfs.provider.gzip.GzipFileProvider;
-import org.apache.commons.vfs.provider.local.DefaultLocalFileProvider;
-import org.apache.commons.vfs.provider.ram.RamFileProvider;
-import org.apache.commons.vfs.provider.sftp.SftpFileProvider;
-import org.apache.commons.vfs.provider.url.UrlFileProvider;
-import org.argeo.ArgeoException;
-
-/**
- * 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#closet()}). 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 ArgeoException("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.server.backup;
-
-import java.text.DateFormat;
-
-import org.apache.commons.vfs.FileSystemManager;
-import org.apache.commons.vfs.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.server.backup;
-
-import org.apache.commons.vfs.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.server.backup;
-
-import org.apache.commons.vfs.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.server.backup;
-
-import org.apache.commons.vfs.FileObject;
-import org.argeo.ArgeoException;
-
-/** 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 ArgeoException("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.server.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.vfs.FileContent;
-import org.apache.commons.vfs.FileObject;
-import org.argeo.ArgeoException;
-
-/**
- * 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 ArgeoException("Process " + commandLine + " failed ("
- + e.getExitValue() + "): " + errStr, e);
- } catch (Exception e) {
- byte[] err = errBos.toByteArray();
- String errStr = new String(err);
- throw new ArgeoException("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.server.backup;
-
-import org.apache.commons.vfs.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.server.backup;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-import org.apache.commons.vfs.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.server.backup;
-
-import java.text.DateFormat;
-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.vfs.FileObject;
-import org.apache.commons.vfs.FileSystemManager;
-import org.apache.commons.vfs.FileSystemOptions;
-import org.apache.commons.vfs.Selectors;
-import org.argeo.ArgeoException;
-import org.joda.time.DateTime;
-import org.joda.time.Period;
-
-/** 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 {
- DateTime nowDt = new DateTime();
- FileObject baseFo = fileSystemManager.resolveFile(
- base + '/' + name, opts);
-
- SortedMap<DateTime, FileObject> toDelete = new TreeMap<DateTime, 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++;
-
- DateTime backupDt = new DateTime(backupDate.getTime());
- Period sinceThen = 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
- DateTime 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 ArgeoException("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.server.backup;
-
-import java.io.File;
-
-import org.apache.commons.vfs.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.server.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.vfs.FileObject;
-import org.apache.commons.vfs.FileSystemException;
-import org.apache.commons.vfs.FileSystemManager;
-import org.apache.commons.vfs.FileSystemOptions;
-import org.apache.commons.vfs.Selectors;
-import org.apache.commons.vfs.UserAuthenticator;
-import org.apache.commons.vfs.auth.StaticUserAuthenticator;
-import org.apache.commons.vfs.impl.DefaultFileSystemConfigBuilder;
-import org.apache.commons.vfs.impl.StandardFileSystemManager;
-import org.argeo.ArgeoException;
-
-/**
- * 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 ArgeoException("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 ArgeoException("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: " + ArgeoException.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 ArgeoException(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
-/*
- * 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.server.dao;
-
-import java.beans.PropertyEditor;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-import org.springframework.beans.BeanWrapper;
-import org.springframework.beans.BeanWrapperImpl;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.core.io.Resource;
-
-public abstract class AbstractMemoryDaoSupport implements LightDaoSupport,
- ApplicationContextAware, InitializingBean {
- private final static Log log = LogFactory
- .getLog(AbstractMemoryDaoSupport.class);
-
- private ClassLoader classLoader = getClass().getClassLoader();
- private ApplicationContext applicationContext;
- private List<Class<?>> additionalClasses = new ArrayList<Class<?>>();
-
- private Map<Class<?>, Map<Object, Object>> model = new HashMap<Class<?>, Map<Object, Object>>();
-
- private Map<String, Object> externalRefs = new HashMap<String, Object>();
-
- private List<String> scannedPackages = new ArrayList<String>();
-
- private List<Resource> resources = new ArrayList<Resource>();
-
- private Map<Class<?>, PropertyEditor> customEditors = new HashMap<Class<?>, PropertyEditor>();;
-
- protected abstract void load(InputStream in, List<Reference> references);
-
- protected abstract Object findInternalRef(Reference reference);
-
- public void afterPropertiesSet() throws Exception {
- init();
- }
-
- public void init() {
- for (PropertyEditor propertyEditor : customEditors.values())
- if (propertyEditor instanceof LightDaoAware) {
- ((LightDaoAware) propertyEditor).setLightDaoSupport(this);
- }
-
- // Load data
- List<Reference> references = new ArrayList<Reference>();
-
- for (Resource res : resources) {
- InputStream in = null;
- try {
- in = res.getInputStream();
- load(in, references);
- } catch (Exception e) {
- throw new ArgeoException("Cannot load stream", e);
- } finally {
- IOUtils.closeQuietly(in);
- }
- }
-
- // Inject references
- for (Reference ref : references) {
- injectReference(ref);
- }
- if (log.isDebugEnabled())
- log.debug(references.size() + " references linked");
- }
-
- public List<Class<?>> getSupportedClasses() {
- List<Class<?>> res = new ArrayList<Class<?>>();
- res.addAll(additionalClasses);
- res.addAll(model.keySet());
- return res;
- }
-
- protected void injectReference(Reference reference) {
- BeanWrapper bw = new BeanWrapperImpl(reference.object);
- Object targetObject;
- if (reference.getExternalRef() != null) {
- String ref = reference.getExternalRef();
- if (externalRefs.containsKey(ref))
- targetObject = externalRefs.get(ref);
- else if (applicationContext != null)
- targetObject = applicationContext.getBean(ref);
- else {
- targetObject = null;
- log.warn("Ref " + ref + " not found");
- }
- } else {
- targetObject = findInternalRef(reference);
- }
- bw.setPropertyValue(reference.property, targetObject);
-
- }
-
- protected BeanWrapper newBeanWrapper(Class<?> targetClass) {
- BeanWrapperImpl bw = new BeanWrapperImpl(targetClass);
- for (Class<?> clss : customEditors.keySet())
- bw.registerCustomEditor(clss, customEditors.get(clss));
- return bw;
- }
-
- @SuppressWarnings("unchecked")
- public <T> T getByKey(Class<T> clss, Object key) {
- if (key == null)
- throw new ArgeoException("Key is null for " + clss);
- return (T) model.get(findClass(clss)).get(key);
- }
-
- /**
- * Slow.
- *
- * @return the first found
- */
- public <T> T getByField(Class<T> clss, String field, Object value) {
- List<T> all = list(clss, null);
- T res = null;
- for (T obj : all) {
- if (new BeanWrapperImpl(obj).getPropertyValue(field).equals(value)) {
- res = obj;
- break;
- }
- }
- return res;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- public <T> List<T> list(Class<T> clss, Object filter) {
- List<T> res = new ArrayList<T>();
-
- Class classToUse = findClass(clss);
- if (classToUse != null)
- res.addAll((Collection<T>) model.get(classToUse).values());
-
- if (applicationContext != null)
- res.addAll(applicationContext.getBeansOfType(clss).values());
-
- return res;
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- protected Class findClass(Class parent) {
- if (model.containsKey(parent))
- return parent;
-
- for (Class clss : model.keySet()) {
- if (parent.isAssignableFrom(clss))
- return clss;// return the first found
- }
- if (log.isDebugEnabled())
- log.warn("No class found for " + parent.getName());
- return null;
- }
-
- public void setApplicationContext(ApplicationContext applicationContext)
- throws BeansException {
- this.applicationContext = applicationContext;
- }
-
- /**
- * When it should be stored under a different class (e.g. super class or
- * interface)
- */
- public void saveOrUpdate(Object key, Object value, Class<?> clss) {
- if (!model.containsKey(clss))
- model.put(clss, new TreeMap<Object, Object>());
- model.get(clss).put(key, value);
- }
-
- protected ClassLoader getClassLoader() {
- return classLoader;
- }
-
- public void setExternalRefs(Map<String, Object> externalRefs) {
- this.externalRefs = externalRefs;
- }
-
- public Map<String, Object> getExternalRefs() {
- return externalRefs;
- }
-
- public void setScannedPackages(List<String> scannedPackages) {
- this.scannedPackages = scannedPackages;
- }
-
- public List<String> getScannedPackages() {
- return scannedPackages;
- }
-
- public void setResources(List<Resource> workbooks) {
- this.resources = workbooks;
- }
-
- public List<Resource> getResources() {
- return resources;
- }
-
- public void setClassLoader(ClassLoader classLoader) {
- this.classLoader = classLoader;
- }
-
- public List<Class<?>> getAdditionalClasses() {
- return additionalClasses;
- }
-
- public void setAdditionalClasses(List<Class<?>> additionalClasses) {
- this.additionalClasses = additionalClasses;
- }
-
- public void setCustomEditors(Map<Class<?>, PropertyEditor> propertyEditors) {
- this.customEditors = propertyEditors;
- }
-
- protected static class Reference {
- private Object object;
- private String property;
- private String externalRef;
-
- public Reference(Object object, String property, String externalRef) {
- this.object = object;
- this.property = property;
- this.externalRef = externalRef;
- }
-
- public Object getObject() {
- return object;
- }
-
- public String getProperty() {
- return property;
- }
-
- public String getExternalRef() {
- return externalRef;
- }
-
- }
-}
+++ /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.server.dao;
-
-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.argeo.ArgeoException;
-
-public abstract class AbstractTabularDaoSupport extends
- AbstractMemoryDaoSupport {
- private final static Log log = LogFactory
- .getLog(AbstractTabularDaoSupport.class);
-
- private Map<String, List<Object>> tabularView = new HashMap<String, List<Object>>();
-
- @Override
- protected Object findInternalRef(Reference reference) {
- TabularInternalReference tabReference = (TabularInternalReference) reference;
- return getFromTabularView(tabReference.getTargetTableName(),
- tabReference.getTargetRow());
- }
-
- protected Object getFromTabularView(String tableName, Integer row) {
- return tabularView.get(tableName).get(row - 2);
- }
-
- protected void registerInTabularView(String tableName, Object object) {
- if (!tabularView.containsKey(tableName))
- tabularView.put(tableName, new ArrayList<Object>());
- tabularView.get(tableName).add(object);
- }
-
- protected Class<?> findClassToInstantiate(String tableName) {
- // TODO: ability to map sheet names and class names
- String className = tableName;
- Class<?> clss = null;
- try {
- clss = getClassLoader().loadClass(className);
- return clss;
- } catch (ClassNotFoundException e) {
- // silent
- }
-
- scannedPkgs: for (String pkg : getScannedPackages()) {
- try {
- clss = getClassLoader().loadClass(pkg.trim() + "." + className);
- break scannedPkgs;
- } catch (ClassNotFoundException e) {
- // silent
- if (log.isTraceEnabled())
- log.trace(e.getMessage());
- }
- }
-
- if (clss == null)
- throw new ArgeoException("Cannot find a class for table "
- + tableName);
-
- return clss;
- }
-
- protected static class TabularInternalReference extends Reference {
- private String targetTableName;
- private Integer targetRow;
-
- public TabularInternalReference(Object object, String property,
- String targetSheet, Integer targetRow) {
- super(object, property, null);
- this.targetTableName = targetSheet;
- this.targetRow = targetRow;
- }
-
- public String getTargetTableName() {
- return targetTableName;
- }
-
- public Integer getTargetRow() {
- return targetRow;
- }
-
- }
-}
+++ /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.server.dao;
-
-public interface LightDaoAware {
- public void setLightDaoSupport(LightDaoSupport lightDaoSupport);
-}
+++ /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.server.dao;
-
-import java.beans.PropertyEditorSupport;
-
-import org.argeo.ArgeoException;
-
-public class LightDaoPropertyEditor extends PropertyEditorSupport implements
- LightDaoAware {
- private LightDaoSupport lightDaoSupport;
-
- private Class<?> targetClass;
- /** Can be null */
- private String businessIdField;
-
- @Override
- public String getAsText() {
- return getValue().toString();
- }
-
- @Override
- public void setAsText(String text) throws IllegalArgumentException {
- if (targetClass == null)
- throw new ArgeoException("Target class cannot be null");
-
- if (businessIdField != null)
- setValue(lightDaoSupport.getByField(targetClass, businessIdField,
- text));
- else
- setValue(lightDaoSupport.getByKey(targetClass, text));
- }
-
- public void setLightDaoSupport(LightDaoSupport lightDaoSupport) {
- this.lightDaoSupport = lightDaoSupport;
- }
-
- public void setTargetClass(Class<?> targetClass) {
- this.targetClass = targetClass;
- }
-
- public void setBusinessIdField(String businessIdField) {
- this.businessIdField = businessIdField;
- }
-
-}
+++ /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.server.dao;
-
-import java.util.List;
-
-/** Minimal generic DAO for easy to implements objects <-> storage mapping. */
-public interface LightDaoSupport {
- /** Retrieve an object of a given type by its unique key. */
- public <T> T getByKey(Class<T> clss, Object key);
-
- /** Retrieve an object of a given type by the value of one of its fields. */
- public <T> T getByField(Class<T> clss, String field, Object value);
-
- /** List all objects, optionally filtering them (implementation dependent) */
- public <T> List<T> list(Class<T> clss, Object filter);
-
- /** Lis all supported object types. */
- public List<Class<?>> getSupportedClasses();
-
- /** Save or update an object */
- public void saveOrUpdate(Object key, Object value, Class<?> clss);
-}
+++ /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.server.mvc;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.server.ServerAnswer;
-import org.springframework.web.servlet.HandlerExceptionResolver;
-import org.springframework.web.servlet.ModelAndView;
-
-public class DefaultHandlerExceptionResolver implements
- HandlerExceptionResolver {
- private final static Log log = LogFactory
- .getLog(DefaultHandlerExceptionResolver.class);
-
- public ModelAndView resolveException(HttpServletRequest request,
- HttpServletResponse response, Object handler, Exception ex) {
- ModelAndView mv = new ModelAndView();
- ServerAnswer serverAnswer = ServerAnswer.error(ex);
- mv.addObject(serverAnswer);
-
- if (log.isDebugEnabled())
- log.error(serverAnswer);
-
- mv.setViewName("500");
- // response.setStatus(500);
- return mv;
- }
-
-}
+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Argeo GmbH\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.server.mvc;\r
-\r
-import javax.servlet.http.HttpServletRequest;\r
-import javax.servlet.http.HttpServletResponse;\r
-\r
-import org.springframework.web.servlet.ModelAndView;\r
-import org.springframework.web.servlet.mvc.ParameterizableViewController;\r
-\r
-/** Dummy controller which simply redirects to a view (typically a JSP)*/\r
-public class EmptyViewController extends ParameterizableViewController {\r
-\r
- protected ModelAndView handleRequestInternal(HttpServletRequest request,\r
- HttpServletResponse response) throws Exception {\r
- ModelAndView modelAndView = new ModelAndView();\r
- modelAndView.setViewName(getViewName());\r
- return modelAndView;\r
-\r
- }\r
-}\r
+++ /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.server.mvc;
-
-public interface MvcConstants {
- public final static String ANSWER_MODEL_KEY = "org.argeo.server.mvc.ANSWER";
- public final static String ANSWER_MODEL_KEY_AS_HTML = "org.argeo.server.mvc.ANSWER_AS_HTML";
-}
+++ /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.server.mvc;
-
-import java.util.Locale;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.argeo.ArgeoException;
-import org.argeo.server.ServerAnswer;
-import org.argeo.server.ServerSerializer;
-import org.springframework.validation.BindingResult;
-import org.springframework.web.servlet.View;
-import org.springframework.web.servlet.view.AbstractView;
-
-/**
- * Can be used as a standalone {@link View} or using
- * {@link SerializingViewResolver}
- */
-public class SerializingView extends AbstractView implements MvcConstants {
- private final String viewName;
- private final Locale locale;
-
- private ServerSerializer serializer;
-
- public SerializingView() {
- this.viewName = null;
- this.locale = Locale.getDefault();
- }
-
- public SerializingView(String viewName, Locale locale,
- ServerSerializer serializer) {
- this.viewName = viewName;
- this.locale = locale;
- this.serializer = serializer;
- }
-
- @SuppressWarnings({ "rawtypes" })
- @Override
- protected void renderMergedOutputModel(Map model,
- HttpServletRequest request, HttpServletResponse response)
- throws Exception {
- Boolean serverAnswersAsHtml = model
- .containsKey(ANSWER_MODEL_KEY_AS_HTML);
-
- final Object answer = findAnswerInModel(model);
-
- if ((answer instanceof ServerAnswer) && serverAnswersAsHtml) {
- response.setContentType("text/html");
- ServerAnswer serverAnswer = (ServerAnswer) answer;
- response.getWriter().append("<pre>");
- response.getWriter().append(serverAnswer.getMessage());
- response.getWriter().append("</pre>");
- } else {
- serializer.serialize(answer, request, response);
- }
- }
-
- @SuppressWarnings("rawtypes")
- protected Object findAnswerInModel(Map model) {
- if (model.size() == 1) {
- return model.values().iterator().next();
- } else if (model.size() == 2) {
- boolean otherIsBindingResult = false;
- Object answerValue = null;
- for (Object value : model.values()) {
- if (value instanceof BindingResult)
- otherIsBindingResult = true;
- else
- answerValue = value;
- }
-
- if (otherIsBindingResult)
- return answerValue;
- }
-
- if (model.containsKey(ANSWER_MODEL_KEY)) {
- return model.get(ANSWER_MODEL_KEY);
- } else if (model.containsKey(ANSWER_MODEL_KEY_AS_HTML)) {
- return model.get(ANSWER_MODEL_KEY_AS_HTML);
- } else if (viewName != null && model.containsKey(viewName)) {
- return model.get(viewName);
- } else {
- if (model.size() == 0)
- throw new ArgeoException("Model is empty.");
- else
- throw new ArgeoException(
- "Model has a size different from 1. Specify a modelKey.");
- }
- }
-
- public String getViewName() {
- return viewName;
- }
-
- public Locale getLocale() {
- return locale;
- }
-
- public void setSerializer(ServerSerializer serializer) {
- this.serializer = serializer;
- }
-
-}
+++ /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.server.mvc;
-
-import java.util.Locale;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.server.ServerSerializer;
-import org.springframework.web.servlet.View;
-import org.springframework.web.servlet.view.AbstractCachingViewResolver;
-
-/**
- * Returns a {@link SerializingView} based on the underlying.
- */
-public class SerializingViewResolver extends AbstractCachingViewResolver {
- private final static Log log = LogFactory
- .getLog(SerializingViewResolver.class);
-
- private ServerSerializer serializer;
-
- @Override
- protected View loadView(String viewName, Locale locale) throws Exception {
- if (log.isTraceEnabled())
- log.trace("viewName=" + viewName);
- return new SerializingView(viewName, locale, serializer);
- }
-
- public void setSerializer(ServerSerializer serializer) {
- this.serializer = serializer;
- }
-
-}
--- /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.server;
+
+
+/** Answer to an execution of a remote service which performed changes. */
+public class BooleanAnswer {
+ private Boolean value = Boolean.TRUE;
+
+ /** Canonical constructor */
+ public BooleanAnswer(Boolean status) {
+ this.value = status;
+ }
+
+ /** Empty constructor */
+ public BooleanAnswer() {
+ }
+
+ public Boolean getValue() {
+ return value;
+ }
+
+}
--- /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.server;
+
+import java.io.Reader;
+
+public interface Deserializer {
+ public <T> T deserialize(Reader reader, Class<T> clss);
+}
--- /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.server;
+
+import java.beans.PropertyEditorSupport;
+import java.io.StringReader;
+
+import org.apache.commons.io.IOUtils;
+
+public class DeserializingEditor extends PropertyEditorSupport {
+ private final Deserializer deserializer;
+ private final Class<?> targetClass;
+
+ public DeserializingEditor(Deserializer deserializer, Class<?> targetClass) {
+ super();
+ this.deserializer = deserializer;
+ this.targetClass = targetClass;
+ }
+
+ @Override
+ public void setAsText(String text) throws IllegalArgumentException {
+ StringReader reader = new StringReader(text);
+ try {
+ setValue(deserializer.deserialize(reader, targetClass));
+ } finally {
+ IOUtils.closeQuietly(reader);
+ }
+ }
+
+}
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.server;\r
+\r
+/**\r
+ * Answer to a request to a remote service that sends back only one primitive\r
+ */\r
+public class PrimitiveAnswer {\r
+\r
+ private Object primitive;\r
+\r
+ /** Canonical constructor */\r
+ public PrimitiveAnswer(Object primitive) {\r
+ this.primitive = primitive;\r
+ }\r
+\r
+ public Object getValue() {\r
+ return primitive;\r
+ }\r
+\r
+}\r
--- /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.server;
+
+import java.io.Writer;
+
+public interface Serializer {
+ /** Will be removed soon. Use {@link #serialize(Object, Writer)} instead. */
+ @Deprecated
+ public void serialize(Writer writer, Object obj);
+
+ public void serialize(Object obj, Writer writer);
+}
--- /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.server;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import org.apache.commons.io.IOUtils;
+import org.argeo.ArgeoException;
+
+/** Answer to an execution of a remote service which performed changes. */
+public class ServerAnswer {
+ public final static String OK = "OK";
+ public final static String ERROR = "ERROR";
+
+ private String status = OK;
+ private String message = "";
+
+ // TODO: add an exception field
+
+ /** Canonical constructor */
+ public ServerAnswer(String status, String message) {
+ setStatus(status);
+ if (message == null)
+ throw new ArgeoException("Message cannot be null");
+ this.message = message;
+ }
+
+ /** Empty constructor */
+ public ServerAnswer() {
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ if (status == null || (!status.equals(OK) && !status.equals(ERROR)))
+ throw new ArgeoException("Bad status format: " + status);
+ this.status = status;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Boolean isOk() {
+ return status.equals(OK);
+ }
+
+ public Boolean isError() {
+ return status.equals(ERROR);
+ }
+
+ public static ServerAnswer error(String message) {
+ return new ServerAnswer(ERROR, message);
+ }
+
+ public static ServerAnswer error(Throwable e) {
+ StringWriter writer = new StringWriter();
+ try {
+ e.printStackTrace(new PrintWriter(writer));
+ return new ServerAnswer(ERROR, writer.toString());
+ } finally {
+ IOUtils.closeQuietly(writer);
+ }
+ }
+
+ public static ServerAnswer ok(String message) {
+ return new ServerAnswer(OK, message);
+ }
+
+ @Override
+ public String toString() {
+ return "ServerAnswer{status:" + status + ", message:" + message + "}";
+ }
+
+}
--- /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.server;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public interface ServerSerializer {
+ public void serialize(Object obj, HttpServletRequest request,
+ HttpServletResponse response);
+}
--- /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.server.backup;
+
+import org.apache.commons.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.provider.sftp.SftpFileSystemConfigBuilder;
+import org.argeo.ArgeoException;
+
+/**
+ * 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 ArgeoException("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 ArgeoException("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 ArgeoException("Unsupported compression "
+ + compression);
+
+ writeBackup(targetFo);
+
+ return targetFo.toString();
+ } catch (Exception e) {
+ throw new ArgeoException("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.server.backup;
+
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.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.server.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.server.backup;
+
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.impl.DefaultFileSystemManager;
+import org.apache.commons.vfs.provider.bzip2.Bzip2FileProvider;
+import org.apache.commons.vfs.provider.ftp.FtpFileProvider;
+import org.apache.commons.vfs.provider.gzip.GzipFileProvider;
+import org.apache.commons.vfs.provider.local.DefaultLocalFileProvider;
+import org.apache.commons.vfs.provider.ram.RamFileProvider;
+import org.apache.commons.vfs.provider.sftp.SftpFileProvider;
+import org.apache.commons.vfs.provider.url.UrlFileProvider;
+import org.argeo.ArgeoException;
+
+/**
+ * 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#closet()}). 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 ArgeoException("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.server.backup;
+
+import java.text.DateFormat;
+
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.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.server.backup;
+
+import org.apache.commons.vfs.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.server.backup;
+
+import org.apache.commons.vfs.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.server.backup;
+
+import org.apache.commons.vfs.FileObject;
+import org.argeo.ArgeoException;
+
+/** 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 ArgeoException("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.server.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.vfs.FileContent;
+import org.apache.commons.vfs.FileObject;
+import org.argeo.ArgeoException;
+
+/**
+ * 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 ArgeoException("Process " + commandLine + " failed ("
+ + e.getExitValue() + "): " + errStr, e);
+ } catch (Exception e) {
+ byte[] err = errBos.toByteArray();
+ String errStr = new String(err);
+ throw new ArgeoException("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.server.backup;
+
+import org.apache.commons.vfs.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.server.backup;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.commons.vfs.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.server.backup;
+
+import java.text.DateFormat;
+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.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.Selectors;
+import org.argeo.ArgeoException;
+import org.joda.time.DateTime;
+import org.joda.time.Period;
+
+/** 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 {
+ DateTime nowDt = new DateTime();
+ FileObject baseFo = fileSystemManager.resolveFile(
+ base + '/' + name, opts);
+
+ SortedMap<DateTime, FileObject> toDelete = new TreeMap<DateTime, 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++;
+
+ DateTime backupDt = new DateTime(backupDate.getTime());
+ Period sinceThen = 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
+ DateTime 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 ArgeoException("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.server.backup;
+
+import java.io.File;
+
+import org.apache.commons.vfs.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.server.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.vfs.FileObject;
+import org.apache.commons.vfs.FileSystemException;
+import org.apache.commons.vfs.FileSystemManager;
+import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.Selectors;
+import org.apache.commons.vfs.UserAuthenticator;
+import org.apache.commons.vfs.auth.StaticUserAuthenticator;
+import org.apache.commons.vfs.impl.DefaultFileSystemConfigBuilder;
+import org.apache.commons.vfs.impl.StandardFileSystemManager;
+import org.argeo.ArgeoException;
+
+/**
+ * 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 ArgeoException("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 ArgeoException("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: " + ArgeoException.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 ArgeoException(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
+/*
+ * 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.server.dao;
+
+import java.beans.PropertyEditor;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.core.io.Resource;
+
+public abstract class AbstractMemoryDaoSupport implements LightDaoSupport,
+ ApplicationContextAware, InitializingBean {
+ private final static Log log = LogFactory
+ .getLog(AbstractMemoryDaoSupport.class);
+
+ private ClassLoader classLoader = getClass().getClassLoader();
+ private ApplicationContext applicationContext;
+ private List<Class<?>> additionalClasses = new ArrayList<Class<?>>();
+
+ private Map<Class<?>, Map<Object, Object>> model = new HashMap<Class<?>, Map<Object, Object>>();
+
+ private Map<String, Object> externalRefs = new HashMap<String, Object>();
+
+ private List<String> scannedPackages = new ArrayList<String>();
+
+ private List<Resource> resources = new ArrayList<Resource>();
+
+ private Map<Class<?>, PropertyEditor> customEditors = new HashMap<Class<?>, PropertyEditor>();;
+
+ protected abstract void load(InputStream in, List<Reference> references);
+
+ protected abstract Object findInternalRef(Reference reference);
+
+ public void afterPropertiesSet() throws Exception {
+ init();
+ }
+
+ public void init() {
+ for (PropertyEditor propertyEditor : customEditors.values())
+ if (propertyEditor instanceof LightDaoAware) {
+ ((LightDaoAware) propertyEditor).setLightDaoSupport(this);
+ }
+
+ // Load data
+ List<Reference> references = new ArrayList<Reference>();
+
+ for (Resource res : resources) {
+ InputStream in = null;
+ try {
+ in = res.getInputStream();
+ load(in, references);
+ } catch (Exception e) {
+ throw new ArgeoException("Cannot load stream", e);
+ } finally {
+ IOUtils.closeQuietly(in);
+ }
+ }
+
+ // Inject references
+ for (Reference ref : references) {
+ injectReference(ref);
+ }
+ if (log.isDebugEnabled())
+ log.debug(references.size() + " references linked");
+ }
+
+ public List<Class<?>> getSupportedClasses() {
+ List<Class<?>> res = new ArrayList<Class<?>>();
+ res.addAll(additionalClasses);
+ res.addAll(model.keySet());
+ return res;
+ }
+
+ protected void injectReference(Reference reference) {
+ BeanWrapper bw = new BeanWrapperImpl(reference.object);
+ Object targetObject;
+ if (reference.getExternalRef() != null) {
+ String ref = reference.getExternalRef();
+ if (externalRefs.containsKey(ref))
+ targetObject = externalRefs.get(ref);
+ else if (applicationContext != null)
+ targetObject = applicationContext.getBean(ref);
+ else {
+ targetObject = null;
+ log.warn("Ref " + ref + " not found");
+ }
+ } else {
+ targetObject = findInternalRef(reference);
+ }
+ bw.setPropertyValue(reference.property, targetObject);
+
+ }
+
+ protected BeanWrapper newBeanWrapper(Class<?> targetClass) {
+ BeanWrapperImpl bw = new BeanWrapperImpl(targetClass);
+ for (Class<?> clss : customEditors.keySet())
+ bw.registerCustomEditor(clss, customEditors.get(clss));
+ return bw;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> T getByKey(Class<T> clss, Object key) {
+ if (key == null)
+ throw new ArgeoException("Key is null for " + clss);
+ return (T) model.get(findClass(clss)).get(key);
+ }
+
+ /**
+ * Slow.
+ *
+ * @return the first found
+ */
+ public <T> T getByField(Class<T> clss, String field, Object value) {
+ List<T> all = list(clss, null);
+ T res = null;
+ for (T obj : all) {
+ if (new BeanWrapperImpl(obj).getPropertyValue(field).equals(value)) {
+ res = obj;
+ break;
+ }
+ }
+ return res;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public <T> List<T> list(Class<T> clss, Object filter) {
+ List<T> res = new ArrayList<T>();
+
+ Class classToUse = findClass(clss);
+ if (classToUse != null)
+ res.addAll((Collection<T>) model.get(classToUse).values());
+
+ if (applicationContext != null)
+ res.addAll(applicationContext.getBeansOfType(clss).values());
+
+ return res;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ protected Class findClass(Class parent) {
+ if (model.containsKey(parent))
+ return parent;
+
+ for (Class clss : model.keySet()) {
+ if (parent.isAssignableFrom(clss))
+ return clss;// return the first found
+ }
+ if (log.isDebugEnabled())
+ log.warn("No class found for " + parent.getName());
+ return null;
+ }
+
+ public void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+
+ /**
+ * When it should be stored under a different class (e.g. super class or
+ * interface)
+ */
+ public void saveOrUpdate(Object key, Object value, Class<?> clss) {
+ if (!model.containsKey(clss))
+ model.put(clss, new TreeMap<Object, Object>());
+ model.get(clss).put(key, value);
+ }
+
+ protected ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ public void setExternalRefs(Map<String, Object> externalRefs) {
+ this.externalRefs = externalRefs;
+ }
+
+ public Map<String, Object> getExternalRefs() {
+ return externalRefs;
+ }
+
+ public void setScannedPackages(List<String> scannedPackages) {
+ this.scannedPackages = scannedPackages;
+ }
+
+ public List<String> getScannedPackages() {
+ return scannedPackages;
+ }
+
+ public void setResources(List<Resource> workbooks) {
+ this.resources = workbooks;
+ }
+
+ public List<Resource> getResources() {
+ return resources;
+ }
+
+ public void setClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ public List<Class<?>> getAdditionalClasses() {
+ return additionalClasses;
+ }
+
+ public void setAdditionalClasses(List<Class<?>> additionalClasses) {
+ this.additionalClasses = additionalClasses;
+ }
+
+ public void setCustomEditors(Map<Class<?>, PropertyEditor> propertyEditors) {
+ this.customEditors = propertyEditors;
+ }
+
+ protected static class Reference {
+ private Object object;
+ private String property;
+ private String externalRef;
+
+ public Reference(Object object, String property, String externalRef) {
+ this.object = object;
+ this.property = property;
+ this.externalRef = externalRef;
+ }
+
+ public Object getObject() {
+ return object;
+ }
+
+ public String getProperty() {
+ return property;
+ }
+
+ public String getExternalRef() {
+ return externalRef;
+ }
+
+ }
+}
--- /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.server.dao;
+
+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.argeo.ArgeoException;
+
+public abstract class AbstractTabularDaoSupport extends
+ AbstractMemoryDaoSupport {
+ private final static Log log = LogFactory
+ .getLog(AbstractTabularDaoSupport.class);
+
+ private Map<String, List<Object>> tabularView = new HashMap<String, List<Object>>();
+
+ @Override
+ protected Object findInternalRef(Reference reference) {
+ TabularInternalReference tabReference = (TabularInternalReference) reference;
+ return getFromTabularView(tabReference.getTargetTableName(),
+ tabReference.getTargetRow());
+ }
+
+ protected Object getFromTabularView(String tableName, Integer row) {
+ return tabularView.get(tableName).get(row - 2);
+ }
+
+ protected void registerInTabularView(String tableName, Object object) {
+ if (!tabularView.containsKey(tableName))
+ tabularView.put(tableName, new ArrayList<Object>());
+ tabularView.get(tableName).add(object);
+ }
+
+ protected Class<?> findClassToInstantiate(String tableName) {
+ // TODO: ability to map sheet names and class names
+ String className = tableName;
+ Class<?> clss = null;
+ try {
+ clss = getClassLoader().loadClass(className);
+ return clss;
+ } catch (ClassNotFoundException e) {
+ // silent
+ }
+
+ scannedPkgs: for (String pkg : getScannedPackages()) {
+ try {
+ clss = getClassLoader().loadClass(pkg.trim() + "." + className);
+ break scannedPkgs;
+ } catch (ClassNotFoundException e) {
+ // silent
+ if (log.isTraceEnabled())
+ log.trace(e.getMessage());
+ }
+ }
+
+ if (clss == null)
+ throw new ArgeoException("Cannot find a class for table "
+ + tableName);
+
+ return clss;
+ }
+
+ protected static class TabularInternalReference extends Reference {
+ private String targetTableName;
+ private Integer targetRow;
+
+ public TabularInternalReference(Object object, String property,
+ String targetSheet, Integer targetRow) {
+ super(object, property, null);
+ this.targetTableName = targetSheet;
+ this.targetRow = targetRow;
+ }
+
+ public String getTargetTableName() {
+ return targetTableName;
+ }
+
+ public Integer getTargetRow() {
+ return targetRow;
+ }
+
+ }
+}
--- /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.server.dao;
+
+public interface LightDaoAware {
+ public void setLightDaoSupport(LightDaoSupport lightDaoSupport);
+}
--- /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.server.dao;
+
+import java.beans.PropertyEditorSupport;
+
+import org.argeo.ArgeoException;
+
+public class LightDaoPropertyEditor extends PropertyEditorSupport implements
+ LightDaoAware {
+ private LightDaoSupport lightDaoSupport;
+
+ private Class<?> targetClass;
+ /** Can be null */
+ private String businessIdField;
+
+ @Override
+ public String getAsText() {
+ return getValue().toString();
+ }
+
+ @Override
+ public void setAsText(String text) throws IllegalArgumentException {
+ if (targetClass == null)
+ throw new ArgeoException("Target class cannot be null");
+
+ if (businessIdField != null)
+ setValue(lightDaoSupport.getByField(targetClass, businessIdField,
+ text));
+ else
+ setValue(lightDaoSupport.getByKey(targetClass, text));
+ }
+
+ public void setLightDaoSupport(LightDaoSupport lightDaoSupport) {
+ this.lightDaoSupport = lightDaoSupport;
+ }
+
+ public void setTargetClass(Class<?> targetClass) {
+ this.targetClass = targetClass;
+ }
+
+ public void setBusinessIdField(String businessIdField) {
+ this.businessIdField = businessIdField;
+ }
+
+}
--- /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.server.dao;
+
+import java.util.List;
+
+/** Minimal generic DAO for easy to implements objects <-> storage mapping. */
+public interface LightDaoSupport {
+ /** Retrieve an object of a given type by its unique key. */
+ public <T> T getByKey(Class<T> clss, Object key);
+
+ /** Retrieve an object of a given type by the value of one of its fields. */
+ public <T> T getByField(Class<T> clss, String field, Object value);
+
+ /** List all objects, optionally filtering them (implementation dependent) */
+ public <T> List<T> list(Class<T> clss, Object filter);
+
+ /** Lis all supported object types. */
+ public List<Class<?>> getSupportedClasses();
+
+ /** Save or update an object */
+ public void saveOrUpdate(Object key, Object value, Class<?> clss);
+}
--- /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.server.mvc;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.server.ServerAnswer;
+import org.springframework.web.servlet.HandlerExceptionResolver;
+import org.springframework.web.servlet.ModelAndView;
+
+public class DefaultHandlerExceptionResolver implements
+ HandlerExceptionResolver {
+ private final static Log log = LogFactory
+ .getLog(DefaultHandlerExceptionResolver.class);
+
+ public ModelAndView resolveException(HttpServletRequest request,
+ HttpServletResponse response, Object handler, Exception ex) {
+ ModelAndView mv = new ModelAndView();
+ ServerAnswer serverAnswer = ServerAnswer.error(ex);
+ mv.addObject(serverAnswer);
+
+ if (log.isDebugEnabled())
+ log.error(serverAnswer);
+
+ mv.setViewName("500");
+ // response.setStatus(500);
+ return mv;
+ }
+
+}
--- /dev/null
+/*\r
+ * Copyright (C) 2007-2012 Argeo GmbH\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package org.argeo.server.mvc;\r
+\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import org.springframework.web.servlet.ModelAndView;\r
+import org.springframework.web.servlet.mvc.ParameterizableViewController;\r
+\r
+/** Dummy controller which simply redirects to a view (typically a JSP)*/\r
+public class EmptyViewController extends ParameterizableViewController {\r
+\r
+ protected ModelAndView handleRequestInternal(HttpServletRequest request,\r
+ HttpServletResponse response) throws Exception {\r
+ ModelAndView modelAndView = new ModelAndView();\r
+ modelAndView.setViewName(getViewName());\r
+ return modelAndView;\r
+\r
+ }\r
+}\r
--- /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.server.mvc;
+
+public interface MvcConstants {
+ public final static String ANSWER_MODEL_KEY = "org.argeo.server.mvc.ANSWER";
+ public final static String ANSWER_MODEL_KEY_AS_HTML = "org.argeo.server.mvc.ANSWER_AS_HTML";
+}
--- /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.server.mvc;
+
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.argeo.ArgeoException;
+import org.argeo.server.ServerAnswer;
+import org.argeo.server.ServerSerializer;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.servlet.View;
+import org.springframework.web.servlet.view.AbstractView;
+
+/**
+ * Can be used as a standalone {@link View} or using
+ * {@link SerializingViewResolver}
+ */
+public class SerializingView extends AbstractView implements MvcConstants {
+ private final String viewName;
+ private final Locale locale;
+
+ private ServerSerializer serializer;
+
+ public SerializingView() {
+ this.viewName = null;
+ this.locale = Locale.getDefault();
+ }
+
+ public SerializingView(String viewName, Locale locale,
+ ServerSerializer serializer) {
+ this.viewName = viewName;
+ this.locale = locale;
+ this.serializer = serializer;
+ }
+
+ @SuppressWarnings({ "rawtypes" })
+ @Override
+ protected void renderMergedOutputModel(Map model,
+ HttpServletRequest request, HttpServletResponse response)
+ throws Exception {
+ Boolean serverAnswersAsHtml = model
+ .containsKey(ANSWER_MODEL_KEY_AS_HTML);
+
+ final Object answer = findAnswerInModel(model);
+
+ if ((answer instanceof ServerAnswer) && serverAnswersAsHtml) {
+ response.setContentType("text/html");
+ ServerAnswer serverAnswer = (ServerAnswer) answer;
+ response.getWriter().append("<pre>");
+ response.getWriter().append(serverAnswer.getMessage());
+ response.getWriter().append("</pre>");
+ } else {
+ serializer.serialize(answer, request, response);
+ }
+ }
+
+ @SuppressWarnings("rawtypes")
+ protected Object findAnswerInModel(Map model) {
+ if (model.size() == 1) {
+ return model.values().iterator().next();
+ } else if (model.size() == 2) {
+ boolean otherIsBindingResult = false;
+ Object answerValue = null;
+ for (Object value : model.values()) {
+ if (value instanceof BindingResult)
+ otherIsBindingResult = true;
+ else
+ answerValue = value;
+ }
+
+ if (otherIsBindingResult)
+ return answerValue;
+ }
+
+ if (model.containsKey(ANSWER_MODEL_KEY)) {
+ return model.get(ANSWER_MODEL_KEY);
+ } else if (model.containsKey(ANSWER_MODEL_KEY_AS_HTML)) {
+ return model.get(ANSWER_MODEL_KEY_AS_HTML);
+ } else if (viewName != null && model.containsKey(viewName)) {
+ return model.get(viewName);
+ } else {
+ if (model.size() == 0)
+ throw new ArgeoException("Model is empty.");
+ else
+ throw new ArgeoException(
+ "Model has a size different from 1. Specify a modelKey.");
+ }
+ }
+
+ public String getViewName() {
+ return viewName;
+ }
+
+ public Locale getLocale() {
+ return locale;
+ }
+
+ public void setSerializer(ServerSerializer serializer) {
+ this.serializer = serializer;
+ }
+
+}
--- /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.server.mvc;
+
+import java.util.Locale;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.server.ServerSerializer;
+import org.springframework.web.servlet.View;
+import org.springframework.web.servlet.view.AbstractCachingViewResolver;
+
+/**
+ * Returns a {@link SerializingView} based on the underlying.
+ */
+public class SerializingViewResolver extends AbstractCachingViewResolver {
+ private final static Log log = LogFactory
+ .getLog(SerializingViewResolver.class);
+
+ private ServerSerializer serializer;
+
+ @Override
+ protected View loadView(String viewName, Locale locale) throws Exception {
+ if (log.isTraceEnabled())
+ log.trace("viewName=" + viewName);
+ return new SerializingView(viewName, locale, serializer);
+ }
+
+ public void setSerializer(ServerSerializer serializer) {
+ this.serializer = serializer;
+ }
+
+}
<?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.6"/>>>
- <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
- <classpathentry kind="src" path="src/main/java"/>
- <classpathentry kind="output" path="target/classes"/>
+ <classpathentry kind="src" path="src" />
+ <classpathentry kind="con"
+ path="org.eclipse.pde.core.requiredPlugins" />
+ <classpathentry kind="con"
+ path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6" />
+ <classpathentry kind="output" path="bin" />
</classpath>
--- /dev/null
+Import-Package: org.springframework.core,\
+org.springframework.beans.factory,\
+javax.xml.transform.*;version="0.0.0",\
+javax.xml.parsers.*;version="0.0.0",\
+org.w3c.dom.*;version="0.0.0",\
+org.xml.sax.*;version="0.0.0",\
+*
-source.. = src/main/java/
-output.. = target/classes/
-bin.includes = META-INF/,\
- .
+source.. = src/
+++ /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.jcr.mvc;
-
-import java.util.Enumeration;
-import java.util.Properties;
-import java.util.StringTokenizer;
-
-import javax.jcr.Repository;
-import javax.jcr.RepositoryFactory;
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.jcr.ArgeoJcrConstants;
-import org.argeo.jcr.ArgeoJcrUtils;
-import org.springframework.beans.BeansException;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.web.context.ServletContextAware;
-import org.springframework.web.servlet.HandlerExecutionChain;
-import org.springframework.web.servlet.HandlerMapping;
-
-/** Handles multiple JCR servers with a single servlet. */
-public abstract class MultipleRepositoryHandlerMapping implements
- HandlerMapping, ApplicationContextAware, ServletContextAware {
- private final static Log log = LogFactory
- .getLog(MultipleRepositoryHandlerMapping.class);
-
- private final static String MKCOL = "MKCOL";
-
- private ConfigurableApplicationContext applicationContext;
- private ServletContext servletContext;
-
- // private RepositoryRegister repositoryRegister;
- private RepositoryFactory repositoryFactory;
-
- /** Actually creates the servlet to be registered. */
- protected abstract HttpServlet createServlet(Repository repository,
- String pathPrefix) throws ServletException;
-
- public HandlerExecutionChain getHandler(HttpServletRequest request)
- throws Exception {
- if (log.isTraceEnabled()) {
- log.trace("getContextPath=" + request.getContextPath());
- log.trace("getServletPath=" + request.getServletPath());
- log.trace("getPathInfo=" + request.getPathInfo());
- }
-
- String pathInfo = request.getPathInfo();
- String repositoryAlias = extractRepositoryAlias(pathInfo);
- if (repositoryAlias.equals(""))
- return null;
-
- // MKCOL on repository or root node doesn't make sense
- // and causes issues
- if (request.getMethod().equals(MKCOL)) {
- StringTokenizer st = new StringTokenizer(pathInfo, "/");
- if (!st.hasMoreTokens())
- return null;
- st.nextToken();// repository
- if (!st.hasMoreTokens())
- return null;
- st.nextToken();// workspace
- if (!st.hasMoreTokens())
- return null;
- }
-
- request.setAttribute(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS,
- repositoryAlias);
- String pathPrefix = request.getServletPath() + '/' + repositoryAlias;
- String beanName = pathPrefix;
-
- if (!applicationContext.containsBean(beanName)) {
- Repository repository = ArgeoJcrUtils.getRepositoryByAlias(
- repositoryFactory, repositoryAlias);
- // Repository repository = repositoryRegister.getRepositories().get(
- // repositoryAlias);
- HttpServlet servlet = createServlet(repository, pathPrefix);
- applicationContext.getBeanFactory().registerSingleton(beanName,
- servlet);
- // TODO: unregister it as well
- }
- HttpServlet remotingServlet = (HttpServlet) applicationContext
- .getBean(beanName);
- HandlerExecutionChain hec = new HandlerExecutionChain(remotingServlet);
- return hec;
- }
-
- /** Returns the first two token of the path */
- // protected String[] extractPrefix(String pathInfo) {
- // String[] res = new String[2];
- // StringTokenizer st = new StringTokenizer(pathInfo, "/");
- // if (st.hasMoreTokens())
- // res[0] = st.nextToken();
- // if (st.hasMoreTokens())
- // res[1] = st.nextToken();
- // return res;
- // }
-
- /** Returns the first token of the path */
- protected String extractRepositoryAlias(String pathInfo) {
- StringBuffer buf = new StringBuffer();
- for (int i = 1; i < pathInfo.length(); i++) {
- char c = pathInfo.charAt(i);
- if (c == '/')
- break;
- buf.append(c);
- }
- return buf.toString();
- }
-
- /** The repository name is the first part of the path info */
- // protected String extractRepositoryName(List<String> pathTokens) {
- // StringBuffer currName = new StringBuffer("");
- // for (String token : pathTokens) {
- // currName.append(token);
- // if (repositoryRegister.getRepositories().containsKey(
- // currName.toString()))
- // return currName.toString();
- // currName.append('/');
- // }
- // throw new ArgeoException("No repository can be found for request "
- // + pathTokens);
- // }
-
- public void setApplicationContext(ApplicationContext applicationContext)
- throws BeansException {
- this.applicationContext = (ConfigurableApplicationContext) applicationContext;
- }
-
- public void setServletContext(ServletContext servletContext) {
- this.servletContext = servletContext;
- }
-
- // public void setRepositoryRegister(RepositoryRegister repositoryRegister)
- // {
- // this.repositoryRegister = repositoryRegister;
- // }
-
- public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
- this.repositoryFactory = repositoryFactory;
- }
-
- protected class DelegatingServletConfig implements ServletConfig {
- private String name;
- private Properties initParameters;
-
- public DelegatingServletConfig(String name, Properties initParameters) {
- super();
- this.name = name;
- this.initParameters = initParameters;
- }
-
- public String getServletName() {
- return name;
- }
-
- public ServletContext getServletContext() {
- return servletContext;
- }
-
- public String getInitParameter(String paramName) {
- return initParameters.getProperty(paramName);
- }
-
- @SuppressWarnings("rawtypes")
- public Enumeration getInitParameterNames() {
- return initParameters.keys();
- }
- }
-}
+++ /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.jcr.mvc;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.jcr.Binary;
-import javax.jcr.Node;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.Property;
-import javax.jcr.RepositoryException;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.ArgeoException;
-import org.argeo.jcr.JcrUtils;
-import org.argeo.jcr.proxy.ResourceProxy;
-
-/** Wraps a proxy via HTTP */
-public class ResourceProxyServlet extends HttpServlet {
- private static final long serialVersionUID = -8886549549223155801L;
-
- private final static Log log = LogFactory
- .getLog(ResourceProxyServlet.class);
-
- private ResourceProxy proxy;
-
- private String contentTypeCharset = "UTF-8";
-
- @Override
- protected void doGet(HttpServletRequest request,
- HttpServletResponse response) throws ServletException, IOException {
- String path = request.getPathInfo();
-
- if (log.isTraceEnabled()) {
- log.trace("path=" + path);
- log.trace("UserPrincipal = " + request.getUserPrincipal().getName());
- log.trace("SessionID = " + request.getSession().getId());
- log.trace("ContextPath = " + request.getContextPath());
- log.trace("ServletPath = " + request.getServletPath());
- log.trace("PathInfo = " + request.getPathInfo());
- log.trace("Method = " + request.getMethod());
- log.trace("User-Agent = " + request.getHeader("User-Agent"));
- }
-
- Node node = null;
- try {
- node = proxy.proxy(path);
- if (node == null)
- response.sendError(404);
- else
- processResponse(node, response);
- } finally {
- if (node != null)
- try {
- JcrUtils.logoutQuietly(node.getSession());
- } catch (RepositoryException e) {
- // silent
- }
- }
-
- }
-
- /** Retrieve the content of the node. */
- protected void processResponse(Node node, HttpServletResponse response) {
- Binary binary = null;
- InputStream in = null;
- try {
- String fileName = node.getName();
- String ext = FilenameUtils.getExtension(fileName);
-
- // TODO use a more generic / standard approach
- // see http://svn.apache.org/viewvc/tomcat/trunk/conf/web.xml
- String contentType;
- if ("xml".equals(ext))
- contentType = "text/xml;charset=" + contentTypeCharset;
- else if ("jar".equals(ext))
- contentType = "application/java-archive";
- else if ("zip".equals(ext))
- contentType = "application/zip";
- else if ("gz".equals(ext))
- contentType = "application/x-gzip";
- else if ("bz2".equals(ext))
- contentType = "application/x-bzip2";
- else if ("tar".equals(ext))
- contentType = "application/x-tar";
- else if ("rpm".equals(ext))
- contentType = "application/x-redhat-package-manager";
- else
- contentType = "application/octet-stream";
- contentType = contentType + ";name=\"" + fileName + "\"";
- response.setHeader("Content-Disposition", "attachment; filename=\""
- + fileName + "\"");
- response.setHeader("Expires", "0");
- response.setHeader("Cache-Control", "no-cache, must-revalidate");
- response.setHeader("Pragma", "no-cache");
-
- response.setContentType(contentType);
-
- try {
- binary = node.getNode(Property.JCR_CONTENT)
- .getProperty(Property.JCR_DATA).getBinary();
- } catch (PathNotFoundException e) {
- log.error("Node " + node + " as no data under content");
- throw e;
- }
- in = binary.getStream();
- IOUtils.copy(in, response.getOutputStream());
- } catch (Exception e) {
- throw new ArgeoException("Cannot download " + node, e);
- } finally {
- IOUtils.closeQuietly(in);
- JcrUtils.closeQuietly(binary);
- }
- }
-
- public void setProxy(ResourceProxy resourceProxy) {
- this.proxy = resourceProxy;
- }
-
-}
--- /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.jcr.mvc;
+
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import javax.jcr.Repository;
+import javax.jcr.RepositoryFactory;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.jcr.ArgeoJcrConstants;
+import org.argeo.jcr.ArgeoJcrUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.web.context.ServletContextAware;
+import org.springframework.web.servlet.HandlerExecutionChain;
+import org.springframework.web.servlet.HandlerMapping;
+
+/** Handles multiple JCR servers with a single servlet. */
+public abstract class MultipleRepositoryHandlerMapping implements
+ HandlerMapping, ApplicationContextAware, ServletContextAware {
+ private final static Log log = LogFactory
+ .getLog(MultipleRepositoryHandlerMapping.class);
+
+ private final static String MKCOL = "MKCOL";
+
+ private ConfigurableApplicationContext applicationContext;
+ private ServletContext servletContext;
+
+ // private RepositoryRegister repositoryRegister;
+ private RepositoryFactory repositoryFactory;
+
+ /** Actually creates the servlet to be registered. */
+ protected abstract HttpServlet createServlet(Repository repository,
+ String pathPrefix) throws ServletException;
+
+ public HandlerExecutionChain getHandler(HttpServletRequest request)
+ throws Exception {
+ if (log.isTraceEnabled()) {
+ log.trace("getContextPath=" + request.getContextPath());
+ log.trace("getServletPath=" + request.getServletPath());
+ log.trace("getPathInfo=" + request.getPathInfo());
+ }
+
+ String pathInfo = request.getPathInfo();
+ String repositoryAlias = extractRepositoryAlias(pathInfo);
+ if (repositoryAlias.equals(""))
+ return null;
+
+ // MKCOL on repository or root node doesn't make sense
+ // and causes issues
+ if (request.getMethod().equals(MKCOL)) {
+ StringTokenizer st = new StringTokenizer(pathInfo, "/");
+ if (!st.hasMoreTokens())
+ return null;
+ st.nextToken();// repository
+ if (!st.hasMoreTokens())
+ return null;
+ st.nextToken();// workspace
+ if (!st.hasMoreTokens())
+ return null;
+ }
+
+ request.setAttribute(ArgeoJcrConstants.JCR_REPOSITORY_ALIAS,
+ repositoryAlias);
+ String pathPrefix = request.getServletPath() + '/' + repositoryAlias;
+ String beanName = pathPrefix;
+
+ if (!applicationContext.containsBean(beanName)) {
+ Repository repository = ArgeoJcrUtils.getRepositoryByAlias(
+ repositoryFactory, repositoryAlias);
+ // Repository repository = repositoryRegister.getRepositories().get(
+ // repositoryAlias);
+ HttpServlet servlet = createServlet(repository, pathPrefix);
+ applicationContext.getBeanFactory().registerSingleton(beanName,
+ servlet);
+ // TODO: unregister it as well
+ }
+ HttpServlet remotingServlet = (HttpServlet) applicationContext
+ .getBean(beanName);
+ HandlerExecutionChain hec = new HandlerExecutionChain(remotingServlet);
+ return hec;
+ }
+
+ /** Returns the first two token of the path */
+ // protected String[] extractPrefix(String pathInfo) {
+ // String[] res = new String[2];
+ // StringTokenizer st = new StringTokenizer(pathInfo, "/");
+ // if (st.hasMoreTokens())
+ // res[0] = st.nextToken();
+ // if (st.hasMoreTokens())
+ // res[1] = st.nextToken();
+ // return res;
+ // }
+
+ /** Returns the first token of the path */
+ protected String extractRepositoryAlias(String pathInfo) {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 1; i < pathInfo.length(); i++) {
+ char c = pathInfo.charAt(i);
+ if (c == '/')
+ break;
+ buf.append(c);
+ }
+ return buf.toString();
+ }
+
+ /** The repository name is the first part of the path info */
+ // protected String extractRepositoryName(List<String> pathTokens) {
+ // StringBuffer currName = new StringBuffer("");
+ // for (String token : pathTokens) {
+ // currName.append(token);
+ // if (repositoryRegister.getRepositories().containsKey(
+ // currName.toString()))
+ // return currName.toString();
+ // currName.append('/');
+ // }
+ // throw new ArgeoException("No repository can be found for request "
+ // + pathTokens);
+ // }
+
+ public void setApplicationContext(ApplicationContext applicationContext)
+ throws BeansException {
+ this.applicationContext = (ConfigurableApplicationContext) applicationContext;
+ }
+
+ public void setServletContext(ServletContext servletContext) {
+ this.servletContext = servletContext;
+ }
+
+ // public void setRepositoryRegister(RepositoryRegister repositoryRegister)
+ // {
+ // this.repositoryRegister = repositoryRegister;
+ // }
+
+ public void setRepositoryFactory(RepositoryFactory repositoryFactory) {
+ this.repositoryFactory = repositoryFactory;
+ }
+
+ protected class DelegatingServletConfig implements ServletConfig {
+ private String name;
+ private Properties initParameters;
+
+ public DelegatingServletConfig(String name, Properties initParameters) {
+ super();
+ this.name = name;
+ this.initParameters = initParameters;
+ }
+
+ public String getServletName() {
+ return name;
+ }
+
+ public ServletContext getServletContext() {
+ return servletContext;
+ }
+
+ public String getInitParameter(String paramName) {
+ return initParameters.getProperty(paramName);
+ }
+
+ @SuppressWarnings("rawtypes")
+ public Enumeration getInitParameterNames() {
+ return initParameters.keys();
+ }
+ }
+}
--- /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.jcr.mvc;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.jcr.Binary;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoException;
+import org.argeo.jcr.JcrUtils;
+import org.argeo.jcr.proxy.ResourceProxy;
+
+/** Wraps a proxy via HTTP */
+public class ResourceProxyServlet extends HttpServlet {
+ private static final long serialVersionUID = -8886549549223155801L;
+
+ private final static Log log = LogFactory
+ .getLog(ResourceProxyServlet.class);
+
+ private ResourceProxy proxy;
+
+ private String contentTypeCharset = "UTF-8";
+
+ @Override
+ protected void doGet(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+ String path = request.getPathInfo();
+
+ if (log.isTraceEnabled()) {
+ log.trace("path=" + path);
+ log.trace("UserPrincipal = " + request.getUserPrincipal().getName());
+ log.trace("SessionID = " + request.getSession().getId());
+ log.trace("ContextPath = " + request.getContextPath());
+ log.trace("ServletPath = " + request.getServletPath());
+ log.trace("PathInfo = " + request.getPathInfo());
+ log.trace("Method = " + request.getMethod());
+ log.trace("User-Agent = " + request.getHeader("User-Agent"));
+ }
+
+ Node node = null;
+ try {
+ node = proxy.proxy(path);
+ if (node == null)
+ response.sendError(404);
+ else
+ processResponse(node, response);
+ } finally {
+ if (node != null)
+ try {
+ JcrUtils.logoutQuietly(node.getSession());
+ } catch (RepositoryException e) {
+ // silent
+ }
+ }
+
+ }
+
+ /** Retrieve the content of the node. */
+ protected void processResponse(Node node, HttpServletResponse response) {
+ Binary binary = null;
+ InputStream in = null;
+ try {
+ String fileName = node.getName();
+ String ext = FilenameUtils.getExtension(fileName);
+
+ // TODO use a more generic / standard approach
+ // see http://svn.apache.org/viewvc/tomcat/trunk/conf/web.xml
+ String contentType;
+ if ("xml".equals(ext))
+ contentType = "text/xml;charset=" + contentTypeCharset;
+ else if ("jar".equals(ext))
+ contentType = "application/java-archive";
+ else if ("zip".equals(ext))
+ contentType = "application/zip";
+ else if ("gz".equals(ext))
+ contentType = "application/x-gzip";
+ else if ("bz2".equals(ext))
+ contentType = "application/x-bzip2";
+ else if ("tar".equals(ext))
+ contentType = "application/x-tar";
+ else if ("rpm".equals(ext))
+ contentType = "application/x-redhat-package-manager";
+ else
+ contentType = "application/octet-stream";
+ contentType = contentType + ";name=\"" + fileName + "\"";
+ response.setHeader("Content-Disposition", "attachment; filename=\""
+ + fileName + "\"");
+ response.setHeader("Expires", "0");
+ response.setHeader("Cache-Control", "no-cache, must-revalidate");
+ response.setHeader("Pragma", "no-cache");
+
+ response.setContentType(contentType);
+
+ try {
+ binary = node.getNode(Property.JCR_CONTENT)
+ .getProperty(Property.JCR_DATA).getBinary();
+ } catch (PathNotFoundException e) {
+ log.error("Node " + node + " as no data under content");
+ throw e;
+ }
+ in = binary.getStream();
+ IOUtils.copy(in, response.getOutputStream());
+ } catch (Exception e) {
+ throw new ArgeoException("Cannot download " + node, e);
+ } finally {
+ IOUtils.closeQuietly(in);
+ JcrUtils.closeQuietly(binary);
+ }
+ }
+
+ public void setProxy(ResourceProxy resourceProxy) {
+ this.proxy = resourceProxy;
+ }
+
+}