Author: adamw Date: 2005-09-26 16:56:01 -0400 (Mon, 26 Sep 2005) New Revision: 1215 Added: trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/ trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/NodeReadOnly.java trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/RepositoryException.java trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/ResourceAlreadyExists.java trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/ResourceDoesNotExist.java trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceLocal.java trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceManagement.java trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnHeadNode.java trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnHistoricNode.java trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnNewDirectory.java trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnNewNode.java trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnOperationFailed.java trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/Tools.java trunk/forge/portal-extensions/shotoku/shotoku-test/ trunk/forge/portal-extensions/shotoku/shotoku-test/maven.xml trunk/forge/portal-extensions/shotoku/shotoku-test/project.properties trunk/forge/portal-extensions/shotoku/shotoku-test/project.xml trunk/forge/portal-extensions/shotoku/shotoku-test/src/ trunk/forge/portal-extensions/shotoku/shotoku-test/src/java/ trunk/forge/portal-extensions/shotoku/shotoku-test/src/java/org/ trunk/forge/portal-extensions/shotoku/shotoku-test/src/java/org/jboss/ trunk/forge/portal-extensions/shotoku/shotoku-test/src/java/org/jboss/shotoku/ trunk/forge/portal-extensions/shotoku/shotoku-test/src/java/org/jboss/shotoku/test/ trunk/forge/portal-extensions/shotoku/shotoku-test/src/java/org/jboss/shotoku/test/ShotokuTest.java trunk/forge/portal-extensions/shotoku/shotoku-test/src/web/ trunk/forge/portal-extensions/shotoku/shotoku-test/src/web/WEB-INF/ trunk/forge/portal-extensions/shotoku/shotoku-test/src/web/WEB-INF/web.xml Modified: trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/AbstractResource.java trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/ContentManager.java trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/Directory.java trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/History.java trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/Node.java trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/NodeList.java trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnRepository.java trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceImpl.java trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceTimer.java trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/AbstractSvnResource.java trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnContentManager.java trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnDirectory.java trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnService.java Log: Further implementation, comments Modified: trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/AbstractResource.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/AbstractResource.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/AbstractResource.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -1,5 +1,7 @@ package org.jboss.shotoku; +import org.jboss.shotoku.exceptions.RepositoryException; + /** * @author adamw * Common parts of nodes and directories interface. @@ -9,8 +11,9 @@ * Gets the value of a given property. * @param propertyName Name of the property to get. * @return Value of the given property. + * @throws RepositoryException */ - public String getProperty(String propertyName); + public String getProperty(String propertyName) throws RepositoryException; /** * Sets the value of a given property. * @param propertyName Name of the property to set. @@ -22,19 +25,23 @@ * @return A directory to which this node/ directory belongs. Null * if this directory is already the root directory. */ - public Directory getParent(); + public Directory getParent() throws RepositoryException; /** * Saves modified properties and possibly content (in case of nodes). * @param logMessage Log message for saving this node/ directory. + * @throws RepositoryException */ - public void save(String logMessage); + public void save(String logMessage) throws RepositoryException; /** * Gets a log message with which this node/ directory was saved. * @return Log message with which this node/ directory was saved. + * @throws RepositoryException */ - public String getLogMessage(); + public String getLogMessage() throws RepositoryException; /** - * Deletes this node or directory. + * Deletes this node or directory. This node should not be used after + * performing this operation. + * @throws RepositoryException */ - public void delete(); + public void delete() throws RepositoryException; } Modified: trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/ContentManager.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/ContentManager.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/ContentManager.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -6,144 +6,169 @@ import org.apache.log4j.Logger; import org.apache.xerces.parsers.DOMParser; +import org.jboss.shotoku.exceptions.ResourceDoesNotExist; +import org.jboss.shotoku.exceptions.RepositoryException; import org.jboss.shotoku.search.SearchParameters; import org.w3c.dom.Document; import org.xml.sax.InputSource; /** - * @author adamw - * A base class which provides access to nodes and directories. + * @author adamw A base class which provides access to nodes and directories. */ public abstract class ContentManager { /** * Gets a root directory that is represented by this content manager. - * @return A directory that is the root directory of this content - * manager. + * + * @return A directory that is the root directory of this content manager. + * @throws RepositoryException */ - public abstract Directory getRootDirectory(); + public abstract Directory getRootDirectory() throws RepositoryException; + /** - * Gets a node which can be found under the given path. - * @param Path for which to get the node. + * Gets a head version of a node which can be found under the given path. + * + * @param path + * for which to get the node. * @return A node corresponding to the gien path. + * @throws ResourceDoesNotExist + * @throws RepositoryException */ - public abstract Node getNode(String path); + public abstract Node getNode(String path) throws ResourceDoesNotExist, + RepositoryException; + /** * Gets a directory which can be found under the given path. - * @param Path for which to get the directory. + * + * @param path + * for which to get the directory. * @return A directory corresponding to the gien path. + * @throws ResourceDoesNotExist + * @throws RepositoryException */ - public abstract Directory getDirectory(String path); + public abstract Directory getDirectory(String path) + throws ResourceDoesNotExist, RepositoryException; + /** * Performs a search with the given parameters. - * @param parameters Parameters for the search. + * + * @param parameters + * Parameters for the search. * @return A list of found nodes. + * @throws RepositoryException */ - public abstract NodeList search(SearchParameters parameters); - + public abstract NodeList search(SearchParameters parameters) + throws RepositoryException; + protected ContentManager(String id, String prefix) { - + } - + /* * Content manager loading. */ - + private static final Logger log = Logger.getLogger(ContentManager.class); - + /** - * <code>defaultId</code> - id of the default content manager. May - * be overriden by a setting in the xml configuration file. + * <code>defaultId</code> - id of the default content manager. May be + * overriden by a setting in the xml configuration file. */ private static String defaultId = "default"; + /** - * <code>contentManagers</code> - map (content manager id -> - * content manager constructor). + * <code>contentManagers</code> - map (content manager id -> content + * manager constructor). */ private static Map<String, Constructor> contentManagers; - + static { contentManagers = new HashMap<String, Constructor>(); - + // Loading configuration file. try { DOMParser parser = new DOMParser(); - parser.parse(new InputSource( - ContentManager.class.getResourceAsStream("/shotoku.xml"))); + parser.parse(new InputSource(ContentManager.class + .getResourceAsStream("/shotoku.xml"))); Document doc = parser.getDocument(); - + org.w3c.dom.Node node = doc.getDocumentElement(); org.w3c.dom.NodeList nodes = node.getChildNodes(); org.w3c.dom.Node n; - + for (int i = 0; i < nodes.getLength(); i++) { n = nodes.item(i); - + if (n.getNodeType() == org.w3c.dom.Node.ELEMENT_NODE) { if ("default-id".equals(n.getNodeName())) { // Overriding the default content manager id. defaultId = Tools.getAttributeValue(n, "id"); - + log.info("Set default id to: " + defaultId); } else if ("content-manager".equals(n.getNodeName())) { // Creating a new content manager (getting its // constructor). String id = Tools.getAttributeValue(n, "id"); - String implementation = - Tools.getAttributeValue(n, "implementation"); - - contentManagers.put(id, - Class.forName(implementation).getConstructor( - new Class[] { String.class, + String implementation = Tools.getAttributeValue(n, + "implementation"); + + contentManagers.put(id, Class.forName(implementation) + .getConstructor( + new Class[] { String.class, String.class })); - - log.info("Added content manager: " + id + ", " + - implementation); + + log.info("Added content manager: " + id + ", " + + implementation); } } - } + } } catch (Exception e) { - log.warn("Error while loading content manager configuration: " + - e); + log.warn("Error while loading content manager configuration: " + e); } } - + /** * Gets a content manager with a default id and an empty prefix. + * * @return A ""-prefixed, default content manager, or null, if a default - * content manager is not registered. + * content manager is not registered. */ public static ContentManager getContentManager() { return getContentManager(""); } - + /** * Gets a content manager with a default id and the given prefix. - * @param prefix Prefix for the new content manager (all paths will - * have this prepended). + * + * @param prefix + * Prefix for the new content manager (all paths will have this + * prepended). * @return A prefixed, default content manager, or null, if a default - * content manager is not registered. + * content manager is not registered. */ public static ContentManager getContentManager(String prefix) { return getContentManager(defaultId, prefix); } - + /** * Gets a content manager with the given id and prefix. - * @param id Id of the content manager. - * @param prefix Prefix for the new content manager (all paths will - * have this prepended). + * + * @param id + * Id of the content manager. + * @param prefix + * Prefix for the new content manager (all paths will have this + * prepended). * @return A prefixed content manager with the given id or null, if a - * content manager with the given id registers. + * content manager with the given id registers. */ public static ContentManager getContentManager(String id, String prefix) { Constructor constructor = contentManagers.get(id); - + if (constructor == null) return null; - + try { - return (ContentManager) - constructor.newInstance(new Object[] { id, prefix }); + return (ContentManager) constructor.newInstance(new Object[] { id, + prefix }); } catch (Exception e) { return null; } Modified: trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/Directory.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/Directory.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/Directory.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -2,51 +2,78 @@ import java.util.List; +import org.jboss.shotoku.exceptions.RepositoryException; +import org.jboss.shotoku.exceptions.ResourceAlreadyExists; + /** - * @author adamw - * Interface that must be implemented by classes which represent - * directories, that is resources, which can contain other - * directories and nodes. + * @author adamw Interface that must be implemented by classes which represent + * directories, that is resources, which can contain other directories + * and nodes. */ public interface Directory extends AbstractResource { /** * Gets a list of nodes that are contained in this directory. + * * @return A list of nodes that are contained in this directory. + * @throws RepositoryException */ - public NodeList getNodes(); + public NodeList getNodes() throws RepositoryException; + /** * Gets a list of directories that are contained in this directory. + * * @return A list of directories that are contained in this directory. + * @throws RepositoryException */ - public List<Directory> getDirectories(); + public List<Directory> getDirectories() throws RepositoryException; + /** - * Creates and returns a new node in this directory. Only after saving, - * this node will be visible by other functions. - * @param name Name of the new node. + * Creates and returns a new node in this directory. Only after saving, this + * node will be visible by other functions. + * + * @param name + * Name of the new node. * @return A new node with the given name. + * @throws ResourceAlreadyExists + * @throws RepositoryException */ - public Node newNode(String name); + public Node newNode(String name) throws ResourceAlreadyExists, + RepositoryException; + /** * Creates a new directory in this directory. Only after saving this * directory, it will be visible by other functions. Also, new nodes/ * directories in it will be possible to create only after saving. - * @param name Name of the directory to create. + * + * @param name + * Name of the directory to create. * @return A new directory with the given name. + * @throws ResourceAlreadyExists + * @throws RepositoryException */ - public Directory newDirectory(String name); + public Directory newDirectory(String name) throws ResourceAlreadyExists, + RepositoryException; + /** * Checks if an index is created on the given property. - * @param propertyName Name of the property for which to check the - * index. + * + * @param propertyName + * Name of the property for which to check the index. * @return True iff an index is created for the given property. + * @throws RepositoryException */ - public boolean hasIndex(String propertyName); + public boolean hasIndex(String propertyName) throws RepositoryException; + /** * Creates or deletes an index on a property. - * @param propertyName Name of the property for which to create/ delete - * an index. - * @param index True if and index should be created, false in an index - * should be deleted. + * + * @param propertyName + * Name of the property for which to create/ delete an index. + * @param index + * True if and index should be created, false in an index should + * be deleted. + * @throws RepositoryException */ - public void setIndex(String propertyName, boolean index); + public void setIndex(String propertyName, boolean index) + throws RepositoryException; } Modified: trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/History.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/History.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/History.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -1,25 +1,38 @@ package org.jboss.shotoku; +import org.jboss.shotoku.exceptions.RepositoryException; +import org.jboss.shotoku.exceptions.ResourceDoesNotExist; + /** - * @author adamw - * An interface that should be implemented by classes which represent - * a node's history. + * @author adamw An interface that should be implemented by classes which + * represent a node's history. */ public interface History { /** - * Gets the number of revisions for this node's history. - * @return + * Gets the number of revisions of this node's history. + * + * @return Number of revisions of this node's history. + * @throws RepositoryException */ - public int getRevisionsCount(); + public int getRevisionsCount() throws RepositoryException; + /** * Gets a node with a given revision. - * @param revision Revision number to get. + * + * @param revision + * Revision number to get. * @return A node at the given revision. + * @throws ResourceDoesNotExist + * @throws RepositoryException */ - public Node getNodeAtRevision(int revision); + public Node getNodeAtRevision(int revision) throws ResourceDoesNotExist, + RepositoryException; + /** * Gets a list of all nodes in this history. + * * @return A list of all nodes in this history. + * @throws RepositoryException */ - public NodeList getAllRevisions(); + public NodeList getAllRevisions() throws RepositoryException; } Modified: trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/Node.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/Node.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/Node.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -2,50 +2,76 @@ import java.io.InputStream; +import org.jboss.shotoku.exceptions.RepositoryException; + /** - * @author adamw - * An interface which should be implemented by classes representing a node, - * that is a resource, which is versionable and has some text content. + * @author adamw An interface which should be implemented by classes + * representing a node, that is a resource, which is versionable and has + * some text content. */ public interface Node extends AbstractResource { /** * Gets the content of this node. + * * @return Content of this node. + * @throws RepositoryException */ - public String getContent(); + public String getContent() throws RepositoryException; + /** * Sets the content of this node. - * @param content New content of this node. + * + * @param content + * New content of this node. */ public void setContent(String content); + /** * Gets a history of this node. + * * @return A history of this node. + * @throws RepositoryException */ - public History getHistory(); + public History getHistory() throws RepositoryException; + /** * Gets the revision number of this node. + * * @return Revision number of this node. + * @throws RepositoryException */ - public int getRevisionNumber(); + public int getRevisionNumber() throws RepositoryException; + /** * Copies this node's content to the given file. - * @param filename Name of the file to which to copy this node's content. + * + * @param filename + * Name of the file to which to copy this node's content. + * @throws RepositoryException */ - public void copyToFile(String filename); + public void copyToFile(String filename) throws RepositoryException; + /** * Gets the content of this node as an input stream. + * * @return Content of this node as an input stream. + * @throws RepositoryException */ - public InputStream getContentInputStream(); + public InputStream getContentInputStream() throws RepositoryException; + /** * Gets the length of this node's content. + * * @return Length of this node's content. + * @throws RepositoryException */ - public long getLength(); + public long getLength() throws RepositoryException; + /** * Gets the last modification time of this node. + * * @return Last modification time of this node. + * @throws RepositoryException */ - public long getLastModfication(); + public long getLastModfication() throws RepositoryException; } Modified: trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/NodeList.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/NodeList.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/NodeList.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -5,7 +5,8 @@ /** * @author adamw - * TODO + * A class representing a list of nodes and providing the possibility to + * manipulate these nodes. */ public class NodeList { private List<Node> nodeList; @@ -18,10 +19,18 @@ this.nodeList = nodeList; } + /** + * Adds the given node to the node list. + * @param node Node to add. + */ public void add(Node node) { nodeList.add(node); } + /** + * Gets a <code>java.util.List</code> representation of this node list. + * @return A <code>java.util.List</code> representation of this node list. + */ public List toList() { return nodeList; } Added: trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/NodeReadOnly.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/NodeReadOnly.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/NodeReadOnly.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -0,0 +1,5 @@ +package org.jboss.shotoku.exceptions; + +public class NodeReadOnly extends RuntimeException { + +} Added: trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/RepositoryException.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/RepositoryException.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/RepositoryException.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -0,0 +1,7 @@ +package org.jboss.shotoku.exceptions; + +public class RepositoryException extends RuntimeException { + public RepositoryException(Exception e) { + super(e); + } +} Added: trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/ResourceAlreadyExists.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/ResourceAlreadyExists.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/ResourceAlreadyExists.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -0,0 +1,5 @@ +package org.jboss.shotoku.exceptions; + +public class ResourceAlreadyExists extends RuntimeException { + +} Added: trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/ResourceDoesNotExist.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/ResourceDoesNotExist.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-base/src/java/org/jboss/shotoku/exceptions/ResourceDoesNotExist.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -0,0 +1,5 @@ +package org.jboss.shotoku.exceptions; + +public class ResourceDoesNotExist extends RuntimeException { + +} Modified: trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/AbstractSvnResource.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/AbstractSvnResource.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/AbstractSvnResource.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -5,8 +5,13 @@ import java.util.Map; import org.jboss.shotoku.AbstractResource; +import org.jboss.shotoku.exceptions.RepositoryException; public abstract class AbstractSvnResource implements AbstractResource { + /** + * <code>modifiedProperties</code> - a map of properties that have been + * modified for this resource and have to be written upon save. + */ private Map<String, String> modifiedProperties; protected SvnService service; @@ -25,19 +30,45 @@ } public String getProperty(String name) { - return service.getProperty(id, fullPath, name); + // First trying to get the properties from the ones that have been + // already modified, only if it hasn't been written, getting it + // from svn. + if (modifiedProperties.containsKey(name)) + return modifiedProperties.get(name); + + try { + return service.getProperty(id, fullPath, name); + } catch (SvnOperationFailed e) { + throw new RepositoryException(e); + } } public void setProperty(String name, String value) { modifiedProperties.put(name, value); } - protected boolean save() { + /** + * Checks if there are any changes to properties in this resource. + * @return True if there are any changes in properties. + */ + protected boolean checkForChanges() { + return modifiedProperties.size() > 1; + } + + /** + * Saves modified properties, if any, and clears the modified + * properties map. + */ + protected void save() { for (String name : modifiedProperties.keySet()) { - service.setProperty(id, fullPath, name, - modifiedProperties.get(name)); + try { + service.setProperty(id, fullPath, name, + modifiedProperties.get(name)); + } catch (SvnOperationFailed e) { + throw new RepositoryException(e); + } } - return modifiedProperties.size() > 1; + modifiedProperties.clear(); } } Modified: trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnContentManager.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnContentManager.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnContentManager.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -6,12 +6,26 @@ import org.jboss.shotoku.Directory; import org.jboss.shotoku.Node; import org.jboss.shotoku.NodeList; -import org.jboss.shotoku.exceptions.NodeDoesNotExist; +import org.jboss.shotoku.exceptions.RepositoryException; +import org.jboss.shotoku.exceptions.ResourceDoesNotExist; import org.jboss.shotoku.search.SearchParameters; +/** + * @author adamw + * An implementation of the content manager based on subversion. + */ public class SvnContentManager extends ContentManager { + /** + * <code>prefix</code> - prefix of this content manager. + */ private String prefix; + /** + * <code>id</code> - id of a corresponding repository. + */ private String id; + /** + * <code>service</code> - service interface binding. + */ private SvnService service; public SvnContentManager(String id, String prefix) { @@ -23,13 +37,29 @@ service = Tools.getService(); } + /** + * Gets a full repository path for the given path - that is, adds a prefix + * this content manager's prefix. + * @param path Path to this resource. + * @return A prefixed path to the given resource. + */ private String getPrefixedPath(String path) { return prefix + '/' + path; } + /** + * Gets a <code>java.io.File</code> object that corresponds to a resource + * that, in the repository, can be found under the given path. + * @param path Path to the resource in the repository. + * @return A <code>java.io.File</code> object for the given path. + */ private File getFileForPath(String path) { - return new File( - service.getFileSystemPath(id, getPrefixedPath(path))); + try { + return new File( + service.getFileSystemPath(id, getPrefixedPath(path))); + } catch (SvnOperationFailed e) { + throw new RepositoryException(e); + } } @Override @@ -42,7 +72,7 @@ File file = getFileForPath(path); if (!file.isFile()) - throw new NodeDoesNotExist(); + throw new ResourceDoesNotExist(); return new SvnHeadNode(id, getPrefixedPath(path), file); } @@ -52,7 +82,7 @@ File file = getFileForPath(path); if (!file.isFile()) - throw new NodeDoesNotExist(); + throw new ResourceDoesNotExist(); return new SvnDirectory(id, getPrefixedPath(path), file); } Modified: trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnDirectory.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnDirectory.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnDirectory.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -1,31 +1,90 @@ package org.jboss.shotoku.svn; import java.io.File; +import java.io.FilenameFilter; +import java.util.ArrayList; import java.util.List; import org.jboss.shotoku.Directory; import org.jboss.shotoku.Node; import org.jboss.shotoku.NodeList; +import org.jboss.shotoku.exceptions.RepositoryException; public class SvnDirectory extends AbstractSvnResource implements Directory { public SvnDirectory(String id, String fullPath, File file) { super(id, fullPath, file); } - + public NodeList getNodes() { - throw new RuntimeException("Operation not yet implemented"); + List<Node> ret = new ArrayList<Node>(); + + try { + // Filtering files from this directory and adding them. + for (String directory : new File(service.getFileSystemPath(id, + fullPath)).list(new FilenameFilter() { + public boolean accept(File dir, String name) { + if (new File(dir.getAbsolutePath() + File.separator + name) + .isDirectory()) + return false; + return true; + } + })) { + String childFullPath = fullPath + '/' + directory; + ret.add(new SvnHeadNode(id, childFullPath, new File(service + .getFileSystemPath(id, childFullPath)))); + } + } catch (SvnOperationFailed e) { + throw new RepositoryException(e); + } + + return new NodeList(ret); } public List<Directory> getDirectories() { - throw new RuntimeException("Operation not yet implemented"); + List<Directory> ret = new ArrayList<Directory>(); + + try { + // Filtering directories from this directory and adding them. + for (String directory : new File(service.getFileSystemPath(id, + fullPath)).list(new FilenameFilter() { + public boolean accept(File dir, String name) { + if (name.equals(".svn")) + return false; + if (new File(dir.getAbsolutePath() + File.separator + name) + .isDirectory()) + return true; + return false; + } + })) { + String childFullPath = fullPath + '/' + directory; + ret.add(new SvnDirectory(id, childFullPath, new File(service + .getFileSystemPath(id, childFullPath)))); + } + } catch (SvnOperationFailed e) { + throw new RepositoryException(e); + } + + return ret; } public Node newNode(String name) { - throw new RuntimeException("Operation not yet implemented"); + String childFullPath = fullPath + '/' + name; + try { + return new SvnNewNode(id, childFullPath, new File(service + .getFileSystemPath(id, childFullPath))); + } catch (SvnOperationFailed e) { + throw new RepositoryException(e); + } } public Directory newDirectory(String name) { - throw new RuntimeException("Operation not yet implemented"); + String childFullPath = fullPath + '/' + name; + try { + return new SvnNewDirectory(id, childFullPath, new File(service + .getFileSystemPath(id, childFullPath))); + } catch (SvnOperationFailed e) { + throw new RepositoryException(e); + } } public boolean hasIndex(String propertyName) { Added: trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnHeadNode.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnHeadNode.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnHeadNode.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -0,0 +1,128 @@ +package org.jboss.shotoku.svn; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; + +import org.jboss.shotoku.Directory; +import org.jboss.shotoku.History; +import org.jboss.shotoku.exceptions.RepositoryException; + +public class SvnHeadNode extends SvnNode { + private String newContent; + private String oldContent; + + public SvnHeadNode(String id, String fullPath, File file) { + super(id, fullPath, file); + newContent = null; + } + + public String getContent() { + if (newContent != null) return newContent; + + if (oldContent == null) { + try { + BufferedReader bf = new BufferedReader(new FileReader(file)); + + StringBuffer sf = new StringBuffer(); + while (true) { + String line = bf.readLine(); + if (line == null) + break; + sf.append(line); + sf.append('\n'); + } + + oldContent = sf.toString(); + bf.close(); + } catch (IOException e) { + throw new RepositoryException(e); + } + } + + return oldContent; + } + + public void setContent(String content) { + newContent = content; + } + + public History getHistory() { + throw new RuntimeException("Operation not yet implemented"); + } + + public int getRevisionNumber() { + throw new RuntimeException("Operation not yet implemented"); + } + + public InputStream getContentInputStream() { + try { + return new FileInputStream(file); + } catch (FileNotFoundException e) { + throw new RepositoryException(e); + } + } + + public long getLength() { + return file.length(); + } + + public long getLastModfication() { + return file.lastModified(); + } + + public Directory getParent() { + throw new RuntimeException("Operation not yet implemented"); + } + + protected boolean checkForChanges() { + return newContent != null || super.checkForChanges(); + } + + public void save(String logMessage) { + // Checking if there is anything to save. + if (!checkForChanges()) return; + + try { + service.getWriteLock(id, fullPath); + + // Saving modified properties. + save(); + + // Saving modified content. + if (newContent != null) { + PrintWriter pw; + + try { + pw = new PrintWriter(file); + } catch (FileNotFoundException e) { + service.putWriteLock(id, fullPath); + throw new RepositoryException(e); + } + + pw.println(newContent); + pw.close(); + + oldContent = newContent; + newContent = null; + } + + service.commit(id, fullPath, logMessage); + } catch (SvnOperationFailed e) { + throw new RepositoryException(e); + } + } + + public String getLogMessage() { + throw new RuntimeException("Operation not yet implemented"); + } + + public void delete() { + throw new RuntimeException("Operation not yet implemented"); + } +} Added: trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnHistoricNode.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnHistoricNode.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnHistoricNode.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -0,0 +1,66 @@ +package org.jboss.shotoku.svn; + +import java.io.File; +import java.io.InputStream; + +import org.jboss.shotoku.Directory; +import org.jboss.shotoku.History; +import org.jboss.shotoku.exceptions.NodeReadOnly; + +public class SvnHistoricNode extends SvnNode { + public SvnHistoricNode(String id, String fullPath, File file) { + super(id, fullPath, file); + } + + public String getContent() { + throw new RuntimeException("Operation not yet implemented"); + } + + public History getHistory() { + throw new RuntimeException("Operation not yet implemented"); + } + + public int getRevisionNumber() { + throw new RuntimeException("Operation not yet implemented"); + } + + public InputStream getContentInputStream() { + throw new RuntimeException("Operation not yet implemented"); + } + + public long getLength() { + throw new RuntimeException("Operation not yet implemented"); + } + + public long getLastModfication() { + throw new RuntimeException("Operation not yet implemented"); + } + + public String getProperty(String arg0) { + throw new RuntimeException("Operation not yet implemented"); + } + + public Directory getParent() { + throw new RuntimeException("Operation not yet implemented"); + } + + public String getLogMessage() { + throw new RuntimeException("Operation not yet implemented"); + } + + public void setContent(String content) { + throw new NodeReadOnly(); + } + + public void setProperty(String name, String value) { + throw new NodeReadOnly(); + } + + public void save(String logMessage) { + throw new NodeReadOnly(); + } + + public void delete() { + throw new NodeReadOnly(); + } +} Added: trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnNewDirectory.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnNewDirectory.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnNewDirectory.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -0,0 +1,97 @@ +package org.jboss.shotoku.svn; + +import java.io.File; +import java.util.List; + +import org.jboss.shotoku.Directory; +import org.jboss.shotoku.Node; +import org.jboss.shotoku.NodeList; +import org.jboss.shotoku.exceptions.RepositoryException; + +public class SvnNewDirectory extends SvnDirectory { + private boolean saved; + + public SvnNewDirectory(String id, String fullPath, File file) { + super(id, fullPath, file); + + saved = false; + } + + @Override + public void delete() { + // We only have to delete a corresponding directory if this directory + // has been saved already. + if (saved) + super.delete(); + } + + @Override + public List<Directory> getDirectories() { + if (saved) + return super.getDirectories(); + else + return null; + } + + @Override + public String getLogMessage() { + if (saved) + return super.getLogMessage(); + else + return null; + } + + @Override + public NodeList getNodes() { + if (saved) + return super.getNodes(); + else + return null; + } + + @Override + public boolean hasIndex(String propertyName) { + if (saved) + return super.hasIndex(propertyName); + else + return false; + } + + @Override + public Directory newDirectory(String name) { + if (saved) + return super.newDirectory(name); + else + return null; + } + + @Override + public Node newNode(String name) { + if (saved) + return super.newNode(name); + else + return null; + } + + @Override + public void save(String logMessage) { + if (!saved) { + file.mkdir(); + + try { + service.add(id, fullPath); + } catch (SvnOperationFailed e) { + throw new RepositoryException(e); + } + saved = true; + } + + super.save(logMessage); + } + + @Override + public void setIndex(String propertyName, boolean index) { + if (saved) + super.setIndex(propertyName, index); + } +} Added: trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnNewNode.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnNewNode.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnNewNode.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -0,0 +1,113 @@ +package org.jboss.shotoku.svn; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.Calendar; + +import org.jboss.shotoku.History; +import org.jboss.shotoku.exceptions.RepositoryException; + +public class SvnNewNode extends SvnHeadNode { + private String content; + private boolean saved; + + public SvnNewNode(String id, String fullPath, File file) { + super(id, fullPath, file); + + content = null; + saved = false; + } + + @Override + public void delete() { + // We only have to delete a corresponding file if this node has + // been saved already. + if (saved) + super.delete(); + } + + @Override + public String getContent() { + if (saved) + return super.getContent(); + else + return content; + } + + @Override + public InputStream getContentInputStream() { + if (saved) + return super.getContentInputStream(); + else + // TODO + return null; + } + + @Override + public History getHistory() { + if (saved) + return super.getHistory(); + else + return null; + } + + @Override + public long getLastModfication() { + if (saved) + return super.getLastModfication(); + else + return Calendar.getInstance().getTimeInMillis(); + } + + @Override + public long getLength() { + if (saved) + return super.getLength(); + else + return content.length(); + } + + @Override + public String getLogMessage() { + if (saved) + return super.getLogMessage(); + else + return null; + } + + @Override + public int getRevisionNumber() { + if (saved) + return super.getRevisionNumber(); + else + return -1; + } + + @Override + public void save(String logMessage) { + if (!saved) { + try { + file.createNewFile(); + service.add(id, fullPath); + } catch (IOException e) { + throw new RepositoryException(e); + } catch (SvnOperationFailed e) { + throw new RepositoryException(e); + } + + saved = true; + } + + super.save(logMessage); + } + + @Override + public void setContent(String content) { + if (saved) + super.setContent(content); + else + this.content = content; + } + +} Added: trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnOperationFailed.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnOperationFailed.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnOperationFailed.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -0,0 +1,11 @@ +package org.jboss.shotoku.svn; + +public class SvnOperationFailed extends Exception { + public SvnOperationFailed(Exception e) { + super(e); + } + + public SvnOperationFailed(String msg) { + super(msg); + } +} Modified: trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnService.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnService.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/SvnService.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -1,17 +1,118 @@ package org.jboss.shotoku.svn; public abstract interface SvnService { - public abstract void commit(String id, String path, String logMessage); + /** + * Gets an exclusive write lock for a given path. The lock should be + * requiered before making any changes to the file. Later, the file + * must be added for a commit, unless an exception is thrown. After + * commiting the file, the lock is released. + * @param id Id of the repository. + * @param path Path to lock. + */ + public abstract void getWriteLock(String id, String path); + /** + * Puts an earlier acquiered exclusive write lock for a given path. + * This should be called only in case of an internal node-implementation + * execption that occures while saving. + * @param id Id of the repository. + * @param path Path to release the lock for. + */ + public abstract void putWriteLock(String id, String path); + /** + * Adds the given path to a commite quese of a repository with the + * given id. + * @param id Id of the repository. + * @param path Path to commit. + * @param logMessage Log message to commit with. + * @throws SvnOperationFailed + */ + public abstract void commit(String id, String path, String logMessage) + throws SvnOperationFailed; + /** + * Sets a property on the given path. + * @param id Id of the repository. + * @param path Path to set the property on. + * @param name Name of the property to set. + * @param value Value of the property to set. + * @throws SvnOperationFailed + */ public abstract void setProperty(String id, String path, String name, - String value); - public abstract String getProperty(String id, String path, String name); + String value) throws SvnOperationFailed; + /** + * Gets a property from the given path. + * @param id Id of the repository. + * @param path Path to get the property from. + * @param name Name of the property to get. + * @return Value of the property or null, if it is not set. + * @throws SvnOperationFailed + */ + public abstract String getProperty(String id, String path, String name) + throws SvnOperationFailed; + /** + * Gets content of a node at the specified revision. + * @param id Id of the repository. + * @param path Path to a file to get the revision of. + * @param revision Number of the revision to get (revisions are counted + * from 1 with step 1). + * @return String representation of this node's content at the given + * revision or null, if this node does not have the given revision. + * @throws SvnOperationFailed + */ public abstract String getNodeAtRevision(String id, String path, - int revision); - public abstract String getLogMessage(String id, String revision); - public abstract int getRevisionCount(String id, String path); - public abstract void delete(String id, String path); - public abstract void add(String id, String path); - public abstract String getFileSystemPath(String id, String path); + int revision) throws SvnOperationFailed; + /** + * Gets a log message with which the given revision was commited. + * @param id Id of the repository. + * @param revision Number of the revision (svn revision number). + * @return Log message with which the given reivison was commited + * or null, if no such revision exists. + * @throws SvnOperationFailed + */ + public abstract String getLogMessage(String id, String revision) + throws SvnOperationFailed; + /** + * Gets the number of revisions of a given path. + * @param id Id of the repository. + * @param path Path for which to determine the number of revisions + * (number of different versions). + * @return Number of revisions of a given path. + * @throws SvnOperationFailed + */ + public abstract int getRevisionCount(String id, String path) + throws SvnOperationFailed; + /** + * Deletes a given path (node/ directory) from the repository. The + * resource is automatically added to a commite queue. + * @param id Id of the repository. + * @param path Path to delete. + * @throws SvnOperationFailed + */ + public abstract void delete(String id, String path) + throws SvnOperationFailed; + /** + * Adds a given path (node/ directory) to a repository. The resource + * is automatically added to a commite queue. + * @param id Id of the repository. + * @param path Path to add. + * @throws SvnOperationFailed + */ + public abstract void add(String id, String path) + throws SvnOperationFailed; + /** + * Gets a full path on the file system to a resource with the given + * repository-path. + * @param id Id of the repository. + * @param path Path to the resource. + * @return A full path on the file system to the given resource (represented + * by a path). + * @throws SvnOperationFailed + */ + public abstract String getFileSystemPath(String id, String path) + throws SvnOperationFailed; + /** + * <code>SVN_SERVICE_NAME</code> - name under which the svn service + * is registered. + */ public final static String SVN_SERVICE_NAME = "shotoku:service=svn"; } Added: trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/Tools.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/Tools.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn/src/java/org/jboss/shotoku/svn/Tools.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -0,0 +1,24 @@ +package org.jboss.shotoku.svn; + +import javax.management.MalformedObjectNameException; + +import org.jboss.mx.util.MBeanProxyExt; +import org.jboss.mx.util.MBeanServerLocator; + +public class Tools { + private static SvnService instance; + + public static SvnService getService() { + try { + if (instance == null) + instance = (SvnService) MBeanProxyExt.create( + SvnService.class, + SvnService.SVN_SERVICE_NAME, + MBeanServerLocator.locate()); + + return instance; + } catch (MalformedObjectNameException e) { + throw new RuntimeException(e); + } + } +} Modified: trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnRepository.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnRepository.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnRepository.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -2,8 +2,11 @@ import java.io.File; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; +import java.util.concurrent.Semaphore; import org.apache.log4j.Logger; import org.tmatesoft.svn.core.SVNException; @@ -15,6 +18,11 @@ import org.tmatesoft.svn.core.wc.SVNUpdateClient; import org.tmatesoft.svn.core.wc.SVNWCUtil; +/** + * @author adamw + * A class for performing operations on a single subversion repository and + * its local working copy. + */ public class SvnRepository { private static final Logger log = Logger.getLogger(SvnRepository.class); @@ -23,6 +31,7 @@ private String localpath; private File wc; private Set<String[]> toCommit; + private Map<String, Semaphore> semaphores; public SvnRepository(String username, String password, String url, String localpath) { @@ -35,8 +44,13 @@ wc = new File(localpath); toCommit = Collections.synchronizedSet(new HashSet<String[]>()); + semaphores = new HashMap<String, Semaphore>(); } + /** + * Tries to perform a cleanup on the local working copy. Called in case + * of execptions that occure while performing other operations. + */ private void tryCleanup() { try { ourClientManager.getWCClient().doCleanup(wc); @@ -45,6 +59,9 @@ } } + /** + * Updates the local working copy. + */ public synchronized void update() { try { SVNURL repositoryURL = SVNURL.parseURIEncoded(url); @@ -69,10 +86,18 @@ } } + /** + * Adds a given file with a given log message to a commit queue. + * @param path Path (file/ directory) to commit. + * @param logMessage Log message with thich to commit. + */ public void addToCommit(String path, String logMessage) { toCommit.add(new String[] { path, logMessage }); } + /** + * Commits all paths (files/ directories) that were scheduled for a commit. + */ public void commit() { String[][] allToCommit; @@ -84,12 +109,16 @@ for (String[] oneToCommit : allToCommit) { SVNCommitClient commitClient = ourClientManager.getCommitClient(); try { + log.info("Commiting: " + oneToCommit[0]); commitClient.doCommit( new File[] { new File(getFileSystemPath(oneToCommit[0])) }, false, oneToCommit[1], true, false); + + putWriteLock(oneToCommit[0]); } catch (SVNException e) { tryCleanup(); - log.warn("Commiting of " + oneToCommit[0] + " failed", e); + putWriteLock(oneToCommit[0]); + log.warn("Commiting: " + oneToCommit[0] + " failed", e); } } } @@ -98,6 +127,34 @@ return replaceSeparators(localpath + '/' + path); } + public void getWriteLock(String path) { + Semaphore s; + + synchronized (semaphores) { + s = semaphores.get(path); + if (s == null) { + s = new Semaphore(1); + semaphores.put(path, s); + } + } + + try { + s.acquire(); + } catch (InterruptedException e) { + // We never interrupt the threads. + } + } + + public void putWriteLock(String path) { + Semaphore s; + + synchronized (semaphores) { + s = semaphores.get(path); + } + + s.release(); + } + private String replaceSeparators(String path) { return '/' == File.separatorChar ? path : path.replace('/', File.separatorChar); Modified: trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceImpl.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceImpl.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceImpl.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -27,7 +27,7 @@ * <code>DEFAULT_TIMER_INTERVAL</code> - default interval lenght of the * timer. */ - private final static long DEFAULT_TIMER_INTERVAL = 1000*60; // 1 minute + private final static long DEFAULT_TIMER_INTERVAL = 1000*5; // 5 seconds private long timerInterval; @EJB @@ -120,6 +120,14 @@ * SvnService implementation. */ + public void getWriteLock(String id, String path) { + repositories.get(id).getWriteLock(path); + } + + public void putWriteLock(String id, String path) { + repositories.get(id).putWriteLock(path); + } + public void commit(String id, String path, String logMessage) { repositories.get(id).addToCommit(path, logMessage); } Added: trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceLocal.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceLocal.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceLocal.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -0,0 +1,7 @@ +package org.jboss.shotoku.svn.service; + +public interface SvnServiceLocal { + public void setTimerInterval(long timerInterval); + public long getTimerInterval(); + public void update(); +} Added: trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceManagement.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceManagement.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceManagement.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -0,0 +1,12 @@ +package org.jboss.shotoku.svn.service; + +import org.jboss.annotation.ejb.Management; +import org.jboss.shotoku.svn.SvnService; + +@Management +public interface SvnServiceManagement extends SvnService, SvnServiceLocal { + public void create() throws Exception; + public void start() throws Exception; + public void stop(); + public void destroy(); +} Modified: trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceTimer.java =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceTimer.java 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-svn-service/src/java/org/jboss/shotoku/svn/service/SvnServiceTimer.java 2005-09-26 20:56:01 UTC (rev 1215) @@ -10,7 +10,6 @@ import javax.ejb.Timer; import javax.management.MalformedObjectNameException; -import org.apache.log4j.Logger; import org.jboss.mx.util.MBeanProxyExt; import org.jboss.mx.util.MBeanServerLocator; import org.jboss.shotoku.svn.SvnService; @@ -18,7 +17,7 @@ @Stateless @Local(SvnServiceTimerLocal.class) public class SvnServiceTimer { - private static final Logger log = Logger.getLogger(SvnServiceTimer.class); + //private static final Logger log = Logger.getLogger(SvnServiceTimer.class); private @Resource SessionContext ctx; public void scheduleTimer(long interval) { @@ -35,9 +34,7 @@ SvnService.SVN_SERVICE_NAME, MBeanServerLocator.locate())); - log.info("Updating svn service ..."); ssi.update(); - log.info("Done updating svn service."); scheduleTimer(ssi.getTimerInterval()); } catch (MalformedObjectNameException e) { Property changes on: trunk/forge/portal-extensions/shotoku/shotoku-test ___________________________________________________________________ Name: svn:ignore + target .classpath .settings .project Added: trunk/forge/portal-extensions/shotoku/shotoku-test/maven.xml =================================================================== --- trunk/forge/portal-extensions/shotoku/shotoku-test/maven.xml 2005-09-26 20:14:14 UTC (rev 1214) +++ trunk/forge/portal-extensions/shotoku/shotoku-test/maven.xml 2005-09-26 20:56:01 UTC (rev 1215) @@ -0,0 +1,30 @@ +<!-- + JBoss, the OpenSource J2EE webOS + Distributable under LGPL license. + See terms of license at gnu.org. + --> +<project xmlns:j="jelly:core" ... [truncated message content] |