001    // Copyright 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.describe;
016    
017    import java.io.BufferedReader;
018    import java.io.IOException;
019    import java.io.InputStreamReader;
020    import java.io.LineNumberReader;
021    import java.io.Reader;
022    import java.net.URL;
023    
024    import org.apache.hivemind.Location;
025    import org.apache.tapestry.IMarkupWriter;
026    import org.apache.tapestry.IRequestCycle;
027    
028    /**
029     * Adapter for displaying {@link org.apache.hivemind.Location} objects as HTML. This may
030     * include showing the content of the {@link org.apache.hivemind.Resource}, with the line indicated
031     * in the Location highlighted.
032     * 
033     * @author Howard M. Lewis Ship
034     * @since 4.0
035     */
036    public class LocationRenderStrategy implements RenderStrategy
037    {
038        /**
039         * Lines before and after the actual location to display.
040         */
041        private static final int RANGE = 5;
042    
043        public void renderObject(Object object, IMarkupWriter writer, IRequestCycle cycle)
044        {
045            Location l = (Location) object;
046    
047            // Always print out the location as a string.
048    
049            writer.print(l.toString());
050    
051            int lineNumber = l.getLineNumber();
052    
053            if (lineNumber < 1)
054                return;
055    
056            URL url = l.getResource().getResourceURL();
057    
058            if (url == null)
059                return;
060    
061            writeResourceContent(writer, url, lineNumber);
062        }
063    
064        private void writeResourceContent(IMarkupWriter writer, URL url, int lineNumber)
065        {
066            LineNumberReader reader = null;
067    
068            try
069            {
070                reader = new LineNumberReader(new BufferedReader(
071                        new InputStreamReader(url.openStream())));
072    
073                writer.beginEmpty("br");
074                writer.begin("table");
075                writer.attribute("class", "location-content");
076    
077                while (true)
078                {
079                    String line = reader.readLine();
080    
081                    if (line == null)
082                        break;
083    
084                    int currentLine = reader.getLineNumber();
085    
086                    if (currentLine > lineNumber + RANGE)
087                        break;
088    
089                    if (currentLine < lineNumber - RANGE)
090                        continue;
091    
092                    writer.begin("tr");
093    
094                    if (currentLine == lineNumber)
095                        writer.attribute("class", "target-line");
096    
097                    writer.begin("td");
098                    writer.attribute("class", "line-number");
099                    writer.print(currentLine);
100                    writer.end();
101    
102                    writer.begin("td");
103                    writer.print(line);
104                    writer.end("tr");
105                    writer.println();
106                }
107    
108                reader.close();
109                reader = null;
110            }
111            catch (Exception ex)
112            {
113                // Ignore it.
114            }
115            finally
116            {
117                writer.end("table");
118                close(reader);
119            }
120        }
121    
122        private void close(Reader reader)
123        {
124            try
125            {
126                if (reader != null)
127                    reader.close();
128            }
129            catch (IOException ex)
130            {
131                // Ignore
132            }
133        }
134    
135    }