+++ /dev/null
-/*\r
- * Copyright (C) 2007-2012 Mathieu Baudier\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package org.argeo.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