content: package org.apache.archiva.webdav;
  
  /*
   * Licensed to the Apache Software Foundation (ASF) under one
   * or more contributor license agreements.  See the NOTICE file
   * distributed with this work for additional information
   * regarding copyright ownership.  The ASF licenses this file
   * to you under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance
   * with the License.  You may obtain a copy of the License at
   *
   *  http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an
   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   * KIND, either express or implied.  See the License for the
   * specific language governing permissions and limitations
   * under the License.
   */
  
  import org.apache.archiva.repository.storage.StorageAsset;
  import org.apache.archiva.webdav.util.IndexWriter;
  import org.apache.archiva.webdav.util.MimeTypes;
  import org.apache.jackrabbit.util.Text;
  import org.apache.jackrabbit.webdav.DavException;
  import org.apache.jackrabbit.webdav.DavResource;
  import org.apache.jackrabbit.webdav.DavResourceFactory;
  import org.apache.jackrabbit.webdav.DavResourceIterator;
  import org.apache.jackrabbit.webdav.DavResourceLocator;
  import org.apache.jackrabbit.webdav.DavSession;
  import org.apache.jackrabbit.webdav.MultiStatusResponse;
  import org.apache.jackrabbit.webdav.io.InputContext;
  import org.apache.jackrabbit.webdav.io.OutputContext;
  import org.apache.jackrabbit.webdav.lock.ActiveLock;
  import org.apache.jackrabbit.webdav.lock.LockInfo;
  import org.apache.jackrabbit.webdav.lock.LockManager;
  import org.apache.jackrabbit.webdav.lock.Scope;
  import org.apache.jackrabbit.webdav.lock.Type;
  import org.apache.jackrabbit.webdav.property.DavProperty;
  import org.apache.jackrabbit.webdav.property.DavPropertyName;
  import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
  import org.apache.jackrabbit.webdav.property.DavPropertySet;
  import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
  import org.apache.jackrabbit.webdav.property.ResourceType;
  
  import java.time.Instant;
  import java.time.LocalDateTime;
  import java.time.format.DateTimeFormatter;
  import java.util.Comparator;
  import java.util.List;
  import java.util.Objects;
  import java.util.stream.Collectors;
  
  /**
   * DavResource for virtual repositories
   */
  public class ArchivaVirtualDavResource
      implements DavResource
  {
      private static final String COMPLIANCE_CLASS = "1";
  
      private ArchivaDavResourceLocator locator;
  
      private DavResourceFactory factory;
  
      private String logicalResource;
  
      private DavPropertySet properties;
  
      private boolean propsInitialized = false;
  
      private static final String METHODS = "OPTIONS, GET, HEAD, POST, TRACE, PROPFIND, PROPPATCH, MKCOL";
  
      private final List<StorageAsset> localResources;
  
      public ArchivaVirtualDavResource(List<StorageAsset> localResources, String logicalResource, MimeTypes mimeTypes,
                                       ArchivaDavResourceLocator locator, DavResourceFactory factory )
      {
          this.localResources = localResources;
          this.logicalResource = logicalResource;
          this.locator = locator;
          this.factory = factory;
          this.properties = new DavPropertySet();
      }
  
      @Override
      public void spool( OutputContext outputContext ) {
          if ( outputContext.hasStream() )
          {
              List<StorageAsset> localResourceFiles = localResources.stream().filter(Objects::nonNull)
                      .filter(repoAsset -> repoAsset.exists())
                      .sorted(Comparator.comparing(o -> o.getName())).collect(Collectors.toList());
  
              IndexWriter writer = new IndexWriter(localResourceFiles, logicalResource );
              writer.write( outputContext );
          }
      }
  
      @Override
      public void addLockManager( LockManager arg0 )
      {
  
      }
  
      @Override
      public void addMember( DavResource arg0, InputContext arg1 )
          throws DavException
      {
  
      }
  
      @SuppressWarnings( "unchecked" )
      @Override
      public MultiStatusResponse alterProperties( List arg0 )
          throws DavException
      {
          return null;
      }
  
      public MultiStatusResponse alterProperties( DavPropertySet arg0, DavPropertyNameSet arg1 )
          throws DavException
      {
          return null;
      }
  
      @Override
      public void copy( DavResource arg0, boolean arg1 )
          throws DavException
      {
  
      }
  
      @Override
      public boolean exists()
      {
          // localResources are already filtered (all files in the list are already existing)
          return true;
      }
  
      @Override
      public ActiveLock getLock( Type arg0, Scope arg1 )
      {
          return null;
      }
  
      @Override
      public ActiveLock[] getLocks()
      {
          return null;
      }
  
      @Override
      public DavResourceIterator getMembers()
      {
          return null;
      }
  
      @Override
      public String getSupportedMethods()
      {
          return METHODS;
      }
  
      @Override
      public long getModificationTime()
      {
          return 0;
      }
  
      @Override
      public boolean hasLock( Type arg0, Scope arg1 )
      {
          return false;
      }
  
      @Override
      public boolean isCollection()
      {
          return true;
      }
  
      @Override
      public boolean isLockable( Type arg0, Scope arg1 )
      {
          return false;
      }
  
      @Override
      public ActiveLock lock( LockInfo arg0 )
          throws DavException
      {
          return null;
      }
  
      @Override
      public void move( DavResource arg0 )
          throws DavException
      {
  
      }
  
      @Override
      public ActiveLock refreshLock( LockInfo arg0, String arg1 )
          throws DavException
      {
          return null;
      }
  
      @Override
      public void removeMember( DavResource arg0 )
          throws DavException
      {
  
      }
  
      @Override
      public void unlock( String arg0 )
          throws DavException
      {
  
      }
  
      @Override
      public String getComplianceClass()
      {
          return COMPLIANCE_CLASS;
      }
  
      @Override
      public DavResourceLocator getLocator()
      {
          return locator;
      }
  
      @Override
      public String getResourcePath()
      {
          return locator.getResourcePath();
      }
  
      @Override
      public String getHref()
      {
          return locator.getHref( isCollection() );
      }
  
      @Override
      public DavResourceFactory getFactory()
      {
          return factory;
      }
  
      @Override
      public String getDisplayName()
      {
          String resPath = getResourcePath();
  
          return ( resPath != null ) ? Text.getName( resPath ) : resPath;
      }
  
      @Override
      public DavSession getSession()
      {
          return null;
      }
  
      @Override
      public DavPropertyName[] getPropertyNames()
      {
          return getProperties().getPropertyNames();
      }
  
      @Override
      public DavProperty getProperty( DavPropertyName name )
      {
          initProperties();
          return properties.get( name );
      }
  
      @Override
      public DavPropertySet getProperties()
      {
          initProperties();
          return properties;
      }
  
      @Override
      public void setProperty( DavProperty property )
          throws DavException
      {
      }
  
      @Override
      public void removeProperty( DavPropertyName propertyName )
          throws DavException
      {
      }
  
      @Override
      public DavResource getCollection()
      {
          DavResource parent = null;
          if ( getResourcePath() != null && !getResourcePath().equals( "/" ) )
          {
              String parentPath = Text.getRelativeParent( getResourcePath(), 1 );
              if ( parentPath.equals( "" ) )
              {
                  parentPath = "/";
              }
              DavResourceLocator parentloc =
                  locator.getFactory().createResourceLocator( locator.getPrefix(), parentPath );
              try
              {
                  // go back to ArchivaDavResourceFactory!
                  parent = factory.createResource( parentloc, null );
              }
              catch ( DavException e )
              {
                  // should not occur
              }
          }
          return parent;
      }
  
      /**
       * Fill the set of properties
       */
      protected void initProperties()
      {
          if ( !exists() || propsInitialized )
          {
              return;
          }
  
          // set (or reset) fundamental properties
          if ( getDisplayName() != null )
          {
              properties.add( new DefaultDavProperty<>( DavPropertyName.DISPLAYNAME, getDisplayName() ) );
          }
          if ( isCollection() )
          {
              properties.add( new ResourceType( ResourceType.COLLECTION ) );
              // Windows XP support
              properties.add( new DefaultDavProperty<>( DavPropertyName.ISCOLLECTION, "1" ) );
          }
          else
          {
              properties.add( new ResourceType( ResourceType.DEFAULT_RESOURCE ) );
  
              // Windows XP support
              properties.add( new DefaultDavProperty<>( DavPropertyName.ISCOLLECTION, "0" ) );
          }
  
          // Need to get the ISO8601 date for properties
          // DateTime dt = new DateTime( 0 );
          // DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
          // String modifiedDate = fmt.print( dt );
          String modifiedDate = LocalDateTime.now( ).format( DateTimeFormatter.ISO_OFFSET_DATE_TIME );
  
          properties.add( new DefaultDavProperty<>( DavPropertyName.GETLASTMODIFIED, modifiedDate ) );
  
          properties.add( new DefaultDavProperty<>( DavPropertyName.CREATIONDATE, modifiedDate ) );
  
          properties.add( new DefaultDavProperty<>( DavPropertyName.GETCONTENTLENGTH, 0 ) );
  
          propsInitialized = true;
      }
  
      public String getLogicalResource()
      {
          return logicalResource;
      }
  
      public void setLogicalResource( String logicalResource )
      {
          this.logicalResource = logicalResource;
      }
  }
  