Interface HierarchyItem

All Known Subinterfaces:
ChangedItem, DeltaVItem, File, Folder, History, Search, SynchronizationCollection, Version, VersionableItem

public interface HierarchyItem
Represents file or folder in the WebDAV repository.

Defines methods common to all WebDAV folders and files. getCreated() and getModified() methods must return Universal Coordinated Time (UTC). getProperties(com.ithit.webdav.server.Property[]) and updateProperties(com.ithit.webdav.server.Property[], com.ithit.webdav.server.Property[]) are called when WebDAV client is reading, adding, updating or deleting custom properties. This interface also provides methods for managing hierarchy: moving, copying and deleting WebDAV items. See copyTo(com.ithit.webdav.server.Folder, java.lang.String, boolean), moveTo(com.ithit.webdav.server.Folder, java.lang.String) and delete() methods. Your file items must implement File interface, folder items - Folder interface.

  • Method Summary

    Modifier and Type
    Method
    Description
    void
    copyTo(Folder folder, String destName, boolean deep)
    Creates a copy of this item with a new name in the destination folder.
    void
    Deletes this item.
    long
    Gets the creation date of the item in repository expressed as the coordinated universal time (UTC).
    long
    Gets the last modification date of the item in repository expressed as the coordinated universal time (UTC).
    Gets the name of the item in repository.
    Unique item path in the repository relative to storage root.
    Gets values of all properties or selected properties for this item.
    Gets names of all properties for this item.
    void
    moveTo(Folder folder, String destName)
    Moves this item to the destination folder under a new name.
    void
    updateProperties(Property[] setProps, Property[] delProps)
    Adds, modifies and removes properties for this item.
  • Method Details

    • getName

      String getName() throws ServerException
      Gets the name of the item in repository.
      Returns:
      Name of this item.
      Throws:
      ServerException - In case of an error.
    • getCreated

      long getCreated() throws ServerException
      Gets the creation date of the item in repository expressed as the coordinated universal time (UTC).
      Returns:
      Creation date of the item.
      Throws:
      ServerException - In case of an error.
    • getModified

      long getModified() throws ServerException
      Gets the last modification date of the item in repository expressed as the coordinated universal time (UTC).
      Returns:
      Modification date of the item.
      Throws:
      ServerException - In case of an error.
    • getPath

      String getPath() throws ServerException
      Unique item path in the repository relative to storage root.

      The URL returned by this method is relative to storage root. If your server root is located at http://webdavserver.com/myserver/ and the item URL is http://webdavserver.com/myserver/myfolder/myitem.doc this property implementation must return myfolder/myitem.doc. To calculate the entire item URL the engine will call DavRequest.getContextPath() property and attach it to url returned by this property.

      Examples:

      • File: myfolder/mydoc.docx
      • Folder: myfolder/folder/
      • History item: myfolder/mydoc.docx?history
      • Version: myfolder/mydoc.docx?version=5

      Returns:
      Item path relative to storage root.
      Throws:
      ServerException - In case of an error.
    • getProperties

      List<Property> getProperties(Property[] props) throws ServerException
      Gets values of all properties or selected properties for this item.
      Parameters:
      props -
      • Array of properties which values are requested.
      • null to get all properties.
      Returns:
      List of properties with values set. If property cannot be found it shall be omitted from the result.
      Throws:
      ServerException - In case of an error.

      The code below is part of Collection Synchronization sample provided with the SDK.
          @Override
          public List<Property> getProperties(Property[] props) throws ServerException {
              List<Property> l = getPropertyNames();
              List<Property> result;
              if (props == null) {
                  return l;
              }
              Set<String> propNames = Arrays.stream(props).map(Property::getName).collect(Collectors.toSet());
              result = l.stream().filter(x -> propNames.contains(x.getName())).collect(Collectors.toList());
              Property snippet = Arrays.stream(props).filter(x -> SNIPPET.equals(x.getName())).findFirst().orElse(null);
              if (snippet != null && this instanceof FileImpl) {
                  result.add(Property.create(snippet.getNamespace(), snippet.getName(), ((FileImpl) this).getSnippet()));
              }
              Property metadata = Arrays.stream(props).filter(x -> METADATA_ETAG.equals(x.getName())).findFirst().orElse(null);
              if (metadata != null) {
                  result.add(Property.create(metadata.getNamespace(), metadata.getName(), getMetadataEtag()));
              }
              return result;
          }
      
      
    • getPropertyNames

      List<Property> getPropertyNames() throws ServerException
      Gets names of all properties for this item.

      Most WebDAV clients never request list of property names, so your implementation can just throw ServerException with WebDavStatus.NOT_ALLOWED status.

      Returns:
      List of all property names for this item.
      Throws:
      ServerException - In case of an error.

      The code below is part of Collection Synchronization sample provided with the SDK.
          @Override
          public List<Property> getPropertyNames() throws ServerException {
              if (ExtendedAttributesExtension.hasExtendedAttribute(getFullPath().toString(), PROPERTIES_ATTRIBUTE)) {
                  String propJson = ExtendedAttributesExtension.getExtendedAttribute(getFullPath().toString(), PROPERTIES_ATTRIBUTE);
                  return SerializationUtils.deserializeList(Property.class, propJson);
              }
              return new LinkedList<>();
          }
      
      
    • updateProperties

      void updateProperties(Property[] setProps, Property[] delProps) throws LockedException, MultistatusException, ServerException
      Adds, modifies and removes properties for this item.
      Parameters:
      setProps - Array of properties to be set.
      delProps - Array of properties to be removed. Property.value field is ignored. Specifying the removal of a property that does not exist is not an error.
      Throws:
      LockedException - this item was locked and client did not provide lock token.
      MultistatusException - If update fails for a property, this exception shall be thrown and contain result of the operation for each property. Status for each property can be one of following:
      • WebDavStatus.OK - the property was successfully updated or deleted.
      • WebDavStatus.CONFLICT - the client has provided a value whose semantics are not appropriate for the property, this includes trying to set read-only properties.
      • WebDavStatus.FAILED_DEPENDENCY - indicates this action would have succeeded if it were not for the conflict with updating/removing some other property.
      ServerException - In case of other error.

      The code below is part of Collection Synchronization sample provided with the SDK.
          @Override
          public void updateProperties(Property[] setProps, Property[] delProps)
                  throws LockedException, MultistatusException, ServerException {
              ensureHasToken();
              for (final Property prop : setProps) {
                  String basicAttributeNS = "urn:schemas-microsoft-com:";
                  // Microsoft Mini-redirector may update file creation date, modification date and access time passing properties:
                  // <Win32CreationTime xmlns="urn:schemas-microsoft-com:">Thu, 28 Mar 2013 20:15:34 GMT</Win32CreationTime>
                  // <Win32LastModifiedTime xmlns="urn:schemas-microsoft-com:">Thu, 28 Mar 2013 20:36:24 GMT</Win32LastModifiedTime>
                  // <Win32LastAccessTime xmlns="urn:schemas-microsoft-com:">Thu, 28 Mar 2013 20:36:24 GMT</Win32LastAccessTime>
                  // In this case update creation and modified date in your storage or do not save this properties at all, otherwise
                  // Windows Explorer will display creation and modification date from this props and it will differ from the values
                  // in the Created and Modified fields in your storage
                  // String basicAttributeNS = "urn:schemas-microsoft-com:";
                  if (prop.getNamespace().equals(basicAttributeNS)) {
                      updateBasicProperties(prop.getXmlValueRaw(), prop.getName());
                  } else {
                      properties = getProperties();
                      Property existingProp = properties.stream().filter(x -> x.getName().equals(prop.getName())).findFirst().orElse(null);
                      if (existingProp != null) {
                          existingProp.setXmlValueRaw(prop.getXmlValueRaw());
                      } else {
                          properties.add(prop);
                      }
                  }
              }
              properties = getProperties();
              Set<String> propNamesToDel = Arrays.stream(delProps).map(Property::getName).collect(Collectors.toSet());
              properties = properties.stream()
                      .filter(e -> !propNamesToDel.contains(e.getName()))
                      .collect(Collectors.toList());
              ExtendedAttributesExtension.setExtendedAttribute(getFullPath().toString(), PROPERTIES_ATTRIBUTE, SerializationUtils.serialize(properties));
              incrementMetadataEtag();
              getEngine().getWebSocketServer().notifyUpdated(getPath(), getWebSocketID());
          }
      
      
    • copyTo

      void copyTo(Folder folder, String destName, boolean deep) throws LockedException, ConflictException, MultistatusException, ServerException
      Creates a copy of this item with a new name in the destination folder.

      If error occurred while copying items located in a subtree, the server should try to continue copy operation and copy all other items. In this case you must throw MultistatusException that contain separate response for every item that was successfully copied or failed to copy.

      A CopyTo method invocation must not copy any locks active on the source item. However, if this method copies the item into a folder that has a deep lock, then the destination item must be added to the lock.

      Parameters:
      folder - Destination folder.
      destName - Name of the destination item.
      deep - Indicates whether to copy entire subtree.
      Throws:
      LockedException - - the destination item was locked and client did not provide lock token.
      ConflictException - - destination folder does not exist.
      MultistatusException - - errors has occured during processing of the subtree. Every item that has been eithre successfully copied or failed to copy must be present in exception with corresponding status.
      ServerException - - In case of other error.

      The code below is part of Collection Synchronization sample provided with the SDK.
          @Override
          public void copyTo(Folder folder, String destName, boolean deep)
                  throws LockedException, MultistatusException, ServerException {
              ((FolderImpl) folder).ensureHasToken();
      
              String relUrl = HierarchyItemImpl.decodeAndConvertToPath(folder.getPath());
              String destinationFolder = Paths.get(getRootFolder(), relUrl).toString();
              if (isRecursive(relUrl)) {
                  throw new ServerException("Cannot copy to subfolder", WebDavStatus.FORBIDDEN);
              }
              final Path destinationFolderPath = Paths.get(destinationFolder);
              if (!Files.exists(destinationFolderPath) || isHidden(destinationFolderPath))
                  throw new ServerException();
              try {
                  Path sourcePath = this.getFullPath();
                  Path destinationFullPath = Paths.get(destinationFolder, destName);
                  FileUtils.copyDirectory(sourcePath.toFile(), destinationFullPath.toFile());
                  addIndex(destinationFullPath, folder.getPath() + destName, destName);
              } catch (IOException e) {
                  throw new ServerException(e);
              }
              setName(destName);
              getEngine().getWebSocketServer().notifyCreated(folder.getPath() + encode(destName), getWebSocketID());
          }
      
      
    • moveTo

      Moves this item to the destination folder under a new name.
      Parameters:
      folder - Destination folder.
      destName - Name of the destination item.
      Throws:
      LockedException - - the source or the destination item was locked and client did not provide lock token.
      ConflictException - - destination folder does not exist.
      MultistatusException - - errors has occured during processing of the subtree. Every processed item must have corresponding response added with corresponding status.
      ServerException - - in case of another error.

      The code below is part of Collection Synchronization sample provided with the SDK.
          @Override
          public void moveTo(Folder folder, String destName) throws LockedException,
                  ConflictException, MultistatusException, ServerException {
              ensureHasToken();
              ((FolderImpl) folder).ensureHasToken();
              String destinationFolder = Paths.get(getRootFolder(), HierarchyItemImpl.decodeAndConvertToPath(folder.getPath())).toString();
              if (!Files.exists(Paths.get(destinationFolder)))
                  throw new ConflictException();
              Path sourcePath = this.getFullPath();
              Path destinationFullPath = Paths.get(destinationFolder, destName);
              try {
                  removeIndex(getFullPath(), this);
                  Files.deleteIfExists(destinationFullPath);
                  Files.move(sourcePath, destinationFullPath);
                  addIndex(destinationFullPath, folder.getPath() + destName, destName);
              } catch (IOException e) {
                  throw new ServerException(e);
              }
              setName(destName);
              this.newPath = destinationFullPath;
              incrementMetadataEtag();
              getEngine().getWebSocketServer().notifyMoved(getPath(), folder.getPath() + encode(destName), getWebSocketID());
          }
      
      
    • delete

      Deletes this item.
      Throws:
      LockedException - - this item or its parent was locked and client did not provide lock token.
      MultistatusException - - errors has occured during processing of the subtree. Every processed item must have corresponding response added to the exception with corresponding status.
      ServerException - - in case of another error.

      The code below is part of Collection Synchronization sample provided with the SDK.
          @Override
          public void delete() throws LockedException, MultistatusException,
                  ServerException {
              ensureHasToken();
              try {
                  removeIndex(getFullPath(), this);
                  FileUtils.cleanDirectory(getFullPath().toFile());
                  // hide folder, it is needed for sync-collection report.
                  Files.setAttribute(getFullPath(), "dos:hidden", true, LinkOption.NOFOLLOW_LINKS);
              } catch (IOException e) {
                  throw new ServerException(e);
              }
              getEngine().getWebSocketServer().notifyDeleted(getPath(), getWebSocketID());
          }