Introduce Ajaxplorer support in SLC
authorMathieu Baudier <mbaudier@argeo.org>
Thu, 7 Oct 2010 16:33:31 +0000 (16:33 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Thu, 7 Oct 2010 16:33:31 +0000 (16:33 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@3829 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

33 files changed:
modules/server/org.argeo.slc.webapp.war/META-INF/MANIFEST.MF
modules/server/org.argeo.slc.webapp.war/WEB-INF/ajaxplorer-servlet.xml [new file with mode: 0644]
modules/server/org.argeo.slc.webapp.war/WEB-INF/web.xml
runtime/org.argeo.slc.server/pom.xml
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/AjxpAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/AjxpAnswer.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/AjxpDriver.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/AjxpDriverException.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/SimpleAjxpDriver.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/AbstractFileDownloadAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/AjxpFile.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileDeleteAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileDownloadAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileDriver.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileImageProxyAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileLsAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileMkdirAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileType.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileUploadAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/LsMode.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/mvc/AjxpDriverRequestHandler.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/mvc/AjxpDriverServlet.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnAjxpFile.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnDeleteAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnDownloadAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnDriver.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnLogAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnLsAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnMkdirAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnUploadAction.java [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/resources/org/argeo/slc/web/ajaxplorer/file/spring.xml [new file with mode: 0644]
runtime/org.argeo.slc.server/src/main/resources/org/argeo/slc/web/ajaxplorer/svn/spring.xml [new file with mode: 0644]

index d5b0eb9a9584517f84706dfa53c73f7316318a9b..87b8dab4c3ecb70770f822539735e4bbb243138b 100644 (file)
@@ -26,6 +26,8 @@ Import-Package: javax.jcr;specification-version="1.0.0",
  org.argeo.slc.msg.event,
  org.argeo.slc.runtime,
  org.argeo.slc.services,
+ org.argeo.slc.web.ajaxplorer.file;specification-version="0.13.0.SNAPSHOT-r3788",
+ org.argeo.slc.web.ajaxplorer.mvc;specification-version="0.13.0.SNAPSHOT-r3788",
  org.argeo.slc.web.mvc,
  org.argeo.slc.web.mvc.controllers,
  org.argeo.slc.web.mvc.provisioning,
diff --git a/modules/server/org.argeo.slc.webapp.war/WEB-INF/ajaxplorer-servlet.xml b/modules/server/org.argeo.slc.webapp.war/WEB-INF/ajaxplorer-servlet.xml
new file mode 100644 (file)
index 0000000..a706606
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
+       xmlns:tx="http://www.springframework.org/schema/tx"
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
+       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
+
+
+       <import resource="classpath:/org/argeo/slc/web/ajaxplorer/file/spring.xml" />
+
+       <bean id="ajxpDriverHandler"
+               class="org.argeo.slc.web.ajaxplorer.mvc.AjxpDriverRequestHandler">
+               <property name="driver" ref="ajxpDriver" />
+       </bean>
+
+       <bean id="ajxpDriver" parent="driver.file.template">
+               <property name="basePath" value="/home/mbaudier/dev/work/dcrawTests" />
+       </bean>
+
+       <bean id="urlMapping"
+               class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
+               <property name="mappings">
+                       <props>
+                               <prop key="**">ajxpDriverHandler</prop>
+                       </props>
+               </property>
+       </bean>
+
+</beans>
\ No newline at end of file
index e4341a78b31060958b98d108f9a163e136dd8201..10f237de2a442c121611a74d6fe359c7caaaa7c6 100644 (file)
                <url-pattern>/jcr-manager/*</url-pattern>
        </servlet-mapping>
 
+       <!-- AjaXplorer servlet -->
+       <servlet>
+               <servlet-name>ajaxplorer</servlet-name>
+               <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+               <init-param>
+                       <param-name>contextClass</param-name>
+                       <param-value>org.springframework.osgi.web.context.support.OsgiBundleXmlWebApplicationContext</param-value>
+               </init-param>
+               <load-on-startup>1</load-on-startup>
+       </servlet>
+
+       <servlet-mapping>
+               <servlet-name>ajaxplorer</servlet-name>
+               <url-pattern>/ajaxplorer/*</url-pattern>
+       </servlet-mapping>
+
        <!-- General -->
        <context-param>
                <param-name>contextConfigLocation</param-name>
index 4a148d63ed97c37ffceb2254e01b52c6e29d7ec2..a39981a6df165531dae0757585a7c4541f7b3984 100644 (file)
@@ -26,6 +26,7 @@
                                                        org.argeo.slc.activemq,
                                                        org.argeo.slc.execution,
                                                        org.springframework.context.support,
+                                                       org.tmatesoft.svn.*;resolution:=optional,
                                                        *
                                                </Import-Package>
                                        </instructions>
                        <artifactId>com.springsource.org.antlr</artifactId>
                </dependency>
 
+               <!-- SVN -->
+               <dependency>
+                       <groupId>com.svnkit</groupId>
+                       <artifactId>com.springsource.org.tmatesoft.svn</artifactId>
+                       <optional>true</optional>
+               </dependency>
+
+               <!--  Commons VFS
+               <dependency>
+                       <groupId>org.apache.commons</groupId>
+                       <artifactId>com.springsource.org.apache.commons.vfs</artifactId>
+               </dependency> -->
+
        </dependencies>
 </project>
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/AjxpAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/AjxpAction.java
new file mode 100644 (file)
index 0000000..23ccc9c
--- /dev/null
@@ -0,0 +1,7 @@
+package org.argeo.slc.web.ajaxplorer;
+
+import javax.servlet.http.HttpServletRequest;
+
+public interface AjxpAction<T extends AjxpDriver>{
+       public AjxpAnswer execute(T driver, HttpServletRequest request);
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/AjxpAnswer.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/AjxpAnswer.java
new file mode 100644 (file)
index 0000000..6c45c33
--- /dev/null
@@ -0,0 +1,12 @@
+package org.argeo.slc.web.ajaxplorer;
+
+import javax.servlet.http.HttpServletResponse;
+
+public interface AjxpAnswer {
+       public static AjxpAnswer DO_NOTHING = new AjxpAnswer(){
+               public void updateResponse(HttpServletResponse response) {
+               }
+       };
+
+       public void updateResponse(HttpServletResponse response);
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/AjxpDriver.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/AjxpDriver.java
new file mode 100644 (file)
index 0000000..e96648e
--- /dev/null
@@ -0,0 +1,7 @@
+package org.argeo.slc.web.ajaxplorer;
+
+import javax.servlet.http.HttpServletRequest;
+
+public interface AjxpDriver {
+       public AjxpAnswer executeAction(HttpServletRequest request); 
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/AjxpDriverException.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/AjxpDriverException.java
new file mode 100644 (file)
index 0000000..647e2b4
--- /dev/null
@@ -0,0 +1,14 @@
+package org.argeo.slc.web.ajaxplorer;
+
+public class AjxpDriverException extends RuntimeException {
+       static final long serialVersionUID = 1l;
+
+       public AjxpDriverException(String arg0) {
+               super(arg0);
+       }
+
+       public AjxpDriverException(String arg0, Throwable arg1) {
+               super(arg0, arg1);
+       }
+
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/SimpleAjxpDriver.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/SimpleAjxpDriver.java
new file mode 100644 (file)
index 0000000..732b41c
--- /dev/null
@@ -0,0 +1,32 @@
+package org.argeo.slc.web.ajaxplorer;
+
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class SimpleAjxpDriver implements AjxpDriver {
+       protected final Log log = LogFactory.getLog(getClass());
+       private Map<String, AjxpAction<? extends AjxpDriver>> actions = new TreeMap<String, AjxpAction<? extends AjxpDriver>>();
+
+       public AjxpAnswer executeAction(HttpServletRequest request) {
+               String actionStr = request.getParameter("get_action");
+               if (actionStr == null) {
+                       actionStr = request.getParameter("action");
+               }
+               if (!actions.containsKey(actionStr)) {
+                       throw new AjxpDriverException("Action " + actionStr
+                                       + " not defined.");
+               }
+               AjxpAction action = actions.get(actionStr);
+               return action.execute(this,request);
+       }
+
+       public void setActions(Map<String, AjxpAction<? extends AjxpDriver>> actions) {
+               this.actions = actions;
+       }
+
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/AbstractFileDownloadAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/AbstractFileDownloadAction.java
new file mode 100644 (file)
index 0000000..c9a71a1
--- /dev/null
@@ -0,0 +1,73 @@
+package org.argeo.slc.web.ajaxplorer.file;
+
+import java.io.File;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.argeo.slc.web.ajaxplorer.AjxpAnswer;
+import org.argeo.slc.web.ajaxplorer.AjxpDriverException;
+
+public abstract class AbstractFileDownloadAction extends FileAction {
+       public AjxpAnswer execute(FileDriver driver, HttpServletRequest request) {
+               String fileStr = request.getParameter(getFileParameter());
+               if (fileStr == null) {
+                       throw new AjxpDriverException(
+                                       "A  file to download needs to be provided.");
+               }
+               File file = new File(driver.getBasePath() + fileStr);
+               return new AxpBasicDownloadAnswer(file);
+       }
+
+       /** Return 'file' by default. */
+       protected String getFileParameter() {
+               return "file";
+       }
+
+       /** To be overridden. Do nothing by default. */
+       protected void setHeaders(HttpServletResponse response, File file) {
+               // do nothing
+       }
+
+       protected class AxpBasicDownloadAnswer implements AjxpAnswer {
+               private final File file;
+
+               public AxpBasicDownloadAnswer(File file) {
+                       this.file = file;
+               }
+
+               public void updateResponse(HttpServletResponse response) {
+                       InputStream in = null;
+                       OutputStream out = null;
+                       try {
+                               setHeaders(response, file);
+
+                               if (log.isDebugEnabled())
+                                       log.debug("Download file " + file);
+                               in = FileUtils.openInputStream(file);
+                               out = response.getOutputStream();
+
+                               copyFile(in, out);
+                               out.flush();
+
+                       } catch (Exception e) {
+                               e.printStackTrace();
+                               throw new AjxpDriverException("Cannot download file " + file, e);
+                       } finally {
+                               IOUtils.closeQuietly(in);
+                               IOUtils.closeQuietly(out);
+                       }
+
+               }
+
+               protected void copyFile(InputStream in, OutputStream out)
+                               throws Exception {
+                       IOUtils.copy(in, out);
+               }
+
+       }
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/AjxpFile.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/AjxpFile.java
new file mode 100644 (file)
index 0000000..22975cb
--- /dev/null
@@ -0,0 +1,125 @@
+package org.argeo.slc.web.ajaxplorer.file;
+
+import java.io.File;
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.web.ajaxplorer.AjxpDriverException;
+
+public class AjxpFile {
+       private final static Log log = LogFactory.getLog(AjxpFile.class);
+
+       // FIXME: more generic modif time format?
+       private final static SimpleDateFormat sdf = new SimpleDateFormat(
+                       "dd/MM/yyyy hh:mm");
+
+       private final File file;
+       private final String parentPath;
+       private final String filePath;
+
+       private final String ext;
+       private final FileType type;
+
+       public AjxpFile(File file, String parentPath) {
+               this.file = file;
+               this.parentPath = parentPath;
+               if (parentPath.equals("/")) {
+                       this.filePath = "/" + file.getName();
+               } else {
+                       this.filePath = parentPath + "/" + file.getName();
+               }
+               this.ext = file.isDirectory() ? null : file.getName().substring(
+                               file.getName().indexOf('.') + 1);
+               this.type = FileType.findType(ext);
+       }
+
+       public String toXml(final LsMode mode, final String encoding) {
+               try {
+                       StringBuffer buf = new StringBuffer();
+                       buf.append("<tree");
+                       addAttr("text", file.getName(), buf);
+                       if (type != FileType.FOLDER) {
+                               if (mode == LsMode.SEARCH)
+                                       addAttr("is_file", "true", buf);// FIXME: consistent value?
+                               else if (mode == LsMode.FILE_LIST) {
+                                       addAttr("filename", filePath, buf);
+                                       addAttr("is_file", "1", buf);
+                                       addAttr("icon", type.getIcon(), buf);
+
+                                       addAttr("modiftime", formatModifTime(), buf);
+                                       addAttr("mimestring", type.getMimeString(), buf);
+                                       addAttr("filesize", formatFileSize(), buf);
+
+                                       if (type.isImage()) {
+                                               addAttr("is_image", "1", buf);
+                                               addAttr("image_type", type.getImageType(), buf);
+                                               addAttr("image_width", "100", buf);// FIXME: read image
+                                               addAttr("image_height", "100", buf);// FIXME: read image
+
+                                       } else {
+                                               addAttr("is_image", "0", buf);
+                                       }
+                               }
+
+                       } else {// dir
+                               if (mode == LsMode.NULL || mode == LsMode.FILE_LIST) {
+                                       addAttr("filename", filePath, buf);
+                                       if (mode == LsMode.NULL) {
+                                               addAttr("icon", "client/images/foldericon.png", buf);
+                                               addAttr("openicon", "client/images/openfoldericon.png",
+                                                               buf);
+                                               addAttr("parentName", parentPath, buf);
+                                               addAttr("src", "content.php?dir="
+                                                               + URLEncoder.encode(filePath, encoding), buf);
+                                               addAttr(
+                                                               "action",
+                                                               "javascript:ajaxplorer.getFoldersTree().clickNode(CURRENT_ID)",
+                                                               buf);
+                                       } else if (mode == LsMode.FILE_LIST) {
+                                               addAttr("icon", type.getIcon(), buf);// FIXME:
+                                               // consistent?
+                                               addAttr("is_file", "0", buf);
+                                               addAttr("is_image", "0", buf);
+                                               addAttr("mimestring", "Directory", buf);
+                                               addAttr("modiftime", formatModifTime(), buf);
+                                               addAttr("filesize", "-", buf);
+                                       }
+                               }
+
+                       }
+
+                       addAdditionalAttrs(buf, mode, encoding);
+
+                       buf.append("/>");
+
+                       if (log.isTraceEnabled())
+                               log.trace(buf.toString());
+
+                       return buf.toString();
+               } catch (Exception e) {
+                       throw new AjxpDriverException("Could not serialize file " + file, e);
+               }
+       }
+
+       private String formatModifTime() {
+               return sdf.format(new Date(file.lastModified()));
+       }
+
+       private String formatFileSize() {
+               return (file.length() / 1024) + " Kb";
+       }
+
+       protected void addAttr(String attrName, String attrValue, StringBuffer buf) {
+               buf.append(" ").append(attrName).append("=\"").append(attrValue)
+                               .append("\"");
+       }
+
+       /** To be overridden, do nothing by default. */
+       protected void addAdditionalAttrs(final StringBuffer buf,
+                       final LsMode mode, final String encoding) {
+
+       }
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileAction.java
new file mode 100644 (file)
index 0000000..fc5fdda
--- /dev/null
@@ -0,0 +1,9 @@
+package org.argeo.slc.web.ajaxplorer.file;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.web.ajaxplorer.AjxpAction;
+
+public abstract class FileAction implements AjxpAction<FileDriver> {
+       protected final Log log = LogFactory.getLog(getClass());
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileDeleteAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileDeleteAction.java
new file mode 100644 (file)
index 0000000..bd8c8f7
--- /dev/null
@@ -0,0 +1,39 @@
+package org.argeo.slc.web.ajaxplorer.file;\r
+\r
+import java.io.File;\r
+import java.util.Map;\r
+\r
+import javax.servlet.http.HttpServletRequest;\r
+\r
+import org.argeo.slc.web.ajaxplorer.AjxpAnswer;\r
+\r
+public class FileDeleteAction<T extends FileDriver> extends FileAction {\r
+\r
+       public AjxpAnswer execute(FileDriver driver, HttpServletRequest request) {\r
+               Map<Object, Object> params = request.getParameterMap();\r
+               for (Object paramKey : params.keySet()) {\r
+                       String param = paramKey.toString();\r
+                       log.debug("param=" + param + " (" + params.get(paramKey));\r
+                       if (param.length() < 4)\r
+                               continue;\r
+                       else {\r
+\r
+                               if (param.substring(0, 4).equals("file")) {\r
+                                       String[] values = (String[]) params.get(paramKey);\r
+                                       for (String path : values) {\r
+                                               File file = driver.getFile(path);\r
+                                               executeDelete((T) driver, file);\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               return AjxpAnswer.DO_NOTHING;\r
+       }\r
+\r
+       protected void executeDelete(T driver, File file) {\r
+               log.debug("Delete file " + file);\r
+               file.delete();\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileDownloadAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileDownloadAction.java
new file mode 100644 (file)
index 0000000..b47c91c
--- /dev/null
@@ -0,0 +1,27 @@
+package org.argeo.slc.web.ajaxplorer.file;
+
+import java.io.File;
+
+import javax.servlet.http.HttpServletResponse;
+
+public class FileDownloadAction extends AbstractFileDownloadAction {
+
+       @Override
+       protected void setHeaders(HttpServletResponse response, File file) {
+               setDefaultDownloadHeaders(response, file.getName(), file.length());
+       }
+
+       public static void setDefaultDownloadHeaders(HttpServletResponse response,
+                       String fileName, Long fileLength) {
+               response.setContentType("application/force-download; name=\""
+                               + fileName + "\"");
+               response.setHeader("Content-Transfer-Encoding", "binary");
+               if (fileLength != null)
+                       response.setContentLength(fileLength.intValue());
+               response.setHeader("Content-Disposition", "attachement; filename=\""
+                               + fileName + "\"");
+               response.setHeader("Expires", "0");
+               response.setHeader("Cache-Control", "no-cache, must-revalidate");
+               response.setHeader("Pragma", "no-cache");
+       }
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileDriver.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileDriver.java
new file mode 100644 (file)
index 0000000..d38ab32
--- /dev/null
@@ -0,0 +1,40 @@
+package org.argeo.slc.web.ajaxplorer.file;
+
+import java.io.File;
+
+import org.argeo.slc.web.ajaxplorer.SimpleAjxpDriver;
+
+public class FileDriver extends SimpleAjxpDriver{
+       private String basePath;
+       private String encoding = "UTF-8";
+
+       public String getBasePath() {
+               return basePath;
+       }
+       
+       public File getBaseDir(){
+               return new File(getBasePath());
+       }
+
+       public void setBasePath(String basePath) {
+               if (basePath.charAt(basePath.length() - 1) != File.separatorChar)
+                       basePath = basePath + File.separatorChar;
+               this.basePath = basePath;
+       }
+
+       public String getEncoding() {
+               return encoding;
+       }
+
+       public void setEncoding(String encoding) {
+               this.encoding = encoding;
+       }
+
+       public File getFile(String relpath) {
+               return new File(getBasePath() + relpath).getAbsoluteFile();
+       }
+
+       public File getFile(String dir, String fileName) {
+               return getFile(dir + File.separator + fileName);
+       }
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileImageProxyAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileImageProxyAction.java
new file mode 100644 (file)
index 0000000..1d2d6de
--- /dev/null
@@ -0,0 +1,17 @@
+package org.argeo.slc.web.ajaxplorer.file;
+
+import java.io.File;
+
+import javax.servlet.http.HttpServletResponse;
+
+public class FileImageProxyAction extends AbstractFileDownloadAction {
+
+       @Override
+       protected void setHeaders(HttpServletResponse response, File file) {
+               FileType fileType = FileType.findType(file);
+               response.setContentType(fileType.getImageType());
+               response.setContentLength((int) file.length());
+               response.setHeader("Cache-Control", "public");
+       }
+
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileLsAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileLsAction.java
new file mode 100644 (file)
index 0000000..4dd4907
--- /dev/null
@@ -0,0 +1,131 @@
+package org.argeo.slc.web.ajaxplorer.file;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.OutputStreamWriter;
+import java.util.List;
+import java.util.Vector;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.io.IOUtils;
+import org.argeo.slc.web.ajaxplorer.AjxpAnswer;
+import org.argeo.slc.web.ajaxplorer.AjxpDriverException;
+
+public class FileLsAction<T extends FileDriver, F extends AjxpFile> extends
+               FileAction {
+
+       public AjxpAnswer execute(FileDriver driver, HttpServletRequest request) {
+               String modeStr = request.getParameter("mode");
+               LsMode mode;
+               if (modeStr == null)
+                       mode = LsMode.NULL;
+               else if (modeStr.equals("complete"))
+                       mode = LsMode.COMPLETE;
+               else if (modeStr.equals("file_list"))
+                       mode = LsMode.FILE_LIST;
+               else if (modeStr.equals("search"))
+                       mode = LsMode.SEARCH;
+               else
+                       throw new AjxpDriverException("Unkown mode " + modeStr);
+
+               String options = request.getParameter("options");
+               if (options != null) {
+                       if ("al".equals(options))
+                               mode = LsMode.FILE_LIST;
+               }
+
+               String path = request.getParameter("dir");
+               if (path == null) {
+                       path = "/";
+               }
+
+               boolean dirOnly = false;
+               if (mode == LsMode.NULL || mode == LsMode.COMPLETE) {
+                       dirOnly = true;
+               }
+
+               List<F> ajxpFiles = listFiles((T) driver, path, dirOnly);
+               /*
+                * File[] files = dir.listFiles(createFileFilter(request, dir));
+                * List<AjxpFile> ajxpFiles = new Vector<AjxpFile>(); for (File file :
+                * files) { if (file.isDirectory()) { ajxpFiles.add(new AjxpFile(file,
+                * path)); } else { if (!dirOnly) ajxpFiles.add(new AjxpFile(file,
+                * path)); } }
+                */
+               return new AxpLsAnswer(driver, ajxpFiles, mode);
+       }
+
+       protected List<F> listFiles(T driver, String path, boolean dirOnly) {
+               File dir = driver.getFile(path);
+
+               if (!dir.exists())
+                       throw new AjxpDriverException("Dir " + dir + " does not exist.");
+
+               FileFilter filter = createFileFilter(dir);
+               File[] files = dir.listFiles(filter);
+               List<F> ajxpFiles = new Vector<F>();
+               for (File file : files) {
+                       if (file.isDirectory()) {
+                               ajxpFiles.add((F) new AjxpFile(file, path));
+                       } else {
+                               if (!dirOnly)
+                                       ajxpFiles.add((F) new AjxpFile(file, path));
+                       }
+               }
+               return ajxpFiles;
+       }
+
+       /** To be overridden. Accept all by default. */
+       protected FileFilter createFileFilter(File dir) {
+               return new FileFilter() {
+                       public boolean accept(File pathname) {
+                               return true;
+                       }
+
+               };
+       }
+
+       protected class AxpLsAnswer implements AjxpAnswer {
+               private final List<F> files;
+               private final LsMode mode;
+               private final FileDriver driver;
+
+               public AxpLsAnswer(FileDriver driver, List<F> files, LsMode mode) {
+                       this.files = files;
+                       this.mode = mode;
+                       this.driver = driver;
+               }
+
+               public void updateResponse(HttpServletResponse response) {
+                       final String encoding = driver.getEncoding();
+                       response.setCharacterEncoding(encoding);
+                       response.setContentType("text/xml");
+
+                       ServletOutputStream out = null;
+                       OutputStreamWriter writer = null;
+                       try {
+                               out = response.getOutputStream();
+                               writer = new OutputStreamWriter(out, encoding);
+                               writer.write("<?xml version=\"1.0\" encoding=\"" + encoding
+                                               + "\"?>");
+                               // TODO add current path
+                               writer.write("<tree>");
+                               for (AjxpFile file : files) {
+                                       writer.write(file.toXml(mode, encoding));
+                               }
+                               writer.write("</tree>");
+                               writer.flush();
+
+                       } catch (Exception e) {
+                               throw new AjxpDriverException("Could not write response.", e);
+                       } finally {
+                               IOUtils.closeQuietly(writer);
+                               IOUtils.closeQuietly(out);
+                       }
+               }
+
+       }
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileMkdirAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileMkdirAction.java
new file mode 100644 (file)
index 0000000..5a58372
--- /dev/null
@@ -0,0 +1,27 @@
+package org.argeo.slc.web.ajaxplorer.file;\r
+\r
+import java.io.File;\r
+\r
+import javax.servlet.http.HttpServletRequest;\r
+\r
+import org.argeo.slc.web.ajaxplorer.AjxpAnswer;\r
+\r
+public class FileMkdirAction<T extends FileDriver> extends FileAction {\r
+\r
+       public AjxpAnswer execute(FileDriver driver,\r
+                       HttpServletRequest request) {\r
+               String dir = request.getParameter("dir");\r
+               String dirName = request.getParameter("dirname");\r
+\r
+               File newDir = driver.getFile(dir, dirName);\r
+               newDir.mkdirs();\r
+\r
+               postProcess((T)driver,newDir);\r
+\r
+               return AjxpAnswer.DO_NOTHING;\r
+       }\r
+\r
+       protected void postProcess(T driver,File newDir) {\r
+\r
+       }\r
+}\r
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileType.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileType.java
new file mode 100644 (file)
index 0000000..bebdc71
--- /dev/null
@@ -0,0 +1,70 @@
+package org.argeo.slc.web.ajaxplorer.file;
+
+import java.io.File;
+
+import org.argeo.slc.web.ajaxplorer.AjxpDriverException;
+
+public enum FileType {
+       FOLDER("folder.png", "Directory"), UNKNOWN("mime_empty.png", "Unkown"), GIF(
+                       "image.png", "GIF Picture"), JPEG("image.png", "JPEG Picture"), PNG(
+                       "image.png", "PNG Picture");
+
+       private final String icon;
+       private final String mimeString;
+
+       FileType(String icon, String mimeString) {
+               this.icon = icon;
+               this.mimeString = mimeString;
+       }
+
+       public String getIcon() {
+               return icon;
+       }
+
+       public String getMimeString() {
+               return mimeString;
+       }
+
+       public boolean isImage() {
+               return this == GIF || this == JPEG || this == PNG;
+       }
+
+       public String getImageType() {
+               switch (this) {
+               case GIF:
+                       return "image/gif";
+               case JPEG:
+                       return "image/jpeg";
+               case PNG:
+                       return "image/png";
+               }
+               throw new AjxpDriverException("Image type undefined for " + this);
+       }
+
+       public static FileType findType(File file) {
+               String ext = file.isDirectory() ? null : file.getName().substring(
+                               file.getName().indexOf('.') + 1);
+               return findType(ext);
+       }
+
+       /**
+        * Find the type based on the extension.
+        * 
+        * @param ext
+        *            the extension, null for a directory
+        */
+       public static FileType findType(String extArg) {
+               if (extArg == null)
+                       return FOLDER;
+
+               String ext = extArg.toLowerCase();
+               if (ext.equals("jpg") || ext.equals("jpeg"))
+                       return JPEG;
+               else if (ext.equals("gif"))
+                       return GIF;
+               else if (ext.equals("png"))
+                       return PNG;
+               else
+                       return UNKNOWN;
+       }
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileUploadAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/FileUploadAction.java
new file mode 100644 (file)
index 0000000..52118f0
--- /dev/null
@@ -0,0 +1,52 @@
+package org.argeo.slc.web.ajaxplorer.file;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.io.IOUtils;
+import org.argeo.slc.web.ajaxplorer.AjxpAnswer;
+import org.argeo.slc.web.ajaxplorer.AjxpDriverException;
+import org.springframework.web.multipart.MultipartFile;
+import org.springframework.web.multipart.MultipartHttpServletRequest;
+
+public class FileUploadAction<T extends FileDriver> extends FileAction {
+
+       public AjxpAnswer execute(FileDriver driver, HttpServletRequest request) {
+               if (!(request instanceof MultipartHttpServletRequest)) {
+                       throw new AjxpDriverException(
+                                       "Cann only deal with MultipartHttpServletRequest");
+               }
+               MultipartHttpServletRequest mpr = (MultipartHttpServletRequest) request;
+               String dir = mpr.getParameter("dir");
+               String fileName = mpr.getParameter("Filename");
+
+               InputStream in = null;
+               OutputStream out = null;
+               File file = null;
+               try {
+                       MultipartFile mpfile = mpr.getFile("Filedata");
+                       in = mpfile.getInputStream();
+                       file = driver.getFile(dir, fileName);
+                       out = new FileOutputStream(file);
+                       IOUtils.copy(in, out);
+               } catch (IOException e) {
+                       throw new AjxpDriverException("Cannot upload file.", e);
+               } finally {
+                       IOUtils.closeQuietly(in);
+                       IOUtils.closeQuietly(out);
+               }
+               postProcess((T)driver, file);
+
+               return AjxpAnswer.DO_NOTHING;
+       }
+
+       protected void postProcess(T driver,File file) {
+
+       }
+
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/LsMode.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/file/LsMode.java
new file mode 100644 (file)
index 0000000..a17727d
--- /dev/null
@@ -0,0 +1,5 @@
+package org.argeo.slc.web.ajaxplorer.file;
+
+public enum LsMode {
+       NULL, COMPLETE, FILE_LIST, SEARCH
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/mvc/AjxpDriverRequestHandler.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/mvc/AjxpDriverRequestHandler.java
new file mode 100644 (file)
index 0000000..10593fc
--- /dev/null
@@ -0,0 +1,71 @@
+package org.argeo.slc.web.ajaxplorer.mvc;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+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.slc.web.ajaxplorer.AjxpAnswer;
+import org.argeo.slc.web.ajaxplorer.AjxpDriver;
+import org.springframework.web.HttpRequestHandler;
+
+public class AjxpDriverRequestHandler implements HttpRequestHandler {
+
+       protected final Log log = LogFactory.getLog(getClass());
+       private AjxpDriver driver;
+
+       public void handleRequest(HttpServletRequest req, HttpServletResponse resp)
+                       throws ServletException, IOException {
+               long id = System.currentTimeMillis();
+               try {
+                       if (log.isDebugEnabled())
+                               logRequest(id, req.getMethod(), req);
+
+                       AjxpAnswer answer = driver.executeAction(req);
+                       answer.updateResponse(resp);
+
+                       if (log.isTraceEnabled())
+                               log.trace(id + " " + req.getMethod() + " completed");
+               } catch (Exception e) {
+                       log.error(id + " Cannot process request.", e);
+                       throw new ServletException("Cannot process request " + id, e);
+               }
+
+       }
+
+       protected void logRequest(long id, String method, HttpServletRequest req) {
+               if (log.isDebugEnabled()) {
+                       StringBuffer buf = new StringBuffer(id + " Received " + method
+                                       + ": ");
+                       buf.append('{');
+                       @SuppressWarnings("unchecked")
+                       Map<String, String[]> params = req.getParameterMap();
+                       int count1 = 0;
+                       for (Map.Entry<String, String[]> entry : params.entrySet()) {
+                               if (count1 != 0)
+                                       buf.append(", ");
+                               buf.append(entry.getKey()).append("={");
+                               int count2 = 0;
+                               for (String value : entry.getValue()) {
+                                       if (count2 != 0)
+                                               buf.append(',');
+                                       buf.append(value);
+                                       count2++;
+                               }
+                               buf.append('}');
+                               count1++;
+                       }
+                       buf.append('}');
+                       log.debug(buf.toString());
+               }
+       }
+
+       public void setDriver(AjxpDriver driver) {
+               this.driver = driver;
+       }
+
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/mvc/AjxpDriverServlet.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/mvc/AjxpDriverServlet.java
new file mode 100644 (file)
index 0000000..09e0fb2
--- /dev/null
@@ -0,0 +1,129 @@
+package org.argeo.slc.web.ajaxplorer.mvc;
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Map;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+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.slc.web.ajaxplorer.AjxpAnswer;
+import org.argeo.slc.web.ajaxplorer.AjxpDriver;
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
+import org.springframework.beans.BeansException;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+import org.springframework.web.servlet.HttpServletBean;
+
+public class AjxpDriverServlet extends HttpServletBean {
+       static final long serialVersionUID = 1l;
+
+       protected final Log log = LogFactory.getLog(getClass());
+       private String driverBean;
+       private AjxpDriver driver;
+
+       @Override
+       public void init(ServletConfig sc) throws ServletException {
+               super.init(sc);
+               WebApplicationContext context = WebApplicationContextUtils
+                               .getRequiredWebApplicationContext(sc.getServletContext());
+               driverBean = sc.getInitParameter("driverBean");
+               if (driverBean == null) {
+                       throw new ServletException(
+                                       "No driver found, please set the driverBean property");
+               }
+
+               logger.info("Loading driver " + driverBean);
+               driver = (AjxpDriver) context.getBean(driverBean);
+
+               // overrideBeanProperties(sc);
+       }
+
+       @Override
+       protected void doGet(HttpServletRequest req, HttpServletResponse resp)
+                       throws ServletException, IOException {
+               processRequest("GET", req, resp);
+       }
+
+       @Override
+       protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+                       throws ServletException, IOException {
+               processRequest("POST", req, resp);
+       }
+
+       protected void processRequest(String method, HttpServletRequest req,
+                       HttpServletResponse resp) throws ServletException, IOException {
+               long id = System.currentTimeMillis();
+               try {
+                       if (log.isDebugEnabled())
+                               logRequest(id, method, req);
+
+                       AjxpAnswer answer = driver.executeAction(req);
+                       answer.updateResponse(resp);
+
+                       if (log.isDebugEnabled())
+                               log.debug(id + " " + method + " completed");
+               } catch (Exception e) {
+                       log.error(id + " Cannot process request.", e);
+                       throw new ServletException("Cannot process request " + id, e);
+               }
+
+       }
+
+       public void setDriverBean(String driverName) {
+               this.driverBean = driverName;
+       }
+
+       protected void logRequest(long id, String method, HttpServletRequest req) {
+               if (log.isDebugEnabled()) {
+                       StringBuffer buf = new StringBuffer(id + " Received " + method
+                                       + ": ");
+                       buf.append('{');
+                       Map<String, String[]> params = req.getParameterMap();
+                       int count1 = 0;
+                       for (Map.Entry<String, String[]> entry : params.entrySet()) {
+                               if (count1 != 0)
+                                       buf.append(", ");
+                               buf.append(entry.getKey()).append("={");
+                               int count2 = 0;
+                               for (String value : entry.getValue()) {
+                                       if (count2 != 0)
+                                               buf.append(',');
+                                       buf.append(value);
+                                       count2++;
+                               }
+                               buf.append('}');
+                               count1++;
+                       }
+                       buf.append('}');
+                       log.debug(buf.toString());
+               }
+       }
+
+       protected void overrideBeanProperties(ServletConfig sc)
+                       throws ServletException {
+               BeanWrapper wrapper = new BeanWrapperImpl(driver);
+               Enumeration<String> en = sc.getInitParameterNames();
+               while (en.hasMoreElements()) {
+                       String name = en.nextElement();
+                       if (name.indexOf(driverBean + '.') == 0
+                                       && name.length() > (driverBean.length() + 1)) {
+                               String propertyName = name.substring(driverBean.length() + 1);
+                               String value = sc.getInitParameter(name);
+                               if (value != null) {
+                                       try {
+                                               wrapper.setPropertyValue(propertyName, value);
+                                       } catch (BeansException e) {
+                                               throw new ServletException("Cannot set property "
+                                                               + propertyName + " of bean " + driverBean, e);
+                                       }
+                               }
+                       }
+               }
+       }
+}
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnAjxpFile.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnAjxpFile.java
new file mode 100644 (file)
index 0000000..87a2c9d
--- /dev/null
@@ -0,0 +1,23 @@
+package org.argeo.slc.web.ajaxplorer.svn;\r
+\r
+import org.argeo.slc.web.ajaxplorer.file.AjxpFile;\r
+import org.argeo.slc.web.ajaxplorer.file.LsMode;\r
+import org.tmatesoft.svn.core.wc.SVNInfo;\r
+\r
+public class SvnAjxpFile extends AjxpFile {\r
+\r
+       protected final SVNInfo info;\r
+\r
+       public SvnAjxpFile(SVNInfo info, String parentPath) {\r
+               super(info.getFile(), parentPath);\r
+               this.info = info;\r
+       }\r
+\r
+       @Override\r
+       protected void addAdditionalAttrs(StringBuffer buf, LsMode mode,\r
+                       String encoding) {\r
+               addAttr("author", info.getAuthor(), buf);\r
+               addAttr("revision", Long.toString(info.getRevision().getNumber()), buf);\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnDeleteAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnDeleteAction.java
new file mode 100644 (file)
index 0000000..7995431
--- /dev/null
@@ -0,0 +1,27 @@
+package org.argeo.slc.web.ajaxplorer.svn;\r
+\r
+import java.io.File;\r
+\r
+import org.argeo.slc.web.ajaxplorer.AjxpDriverException;\r
+import org.argeo.slc.web.ajaxplorer.file.FileDeleteAction;\r
+import org.tmatesoft.svn.core.SVNException;\r
+\r
+public class SvnDeleteAction extends FileDeleteAction<SvnDriver> {\r
+       @Override\r
+       protected void executeDelete(SvnDriver driver, File file) {\r
+               try {\r
+                       driver.beginWriteAction(file.getParentFile());\r
+\r
+                       log.debug("SVN Delete: " + file);\r
+                       driver.getManager().getWCClient().doDelete(file, true, false);\r
+\r
+                       driver.commitAll("Commit delete of " + file.getName());\r
+                       driver.completeWriteAction(file.getParentFile());\r
+               } catch (SVNException e) {\r
+                       throw new AjxpDriverException("Cannot delete file " + file, e);\r
+               } finally {\r
+                       driver.rollbackWriteAction(file.getParentFile());\r
+               }\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnDownloadAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnDownloadAction.java
new file mode 100644 (file)
index 0000000..4700342
--- /dev/null
@@ -0,0 +1,72 @@
+package org.argeo.slc.web.ajaxplorer.svn;\r
+\r
+import javax.servlet.ServletOutputStream;\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import org.apache.commons.io.IOUtils;\r
+import org.argeo.slc.web.ajaxplorer.AjxpAction;\r
+import org.argeo.slc.web.ajaxplorer.AjxpAnswer;\r
+import org.argeo.slc.web.ajaxplorer.AjxpDriverException;\r
+import org.argeo.slc.web.ajaxplorer.file.FileDownloadAction;\r
+import org.tmatesoft.svn.core.io.SVNRepository;\r
+\r
+public class SvnDownloadAction implements AjxpAction<SvnDriver> {\r
+\r
+       public AjxpAnswer execute(SvnDriver driver, HttpServletRequest request) {\r
+               String path = request.getParameter("file");\r
+               if (path.charAt(path.length() - 1) == '/') {\r
+                       // probably a directory\r
+                       return AjxpAnswer.DO_NOTHING;\r
+               }\r
+\r
+               String revStr = request.getParameter("rev");\r
+               Long rev = Long.parseLong(revStr);\r
+               return new SvnDownloadAnswer(driver, path, rev);\r
+       }\r
+\r
+       public class SvnDownloadAnswer implements AjxpAnswer {\r
+               private final SvnDriver driver;\r
+               private final String path;\r
+               private final Long rev;\r
+\r
+               public SvnDownloadAnswer(SvnDriver driver, String path, Long rev) {\r
+                       this.driver = driver;\r
+                       this.path = path;\r
+                       this.rev = rev;\r
+               }\r
+\r
+               public void updateResponse(HttpServletResponse response) {\r
+                       ServletOutputStream out = null;\r
+                       try {\r
+                               FileDownloadAction.setDefaultDownloadHeaders(response,\r
+                                               getFileName(), null);\r
+                               response.setHeader("AjaXplorer-SvnFileName", getFileName());\r
+\r
+                               SVNRepository repository = driver.getRepository();\r
+                               out = response.getOutputStream();\r
+                               repository.getFile(path, rev, null, out);\r
+                       } catch (Exception e) {\r
+                               throw new AjxpDriverException("Cannot download revision " + rev\r
+                                               + " of path " + path, e);\r
+                       } finally {\r
+                               IOUtils.closeQuietly(out);\r
+                       }\r
+               }\r
+\r
+               protected String getFileName() {\r
+                       int lastIndexSlash = path.lastIndexOf('/');\r
+                       final String origFileName;\r
+                       if (lastIndexSlash != -1) {\r
+                               origFileName = path.substring(lastIndexSlash + 1);\r
+                       } else {\r
+                               origFileName = path;\r
+                       }\r
+\r
+                       int lastIndexPoint = origFileName.lastIndexOf('.');\r
+                       String prefix = origFileName.substring(0, lastIndexPoint);\r
+                       String ext = origFileName.substring(lastIndexPoint);\r
+                       return prefix + "-" + rev + ext;\r
+               }\r
+       }\r
+}\r
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnDriver.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnDriver.java
new file mode 100644 (file)
index 0000000..2d6b3e4
--- /dev/null
@@ -0,0 +1,249 @@
+package org.argeo.slc.web.ajaxplorer.svn;\r
+\r
+import java.io.File;\r
+\r
+import org.argeo.slc.web.ajaxplorer.AjxpDriverException;\r
+import org.argeo.slc.web.ajaxplorer.file.FileDriver;\r
+import org.springframework.beans.factory.BeanNameAware;\r
+import org.tmatesoft.svn.core.SVNException;\r
+import org.tmatesoft.svn.core.SVNURL;\r
+import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory;\r
+import org.tmatesoft.svn.core.io.SVNRepository;\r
+import org.tmatesoft.svn.core.wc.SVNClientManager;\r
+import org.tmatesoft.svn.core.wc.SVNInfo;\r
+import org.tmatesoft.svn.core.wc.SVNRevision;\r
+import org.tmatesoft.svn.core.wc.admin.SVNAdminClient;\r
+\r
+public class SvnDriver extends FileDriver implements BeanNameAware {\r
+       private final static String DEFAULT_DATA_PATH = System\r
+                       .getProperty("user.home")\r
+                       + File.separator + "AjaXplorerArchiver" + File.separator + "data";\r
+\r
+       private final static long WRITE_ACTION_TIMEOUT = 10 * 60 * 1000;\r
+\r
+       private SVNURL baseUrl;\r
+       private SVNClientManager manager;\r
+\r
+       private String beanName;\r
+\r
+       private boolean isInWriteAction = false;\r
+\r
+       public void init() {\r
+               FSRepositoryFactory.setup();\r
+               manager = SVNClientManager.newInstance();\r
+\r
+               String basePath = getBasePath();\r
+               if (basePath != null) {\r
+                       File baseDir = new File(basePath);\r
+                       if (baseDir.exists()) {// base dir exists\r
+                               boolean shouldCheckOut = baseDirChecks(baseDir);\r
+                               if (shouldCheckOut) {\r
+                                       checkOut(baseDir);\r
+                               }\r
+                       } else {\r
+                               checkOut(baseDir);\r
+                       }\r
+               } else {\r
+                       String defaultBasePath = DEFAULT_DATA_PATH + File.separator\r
+                                       + "svnwc" + File.separator + beanName;\r
+                       log.warn("No base path provided, use " + defaultBasePath);\r
+                       setBasePath(defaultBasePath);\r
+\r
+                       File baseDir = new File(getBasePath());\r
+                       if (!baseDir.exists()) {\r
+                               baseDir.mkdirs();\r
+                       }\r
+\r
+                       if (baseDirChecks(baseDir)) {\r
+                               if (getBaseUrl() == null) {\r
+                                       String defaultRepoPath = DEFAULT_DATA_PATH + File.separator\r
+                                                       + "svnrepos" + File.separator + beanName;\r
+                                       log.warn("No base URL found, create repository at "\r
+                                                       + defaultRepoPath);\r
+                                       baseUrl = createRepository(new File(defaultRepoPath));\r
+                               }\r
+                               checkOut(new File(getBasePath()));\r
+                       }\r
+               }\r
+               log.info("SVN driver initialized with base url " + getBaseUrl()\r
+                               + " and base path " + getBasePath());\r
+       }\r
+\r
+       /** Builds a SVN URL. */\r
+       public SVNURL getSVNURL(String relativePath) {\r
+               try {\r
+                       return baseUrl.appendPath(relativePath, false);\r
+               } catch (SVNException e) {\r
+                       throw new AjxpDriverException(\r
+                                       "Cannot build URL from relative path " + relativePath\r
+                                                       + " and base url " + baseUrl);\r
+               }\r
+       }\r
+\r
+       public SVNRepository getRepository() {\r
+               try {\r
+                       return manager.createRepository(baseUrl, true);\r
+               } catch (SVNException e) {\r
+                       throw new AjxpDriverException("Cannot create repository for "\r
+                                       + baseUrl, e);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Verifies that the provided existing base dir is ok and whether one should\r
+        * check out. Set the base url from the working copy.\r
+        * \r
+        * @return whether one should check out.\r
+        */\r
+       protected boolean baseDirChecks(File baseDir) {\r
+               if (!baseDir.isDirectory()) {\r
+                       throw new AjxpDriverException("Base path " + baseDir\r
+                                       + " is not a directory.");\r
+               }\r
+\r
+               try {// retrieves SVN infos\r
+                       SVNInfo info = manager.getWCClient().doInfo(baseDir,\r
+                                       SVNRevision.WORKING);\r
+                       SVNURL baseUrlTemp = info.getURL();\r
+                       if (baseUrl != null) {\r
+                               if (!baseUrl.equals(baseUrlTemp)) {\r
+                                       throw new AjxpDriverException(\r
+                                                       "SVN URL of the working copy "\r
+                                                                       + baseUrlTemp\r
+                                                                       + " is not compatible with provided baseUrl "\r
+                                                                       + baseUrl);\r
+                               }\r
+                       } else {\r
+                               this.baseUrl = baseUrlTemp;\r
+                       }\r
+                       return false;\r
+               } catch (SVNException e) {// no info retrieved\r
+                       log\r
+                                       .warn("Could not retrieve SVN info from "\r
+                                                       + baseDir\r
+                                                       + "("\r
+                                                       + e.getMessage()\r
+                                                       + "). Guess that it is and empty dir and try to check out from provided URL.");\r
+                       if (baseDir.listFiles().length != 0) {\r
+                               throw new AjxpDriverException("Base dir " + baseDir\r
+                                               + " is not a working copy and not an empty dir.");\r
+                       }\r
+                       return true;\r
+               }\r
+       }\r
+\r
+       protected void checkOut(File baseDir) {\r
+               if (getBaseUrl() == null) {\r
+                       throw new AjxpDriverException(\r
+                                       "No SVN URL provided, cannot check out.");\r
+               }\r
+\r
+               // Make sure directory exists\r
+               baseDir.mkdirs();\r
+\r
+               try {\r
+                       long revision = manager.getUpdateClient().doCheckout(getBaseUrl(),\r
+                                       baseDir, SVNRevision.UNDEFINED, SVNRevision.HEAD, true);\r
+                       log.info("Checked out from " + baseUrl + " to " + baseDir\r
+                                       + " at revision " + revision);\r
+               } catch (SVNException e) {\r
+                       throw new AjxpDriverException("Cannot check out from " + baseUrl\r
+                                       + " to " + baseDir, e);\r
+               }\r
+       }\r
+\r
+       protected SVNURL createRepository(File repoDir) {\r
+               try {\r
+                       SVNAdminClient adminClient = manager.getAdminClient();\r
+                       return adminClient.doCreateRepository(repoDir, null, true, false);\r
+               } catch (SVNException e) {\r
+                       throw new AjxpDriverException("Cannot create repository at "\r
+                                       + repoDir, e);\r
+               }\r
+       }\r
+\r
+       private void updateIfRequired(File dir) {\r
+               try {\r
+                       SVNInfo wcInfo = manager.getWCClient().doInfo(getBaseDir(),\r
+                                       SVNRevision.WORKING);\r
+                       SVNRevision wcRev = wcInfo.getRevision();\r
+                       SVNInfo repoInfo = manager.getWCClient().doInfo(getBaseUrl(),\r
+                                       null, SVNRevision.HEAD);\r
+                       SVNRevision repoRev = repoInfo.getRevision();\r
+\r
+                       if (log.isTraceEnabled())\r
+                               log\r
+                                               .trace("WC Revision=" + wcRev + ", Repo Revision="\r
+                                                               + repoRev);\r
+\r
+                       if (!wcRev.equals(repoRev)) {\r
+                               log.debug("Update working copy from revision " + wcRev\r
+                                               + " to revision " + repoRev);\r
+                               manager.getUpdateClient().doUpdate(getBaseDir(),\r
+                                               SVNRevision.HEAD, true);\r
+                       }\r
+               } catch (SVNException e) {\r
+                       throw new AjxpDriverException("Cannot update working copy "\r
+                                       + getBaseDir(),e);\r
+               }\r
+       }\r
+\r
+       public synchronized void beginWriteAction(File dir) {\r
+               if (isInWriteAction) {\r
+                       try {\r
+                               wait(WRITE_ACTION_TIMEOUT);\r
+                       } catch (InterruptedException e) {\r
+                               // silent\r
+                       }\r
+                       if (isInWriteAction) {\r
+                               throw new AjxpDriverException(\r
+                                               "Still in write action after timeout "\r
+                                                               + WRITE_ACTION_TIMEOUT + " ms.");\r
+                       }\r
+               }\r
+\r
+               isInWriteAction = true;\r
+               updateIfRequired(dir);\r
+       }\r
+\r
+       public synchronized void completeWriteAction(File dir) {\r
+               isInWriteAction = false;\r
+               notifyAll();\r
+       }\r
+\r
+       public synchronized void rollbackWriteAction(File dir) {\r
+               // TODO: revert?\r
+               isInWriteAction = false;\r
+               notifyAll();\r
+       }\r
+       \r
+       public void commitAll(String message) throws SVNException{\r
+               if(log.isTraceEnabled())\r
+               log.trace("SVN Commit: " + getBaseDir());\r
+               manager.getCommitClient().doCommit(new File[] { getBaseDir() }, true,\r
+                               message, true, true);\r
+\r
+       }\r
+\r
+       /** Spring bean name, set at initialization. */\r
+       public void setBeanName(String beanName) {\r
+               this.beanName = beanName;\r
+       }\r
+\r
+       public void setBaseUrl(String baseUrl) {\r
+               try {\r
+                       this.baseUrl = SVNURL.parseURIDecoded(baseUrl);\r
+               } catch (SVNException e) {\r
+                       throw new AjxpDriverException("Cannot parse SVN URL " + baseUrl, e);\r
+               }\r
+       }\r
+\r
+       public SVNURL getBaseUrl() {\r
+               return baseUrl;\r
+       }\r
+\r
+       public SVNClientManager getManager() {\r
+               return manager;\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnLogAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnLogAction.java
new file mode 100644 (file)
index 0000000..77b9af0
--- /dev/null
@@ -0,0 +1,112 @@
+package org.argeo.slc.web.ajaxplorer.svn;\r
+\r
+import java.io.File;\r
+import java.io.PrintWriter;\r
+import java.text.SimpleDateFormat;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Vector;\r
+\r
+import javax.servlet.http.HttpServletRequest;\r
+import javax.servlet.http.HttpServletResponse;\r
+\r
+import org.apache.commons.io.IOUtils;\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+import org.argeo.slc.web.ajaxplorer.AjxpAction;\r
+import org.argeo.slc.web.ajaxplorer.AjxpAnswer;\r
+import org.argeo.slc.web.ajaxplorer.AjxpDriverException;\r
+import org.tmatesoft.svn.core.ISVNLogEntryHandler;\r
+import org.tmatesoft.svn.core.SVNException;\r
+import org.tmatesoft.svn.core.SVNLogEntry;\r
+import org.tmatesoft.svn.core.SVNLogEntryPath;\r
+import org.tmatesoft.svn.core.wc.SVNRevision;\r
+\r
+public class SvnLogAction implements AjxpAction<SvnDriver> {\r
+       private final SimpleDateFormat sdfIso = new SimpleDateFormat(\r
+                       "yyyy-MM-dd HH:mm:ss");\r
+       private final Log log = LogFactory.getLog(getClass());\r
+\r
+       public AjxpAnswer execute(SvnDriver driver, HttpServletRequest request) {\r
+               String fileStr = request.getParameter("file");\r
+               log.debug("Log file " + fileStr);\r
+               if (fileStr == null) {\r
+                       throw new AjxpDriverException("A  file needs to be provided.");\r
+               }\r
+               File file = new File(driver.getBasePath() + fileStr);\r
+               return new SvnLogAnswer(driver, file);\r
+       }\r
+\r
+       protected class SvnLogAnswer implements AjxpAnswer {\r
+               private final SvnDriver driver;\r
+               private final File file;\r
+\r
+               public SvnLogAnswer(SvnDriver driver, File file) {\r
+                       this.driver = driver;\r
+                       this.file = file;\r
+               }\r
+\r
+               public void updateResponse(HttpServletResponse response) {\r
+                       PrintWriter writer = null;\r
+                       try {\r
+                               writer = response.getWriter();\r
+                               writer.append("<tree>");\r
+                               writer.append("<log>");\r
+\r
+                               final List<SVNLogEntry> logEntries = new Vector<SVNLogEntry>();\r
+                               ISVNLogEntryHandler logHandler = new ISVNLogEntryHandler() {\r
+                                       public void handleLogEntry(SVNLogEntry logEntry)\r
+                                                       throws SVNException {\r
+                                               logEntries.add(logEntry);\r
+                                       }\r
+                               };\r
+\r
+                               driver.getManager().getLogClient().doLog(new File[] { file },\r
+                                               SVNRevision.create(0), SVNRevision.HEAD, true, true,\r
+                                               100, logHandler);\r
+\r
+                               for (int i = logEntries.size() - 1; i >= 0; i--) {\r
+                                       String xml = logEntryAsXml(logEntries.get(i), file);\r
+                                       if(log.isTraceEnabled())\r
+                                               log.trace(xml);\r
+                                       writer.append(xml);\r
+                               }\r
+\r
+                               writer.append("</log>");\r
+                               writer.append("</tree>");\r
+                       } catch (Exception e) {\r
+                               throw new AjxpDriverException(\r
+                                               "Cannot retrieve log for " + file, e);\r
+                       } finally {\r
+                               IOUtils.closeQuietly(writer);\r
+                       }\r
+               }\r
+\r
+       }\r
+\r
+       protected String logEntryAsXml(SVNLogEntry entry, File file) {\r
+               StringBuffer buf = new StringBuffer();\r
+               buf.append("<logentry");\r
+               buf.append(" revision=\"").append(entry.getRevision()).append("\"");\r
+               buf.append(" is_file=\"").append(file.isDirectory() ? "0" : "1")\r
+                               .append("\"");\r
+               buf.append(">");\r
+\r
+               buf.append("<author>").append(entry.getAuthor()).append("</author>");\r
+               buf.append("<date>").append(sdfIso.format(entry.getDate())).append(\r
+                               "</date>");\r
+\r
+               buf.append("<paths>");\r
+               Map<Object, SVNLogEntryPath> paths = entry.getChangedPaths();\r
+               for (SVNLogEntryPath path : paths.values()) {\r
+                       buf.append("<path>").append(path.getPath()).append("</path>");\r
+               }\r
+               buf.append("</paths>");\r
+\r
+               buf.append("<msg>").append(entry.getMessage()).append("</msg>");\r
+\r
+               buf.append("</logentry>");\r
+               return buf.toString();\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnLsAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnLsAction.java
new file mode 100644 (file)
index 0000000..5d9dae5
--- /dev/null
@@ -0,0 +1,59 @@
+package org.argeo.slc.web.ajaxplorer.svn;\r
+\r
+import java.io.File;\r
+import java.io.FileFilter;\r
+import java.util.List;\r
+import java.util.Vector;\r
+\r
+import org.argeo.slc.web.ajaxplorer.AjxpDriverException;\r
+import org.argeo.slc.web.ajaxplorer.file.FileLsAction;\r
+import org.tmatesoft.svn.core.SVNException;\r
+import org.tmatesoft.svn.core.wc.SVNInfo;\r
+import org.tmatesoft.svn.core.wc.SVNRevision;\r
+import org.tmatesoft.svn.core.wc.SVNWCClient;\r
+\r
+public class SvnLsAction extends FileLsAction<SvnDriver, SvnAjxpFile> {\r
+\r
+       @Override\r
+       protected List<SvnAjxpFile> listFiles(SvnDriver driver, final String path,\r
+                       final boolean dirOnly) {\r
+               try {\r
+                       File dir = driver.getFile(path);\r
+                       SVNWCClient client = driver.getManager().getWCClient();\r
+\r
+                       final List<SvnAjxpFile> res = new Vector<SvnAjxpFile>();\r
+                       FileFilter filter = createFileFilter(dir);\r
+                       File[] files = dir.listFiles(filter);\r
+                       for (File file : files) {\r
+                               //SVNStatus status = driver.getManager().getStatusClient().doStatus(file, false);\r
+                               \r
+                               SVNInfo info = client.doInfo(file, SVNRevision.WORKING);\r
+                               if (dirOnly) {\r
+                                       if (file.isDirectory())\r
+                                               res.add(new SvnAjxpFile(info, path));\r
+                               } else {\r
+                                       res.add(new SvnAjxpFile(info, path));\r
+                               }\r
+                       }\r
+                       return res;\r
+               } catch (SVNException e) {\r
+                       throw new AjxpDriverException("Cannot list svn dir " + path, e);\r
+               }\r
+       }\r
+\r
+       @Override\r
+       protected FileFilter createFileFilter(File dir) {\r
+               return new FileFilter() {\r
+\r
+                       public boolean accept(File pathname) {\r
+                               if (pathname.getName().equals(".svn")) {\r
+                                       return false;\r
+                               } else {\r
+                                       return true;\r
+                               }\r
+                       }\r
+\r
+               };\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnMkdirAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnMkdirAction.java
new file mode 100644 (file)
index 0000000..32f3b25
--- /dev/null
@@ -0,0 +1,28 @@
+package org.argeo.slc.web.ajaxplorer.svn;\r
+\r
+import java.io.File;\r
+\r
+import org.argeo.slc.web.ajaxplorer.AjxpDriverException;\r
+import org.argeo.slc.web.ajaxplorer.file.FileMkdirAction;\r
+import org.tmatesoft.svn.core.SVNException;\r
+\r
+public class SvnMkdirAction extends FileMkdirAction<SvnDriver> {\r
+       @Override\r
+       protected void postProcess(SvnDriver driver, File newDir) {\r
+               try {\r
+                       driver.beginWriteAction(newDir.getParentFile());\r
+\r
+                       log.debug("SVN Add: " + newDir);\r
+                       driver.getManager().getWCClient().doAdd(newDir, true,\r
+                                       newDir.isDirectory(), true, true);\r
+\r
+                       driver.commitAll("Commit new dir " + newDir.getName());\r
+                       driver.completeWriteAction(newDir.getParentFile());\r
+               } catch (SVNException e) {\r
+                       throw new AjxpDriverException("Cannot commit new dir" + newDir, e);\r
+               } finally {\r
+                       driver.rollbackWriteAction(newDir.getParentFile());\r
+               }\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnUploadAction.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/ajaxplorer/svn/SvnUploadAction.java
new file mode 100644 (file)
index 0000000..384fbe5
--- /dev/null
@@ -0,0 +1,28 @@
+package org.argeo.slc.web.ajaxplorer.svn;\r
+\r
+import java.io.File;\r
+\r
+import org.argeo.slc.web.ajaxplorer.AjxpDriverException;\r
+import org.argeo.slc.web.ajaxplorer.file.FileUploadAction;\r
+import org.tmatesoft.svn.core.SVNException;\r
+\r
+public class SvnUploadAction extends FileUploadAction<SvnDriver> {\r
+       @Override\r
+       protected void postProcess(SvnDriver driver, File file) {\r
+               try {\r
+                       driver.beginWriteAction(file.getParentFile());\r
+\r
+                       log.debug("SVN Add: " + file);\r
+                       driver.getManager().getWCClient().doAdd(file, true,\r
+                                       file.isDirectory(), true, true);\r
+\r
+                       driver.commitAll("Commit file " + file.getName());\r
+                       driver.completeWriteAction(file.getParentFile());\r
+               } catch (SVNException e) {\r
+                       throw new AjxpDriverException("Cannot commit file " + file, e);\r
+               } finally {\r
+                       driver.rollbackWriteAction(file.getParentFile());\r
+               }\r
+       }\r
+\r
+}\r
diff --git a/runtime/org.argeo.slc.server/src/main/resources/org/argeo/slc/web/ajaxplorer/file/spring.xml b/runtime/org.argeo.slc.server/src/main/resources/org/argeo/slc/web/ajaxplorer/file/spring.xml
new file mode 100644 (file)
index 0000000..25a9127
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+       xmlns:aop="http://www.springframework.org/schema/aop"\r
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"\r
+       default-lazy-init="true">\r
+\r
+       <bean id="driver.file.template"\r
+               class="org.argeo.slc.web.ajaxplorer.file.FileDriver"\r
+               abstract="true">\r
+               <property name="actions">\r
+                       <map>\r
+                               <entry key="ls" value-ref="action.file.ls" />\r
+                               <entry key="download" value-ref="action.file.download" />\r
+                               <entry key="image_proxy"\r
+                                       value-ref="action.file.image_proxy" />\r
+                               <entry key="upload" value-ref="action.file.upload" />\r
+                               <entry key="mkdir" value-ref="action.file.mkdir" />\r
+                               <entry key="delete" value-ref="action.file.delete" />\r
+                       </map>\r
+               </property>\r
+       </bean>\r
+\r
+       <!-- ACTIONS FS -->\r
+       <bean id="action.file.ls"\r
+               class="org.argeo.slc.web.ajaxplorer.file.FileLsAction" />\r
+\r
+       <bean id="action.file.download"\r
+               class="org.argeo.slc.web.ajaxplorer.file.FileDownloadAction" />\r
+\r
+       <bean id="action.file.image_proxy"\r
+               class="org.argeo.slc.web.ajaxplorer.file.FileImageProxyAction" />\r
+\r
+       <bean id="action.file.upload"\r
+               class="org.argeo.slc.web.ajaxplorer.file.FileUploadAction" />\r
+\r
+       <bean id="action.file.mkdir"\r
+               class="org.argeo.slc.web.ajaxplorer.file.FileMkdirAction" />\r
+\r
+       <bean id="action.file.delete"\r
+               class="org.argeo.slc.web.ajaxplorer.file.FileDeleteAction" />\r
+</beans>
\ No newline at end of file
diff --git a/runtime/org.argeo.slc.server/src/main/resources/org/argeo/slc/web/ajaxplorer/svn/spring.xml b/runtime/org.argeo.slc.server/src/main/resources/org/argeo/slc/web/ajaxplorer/svn/spring.xml
new file mode 100644 (file)
index 0000000..10f7f85
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"\r
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"\r
+       default-lazy-init="true">\r
+\r
+       <import resource="classpath:/org/argeo/slc/web/ajaxplorer/file/spring.xml" />\r
+\r
+       <bean id="driver.svn.template" class="org.argeo.slc.web.ajaxplorer.svn.SvnDriver"\r
+               init-method="init" abstract="true">\r
+               <property name="actions">\r
+                       <map>\r
+                               <entry key="ls" value-ref="action.svn.ls" />\r
+                               <entry key="download" value-ref="action.svn.download" />\r
+                               <entry key="image_proxy" value-ref="action.svn.image_proxy" />\r
+                               <entry key="upload" value-ref="action.svn.upload" />\r
+                               <entry key="mkdir" value-ref="action.svn.mkdir" />\r
+                               <entry key="delete" value-ref="action.svn.delete" />\r
+                               <entry key="svnlog" value-ref="action.svn.svnlog" />\r
+                               <entry key="svndownload" value-ref="action.svn.svndownload" />\r
+                       </map>\r
+               </property>\r
+       </bean>\r
+\r
+       <!-- ACTIONS SVN -->\r
+       <bean id="action.svn.ls" class="org.argeo.slc.web.ajaxplorer.svn.SvnLsAction" />\r
+\r
+       <bean id="action.svn.upload" class="org.argeo.slc.web.ajaxplorer.svn.SvnUploadAction" />\r
+\r
+       <bean id="action.svn.mkdir" class="org.argeo.slc.web.ajaxplorer.svn.SvnMkdirAction" />\r
+\r
+       <bean id="action.svn.delete" class="org.argeo.slc.web.ajaxplorer.svn.SvnDeleteAction" />\r
+\r
+       <bean id="action.svn.svnlog" class="org.argeo.slc.web.ajaxplorer.svn.SvnLogAction" />\r
+\r
+       <bean id="action.svn.download" class="org.argeo.slc.web.ajaxplorer.file.FileDownloadAction" />\r
+\r
+       <bean id="action.svn.image_proxy" class="org.argeo.slc.web.ajaxplorer.file.FileImageProxyAction" />\r
+\r
+       <bean id="action.svn.svndownload" class="org.argeo.slc.web.ajaxplorer.svn.SvnDownloadAction" />\r
+\r
+\r
+</beans>
\ No newline at end of file