New project conventions
authorMathieu Baudier <mbaudier@argeo.org>
Tue, 25 Nov 2014 13:35:45 +0000 (13:35 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Tue, 25 Nov 2014 13:35:45 +0000 (13:35 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@7534 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

86 files changed:
org.argeo.security.auth.ldap/bnd.bnd [new file with mode: 0644]
org.argeo.security.auth.ldap/pom.xml
org.argeo.security.dao.cli/bnd.bnd [new file with mode: 0644]
org.argeo.security.dao.cli/pom.xml
org.argeo.security.dao.jackrabbit/bnd.bnd [new file with mode: 0644]
org.argeo.security.dao.jackrabbit/pom.xml
org.argeo.security.dao.ldap/bnd.bnd [new file with mode: 0644]
org.argeo.security.dao.ldap/pom.xml
org.argeo.security.dao.os/bnd.bnd [new file with mode: 0644]
org.argeo.security.dao.os/pom.xml
org.argeo.server.core/.classpath
org.argeo.server.core/bnd.bnd [new file with mode: 0644]
org.argeo.server.core/build.properties
org.argeo.server.core/pom.xml
org.argeo.server.core/src/main/java/org/argeo/server/BooleanAnswer.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/Deserializer.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/DeserializingEditor.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/PrimitiveAnswer.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/Serializer.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/ServerSerializer.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/backup/AbstractAtomicBackup.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/backup/AtomicBackup.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupContext.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupFileSystemManager.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupPurge.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupUtils.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/backup/MySqlBackup.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/backup/OpenLdapBackup.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/backup/OsCallBackup.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/backup/PostgreSqlBackup.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupContext.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupPurge.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/backup/SvnBackup.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/backup/SystemBackup.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractMemoryDaoSupport.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractTabularDaoSupport.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoAware.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoPropertyEditor.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoSupport.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/mvc/EmptyViewController.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/mvc/MvcConstants.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingView.java [deleted file]
org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingViewResolver.java [deleted file]
org.argeo.server.core/src/org/argeo/server/BooleanAnswer.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/Deserializer.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/DeserializingEditor.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/PrimitiveAnswer.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/Serializer.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/ServerAnswer.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/ServerSerializer.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/backup/AbstractAtomicBackup.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/backup/AtomicBackup.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/backup/BackupContext.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/backup/BackupFileSystemManager.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/backup/BackupPurge.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/backup/BackupUtils.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/backup/MySqlBackup.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/backup/OpenLdapBackup.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/backup/OsCallBackup.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/backup/PostgreSqlBackup.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/backup/SimpleBackupContext.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/backup/SimpleBackupPurge.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/backup/SvnBackup.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/backup/SystemBackup.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/dao/AbstractMemoryDaoSupport.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/dao/AbstractTabularDaoSupport.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/dao/LightDaoAware.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/dao/LightDaoPropertyEditor.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/dao/LightDaoSupport.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/mvc/EmptyViewController.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/mvc/MvcConstants.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/mvc/SerializingView.java [new file with mode: 0644]
org.argeo.server.core/src/org/argeo/server/mvc/SerializingViewResolver.java [new file with mode: 0644]
org.argeo.server.jcr.mvc/.classpath
org.argeo.server.jcr.mvc/bin/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping$DelegatingServletConfig.class [new file with mode: 0644]
org.argeo.server.jcr.mvc/bin/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.class [new file with mode: 0644]
org.argeo.server.jcr.mvc/bin/org/argeo/jcr/mvc/ResourceProxyServlet.class [new file with mode: 0644]
org.argeo.server.jcr.mvc/bnd.bnd [new file with mode: 0644]
org.argeo.server.jcr.mvc/build.properties
org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.java [deleted file]
org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/ResourceProxyServlet.java [deleted file]
org.argeo.server.jcr.mvc/src/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.java [new file with mode: 0644]
org.argeo.server.jcr.mvc/src/org/argeo/jcr/mvc/ResourceProxyServlet.java [new file with mode: 0644]

diff --git a/org.argeo.security.auth.ldap/bnd.bnd b/org.argeo.security.auth.ldap/bnd.bnd
new file mode 100644 (file)
index 0000000..85e0e5c
--- /dev/null
@@ -0,0 +1,5 @@
+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
index a4410a91fa84b3b5437a7822e5e53e75a082dbe8..c26dda86d91d3c19d180930a24668c04e6bfa756 100644 (file)
@@ -8,23 +8,4 @@
        </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
diff --git a/org.argeo.security.dao.cli/bnd.bnd b/org.argeo.security.dao.cli/bnd.bnd
new file mode 100644 (file)
index 0000000..0df3b4a
--- /dev/null
@@ -0,0 +1 @@
+Import-Package: org.argeo.jcr,*
\ No newline at end of file
index c354eacbd12cf60fbce7982d3dc3ca20c7f0d8ca..553edb01913f99dfa677555707259939833f9531 100644 (file)
@@ -8,20 +8,4 @@
        </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
diff --git a/org.argeo.security.dao.jackrabbit/bnd.bnd b/org.argeo.security.dao.jackrabbit/bnd.bnd
new file mode 100644 (file)
index 0000000..e69de29
index 86f837e6a6a098ce42de86da8d31684f1e56b352..2c7027e26c523c035c8ce0935f0a3fe0359c739d 100644 (file)
@@ -8,12 +8,4 @@
        </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
diff --git a/org.argeo.security.dao.ldap/bnd.bnd b/org.argeo.security.dao.ldap/bnd.bnd
new file mode 100644 (file)
index 0000000..85e0e5c
--- /dev/null
@@ -0,0 +1,5 @@
+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
index d4ca96c6b32d332063dbade938997adc65ce870f..bb2482f435650b399b3debe8db6fa41d130dbd01 100644 (file)
@@ -8,23 +8,4 @@
        </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
diff --git a/org.argeo.security.dao.os/bnd.bnd b/org.argeo.security.dao.os/bnd.bnd
new file mode 100644 (file)
index 0000000..0df3b4a
--- /dev/null
@@ -0,0 +1 @@
+Import-Package: org.argeo.jcr,*
\ No newline at end of file
index 7ec6fe6c3fe15ffbc57b6a61f587c0cdcf4cd811..05ee4ccd4ce250f10162216bdee337719bfd0667 100644 (file)
@@ -8,20 +8,4 @@
        </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
index 3bf3adef58f92318093cb5e45f6456a0ac2f7079..d2953a684d400476bf716ed6a6c3c3ae486fcd0e 100644 (file)
@@ -1,7 +1,9 @@
 <?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>
diff --git a/org.argeo.server.core/bnd.bnd b/org.argeo.server.core/bnd.bnd
new file mode 100644 (file)
index 0000000..8a56d16
--- /dev/null
@@ -0,0 +1,3 @@
+Import-Package: javax.servlet,\
+org.springframework.web.context,\
+*
\ No newline at end of file
index 92847ec0817a04bf09f963cf30d0264f907c0071..da395131aad61cd1fd7a0cb65ff79cb81454e272 100644 (file)
@@ -1,4 +1,4 @@
-source.. = src/main/java/
+source.. = src/
 additional.bundles = slf4j.api,\
                      slf4j.org.apache.commons.logging,\
                      slf4j.log4j,\
index f8a23d5a2546042f3245543f0bfba301a43d305d..386f179b61feada289ed0dcefcb0f80f7e96d20a 100644 (file)
@@ -9,39 +9,6 @@
        </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>
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/BooleanAnswer.java b/org.argeo.server.core/src/main/java/org/argeo/server/BooleanAnswer.java
deleted file mode 100644 (file)
index 2b7ffb2..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-       }
-
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/Deserializer.java b/org.argeo.server.core/src/main/java/org/argeo/server/Deserializer.java
deleted file mode 100644 (file)
index 4d7faf9..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.server;
-
-import java.io.Reader;
-
-public interface Deserializer {
-       public <T> T deserialize(Reader reader, Class<T> clss);
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/DeserializingEditor.java b/org.argeo.server.core/src/main/java/org/argeo/server/DeserializingEditor.java
deleted file mode 100644 (file)
index 915b71c..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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);
-               }
-       }
-
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/PrimitiveAnswer.java b/org.argeo.server.core/src/main/java/org/argeo/server/PrimitiveAnswer.java
deleted file mode 100644 (file)
index c69ffed..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*\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
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/Serializer.java b/org.argeo.server.core/src/main/java/org/argeo/server/Serializer.java
deleted file mode 100644 (file)
index 890b17c..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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);
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java b/org.argeo.server.core/src/main/java/org/argeo/server/ServerAnswer.java
deleted file mode 100644 (file)
index 2f9cbee..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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 + "}";
-       }
-
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/ServerSerializer.java b/org.argeo.server.core/src/main/java/org/argeo/server/ServerSerializer.java
deleted file mode 100644 (file)
index cdb1632..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.server;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-public interface ServerSerializer {
-       public void serialize(Object obj, HttpServletRequest request,
-                       HttpServletResponse response);
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/AbstractAtomicBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/AbstractAtomicBackup.java
deleted file mode 100644 (file)
index 53972e5..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-       }
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/AtomicBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/AtomicBackup.java
deleted file mode 100644 (file)
index 3ebe4b5..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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);
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupContext.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupContext.java
deleted file mode 100644 (file)
index 5f6442f..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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();
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupFileSystemManager.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupFileSystemManager.java
deleted file mode 100644 (file)
index 9a0549c..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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);
-               }
-       }
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupPurge.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupPurge.java
deleted file mode 100644 (file)
index 37eecd6..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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);
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupUtils.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/BackupUtils.java
deleted file mode 100644 (file)
index e949b0c..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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() {
-       }
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/MySqlBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/MySqlBackup.java
deleted file mode 100644 (file)
index 8d33771..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-       }
-
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/OpenLdapBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/OpenLdapBackup.java
deleted file mode 100644 (file)
index eb5ce2d..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-       }
-
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/OsCallBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/OsCallBackup.java
deleted file mode 100644 (file)
index 816157c..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-       }
-
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/PostgreSqlBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/PostgreSqlBackup.java
deleted file mode 100644 (file)
index 37716bb..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-       }
-
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupContext.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupContext.java
deleted file mode 100644 (file)
index 872f31c..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-       }
-
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupPurge.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/SimpleBackupPurge.java
deleted file mode 100644 (file)
index 035c49c..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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);
-               }
-
-       }
-
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/SvnBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/SvnBackup.java
deleted file mode 100644 (file)
index 636bbca..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-       }
-
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/backup/SystemBackup.java b/org.argeo.server.core/src/main/java/org/argeo/server/backup/SystemBackup.java
deleted file mode 100644 (file)
index 92f73c7..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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();
-                       }
-               }
-       }
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractMemoryDaoSupport.java b/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractMemoryDaoSupport.java
deleted file mode 100644 (file)
index f9af51b..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-               }
-
-       }
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractTabularDaoSupport.java b/org.argeo.server.core/src/main/java/org/argeo/server/dao/AbstractTabularDaoSupport.java
deleted file mode 100644 (file)
index 1ca5a10..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-               }
-
-       }
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoAware.java b/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoAware.java
deleted file mode 100644 (file)
index 5ae7bea..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.server.dao;
-
-public interface LightDaoAware {
-       public void setLightDaoSupport(LightDaoSupport lightDaoSupport);
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoPropertyEditor.java b/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoPropertyEditor.java
deleted file mode 100644 (file)
index de6ba70..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-       }
-
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoSupport.java b/org.argeo.server.core/src/main/java/org/argeo/server/dao/LightDaoSupport.java
deleted file mode 100644 (file)
index 6ea1b75..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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);
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java
deleted file mode 100644 (file)
index 6269bd0..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-       }
-
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/mvc/EmptyViewController.java b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/EmptyViewController.java
deleted file mode 100644 (file)
index c83d4ae..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*\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
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/mvc/MvcConstants.java b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/MvcConstants.java
deleted file mode 100644 (file)
index d5c32dc..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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";
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingView.java b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingView.java
deleted file mode 100644 (file)
index b42a9a0..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-       }
-
-}
diff --git a/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingViewResolver.java b/org.argeo.server.core/src/main/java/org/argeo/server/mvc/SerializingViewResolver.java
deleted file mode 100644 (file)
index 9331543..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-       }
-
-}
diff --git a/org.argeo.server.core/src/org/argeo/server/BooleanAnswer.java b/org.argeo.server.core/src/org/argeo/server/BooleanAnswer.java
new file mode 100644 (file)
index 0000000..2b7ffb2
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.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;
+       }
+
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/Deserializer.java b/org.argeo.server.core/src/org/argeo/server/Deserializer.java
new file mode 100644 (file)
index 0000000..4d7faf9
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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);
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/DeserializingEditor.java b/org.argeo.server.core/src/org/argeo/server/DeserializingEditor.java
new file mode 100644 (file)
index 0000000..915b71c
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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);
+               }
+       }
+
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/PrimitiveAnswer.java b/org.argeo.server.core/src/org/argeo/server/PrimitiveAnswer.java
new file mode 100644 (file)
index 0000000..c69ffed
--- /dev/null
@@ -0,0 +1,34 @@
+/*\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
diff --git a/org.argeo.server.core/src/org/argeo/server/Serializer.java b/org.argeo.server.core/src/org/argeo/server/Serializer.java
new file mode 100644 (file)
index 0000000..890b17c
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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);
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/ServerAnswer.java b/org.argeo.server.core/src/org/argeo/server/ServerAnswer.java
new file mode 100644 (file)
index 0000000..2f9cbee
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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 + "}";
+       }
+
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/ServerSerializer.java b/org.argeo.server.core/src/org/argeo/server/ServerSerializer.java
new file mode 100644 (file)
index 0000000..cdb1632
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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);
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/backup/AbstractAtomicBackup.java b/org.argeo.server.core/src/org/argeo/server/backup/AbstractAtomicBackup.java
new file mode 100644 (file)
index 0000000..53972e5
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.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;
+       }
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/backup/AtomicBackup.java b/org.argeo.server.core/src/org/argeo/server/backup/AtomicBackup.java
new file mode 100644 (file)
index 0000000..3ebe4b5
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.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);
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/backup/BackupContext.java b/org.argeo.server.core/src/org/argeo/server/backup/BackupContext.java
new file mode 100644 (file)
index 0000000..5f6442f
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.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();
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/backup/BackupFileSystemManager.java b/org.argeo.server.core/src/org/argeo/server/backup/BackupFileSystemManager.java
new file mode 100644 (file)
index 0000000..9a0549c
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.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);
+               }
+       }
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/backup/BackupPurge.java b/org.argeo.server.core/src/org/argeo/server/backup/BackupPurge.java
new file mode 100644 (file)
index 0000000..37eecd6
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.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);
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/backup/BackupUtils.java b/org.argeo.server.core/src/org/argeo/server/backup/BackupUtils.java
new file mode 100644 (file)
index 0000000..e949b0c
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.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() {
+       }
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/backup/MySqlBackup.java b/org.argeo.server.core/src/org/argeo/server/backup/MySqlBackup.java
new file mode 100644 (file)
index 0000000..8d33771
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.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;
+       }
+
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/backup/OpenLdapBackup.java b/org.argeo.server.core/src/org/argeo/server/backup/OpenLdapBackup.java
new file mode 100644 (file)
index 0000000..eb5ce2d
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.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;
+       }
+
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/backup/OsCallBackup.java b/org.argeo.server.core/src/org/argeo/server/backup/OsCallBackup.java
new file mode 100644 (file)
index 0000000..816157c
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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;
+       }
+
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/backup/PostgreSqlBackup.java b/org.argeo.server.core/src/org/argeo/server/backup/PostgreSqlBackup.java
new file mode 100644 (file)
index 0000000..37716bb
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.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;
+       }
+
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/backup/SimpleBackupContext.java b/org.argeo.server.core/src/org/argeo/server/backup/SimpleBackupContext.java
new file mode 100644 (file)
index 0000000..872f31c
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.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;
+       }
+
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/backup/SimpleBackupPurge.java b/org.argeo.server.core/src/org/argeo/server/backup/SimpleBackupPurge.java
new file mode 100644 (file)
index 0000000..035c49c
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * 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);
+               }
+
+       }
+
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/backup/SvnBackup.java b/org.argeo.server.core/src/org/argeo/server/backup/SvnBackup.java
new file mode 100644 (file)
index 0000000..636bbca
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.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;
+       }
+
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/backup/SystemBackup.java b/org.argeo.server.core/src/org/argeo/server/backup/SystemBackup.java
new file mode 100644 (file)
index 0000000..92f73c7
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * 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();
+                       }
+               }
+       }
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/dao/AbstractMemoryDaoSupport.java b/org.argeo.server.core/src/org/argeo/server/dao/AbstractMemoryDaoSupport.java
new file mode 100644 (file)
index 0000000..f9af51b
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+ * 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;
+               }
+
+       }
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/dao/AbstractTabularDaoSupport.java b/org.argeo.server.core/src/org/argeo/server/dao/AbstractTabularDaoSupport.java
new file mode 100644 (file)
index 0000000..1ca5a10
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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;
+               }
+
+       }
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/dao/LightDaoAware.java b/org.argeo.server.core/src/org/argeo/server/dao/LightDaoAware.java
new file mode 100644 (file)
index 0000000..5ae7bea
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * 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);
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/dao/LightDaoPropertyEditor.java b/org.argeo.server.core/src/org/argeo/server/dao/LightDaoPropertyEditor.java
new file mode 100644 (file)
index 0000000..de6ba70
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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;
+       }
+
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/dao/LightDaoSupport.java b/org.argeo.server.core/src/org/argeo/server/dao/LightDaoSupport.java
new file mode 100644 (file)
index 0000000..6ea1b75
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *         http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.argeo.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);
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java b/org.argeo.server.core/src/org/argeo/server/mvc/DefaultHandlerExceptionResolver.java
new file mode 100644 (file)
index 0000000..6269bd0
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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;
+       }
+
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/mvc/EmptyViewController.java b/org.argeo.server.core/src/org/argeo/server/mvc/EmptyViewController.java
new file mode 100644 (file)
index 0000000..c83d4ae
--- /dev/null
@@ -0,0 +1,34 @@
+/*\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
diff --git a/org.argeo.server.core/src/org/argeo/server/mvc/MvcConstants.java b/org.argeo.server.core/src/org/argeo/server/mvc/MvcConstants.java
new file mode 100644 (file)
index 0000000..d5c32dc
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * 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";
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/mvc/SerializingView.java b/org.argeo.server.core/src/org/argeo/server/mvc/SerializingView.java
new file mode 100644 (file)
index 0000000..b42a9a0
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * 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;
+       }
+
+}
diff --git a/org.argeo.server.core/src/org/argeo/server/mvc/SerializingViewResolver.java b/org.argeo.server.core/src/org/argeo/server/mvc/SerializingViewResolver.java
new file mode 100644 (file)
index 0000000..9331543
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * 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;
+       }
+
+}
index c5931a083cd4ad1714f5a9bdc3ea1b2fc05cd360..d2953a684d400476bf716ed6a6c3c3ae486fcd0e 100644 (file)
@@ -1,7 +1,9 @@
 <?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>
diff --git a/org.argeo.server.jcr.mvc/bin/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping$DelegatingServletConfig.class b/org.argeo.server.jcr.mvc/bin/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping$DelegatingServletConfig.class
new file mode 100644 (file)
index 0000000..086b9fa
Binary files /dev/null and b/org.argeo.server.jcr.mvc/bin/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping$DelegatingServletConfig.class differ
diff --git a/org.argeo.server.jcr.mvc/bin/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.class b/org.argeo.server.jcr.mvc/bin/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.class
new file mode 100644 (file)
index 0000000..66c2ea3
Binary files /dev/null and b/org.argeo.server.jcr.mvc/bin/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.class differ
diff --git a/org.argeo.server.jcr.mvc/bin/org/argeo/jcr/mvc/ResourceProxyServlet.class b/org.argeo.server.jcr.mvc/bin/org/argeo/jcr/mvc/ResourceProxyServlet.class
new file mode 100644 (file)
index 0000000..d1dc1db
Binary files /dev/null and b/org.argeo.server.jcr.mvc/bin/org/argeo/jcr/mvc/ResourceProxyServlet.class differ
diff --git a/org.argeo.server.jcr.mvc/bnd.bnd b/org.argeo.server.jcr.mvc/bnd.bnd
new file mode 100644 (file)
index 0000000..b26c2e3
--- /dev/null
@@ -0,0 +1,7 @@
+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",\
+*
index 5fc538bc83f35ba123c9f84f2eb6124dd65c8789..30f715358d984db427238bb1984c0d19b6ca4004 100644 (file)
@@ -1,4 +1 @@
-source.. = src/main/java/
-output.. = target/classes/
-bin.includes = META-INF/,\
-               .
+source.. = src/
diff --git a/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.java b/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.java
deleted file mode 100644 (file)
index fb3f1ae..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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();
-               }
-       }
-}
diff --git a/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/ResourceProxyServlet.java b/org.argeo.server.jcr.mvc/src/main/java/org/argeo/jcr/mvc/ResourceProxyServlet.java
deleted file mode 100644 (file)
index c821be0..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.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;
-       }
-
-}
diff --git a/org.argeo.server.jcr.mvc/src/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.java b/org.argeo.server.jcr.mvc/src/org/argeo/jcr/mvc/MultipleRepositoryHandlerMapping.java
new file mode 100644 (file)
index 0000000..fb3f1ae
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * 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();
+               }
+       }
+}
diff --git a/org.argeo.server.jcr.mvc/src/org/argeo/jcr/mvc/ResourceProxyServlet.java b/org.argeo.server.jcr.mvc/src/org/argeo/jcr/mvc/ResourceProxyServlet.java
new file mode 100644 (file)
index 0000000..c821be0
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * 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;
+       }
+
+}