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
015package org.apache.tapestry.describe;
016
017import java.io.BufferedReader;
018import java.io.IOException;
019import java.io.InputStreamReader;
020import java.io.LineNumberReader;
021import java.io.Reader;
022import java.net.URL;
023
024import org.apache.hivemind.Location;
025import org.apache.tapestry.IMarkupWriter;
026import 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 */
036public 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}