/**
 * @version 1.1.0
 * @author TMate Software Ltd.
 */
public class DAVFileRevisionHandler extends BasicDAVDeltaHandler {

  public static StringBuffer generateFileRevisionsRequest(
      StringBuffer buffer, long startRevision, long endRevision, String path) {
    buffer = buffer == null ? new StringBuffer() : buffer;
    buffer.append("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
    buffer.append("<S:file-revs-report xmlns:S=\"svn:\">");
    if (startRevision >= 0) {
      buffer.append("<S:start-revision>" + startRevision + "</S:start-revision>");
    }
    if (endRevision >= 0) {
      buffer.append("<S:end-revision>" + endRevision + "</S:end-revision>");
    }
    buffer.append("<S:path>" + SVNEncodingUtil.xmlEncodeCDATA(path) + "</S:path>");
    buffer.append("</S:file-revs-report>");
    return buffer;
  }

  private static final DAVElement REVISION_PROPERTY =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "rev-prop");
  private static final DAVElement FILE_REVISION =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "file-rev");

  private static final DAVElement SET_PROPERTY =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "set-prop");
  private static final DAVElement DELETE_PROPERTY =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "remove-prop");

  private ISVNFileRevisionHandler myFileRevisionsHandler;
  private String myPath;
  private long myRevision;
  private Map myProperties;
  private Map myPropertiesDelta;
  private String myPropertyName;
  private String myPropertyEncoding;

  private int myCount;

  public DAVFileRevisionHandler(ISVNFileRevisionHandler handler) {
    myFileRevisionsHandler = handler;
    myCount = 0;
    init();
  }

  protected void startElement(DAVElement parent, DAVElement element, Attributes attrs)
      throws SVNException {
    if (element == FILE_REVISION) {
      myPath = attrs.getValue("path");
      myRevision = Long.parseLong(attrs.getValue("rev"));
    } else if (element == REVISION_PROPERTY
        || element == SET_PROPERTY
        || element == DELETE_PROPERTY) {
      myPropertyName = attrs.getValue("name");
      myPropertyEncoding = attrs.getValue("encoding");
    }
    if (element == TX_DELTA) {
      // handle file revision with props.
      if (myPath != null && myFileRevisionsHandler != null) {
        if (myProperties == null) {
          myProperties = Collections.EMPTY_MAP;
        }
        if (myPropertiesDelta == null) {
          myPropertiesDelta = Collections.EMPTY_MAP;
        }
        SVNFileRevision revision =
            new SVNFileRevision(myPath, myRevision, myProperties, myPropertiesDelta);
        myFileRevisionsHandler.openRevision(revision);
        myProperties = null;
        myPropertiesDelta = null;
        myPath = null;
        myFileRevisionsHandler.applyTextDelta(myPath, null);
      }
      setDeltaProcessing(true);
    }
  }

  protected void endElement(DAVElement parent, DAVElement element, StringBuffer cdata)
      throws SVNException {
    if (element == FILE_REVISION) {
      if (myPath != null && myFileRevisionsHandler != null) {
        // handle file revision if was not handled yet (no tx delta).
        if (myProperties == null) {
          myProperties = Collections.EMPTY_MAP;
        }
        if (myPropertiesDelta == null) {
          myPropertiesDelta = Collections.EMPTY_MAP;
        }
        SVNFileRevision revision =
            new SVNFileRevision(myPath, myRevision, myProperties, myPropertiesDelta);
        myFileRevisionsHandler.openRevision(revision);
      }
      // handle close revision with props?
      if (myFileRevisionsHandler != null) {
        myFileRevisionsHandler.closeRevision(myPath);
      }
      myPath = null;
      myProperties = null;
      myPropertiesDelta = null;
      myPropertyEncoding = null;
      myPropertyName = null;
    } else if (element == TX_DELTA) {
      setDeltaProcessing(false);
      myCount++;
    } else if (element == REVISION_PROPERTY) {
      if (myProperties == null) {
        myProperties = new HashMap();
      }
      myProperties.put(myPropertyName, cdata != null ? cdata.toString() : "");
      myPropertyName = null;
    } else if (element == SET_PROPERTY) {
      if (myPropertiesDelta == null) {
        myPropertiesDelta = new HashMap();
      }
      if (myPropertyName != null) {
        String value;
        if ("base64".equals(myPropertyEncoding)) {
          byte[] bytes = allocateBuffer(cdata.length());
          int length =
              SVNBase64.base64ToByteArray(new StringBuffer(cdata.toString().trim()), bytes);
          try {
            value = new String(bytes, 0, length, "UTF-8");
          } catch (UnsupportedEncodingException e) {
            value = new String(bytes, 0, length);
          }
        } else {
          value = cdata.toString();
        }
        myPropertiesDelta.put(myPropertyName, value);
      }
      myPropertyName = null;
      myPropertyEncoding = null;
    } else if (element == DELETE_PROPERTY) {
      if (myPropertiesDelta == null) {
        myPropertiesDelta = new HashMap();
      }
      if (myPropertyName != null) {
        myPropertiesDelta.put(myPropertyName, null);
      }
      myPropertyEncoding = null;
      myPropertyName = null;
    }
  }

  public int getEntriesCount() {
    return myCount;
  }

  protected ISVNDeltaConsumer getDeltaConsumer() {
    return myFileRevisionsHandler;
  }

  protected String getCurrentPath() {
    return myPath;
  }
}
Esempio n. 2
0
/**
 * @author TMate Software Ltd.
 * @version 1.3
 */
public class DAVReplayHandler extends DAVEditorHandler {

  public static StringBuffer generateReplayRequest(
      long highRevision, long lowRevision, boolean sendDeltas) {
    StringBuffer xmlBuffer = new StringBuffer();
    SVNXMLUtil.addXMLHeader(xmlBuffer);
    SVNXMLUtil.openNamespaceDeclarationTag(
        SVNXMLUtil.SVN_NAMESPACE_PREFIX,
        "replay-report",
        SVN_NAMESPACES_LIST,
        SVNXMLUtil.PREFIX_MAP,
        xmlBuffer);
    SVNXMLUtil.openCDataTag(
        SVNXMLUtil.SVN_NAMESPACE_PREFIX, "revision", String.valueOf(highRevision), xmlBuffer);
    SVNXMLUtil.openCDataTag(
        SVNXMLUtil.SVN_NAMESPACE_PREFIX, "low-water-mark", String.valueOf(lowRevision), xmlBuffer);
    SVNXMLUtil.openCDataTag(
        SVNXMLUtil.SVN_NAMESPACE_PREFIX, "send-deltas", sendDeltas ? "1" : "0", xmlBuffer);
    SVNXMLUtil.addXMLFooter(SVNXMLUtil.SVN_NAMESPACE_PREFIX, "replay-report", xmlBuffer);
    return xmlBuffer;
  }

  protected static final DAVElement EDITOR_REPORT =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "editor-report");
  protected static final DAVElement OPEN_ROOT =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "open-root");
  protected static final DAVElement APPLY_TEXT_DELTA =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "apply-textdelta");
  protected static final DAVElement CLOSE_FILE =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "close-file");
  protected static final DAVElement CLOSE_DIRECTORY =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "close-directory");
  protected static final DAVElement CHANGE_FILE_PROPERTY =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "change-file-prop");
  protected static final DAVElement CHANGE_DIR_PROPERTY =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "change-dir-prop");

  protected static final String CHECKSUM_ATTR = "checksum";
  protected static final String DEL_ATTR = "del";

  public DAVReplayHandler(ISVNEditor editor, boolean fetchContent) {
    super(null, null, editor, null, fetchContent, false);
  }

  protected void startElement(DAVElement parent, DAVElement element, Attributes attrs)
      throws SVNException {
    if (element == TARGET_REVISION) {
      String rev = attrs.getValue(REVISION_ATTR);
      if (rev == null) {
        SVNErrorMessage err =
            SVNErrorMessage.create(
                SVNErrorCode.RA_DAV_MALFORMED_DATA,
                "Missing revision attr in target-revision element");
        SVNErrorManager.error(err, SVNLogType.NETWORK);
      } else {
        try {
          myEditor.targetRevision(Long.parseLong(rev));
        } catch (NumberFormatException nfe) {
          SVNErrorManager.error(
              SVNErrorMessage.create(SVNErrorCode.RA_DAV_MALFORMED_DATA, nfe), SVNLogType.NETWORK);
        }
      }
    } else if (element == OPEN_ROOT) {
      String rev = attrs.getValue(REVISION_ATTR);
      if (rev == null) {
        SVNErrorMessage err =
            SVNErrorMessage.create(
                SVNErrorCode.RA_DAV_MALFORMED_DATA, "Missing revision attr in open-root element");
        SVNErrorManager.error(err, SVNLogType.NETWORK);
      } else {
        try {
          myEditor.openRoot(Long.parseLong(rev));
        } catch (NumberFormatException nfe) {
          SVNErrorManager.error(
              SVNErrorMessage.create(SVNErrorCode.RA_DAV_MALFORMED_DATA, nfe), SVNLogType.NETWORK);
        }
        myPath = "";
        myIsDirectory = true;
      }
    } else if (element == DELETE_ENTRY) {
      String path = attrs.getValue(NAME_ATTR);
      String rev = attrs.getValue(REVISION_ATTR);
      if (path == null) {
        SVNErrorMessage err =
            SVNErrorMessage.create(
                SVNErrorCode.RA_DAV_MALFORMED_DATA, "Missing name attr in delete-entry element");
        SVNErrorManager.error(err, SVNLogType.NETWORK);
      } else if (rev == null) {
        SVNErrorMessage err =
            SVNErrorMessage.create(
                SVNErrorCode.RA_DAV_MALFORMED_DATA, "Missing rev attr in delete-entry element");
        SVNErrorManager.error(err, SVNLogType.NETWORK);
      } else {
        try {
          myEditor.deleteEntry(path, Long.parseLong(rev));
        } catch (NumberFormatException nfe) {
          SVNErrorManager.error(
              SVNErrorMessage.create(SVNErrorCode.RA_DAV_MALFORMED_DATA, nfe), SVNLogType.NETWORK);
        }
      }
    } else if (element == OPEN_DIRECTORY || element == ADD_DIRECTORY) {
      String path = attrs.getValue(NAME_ATTR);
      String rev = attrs.getValue(REVISION_ATTR);

      if (path == null) {
        SVNErrorMessage err =
            SVNErrorMessage.create(
                SVNErrorCode.RA_DAV_MALFORMED_DATA,
                "Missing name attr in "
                    + (element == OPEN_DIRECTORY ? "open-directory" : "add-directory")
                    + " element");
        SVNErrorManager.error(err, SVNLogType.NETWORK);
      } else {
        long revision = -1;
        if (rev != null) {
          try {
            revision = Long.parseLong(rev);
          } catch (NumberFormatException nfe) {
            SVNErrorManager.error(
                SVNErrorMessage.create(SVNErrorCode.RA_DAV_MALFORMED_DATA, nfe),
                SVNLogType.NETWORK);
          }
        }
        if (element == OPEN_DIRECTORY) {
          myEditor.openDir(path, revision);
        } else {
          String copyFromPath = attrs.getValue(COPYFROM_PATH_ATTR);
          String cfRevision = attrs.getValue(COPYFROM_REV_ATTR);
          long copyFromRevision = -1;
          if (cfRevision != null) {
            try {
              copyFromRevision = Long.parseLong(cfRevision);
            } catch (NumberFormatException nfe) {
              SVNErrorManager.error(
                  SVNErrorMessage.create(SVNErrorCode.RA_DAV_MALFORMED_DATA, nfe),
                  SVNLogType.NETWORK);
            }
          }
          myEditor.addDir(path, copyFromPath, copyFromRevision);
        }
      }
      myPath = path;
      myIsDirectory = true;
    } else if (element == OPEN_FILE || element == ADD_FILE) {
      String path = attrs.getValue(NAME_ATTR);
      if (path == null) {
        SVNErrorMessage err =
            SVNErrorMessage.create(
                SVNErrorCode.RA_DAV_MALFORMED_DATA,
                "Missing name attr in "
                    + (element == OPEN_FILE ? "open-file" : "add-file")
                    + " element");
        SVNErrorManager.error(err, SVNLogType.NETWORK);
      }

      if (element == ADD_FILE) {
        String copyFromPath = attrs.getValue(COPYFROM_PATH_ATTR);
        String cfRevision = attrs.getValue(COPYFROM_REV_ATTR);
        long copyFromRevision = -1;
        if (cfRevision != null) {
          try {
            copyFromRevision = Long.parseLong(cfRevision);
          } catch (NumberFormatException nfe) {
            SVNErrorManager.error(
                SVNErrorMessage.create(SVNErrorCode.RA_DAV_MALFORMED_DATA, nfe),
                SVNLogType.NETWORK);
          }
        }
        myEditor.addFile(path, copyFromPath, copyFromRevision);
      } else {
        String rev = attrs.getValue(REVISION_ATTR);
        long revision = -1;
        if (rev != null) {
          try {
            revision = Long.parseLong(rev);
          } catch (NumberFormatException nfe) {
            SVNErrorManager.error(
                SVNErrorMessage.create(SVNErrorCode.RA_DAV_MALFORMED_DATA, nfe),
                SVNLogType.NETWORK);
          }
        }
        myEditor.openFile(path, revision);
      }
      myIsDirectory = false;
      myPath = path;
    } else if (element == APPLY_TEXT_DELTA) {
      if (myIsDirectory) {
        SVNErrorMessage err =
            SVNErrorMessage.create(
                SVNErrorCode.RA_DAV_MALFORMED_DATA,
                "Got apply-textdelta element without preceding add-file or open-file");
        SVNErrorManager.error(err, SVNLogType.NETWORK);
      }

      String checksum = attrs.getValue(CHECKSUM_ATTR);
      try {
        myEditor.applyTextDelta(myPath, checksum);
        setDeltaProcessing(true);
      } catch (SVNException svne) {
        //
      }
    } else if (element == CLOSE_FILE) {
      if (myIsDirectory) {
        SVNErrorMessage err =
            SVNErrorMessage.create(
                SVNErrorCode.RA_DAV_MALFORMED_DATA,
                "Got close-file element without preceding add-file or open-file");
        SVNErrorManager.error(err, SVNLogType.NETWORK);
      } else {
        String checksum = attrs.getValue(CHECKSUM_ATTR);
        myEditor.closeFile(myPath, checksum);
        myIsDirectory = true;
      }
    } else if (element == CLOSE_DIRECTORY) {
      if (!myIsDirectory) {
        SVNErrorMessage err =
            SVNErrorMessage.create(
                SVNErrorCode.RA_DAV_MALFORMED_DATA,
                "Got close-directory element without ever opening a directory");
        SVNErrorManager.error(err, SVNLogType.NETWORK);
      } else {
        myEditor.closeDir();
      }
    } else if (element == CHANGE_FILE_PROPERTY || element == CHANGE_DIR_PROPERTY) {
      String name = attrs.getValue(NAME_ATTR);
      if (name == null) {
        SVNErrorMessage err =
            SVNErrorMessage.create(
                SVNErrorCode.RA_DAV_MALFORMED_DATA,
                "Missing name attr in "
                    + (element == CHANGE_FILE_PROPERTY ? "change-file-prop" : "change-dir-prop")
                    + " element");
        SVNErrorManager.error(err, SVNLogType.NETWORK);
      } else {
        if (attrs.getValue(DEL_ATTR) != null) {
          if (element == CHANGE_FILE_PROPERTY) {
            myEditor.changeFileProperty(myPath, name, null);
          } else {
            myEditor.changeDirProperty(name, null);
          }
          myPropertyName = null;
        } else {
          myPropertyName = name;
        }
      }
    }
  }

  protected void endElement(DAVElement parent, DAVElement element, StringBuffer cdata)
      throws SVNException {
    if (element == APPLY_TEXT_DELTA) {
      setDeltaProcessing(false);
    } else if (element == CHANGE_FILE_PROPERTY || element == CHANGE_DIR_PROPERTY) {
      if (cdata != null && !"".equals(cdata.toString()) && myPropertyName == null) {
        SVNErrorMessage err =
            SVNErrorMessage.create(
                SVNErrorCode.RA_DAV_MALFORMED_DATA, "Got cdata content for a prop delete");
        SVNErrorManager.error(err, SVNLogType.NETWORK);
      }
      if (myPropertyName != null) {
        StringBuffer sb = SVNBase64.normalizeBase64(cdata);
        byte[] buffer = allocateBuffer(sb.length());
        int length = SVNBase64.base64ToByteArray(sb, buffer);
        SVNPropertyValue property = SVNPropertyValue.create(myPropertyName, buffer, 0, length);
        if (element == CHANGE_FILE_PROPERTY) {
          myEditor.changeFileProperty(myPath, myPropertyName, property);
        } else {
          myEditor.changeDirProperty(myPropertyName, property);
        }
      }
    }
  }
}
Esempio n. 3
0
/**
 * @version 1.3
 * @author TMate Software Ltd.
 */
public class DAVElement {

  private static Map ourProperties = new SVNHashMap();

  public static DAVElement getElement(String namespace, String name) {
    if (namespace == null) {
      namespace = "";
    }
    Map properties = (Map) ourProperties.get(namespace);
    if (properties == null) {
      properties = new SVNHashMap();
      ourProperties.put(namespace, properties);
    }
    name = name.replace(XMLReader.COLON_REPLACEMENT, ':');
    DAVElement property = (DAVElement) properties.get(name);
    if (property == null) {
      property = new DAVElement(namespace, name);
      properties.put(name, property);
    }
    return property;
  }

  public static final String SVN_DAV_PROPERTY_NAMESPACE = "http://subversion.tigris.org/xmlns/dav/";
  public static final String SVN_CUSTOM_PROPERTY_NAMESPACE =
      "http://subversion.tigris.org/xmlns/custom/";
  public static final String SVN_SVN_PROPERTY_NAMESPACE = "http://subversion.tigris.org/xmlns/svn/";
  public static final String SVN_APACHE_PROPERTY_NAMESPACE = "http://apache.org/dav/xmlns";

  public static final String SVN_DAV_ERROR_NAMESPACE = "svn:";
  public static final String DAV_NAMESPACE = "DAV:";
  public static final String SVN_NAMESPACE = "svn:";

  public static final String DEPTH_OPTION = SVN_DAV_PROPERTY_NAMESPACE + "svn/depth";
  public static final String MERGE_INFO_OPTION = SVN_DAV_PROPERTY_NAMESPACE + "svn/mergeinfo";
  public static final String LOG_REVPROPS_OPTION = SVN_DAV_PROPERTY_NAMESPACE + "svn/log-revprops";
  public static final String PARTIAL_REPLAY_OPTION =
      SVN_DAV_PROPERTY_NAMESPACE + "svn/partial-replay";
  public static final String ATOMIC_REVPROPS_OPTION =
      SVN_DAV_PROPERTY_NAMESPACE + "svn/atomic-revprops";
  public static final String INHERITED_PROPS_OPTION =
      SVN_DAV_PROPERTY_NAMESPACE + "svn/inherited-props";

  public static final DAVElement ACTIVITY = getElement(DAV_NAMESPACE, "activity");
  public static final DAVElement VERSION_HISTORY = getElement(DAV_NAMESPACE, "version-history");
  public static final DAVElement DISPLAY_NAME = getElement(DAV_NAMESPACE, "displayname");
  public static final DAVElement SUPPORTED_LIVE_PROPERTY =
      getElement(DAV_NAMESPACE, "supported-live-property");
  public static final DAVElement MERGE_RESPONSE = getElement(DAV_NAMESPACE, "merge-response");
  public static final DAVElement UPDATE_SET = getElement(DAV_NAMESPACE, "updated-set");
  public static final DAVElement NO_AUTO_MERGE = getElement(DAV_NAMESPACE, "no-auto-merge");
  public static final DAVElement NO_CHECKOUT = getElement(DAV_NAMESPACE, "no-checkout");
  public static final DAVElement SOURCE = getElement(DAV_NAMESPACE, "source");
  public static final DAVElement MULTISTATUS = getElement(DAV_NAMESPACE, "multistatus");
  public static final DAVElement RESPONSE = getElement(DAV_NAMESPACE, "response");
  public static final DAVElement RESPONSE_DESCRIPTION =
      getElement(DAV_NAMESPACE, "responsedescription");
  public static final DAVElement HREF = getElement(DAV_NAMESPACE, "href");
  public static final DAVElement PROPSTAT = getElement(DAV_NAMESPACE, "propstat");
  public static final DAVElement PROP = getElement(DAV_NAMESPACE, "prop");
  public static final DAVElement STATUS = getElement(DAV_NAMESPACE, "status");
  public static final DAVElement BASELINE = getElement(DAV_NAMESPACE, "baseline");
  public static final DAVElement BASELINE_COLLECTION =
      getElement(DAV_NAMESPACE, "baseline-collection");
  public static final DAVElement CHECKED_IN = getElement(DAV_NAMESPACE, "checked-in");
  public static final DAVElement COLLECTION = getElement(DAV_NAMESPACE, "collection");
  public static final DAVElement RESOURCE_TYPE = getElement(DAV_NAMESPACE, "resourcetype");
  public static final DAVElement VERSION_CONTROLLED_CONFIGURATION =
      getElement(DAV_NAMESPACE, "version-controlled-configuration");
  public static final DAVElement VERSION_NAME = getElement(DAV_NAMESPACE, "version-name");
  public static final DAVElement GET_CONTENT_LENGTH = getElement(DAV_NAMESPACE, "getcontentlength");
  public static final DAVElement CREATION_DATE = getElement(DAV_NAMESPACE, "creationdate");
  public static final DAVElement CREATOR_DISPLAY_NAME =
      getElement(DAV_NAMESPACE, "creator-displayname");
  public static final DAVElement COMMENT = getElement(DAV_NAMESPACE, "comment");
  public static final DAVElement DATE = getElement(SVN_NAMESPACE, "date");
  public static final DAVElement POST_COMMIT_ERROR =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "post-commit-err");
  public static final DAVElement PROPFIND = DAVElement.getElement(DAV_NAMESPACE, "propfind");
  public static final DAVElement ALLPROP = DAVElement.getElement(DAV_NAMESPACE, "allprop");
  public static final DAVElement PROPNAME = DAVElement.getElement(DAV_NAMESPACE, "propname");
  public static final DAVElement ACTIVE_LOCK = DAVElement.getElement(DAV_NAMESPACE, "activelock");
  public static final DAVElement LOCK_TYPE = DAVElement.getElement(DAV_NAMESPACE, "locktype");
  public static final DAVElement LOCK_SCOPE = DAVElement.getElement(DAV_NAMESPACE, "lockscope");
  public static final DAVElement WRITE = DAVElement.getElement(DAV_NAMESPACE, "write");
  public static final DAVElement EXCLUSIVE = DAVElement.getElement(DAV_NAMESPACE, "exclusive");
  public static final DAVElement SHARED = DAVElement.getElement(DAV_NAMESPACE, "shared");
  public static final DAVElement DEPTH = DAVElement.getElement(DAV_NAMESPACE, "depth");

  public static final DAVElement SUPPORTED_LOCK = getElement(DAV_NAMESPACE, "supportedlock");
  public static final DAVElement LOCK_DISCOVERY = getElement(DAV_NAMESPACE, "lockdiscovery");
  public static final DAVElement LOCK_OWNER = getElement(DAV_NAMESPACE, "owner");
  public static final DAVElement LOCK_TIMEOUT = getElement(DAV_NAMESPACE, "timeout");
  public static final DAVElement LOCK_TOKEN = getElement(DAV_NAMESPACE, "locktoken");
  public static final DAVElement LOCK_ENTRY = getElement(DAV_NAMESPACE, "lockentry");

  public static final DAVElement SVN_LOCK_TOKEN_LIST = getElement(SVN_NAMESPACE, "lock-token-list");
  public static final DAVElement SVN_LOCK = getElement(SVN_NAMESPACE, "lock");
  public static final DAVElement SVN_LOCK_PATH = getElement(SVN_NAMESPACE, "path");
  public static final DAVElement SVN_LOCK_TOKEN = getElement(SVN_NAMESPACE, "token");
  public static final DAVElement SVN_LOCK_COMMENT = getElement(SVN_NAMESPACE, "comment");
  public static final DAVElement SVN_LOCK_OWNER = getElement(SVN_NAMESPACE, "owner");
  public static final DAVElement SVN_LOCK_CREATION_DATE = getElement(SVN_NAMESPACE, "creationdate");
  public static final DAVElement SVN_LOCK_EXPIRATION_DATE =
      getElement(SVN_NAMESPACE, "expirationdate");

  // servlet defined svn namespace properties
  public static final DAVElement PATH = DAVElement.getElement(DAVElement.SVN_NAMESPACE, "path");
  public static final DAVElement REVISION =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "revision");
  public static final DAVElement START_REVISION =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "start-revision");
  public static final DAVElement END_REVISION =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "end-revision");
  public static final DAVElement PEG_REVISION =
      DAVElement.getElement(DAVElement.SVN_NAMESPACE, "peg-revision");
  public static final DAVElement INCLUDE_MERGED_REVISIONS =
      getElement(SVN_NAMESPACE, "include-merged-revisions");

  public static final DAVElement BASELINE_RELATIVE_PATH =
      getElement(SVN_DAV_PROPERTY_NAMESPACE, "baseline-relative-path");
  public static final DAVElement REPOSITORY_UUID =
      getElement(SVN_DAV_PROPERTY_NAMESPACE, "repository-uuid");
  public static final DAVElement MD5_CHECKSUM =
      getElement(SVN_DAV_PROPERTY_NAMESPACE, "md5-checksum");
  public static final DAVElement DEADPROP_COUNT =
      getElement(SVN_DAV_PROPERTY_NAMESPACE, "deadprop-count");

  public static final DAVElement AUTO_VERSION = getElement(DAV_NAMESPACE, "auto-version");

  public static final DAVElement MERGE_INFO_ITEM = getElement(SVN_NAMESPACE, "mergeinfo-item");
  public static final DAVElement MERGE_INFO_PATH = getElement(SVN_NAMESPACE, "mergeinfo-path");
  public static final DAVElement MERGE_INFO_INFO = getElement(SVN_NAMESPACE, "mergeinfo-info");

  // Supported live properties
  public static final DAVElement GET_CONTENT_LANGUAGE =
      getElement(DAV_NAMESPACE, "getcontentlanguage");
  public static final DAVElement GET_CONTENT_TYPE = getElement(DAV_NAMESPACE, "getcontenttype");
  public static final DAVElement GET_ETAG = getElement(DAV_NAMESPACE, "getetag");
  public static final DAVElement GET_LAST_MODIFIED = getElement(DAV_NAMESPACE, "getlastmodified");

  public static final DAVElement[] STARTING_PROPERTIES = {
    VERSION_CONTROLLED_CONFIGURATION, RESOURCE_TYPE, BASELINE_RELATIVE_PATH, REPOSITORY_UUID
  };
  public static final DAVElement[] BASELINE_PROPERTIES = {BASELINE_COLLECTION, VERSION_NAME};

  private String myPropertyName;
  private String myNamespace;
  public static final DAVElement LOG = getElement(SVN_SVN_PROPERTY_NAMESPACE, "log");

  private DAVElement(String namespace, String propertyName) {
    myNamespace = namespace;
    myPropertyName = propertyName;
  }

  public String getNamespace() {
    return myNamespace;
  }

  public String getName() {
    return myPropertyName;
  }

  public String toString() {
    StringBuffer sb = new StringBuffer();
    sb.append(getNamespace());
    if (!getNamespace().endsWith(":")) {
      sb.append(":");
    }
    sb.append(getName());
    return sb.toString();
  }

  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((myNamespace == null) ? 0 : myNamespace.hashCode());
    result = prime * result + ((myPropertyName == null) ? 0 : myPropertyName.hashCode());
    return result;
  }

  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }

    if (obj == null) {
      return false;
    }

    if (getClass() != obj.getClass()) {
      return false;
    }

    DAVElement other = (DAVElement) obj;
    if (myNamespace == null) {
      if (other.myNamespace != null) {
        return false;
      }
    } else if (!myNamespace.equals(other.myNamespace)) {
      return false;
    }

    if (myPropertyName == null) {
      if (other.myPropertyName != null) {
        return false;
      }
    } else if (!myPropertyName.equals(other.myPropertyName)) {
      return false;
    }

    return true;
  }
}