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
030     * HTML. This may include showing the content of the
031     * {@link org.apache.hivemind.Resource}, with the line indicated in the
032     * Location highlighted.
033     * 
034     * @author Howard M. Lewis Ship
035     * @since 4.0
036     */
037    public class LocationRenderStrategy implements RenderStrategy
038    {
039    
040        /**
041         * Lines before and after the actual location to display.
042         */
043        private static final int RANGE = 5;
044    
045        public void renderObject(Object object, IMarkupWriter writer,
046                IRequestCycle cycle)
047        {
048            Location l = (Location) object;
049    
050            // Always print out the location as a string.
051    
052            writer.print(l.toString());
053    
054            int lineNumber = l.getLineNumber();
055    
056            if (lineNumber < 1) return;
057    
058            URL url = l.getResource().getResourceURL();
059    
060            if (url == null) return;
061    
062            writeResourceContent(writer, url, lineNumber);
063        }
064    
065        private void writeResourceContent(IMarkupWriter writer, URL url,
066                int lineNumber)
067        {
068            LineNumberReader reader = null;
069    
070            try
071            {
072                reader = new LineNumberReader(new BufferedReader(
073                        new InputStreamReader(url.openStream())));
074    
075                writer.beginEmpty("br");
076                writer.begin("table");
077                writer.attribute("class", "location-content");
078    
079                while(true)
080                {
081                    String line = reader.readLine();
082    
083                    if (line == null) break;
084    
085                    int currentLine = reader.getLineNumber();
086    
087                    if (currentLine > lineNumber + RANGE) break;
088    
089                    if (currentLine < lineNumber - RANGE) continue;
090    
091                    writer.begin("tr");
092    
093                    if (currentLine == lineNumber)
094                        writer.attribute("class", "target-line");
095    
096                    writer.begin("td");
097                    writer.attribute("class", "line-number");
098                    writer.print(currentLine);
099                    writer.end();
100    
101                    writer.begin("td");
102                    writer.print(line);
103                    writer.end("tr");
104                    writer.println();
105                }
106    
107                reader.close();
108                reader = null;
109            }
110            catch (Exception ex)
111            {
112                // Ignore it.
113            }
114            finally
115            {
116                writer.end("table");
117                close(reader);
118            }
119        }
120    
121        private void close(Reader reader)
122        {
123            try
124            {
125                if (reader != null) reader.close();
126            }
127            catch (IOException ex)
128            {
129                // Ignore
130            }
131        }
132    
133    }