View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   */ 
19  package org.apache.rat.annotation;
20  
21  import java.io.BufferedReader;
22  import java.io.File;
23  import java.io.FileReader;
24  import java.io.FileWriter;
25  import java.io.IOException;
26  
27  /**
28   * Add a licence header to a document. This appender does not check for the
29   * existence of an existing licence header, it is assumed that either a second
30   * licence header is intentional or that there is no licence header present
31   * already.
32   * 
33   */
34  public abstract class AbstractLicenceAppender {
35    private static final int TYPE_UNKNOWN = 0;
36    private static final int TYPE_JAVA = 1;
37    private static final int TYPE_XML = 2;
38    private static final int TYPE_HTML = 3;
39    private static final int TYPE_CSS = 4;
40    private static final int TYPE_JAVASCRIPT = 5;
41    private static final int TYPE_APT = 6;
42    private static final int TYPE_PROPERTIES = 7;
43    private static final int TYPE_PYTHON = 8;
44    private static final int TYPE_C      = 9;
45    private static final int TYPE_H      = 10;
46    private static final int TYPE_SH     = 11;
47    private static final int TYPE_BAT    = 12;
48    private boolean isForced;
49  
50    public AbstractLicenceAppender() {
51      super();
52    }
53  
54    /**
55     * Append the default licence header to the supplied document.
56     * 
57     * @param document
58     * @throws IOException
59     *           if there is a problem either reading or writing the file
60     */
61    public void append(File document) throws IOException {
62      int type = getType(document);
63      if (type == TYPE_UNKNOWN) {
64        return;
65      }
66      File newDocument = new File(document.getAbsolutePath() + ".new");
67      FileWriter writer = new FileWriter(newDocument);
68    
69      FileReader fr = new FileReader(document);
70      BufferedReader br = new BufferedReader(fr);
71      
72      if (type == TYPE_CSS 
73          || type == TYPE_JAVASCRIPT 
74          || type == TYPE_APT 
75          || type == TYPE_PROPERTIES
76          || type == TYPE_C
77          || type == TYPE_H
78          || type == TYPE_HTML) {
79        writer.write(getLicenceHeader(document));
80        writer.write('\n');
81      }
82    
83      String line;
84      boolean first = true;
85      while ((line = br.readLine()) != null) {
86        if (first && type == TYPE_PYTHON) {
87          doFirstLine(document, writer, line, "#!/usr/bin");
88        } else if (first && type == TYPE_BAT) {
89          doFirstLine(document, writer, line, "@echo off");
90        } else if (first && type == TYPE_SH) {
91          doFirstLine(document, writer, line, "#!/bin");
92        } else {
93          writer.write(line);
94          writer.write('\n');
95        }
96  
97        if (type == TYPE_JAVA && line.startsWith("package ")) {
98          writer.write(getLicenceHeader(document));
99          writer.write('\n');
100       }
101       if (type == TYPE_XML && line.startsWith("<?xml ")) {
102         writer.write(getLicenceHeader(document));
103         writer.write('\n');
104       }
105       first = false;
106     }
107     br.close();
108     writer.close();
109     
110     if (isForced) {
111       document.delete();
112       boolean renamed = newDocument.renameTo(document.getAbsoluteFile());
113       if (!renamed) {
114         System.err.println("Failed to rename new file, original file remains unchanged.");
115       }
116     }
117   }
118 
119   /**
120    * Check first line for specified text and process.
121    */
122   private void doFirstLine(File document, FileWriter writer, String line, String lookfor) throws IOException  {
123     if (line.startsWith(lookfor)) {
124         writer.write(line);
125         writer.write('\n');
126         writer.write(getLicenceHeader(document));
127     } else {
128         writer.write(getLicenceHeader(document));
129         writer.write(line);
130         writer.write('\n');
131     }
132   }
133 
134   /**
135    * Detect the type of document.
136    * 
137    * @param document
138    * @return not null
139    * @TODO use existing mechanism to detect the type of a file and record it in the report output, thus we will not need this duplication here.
140    */
141   protected int getType(File document) {
142     if (document.getPath().endsWith(".java")) {
143       return TYPE_JAVA;
144     } else if (document.getPath().endsWith(".xml") || document.getPath().endsWith(".xsl")) {
145       return TYPE_XML;
146     } else if (document.getPath().endsWith(".html") || document.getPath().endsWith(".htm")) {
147       return TYPE_HTML;
148     } else if (document.getPath().endsWith(".rdf") || document.getPath().endsWith(".xsl")) {
149         return TYPE_XML;
150     } else if (document.getPath().endsWith(".css")) {
151       return TYPE_CSS;
152     } else if (document.getPath().endsWith(".js")) {
153       return TYPE_JAVASCRIPT;
154     } else if (document.getPath().endsWith(".apt")) {
155       return TYPE_APT;
156     } else if (document.getPath().endsWith(".properties")) {
157       return TYPE_PROPERTIES;
158     } else if (document.getPath().endsWith(".py")) {
159       return TYPE_PYTHON;
160     } else if (document.getPath().endsWith(".c")) {
161       return TYPE_C;
162     } else if (document.getPath().endsWith(".h")) {
163       return TYPE_H;
164     } else if (document.getPath().endsWith(".sh")) {
165       return TYPE_SH;
166     } else if (document.getPath().endsWith(".bat")) {
167       return TYPE_BAT;
168     }
169     return TYPE_UNKNOWN;
170   }
171 
172   /**
173    * Set the force flag on this appender. If this flag is set
174    * to true then files will be modified directly, otherwise
175    * new files will be created alongside the existing files.
176    * 
177    * @param b
178    */
179   public void setForce(boolean b) {
180     isForced = b;    
181   }
182   
183   /**
184    * Get the licence header for a document.
185    */
186   public abstract String getLicenceHeader(File document);
187   
188   /**
189    * Get the first line of the licence header formatted
190    * for the given type of file.
191    * 
192    * @param type the type of file, see the TYPE_* constants
193    * @return not null
194    */
195   protected String getFirstLine(int type) {
196     switch (type) {
197       case TYPE_JAVA: return "/*\n";
198       case TYPE_C:    return "/*\n";
199       case TYPE_H:    return "/*\n";
200       case TYPE_XML: return "<!--\n";
201       case TYPE_HTML: return "<!--\n";
202       case TYPE_CSS: return "/*\n";
203       case TYPE_JAVASCRIPT: return "/*\n";
204       case TYPE_APT: return "~~\n";
205       case TYPE_PROPERTIES: return "#\n";
206       case TYPE_PYTHON:     return "#\n";
207       case TYPE_SH:         return "#\n";
208       case TYPE_BAT:        return "rem\n";
209       default: return "";
210     }
211   }
212   
213 
214   /**
215    * Get the last line of the licence header formatted
216    * for the given type of file.
217    * 
218    * @param type the type of file, see the TYPE_* constants
219    * @return not null
220    */
221   protected String getLastLine(int type) {
222     switch (type) {
223       case TYPE_JAVA: return " */\n";
224       case TYPE_C:    return " */\n";
225       case TYPE_H:    return " */\n";
226       case TYPE_XML: return "-->\n";
227       case TYPE_HTML: return "-->\n";
228       case TYPE_CSS: return " */\n";
229       case TYPE_JAVASCRIPT: return " */\n";
230       case TYPE_APT: return "~~\n";
231       case TYPE_PROPERTIES: return "#\n";
232       case TYPE_PYTHON:     return "#\n";
233       case TYPE_SH:         return "#\n";
234       case TYPE_BAT:        return "rem\n";
235       default: return "";
236     }
237   }
238   
239 
240   /**
241    * Get a line of the licence header formatted
242    * for the given type of file.
243    * 
244    * @param type the type of file, see the TYPE_* constants
245    * @param content the content for this line
246    * @return not null
247    */
248   protected String getLine(int type, String content) {
249     if (content != null && content.length() > 0) {
250         content = " " + content;
251     }
252     switch (type) {
253       case TYPE_JAVA: return " *" + content + "\n";
254       case TYPE_C:    return " *" + content + "\n";
255       case TYPE_H:    return " *" + content + "\n";
256       case TYPE_XML: return         content + "\n";
257       case TYPE_HTML: return        content + "\n";
258       case TYPE_CSS: return " *"  + content + "\n";
259       case TYPE_JAVASCRIPT: return " *" + content + "\n";
260       case TYPE_APT: return "~~" + content + "\n";
261       case TYPE_PROPERTIES: return "#" + content + "\n";
262       case TYPE_PYTHON:     return "#" + content + "\n";
263       case TYPE_SH:         return "#" + content + "\n";
264       case TYPE_BAT:        return "rem" + content + "\n";
265       default: return "";
266     }
267   }
268 }