This project has retired. For details please refer to its Attic page.
Source code
001package org.apache.archiva.webdav.util;
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.commons.lang3.StringUtils;
024import org.apache.jackrabbit.webdav.io.OutputContext;
025import org.slf4j.Logger;
026import org.slf4j.LoggerFactory;
027
028import java.io.IOException;
029import java.io.PrintWriter;
030import java.nio.file.Path;
031import java.nio.file.Paths;
032import java.text.DateFormat;
033import java.util.ArrayList;
034import java.util.Comparator;
035import java.util.Date;
036import java.util.List;
037import java.util.Locale;
038import java.util.Map;
039import java.util.SortedMap;
040import java.util.TreeMap;
041
042/**
043 */
044public class IndexWriter
045{
046
047    private static final Logger log = LoggerFactory.getLogger( IndexWriter.class );
048
049    private final String logicalResource;
050
051    private final List<StorageAsset> repositoryAssets;
052
053
054    private final boolean isVirtual;
055
056    public IndexWriter( StorageAsset reference, String logicalResource )
057    {
058        this.repositoryAssets = new ArrayList<>(  );
059        this.repositoryAssets.add(reference);
060        this.logicalResource = logicalResource;
061        this.isVirtual = false;
062    }
063
064    public IndexWriter( List<StorageAsset> localResources, String logicalResource )
065    {
066        this.logicalResource = logicalResource;
067        this.repositoryAssets = localResources;
068        this.isVirtual = true;
069    }
070
071    public void write( OutputContext outputContext )
072    {
073        outputContext.setModificationTime( new Date().getTime() );
074        outputContext.setContentType( "text/html" );
075        outputContext.setETag( "" ); // skygo ETag MRM-1127 seems to be fixed
076        if ( outputContext.hasStream() )
077        {
078            PrintWriter writer = new PrintWriter( outputContext.getOutputStream() );
079            writeDocumentStart( writer );
080            try
081            {
082                writeHyperlinks( writer );
083            }
084            catch ( IOException e )
085            {
086                log.error("Could not write hyperlinks {}", e.getMessage(), e);
087            }
088            writeDocumentEnd( writer );
089            writer.flush();
090            writer.close();
091        }
092    }
093
094    private void writeDocumentStart( PrintWriter writer )
095    {
096        writer.println("<!DOCTYPE html>");
097        writer.println( "<html>" );
098        writer.println( "<head>" );
099        writer.println( "<title>Collection: /" + logicalResource + "</title>" );
100        writer.println( "<style type=\"text/css\">" );
101        writer.println( "ul{list-style:none;}" ); 
102        
103        StringBuilder relative = new StringBuilder("../../");
104        if ( logicalResource != null && logicalResource.length() > 0 )
105        {
106            String tmpRelative = StringUtils.replace( logicalResource, "\\", "/" );
107            for (int i=0;i<tmpRelative.split("/").length;i++) 
108            {
109                relative.append("../");
110            }
111        }
112        writer.println( ".file{background:url(" + relative.toString() + "images/package-x-generic.png) no-repeat scroll 0 0 transparent;}" );
113        writer.println( ".folder{background:url(" + relative.toString() + "images/folder.png) no-repeat scroll 0 0 transparent;}" );
114        writer.println( "a{color:#0088CC;text-decoration: none;padding-left:20px;}" );
115        writer.println( ".collection tr:nth-child(odd){background-color:#fafafa;}" );
116        writer.println( "tr td:nth-child(2){width:150px;color:#cc8800;text-align:right;}" );
117        writer.println( "tr td:nth-child(3){width:150px;color:#0000cc;text-align:center;}" );
118        writer.println( "th td:nth-child(2){width:150px;}" );
119        writer.println( "th td:nth-child(3){width:150px;}" );
120        writer.println( "</style>" );
121        writer.println( "<link rel=\"shortcut icon\" href=\"../../favicon.ico\"/>" );
122        writer.println( "</head>" );
123        writer.println( "<body>" );
124        writer.println( "<h3>Collection: /" + logicalResource + "</h3>" );
125
126        //Check if not root
127        if ( logicalResource != null && logicalResource.length() > 0 )
128        {
129            Path file = Paths.get( logicalResource );
130            String parentName = file.getParent() == null ? "/" : file.getParent().toString();
131
132            //convert to unix path in case archiva is hosted on windows
133            parentName = StringUtils.replace( parentName, "\\", "/" );
134
135            writer.println( "<ul>" );
136            writer.println( "<li><a class=\"folder\" href=\"../\">" + parentName + "</a> <i><small>(Parent)</small></i></li>" );
137            writer.println( "</ul>" );
138        }
139
140        writer.println( "<table class=\"collection\">" );
141        writer.println( "<tr><th>Name</th><th>Size (Bytes)</th><th>Last Modified</th></tr>" );
142    }
143
144    private void writeDocumentEnd( PrintWriter writer )
145    {
146        writer.println( "</table>" );
147        writer.println( "</body>" );
148        writer.println( "</html>" );
149    }
150
151    private void writeHyperlinks( PrintWriter writer ) throws IOException
152    {
153        if ( !isVirtual )
154        {
155            for ( StorageAsset localResource : repositoryAssets )
156            {
157                localResource.list().stream().sorted(
158                    Comparator.comparing( StorageAsset::getName )
159                ).forEach( asset -> {
160                    writeHyperlink( writer, asset.getName(), asset.getModificationTime().toEpochMilli(), asset.getSize(),
161                        asset.isContainer() );
162                } );
163            }
164        }
165        else
166        {
167            // virtual repository - filter unique directories
168            SortedMap<String, StorageAsset> uniqueChildFiles = new TreeMap<>();
169            for ( StorageAsset resource : repositoryAssets )
170            {
171                List<StorageAsset> files = resource.list();
172                for ( StorageAsset file : files )
173                {
174                    // the first entry wins
175                    if (!uniqueChildFiles.containsKey( file.getName() )) {
176                        uniqueChildFiles.put(file.getName(), file);
177                    }
178                }
179            }
180            for ( Map.Entry<String, StorageAsset> entry : uniqueChildFiles.entrySet())
181            {
182                final StorageAsset asset = entry.getValue();
183                 writeHyperlink( writer, asset.getName(), asset.getModificationTime().toEpochMilli(),
184                            asset.getSize(), asset.isContainer());
185            }
186        }
187    }
188
189    private static String fileDateFormat( long date ) 
190    {
191        DateFormat dateFormatter = DateFormat.getDateTimeInstance( DateFormat.SHORT, DateFormat.SHORT, Locale.getDefault() );
192        Date aDate = new Date( date );
193        return dateFormatter.format( aDate );
194    }
195    
196    private void writeHyperlink( PrintWriter writer, String resourceName, long lastModified, long fileSize, boolean directory )
197    {
198        if ( directory )
199        {
200            writer.println( "<tr><td><a class=\"folder\" href=\"" + resourceName + "/\">" + resourceName + "</a></td><td>&nbsp;</td><td>&nbsp;</td></tr>" );
201        }
202        else
203        {
204            writer.println( "<tr><td><a class=\"file\" href=\"" + resourceName + "\">" + resourceName + "</a></td><td class=\"size\">" + fileSize + "&nbsp;&nbsp;</td><td class=\"date\">" + fileDateFormat( lastModified ) + "</td></tr>" );
205        }
206    }
207}