001    package 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    
022    import org.apache.jackrabbit.util.Text;
023    import org.apache.jackrabbit.webdav.DavException;
024    import org.apache.jackrabbit.webdav.DavResource;
025    import org.apache.jackrabbit.webdav.DavResourceFactory;
026    import org.apache.jackrabbit.webdav.DavResourceIterator;
027    import org.apache.jackrabbit.webdav.DavResourceLocator;
028    import org.apache.jackrabbit.webdav.DavSession;
029    import org.apache.jackrabbit.webdav.MultiStatusResponse;
030    import org.apache.jackrabbit.webdav.io.InputContext;
031    import org.apache.jackrabbit.webdav.io.OutputContext;
032    import org.apache.jackrabbit.webdav.lock.ActiveLock;
033    import org.apache.jackrabbit.webdav.lock.LockInfo;
034    import org.apache.jackrabbit.webdav.lock.LockManager;
035    import org.apache.jackrabbit.webdav.lock.Scope;
036    import org.apache.jackrabbit.webdav.lock.Type;
037    import org.apache.jackrabbit.webdav.property.DavProperty;
038    import org.apache.jackrabbit.webdav.property.DavPropertyName;
039    import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
040    import org.apache.jackrabbit.webdav.property.DavPropertySet;
041    import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
042    import org.apache.jackrabbit.webdav.property.ResourceType;
043    import org.apache.archiva.webdav.util.IndexWriter;
044    import org.apache.archiva.webdav.util.MimeTypes;
045    import org.joda.time.DateTime;
046    import org.joda.time.format.DateTimeFormatter;
047    import org.joda.time.format.ISODateTimeFormat;
048    
049    import java.io.File;
050    import java.io.IOException;
051    import java.util.ArrayList;
052    import java.util.Collections;
053    import java.util.List;
054    
055    /**
056     * DavResource for virtual repositories
057     */
058    public class ArchivaVirtualDavResource
059        implements DavResource
060    {
061        private static final String COMPLIANCE_CLASS = "1";
062    
063        private ArchivaDavResourceLocator locator;
064    
065        private DavResourceFactory factory;
066    
067        private String logicalResource;
068    
069        private DavPropertySet properties;
070    
071        private boolean propsInitialized = false;
072    
073        private static final String METHODS = "OPTIONS, GET, HEAD, POST, TRACE, PROPFIND, PROPPATCH, MKCOL";
074    
075        private final List<File> localResources;
076    
077        public ArchivaVirtualDavResource( List<File> localResources, String logicalResource, MimeTypes mimeTypes,
078                                          ArchivaDavResourceLocator locator, DavResourceFactory factory )
079        {
080            this.localResources = localResources;
081            this.logicalResource = logicalResource;
082            this.locator = locator;
083            this.factory = factory;
084            this.properties = new DavPropertySet();
085        }
086    
087        public void spool( OutputContext outputContext )
088            throws IOException
089        {
090            if ( outputContext.hasStream() )
091            {
092                Collections.sort( localResources );
093                List<File> localResourceFiles = new ArrayList<File>();
094    
095                for ( File resourceFile : localResources )
096                {
097                    if ( resourceFile.exists() )
098                    {
099                        localResourceFiles.add( resourceFile );
100                    }
101                }
102    
103                IndexWriter writer = new IndexWriter( this, localResourceFiles, logicalResource );
104                writer.write( outputContext );
105            }
106        }
107    
108        public void addLockManager( LockManager arg0 )
109        {
110    
111        }
112    
113        public void addMember( DavResource arg0, InputContext arg1 )
114            throws DavException
115        {
116    
117        }
118    
119        @SuppressWarnings( "unchecked" )
120        public MultiStatusResponse alterProperties( List arg0 )
121            throws DavException
122        {
123            return null;
124        }
125    
126        public MultiStatusResponse alterProperties( DavPropertySet arg0, DavPropertyNameSet arg1 )
127            throws DavException
128        {
129            return null;
130        }
131    
132        public void copy( DavResource arg0, boolean arg1 )
133            throws DavException
134        {
135    
136        }
137    
138        public boolean exists()
139        {
140            // localResources are already filtered (all files in the list are already existing)
141            return true;
142        }
143    
144        public ActiveLock getLock( Type arg0, Scope arg1 )
145        {
146            return null;
147        }
148    
149        public ActiveLock[] getLocks()
150        {
151            return null;
152        }
153    
154        public DavResourceIterator getMembers()
155        {
156            return null;
157        }
158    
159        public String getSupportedMethods()
160        {
161            return METHODS;
162        }
163    
164        public long getModificationTime()
165        {
166            return 0;
167        }
168    
169        public boolean hasLock( Type arg0, Scope arg1 )
170        {
171            return false;
172        }
173    
174        public boolean isCollection()
175        {
176            return true;
177        }
178    
179        public boolean isLockable( Type arg0, Scope arg1 )
180        {
181            return false;
182        }
183    
184        public ActiveLock lock( LockInfo arg0 )
185            throws DavException
186        {
187            return null;
188        }
189    
190        public void move( DavResource arg0 )
191            throws DavException
192        {
193    
194        }
195    
196        public ActiveLock refreshLock( LockInfo arg0, String arg1 )
197            throws DavException
198        {
199            return null;
200        }
201    
202        public void removeMember( DavResource arg0 )
203            throws DavException
204        {
205    
206        }
207    
208        public void unlock( String arg0 )
209            throws DavException
210        {
211    
212        }
213    
214        public String getComplianceClass()
215        {
216            return COMPLIANCE_CLASS;
217        }
218    
219        public DavResourceLocator getLocator()
220        {
221            return locator;
222        }
223    
224        public String getResourcePath()
225        {
226            return locator.getResourcePath();
227        }
228    
229        public String getHref()
230        {
231            return locator.getHref( isCollection() );
232        }
233    
234        public DavResourceFactory getFactory()
235        {
236            return factory;
237        }
238    
239        public String getDisplayName()
240        {
241            String resPath = getResourcePath();
242    
243            return ( resPath != null ) ? Text.getName( resPath ) : resPath;
244        }
245    
246        public DavSession getSession()
247        {
248            return null;
249        }
250    
251        public DavPropertyName[] getPropertyNames()
252        {
253            return getProperties().getPropertyNames();
254        }
255    
256        public DavProperty getProperty( DavPropertyName name )
257        {
258            initProperties();
259            return properties.get( name );
260        }
261    
262        public DavPropertySet getProperties()
263        {
264            initProperties();
265            return properties;
266        }
267    
268        public void setProperty( DavProperty property )
269            throws DavException
270        {
271        }
272    
273        public void removeProperty( DavPropertyName propertyName )
274            throws DavException
275        {
276        }
277    
278        public DavResource getCollection()
279        {
280            DavResource parent = null;
281            if ( getResourcePath() != null && !getResourcePath().equals( "/" ) )
282            {
283                String parentPath = Text.getRelativeParent( getResourcePath(), 1 );
284                if ( parentPath.equals( "" ) )
285                {
286                    parentPath = "/";
287                }
288                DavResourceLocator parentloc =
289                    locator.getFactory().createResourceLocator( locator.getPrefix(), parentPath );
290                try
291                {
292                    // go back to ArchivaDavResourceFactory!
293                    parent = factory.createResource( parentloc, null );
294                }
295                catch ( DavException e )
296                {
297                    // should not occur
298                }
299            }
300            return parent;
301        }
302    
303        /**
304         * Fill the set of properties
305         */
306        protected void initProperties()
307        {
308            if ( !exists() || propsInitialized )
309            {
310                return;
311            }
312    
313            // set (or reset) fundamental properties
314            if ( getDisplayName() != null )
315            {
316                properties.add( new DefaultDavProperty( DavPropertyName.DISPLAYNAME, getDisplayName() ) );
317            }
318            if ( isCollection() )
319            {
320                properties.add( new ResourceType( ResourceType.COLLECTION ) );
321                // Windows XP support
322                properties.add( new DefaultDavProperty( DavPropertyName.ISCOLLECTION, "1" ) );
323            }
324            else
325            {
326                properties.add( new ResourceType( ResourceType.DEFAULT_RESOURCE ) );
327    
328                // Windows XP support
329                properties.add( new DefaultDavProperty( DavPropertyName.ISCOLLECTION, "0" ) );
330            }
331    
332            // Need to get the ISO8601 date for properties
333            DateTime dt = new DateTime( 0 );
334            DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
335            String modifiedDate = fmt.print( dt );
336    
337            properties.add( new DefaultDavProperty( DavPropertyName.GETLASTMODIFIED, modifiedDate ) );
338    
339            properties.add( new DefaultDavProperty( DavPropertyName.CREATIONDATE, modifiedDate ) );
340    
341            properties.add( new DefaultDavProperty( DavPropertyName.GETCONTENTLENGTH, 0 ) );
342    
343            propsInitialized = true;
344        }
345    
346    }