001    /*
002     * Copyright 2004-2006 Geert Bevin <gbevin[remove] at uwyn dot com>
003     * Distributed under the terms of either:
004     * - the common development and distribution license (CDDL), v1.0; or
005     * - the GNU Lesser General Public License, v2.1 or later
006     * $Id: JHighlight.java 3108 2006-03-13 18:03:00Z gbevin $
007     */
008    package com.uwyn.jhighlight;
009    
010    import com.uwyn.jhighlight.renderer.XhtmlRendererFactory;
011    import com.uwyn.jhighlight.tools.FileUtils;
012    import java.io.File;
013    import java.io.FileOutputStream;
014    import java.io.IOException;
015    import java.util.ArrayList;
016    import java.util.Iterator;
017    import java.util.Set;
018    import java.util.regex.Pattern;
019    
020    /**
021     * Provides console access to the source code syntax highlighting for Java,
022     * HTML, XHTML, XML and LZX files. The rendering will be done in HTML.
023     * <p>The following file extensions will be processed: <code>.java</code>,
024     * <code>.html</code>, <code>.htm</code>, <code>.xhtml</code>,
025     * <code>.xml</code> and <code>.lzx</code>.
026     * <p>Execute the highlighting with the following syntax:
027     * <pre>java com.uwyn.jhighlight.JHighlight [--verbose] [--fragment] [-d destdir] [-e encoding] file|dir ...</pre>
028     * <table border="0">
029     * <tr>
030     * <td><code>--verbose</code></td>
031     * <td>Output messages about what the parser is doing.</td>
032     * </tr>
033     * <tr>
034     * <td><code>--fragment</code></td>
035     * <td>Output fragments instead of complete documents.</td>
036     * </tr>
037     * <tr>
038     * <td><code>-d</code></td>
039     * <td>Specify the destination directory</td>
040     * </tr>
041     * <tr>
042     * <td><code>-e</code></td>
043     * <td>Specify the encoding of the files</td>
044     * </tr>
045     * </table>
046     * <p><a href="https://rife.dev.java.net">RIFE</a> template tags are also
047     * supported and will be clearly highlighted.
048     *
049     * @author Geert Bevin (gbevin[remove] at uwyn dot com)
050     * @version $Revision: 3108 $
051     * @since 1.0
052     */
053    public class JHighlight
054    {
055            public static void main(String[] arguments) throws Throwable
056            {
057                    String      destdir_name = null;
058                    boolean     verbose = false;
059                    String          encoding = null;
060                    boolean     fragment = false;
061                    ArrayList   names = new ArrayList();
062                    
063                    boolean valid_arguments = true;
064                    if (arguments.length < 1)
065                    {
066                            valid_arguments = false;
067                    }
068                    else
069                    {
070                            boolean next_is_destdir = false;
071                            boolean next_is_encoding = false;
072                            String argument;
073                            for (int i = 0; i < arguments.length; i++)
074                            {
075                                    argument = arguments[i];
076                                    if (next_is_destdir)
077                                    {
078                                            destdir_name = argument;
079                                            next_is_destdir = false;
080                                            continue;
081                                    }
082                                    
083                                    if (next_is_encoding)
084                                    {
085                                            encoding = argument;
086                                            next_is_encoding = false;
087                                            continue;
088                                    }
089                                    
090                                    if (argument.equals("-d"))
091                                    {
092                                            next_is_destdir = true;
093                                            continue;
094                                    }
095                                    
096                                    if (argument.equals("-e"))
097                                    {
098                                            next_is_encoding = true;
099                                            continue;
100                                    }
101                                    
102                                    if (argument.equals("--verbose"))
103                                    {
104                                            verbose = true;
105                                            continue;
106                                    }
107                                    
108                                    if (argument.equals("--fragment"))
109                                    {
110                                            fragment = true;
111                                            continue;
112                                    }
113                                    
114                                    names.add(argument);
115                            }
116                    }
117                    
118                    if (0 == names.size())
119                    {
120                            valid_arguments = false;
121                    }
122                    
123                    if (!valid_arguments)
124                    {
125                            System.err.println("Usage : java " + JHighlight.class.getName() + " [--verbose] [--fragment] [-d destdir] [-e encoding] file|dir ...");
126                            System.err.println("Generates highlighted XHTML files from all Java and XML source files");
127                            System.err.println("in the specified directories.");
128                            System.err.println("  --verbose  Output messages about what the parser is doing");
129                            System.err.println("  --fragment Output fragments instead of complete documents");
130                            System.err.println("  -d         Specify the destination directory");
131                            System.err.println("  -e         Specify the encoding of the files");
132                            System.exit(1);
133                    }
134                    
135                    File    destdir = null;
136                    if (destdir_name != null)
137                    {
138                            destdir = new File(destdir_name);
139                            if (!destdir.exists())
140                            {
141                                    throw new IOException("The destination directory '" + destdir_name + "' doesn't exist.");
142                            }
143                            if (!destdir.canWrite())
144                            {
145                                    throw new IOException("The destination directory '" + destdir_name + "' is not writable.");
146                            }
147                            if (!destdir.isDirectory())
148                            {
149                                    throw new IOException("The destination directory '" + destdir_name + "' is not a directory.");
150                            }
151                    }
152                    
153                    Iterator    names_it = names.iterator();
154                    String      name;
155                    while (names_it.hasNext())
156                    {
157                            name = (String)names_it.next();
158                            
159                            File    location = new File(name);
160                            if (!location.exists())
161                            {
162                                    throw new IOException("The source location '" + name + "' doesn't exist.");
163                            }
164                            if (!location.canRead())
165                            {
166                                    throw new IOException("The source location '" + name + "' is not readable.");
167                            }
168                            
169                            if (!location.isDirectory())
170                            {
171                                    File out = null;
172                                    if (null == destdir)
173                                    {
174                                            out = new File(location.getAbsolutePath() + ".html");
175                                    }
176                                    else
177                                    {
178                                            out = new File(destdir, location.getName() + ".html");
179                                    }
180                                    
181                                    highlightFile(location.getName(), location, out, encoding, fragment, verbose);
182                            }
183                            else
184                            {
185                                    Set                     supported_types = XhtmlRendererFactory.getSupportedTypes();
186                                    Pattern[]       included = new Pattern[supported_types.size()];
187                                    Pattern[]       excluded = new Pattern[supported_types.size()+5];
188                                    excluded[0] = Pattern.compile(".*SCCS.*");
189                                    excluded[0] = Pattern.compile(".*svn.*");
190                                    excluded[0] = Pattern.compile(".*CVS.*");
191                                    excluded[0] = Pattern.compile(".*jetty.*");
192                                    excluded[0] = Pattern.compile(".*tomcat.*");
193                                    
194                                    Iterator        types_it = supported_types.iterator();
195                                    String          type;
196                                    int                     counter = 0;
197                                    while (types_it.hasNext())
198                                    {
199                                            type = (String)types_it.next();
200                                            included[counter] = Pattern.compile(".*\\."+type+"$");
201                                            excluded[counter+5] = Pattern.compile(".*\\."+type+"\\.html\\.*");
202    
203                                            counter++;
204                                    }
205    
206                                    ArrayList file_names = FileUtils.getFileList(location, included, excluded);
207                                    
208                                    Iterator    file_names_it = file_names.iterator();
209                                    String      file_name;
210                                    while (file_names_it.hasNext())
211                                    {
212                                            file_name = (String)file_names_it.next();
213                                            
214                                            File in = new File(location.getAbsolutePath() + File.separator + file_name);
215                                            File out = null;
216                                            if (null == destdir)
217                                            {
218                                                    out = new File(location.getAbsolutePath() + File.separator + file_name + ".html");
219                                            }
220                                            else
221                                            {
222                                                    out = new File(destdir, location.getName() + File.separator + file_name + ".html");
223                                            }
224                                            
225                                            highlightFile(location.getName() + File.separator + file_name, in, out, encoding, fragment, verbose);
226                                    }
227                            }
228                    }
229            }
230            
231            private static void highlightFile(String name, File in, File out, String encoding, boolean fragment, boolean verbose)
232            throws IOException
233            {
234                    out.getParentFile().mkdirs();
235                    
236                    if (verbose)
237                    {
238                            System.out.print(name + " ... ");
239                    }
240                    
241                    XhtmlRendererFactory.getRenderer(FileUtils.getExtension(name))
242                            .highlight(name,
243                                               in.toURL().openStream(),
244                                               new FileOutputStream(out),
245                                               encoding,
246                                               fragment);
247                    
248                    if (verbose)
249                    {
250                            System.out.println("done.");
251                    }
252            }
253    }