001package org.apache.archiva.webdav; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import org.apache.archiva.repository.storage.StorageAsset; 023import org.apache.archiva.webdav.util.IndexWriter; 024import org.apache.archiva.webdav.util.MimeTypes; 025import org.apache.jackrabbit.util.Text; 026import org.apache.jackrabbit.webdav.DavException; 027import org.apache.jackrabbit.webdav.DavResource; 028import org.apache.jackrabbit.webdav.DavResourceFactory; 029import org.apache.jackrabbit.webdav.DavResourceIterator; 030import org.apache.jackrabbit.webdav.DavResourceLocator; 031import org.apache.jackrabbit.webdav.DavSession; 032import org.apache.jackrabbit.webdav.MultiStatusResponse; 033import org.apache.jackrabbit.webdav.io.InputContext; 034import org.apache.jackrabbit.webdav.io.OutputContext; 035import org.apache.jackrabbit.webdav.lock.ActiveLock; 036import org.apache.jackrabbit.webdav.lock.LockInfo; 037import org.apache.jackrabbit.webdav.lock.LockManager; 038import org.apache.jackrabbit.webdav.lock.Scope; 039import org.apache.jackrabbit.webdav.lock.Type; 040import org.apache.jackrabbit.webdav.property.DavProperty; 041import org.apache.jackrabbit.webdav.property.DavPropertyName; 042import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; 043import org.apache.jackrabbit.webdav.property.DavPropertySet; 044import org.apache.jackrabbit.webdav.property.DefaultDavProperty; 045import org.apache.jackrabbit.webdav.property.ResourceType; 046import org.joda.time.DateTime; 047import org.joda.time.format.DateTimeFormatter; 048import org.joda.time.format.ISODateTimeFormat; 049 050import java.util.*; 051import java.util.stream.Collectors; 052 053/** 054 * DavResource for virtual repositories 055 */ 056public class ArchivaVirtualDavResource 057 implements DavResource 058{ 059 private static final String COMPLIANCE_CLASS = "1"; 060 061 private ArchivaDavResourceLocator locator; 062 063 private DavResourceFactory factory; 064 065 private String logicalResource; 066 067 private DavPropertySet properties; 068 069 private boolean propsInitialized = false; 070 071 private static final String METHODS = "OPTIONS, GET, HEAD, POST, TRACE, PROPFIND, PROPPATCH, MKCOL"; 072 073 private final List<StorageAsset> localResources; 074 075 public ArchivaVirtualDavResource(List<StorageAsset> localResources, String logicalResource, MimeTypes mimeTypes, 076 ArchivaDavResourceLocator locator, DavResourceFactory factory ) 077 { 078 this.localResources = localResources; 079 this.logicalResource = logicalResource; 080 this.locator = locator; 081 this.factory = factory; 082 this.properties = new DavPropertySet(); 083 } 084 085 @Override 086 public void spool( OutputContext outputContext ) { 087 if ( outputContext.hasStream() ) 088 { 089 List<StorageAsset> localResourceFiles = localResources.stream().filter(Objects::nonNull) 090 .filter(repoAsset -> repoAsset.exists()) 091 .sorted(Comparator.comparing(o -> o.getName())).collect(Collectors.toList()); 092 093 IndexWriter writer = new IndexWriter(localResourceFiles, logicalResource ); 094 writer.write( outputContext ); 095 } 096 } 097 098 @Override 099 public void addLockManager( LockManager arg0 ) 100 { 101 102 } 103 104 @Override 105 public void addMember( DavResource arg0, InputContext arg1 ) 106 throws DavException 107 { 108 109 } 110 111 @SuppressWarnings( "unchecked" ) 112 @Override 113 public MultiStatusResponse alterProperties( List arg0 ) 114 throws DavException 115 { 116 return null; 117 } 118 119 public MultiStatusResponse alterProperties( DavPropertySet arg0, DavPropertyNameSet arg1 ) 120 throws DavException 121 { 122 return null; 123 } 124 125 @Override 126 public void copy( DavResource arg0, boolean arg1 ) 127 throws DavException 128 { 129 130 } 131 132 @Override 133 public boolean exists() 134 { 135 // localResources are already filtered (all files in the list are already existing) 136 return true; 137 } 138 139 @Override 140 public ActiveLock getLock( Type arg0, Scope arg1 ) 141 { 142 return null; 143 } 144 145 @Override 146 public ActiveLock[] getLocks() 147 { 148 return null; 149 } 150 151 @Override 152 public DavResourceIterator getMembers() 153 { 154 return null; 155 } 156 157 @Override 158 public String getSupportedMethods() 159 { 160 return METHODS; 161 } 162 163 @Override 164 public long getModificationTime() 165 { 166 return 0; 167 } 168 169 @Override 170 public boolean hasLock( Type arg0, Scope arg1 ) 171 { 172 return false; 173 } 174 175 @Override 176 public boolean isCollection() 177 { 178 return true; 179 } 180 181 @Override 182 public boolean isLockable( Type arg0, Scope arg1 ) 183 { 184 return false; 185 } 186 187 @Override 188 public ActiveLock lock( LockInfo arg0 ) 189 throws DavException 190 { 191 return null; 192 } 193 194 @Override 195 public void move( DavResource arg0 ) 196 throws DavException 197 { 198 199 } 200 201 @Override 202 public ActiveLock refreshLock( LockInfo arg0, String arg1 ) 203 throws DavException 204 { 205 return null; 206 } 207 208 @Override 209 public void removeMember( DavResource arg0 ) 210 throws DavException 211 { 212 213 } 214 215 @Override 216 public void unlock( String arg0 ) 217 throws DavException 218 { 219 220 } 221 222 @Override 223 public String getComplianceClass() 224 { 225 return COMPLIANCE_CLASS; 226 } 227 228 @Override 229 public DavResourceLocator getLocator() 230 { 231 return locator; 232 } 233 234 @Override 235 public String getResourcePath() 236 { 237 return locator.getResourcePath(); 238 } 239 240 @Override 241 public String getHref() 242 { 243 return locator.getHref( isCollection() ); 244 } 245 246 @Override 247 public DavResourceFactory getFactory() 248 { 249 return factory; 250 } 251 252 @Override 253 public String getDisplayName() 254 { 255 String resPath = getResourcePath(); 256 257 return ( resPath != null ) ? Text.getName( resPath ) : resPath; 258 } 259 260 @Override 261 public DavSession getSession() 262 { 263 return null; 264 } 265 266 @Override 267 public DavPropertyName[] getPropertyNames() 268 { 269 return getProperties().getPropertyNames(); 270 } 271 272 @Override 273 public DavProperty getProperty( DavPropertyName name ) 274 { 275 initProperties(); 276 return properties.get( name ); 277 } 278 279 @Override 280 public DavPropertySet getProperties() 281 { 282 initProperties(); 283 return properties; 284 } 285 286 @Override 287 public void setProperty( DavProperty property ) 288 throws DavException 289 { 290 } 291 292 @Override 293 public void removeProperty( DavPropertyName propertyName ) 294 throws DavException 295 { 296 } 297 298 @Override 299 public DavResource getCollection() 300 { 301 DavResource parent = null; 302 if ( getResourcePath() != null && !getResourcePath().equals( "/" ) ) 303 { 304 String parentPath = Text.getRelativeParent( getResourcePath(), 1 ); 305 if ( parentPath.equals( "" ) ) 306 { 307 parentPath = "/"; 308 } 309 DavResourceLocator parentloc = 310 locator.getFactory().createResourceLocator( locator.getPrefix(), parentPath ); 311 try 312 { 313 // go back to ArchivaDavResourceFactory! 314 parent = factory.createResource( parentloc, null ); 315 } 316 catch ( DavException e ) 317 { 318 // should not occur 319 } 320 } 321 return parent; 322 } 323 324 /** 325 * Fill the set of properties 326 */ 327 protected void initProperties() 328 { 329 if ( !exists() || propsInitialized ) 330 { 331 return; 332 } 333 334 // set (or reset) fundamental properties 335 if ( getDisplayName() != null ) 336 { 337 properties.add( new DefaultDavProperty<>( DavPropertyName.DISPLAYNAME, getDisplayName() ) ); 338 } 339 if ( isCollection() ) 340 { 341 properties.add( new ResourceType( ResourceType.COLLECTION ) ); 342 // Windows XP support 343 properties.add( new DefaultDavProperty<>( DavPropertyName.ISCOLLECTION, "1" ) ); 344 } 345 else 346 { 347 properties.add( new ResourceType( ResourceType.DEFAULT_RESOURCE ) ); 348 349 // Windows XP support 350 properties.add( new DefaultDavProperty<>( DavPropertyName.ISCOLLECTION, "0" ) ); 351 } 352 353 // Need to get the ISO8601 date for properties 354 DateTime dt = new DateTime( 0 ); 355 DateTimeFormatter fmt = ISODateTimeFormat.dateTime(); 356 String modifiedDate = fmt.print( dt ); 357 358 properties.add( new DefaultDavProperty<>( DavPropertyName.GETLASTMODIFIED, modifiedDate ) ); 359 360 properties.add( new DefaultDavProperty<>( DavPropertyName.CREATIONDATE, modifiedDate ) ); 361 362 properties.add( new DefaultDavProperty<>( DavPropertyName.GETCONTENTLENGTH, 0 ) ); 363 364 propsInitialized = true; 365 } 366 367 public String getLogicalResource() 368 { 369 return logicalResource; 370 } 371 372 public void setLogicalResource( String logicalResource ) 373 { 374 this.logicalResource = logicalResource; 375 } 376}