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,
--- /dev/null
+<?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
<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>
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>
--- /dev/null
+package org.argeo.slc.web.ajaxplorer;
+
+import javax.servlet.http.HttpServletRequest;
+
+public interface AjxpAction<T extends AjxpDriver>{
+ public AjxpAnswer execute(T driver, HttpServletRequest request);
+}
--- /dev/null
+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);
+}
--- /dev/null
+package org.argeo.slc.web.ajaxplorer;
+
+import javax.servlet.http.HttpServletRequest;
+
+public interface AjxpDriver {
+ public AjxpAnswer executeAction(HttpServletRequest request);
+}
--- /dev/null
+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);
+ }
+
+}
--- /dev/null
+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;
+ }
+
+}
--- /dev/null
+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);
+ }
+
+ }
+}
--- /dev/null
+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) {
+
+ }
+}
--- /dev/null
+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());
+}
--- /dev/null
+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
--- /dev/null
+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");
+ }
+}
--- /dev/null
+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);
+ }
+}
--- /dev/null
+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");
+ }
+
+}
--- /dev/null
+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);
+ }
+ }
+
+ }
+}
--- /dev/null
+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
--- /dev/null
+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;
+ }
+}
--- /dev/null
+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) {
+
+ }
+
+}
--- /dev/null
+package org.argeo.slc.web.ajaxplorer.file;
+
+public enum LsMode {
+ NULL, COMPLETE, FILE_LIST, SEARCH
+}
--- /dev/null
+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;
+ }
+
+}
--- /dev/null
+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);
+ }
+ }
+ }
+ }
+ }
+}
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+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
--- /dev/null
+<?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
--- /dev/null
+<?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