Richard S. Hall | 85bafab | 2009-07-13 13:25:46 +0000 | [diff] [blame] | 1 | #!/usr/bin/env perl |
| 2 | |
| 3 | # Licensed to the Apache Software Foundation (ASF) under one |
| 4 | # or more contributor license agreements. See the NOTICE file |
| 5 | # distributed with this work for additional information |
| 6 | # regarding copyright ownership. The ASF licenses this file |
| 7 | # to you under the Apache License, Version 2.0 (the |
| 8 | # "License"); you may not use this file except in compliance |
| 9 | # with the License. You may obtain a copy of the License at |
| 10 | # |
| 11 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 12 | # |
| 13 | # Unless required by applicable law or agreed to in writing, |
| 14 | # software distributed under the License is distributed on an |
| 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 16 | # KIND, either express or implied. See the License for the |
| 17 | # specific language governing permissions and limitations |
| 18 | # under the License. |
| 19 | |
| 20 | use FileHandle; |
| 21 | |
| 22 | my $dryrun = 0; |
| 23 | my $quiet = 0; |
| 24 | |
| 25 | # |
| 26 | # Usage: notice.pl [-n] [-q] files... |
| 27 | # |
| 28 | |
| 29 | my $NOTICE = <<'EOT'; |
| 30 | Licensed to the Apache Software Foundation (ASF) under one |
| 31 | or more contributor license agreements. See the NOTICE file |
| 32 | distributed with this work for additional information |
| 33 | regarding copyright ownership. The ASF licenses this file |
| 34 | to you under the Apache License, Version 2.0 (the |
| 35 | "License"); you may not use this file except in compliance |
| 36 | with the License. You may obtain a copy of the License at |
| 37 | |
| 38 | http://www.apache.org/licenses/LICENSE-2.0 |
| 39 | |
| 40 | Unless required by applicable law or agreed to in writing, |
| 41 | software distributed under the License is distributed on an |
| 42 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| 43 | KIND, either express or implied. See the License for the |
| 44 | specific language governing permissions and limitations |
| 45 | under the License. |
| 46 | EOT |
| 47 | |
| 48 | # Note: source code notices must not be changed by code formatter |
| 49 | |
| 50 | my $NOTICE_java = $NOTICE; |
| 51 | $NOTICE_java =~ s/^/ * /gm; |
| 52 | $NOTICE_java = "/*\n" . $NOTICE_java . " */\n\n"; |
| 53 | |
| 54 | my $NOTICE_xml = $NOTICE; |
| 55 | $NOTICE_xml =~ s/^/ /gm; |
| 56 | $NOTICE_xml = "<!--\n" . $NOTICE_xml . "-->\n"; |
| 57 | |
| 58 | my $NOTICE_sh = $NOTICE; |
| 59 | $NOTICE_sh =~ s/^/# /gm; |
| 60 | |
| 61 | my $NOTICE_bat = $NOTICE; |
| 62 | $NOTICE_bat =~ s/^/:: /gm; |
| 63 | |
| 64 | sub addNotice { |
| 65 | my ($fh, $file, $notice) = @_; |
| 66 | print "$file\n"; |
| 67 | |
| 68 | return if ($dryrun); |
| 69 | |
| 70 | my $tmp = "$file.tmp"; |
| 71 | my $fh2 = new FileHandle(">$tmp"); |
| 72 | |
| 73 | print $fh2 $notice; |
| 74 | while (<$fh>) { |
| 75 | print $fh2 $_; |
| 76 | } |
| 77 | |
| 78 | unlink($file); |
| 79 | rename($tmp, $file); |
| 80 | } |
| 81 | |
| 82 | # |
| 83 | # locate existing copyright & license |
| 84 | # starts at top of file |
| 85 | # ends at "package" statement |
| 86 | # |
| 87 | sub notice_java { |
| 88 | my $file = shift; |
| 89 | my $fh = new FileHandle($file); |
| 90 | my $header; |
| 91 | my $package = undef; |
| 92 | |
| 93 | while (<$fh>) { |
| 94 | if (/^package\s+[\w.]+\s*;/) { |
| 95 | $package = $_; |
| 96 | last; |
| 97 | } |
| 98 | last if ($. > 200); |
| 99 | $header .= $_; |
| 100 | } |
| 101 | |
| 102 | if (! $package) { |
| 103 | print STDERR "$file: ERROR: no package statement.\n"; |
| 104 | return; |
| 105 | } |
| 106 | |
| 107 | return if ($header eq $NOTICE_java); |
| 108 | |
| 109 | # completely replace all before package statement |
| 110 | # so DON'T change below, without changing above |
| 111 | # to stop at end-of-first-comment. |
| 112 | $header = ''; |
| 113 | #$header = '' if ($header =~ /copyright/im); |
| 114 | #$header = "\n" . $header unless ($header =~ /^\n/); |
| 115 | |
| 116 | addNotice($fh, $file, $NOTICE_java . $header . $package); |
| 117 | } |
| 118 | |
| 119 | sub notice_xml { |
| 120 | my $file = shift; |
| 121 | my $fh = new FileHandle($file); |
| 122 | my $header = undef; |
| 123 | my $decl = qq(<?xml version="1.0"?>\n); |
| 124 | my $end = 0; |
| 125 | my $start = 0; |
| 126 | |
| 127 | while (<$fh>) { |
| 128 | if ($. == 1 && /^\<\?/) { |
| 129 | $decl = $_; |
| 130 | next; |
| 131 | } |
| 132 | |
| 133 | $header .= $_; |
| 134 | |
| 135 | if (!$start) { |
| 136 | last unless (/^<!--/); |
| 137 | $start = 1; |
| 138 | } |
| 139 | |
| 140 | if (/-->/) { |
| 141 | $end = 1; |
| 142 | last; |
| 143 | } |
| 144 | } |
| 145 | |
| 146 | return if ($header eq $NOTICE_xml); |
| 147 | |
| 148 | $header = '' if ($header =~ /copyright/im); |
| 149 | |
| 150 | if ($start && !$end) { |
| 151 | print STDERR "$file: ERROR: initial comment not terminated.\n"; |
| 152 | return; |
| 153 | } |
| 154 | |
| 155 | addNotice($fh, $file, $decl . $NOTICE_xml . $header); |
| 156 | } |
| 157 | |
| 158 | sub notice_sh { |
| 159 | my $file = shift; |
| 160 | my $fh = new FileHandle($file); |
| 161 | my $header = undef; |
| 162 | my $hashbang = undef; |
| 163 | my $end = ''; |
| 164 | my $start = ''; |
| 165 | |
| 166 | while (<$fh>) { |
| 167 | if ($. == 1 && /^#!/) { |
| 168 | $hashbang = $_; |
| 169 | next; |
| 170 | } |
| 171 | |
| 172 | if (!$start) { |
| 173 | unless (/^(#|\s*$)/) { |
| 174 | $header = $_; |
| 175 | last; |
| 176 | } |
| 177 | $start = 1; |
| 178 | next if (/^\s*$/); |
| 179 | } |
| 180 | |
| 181 | if (!/^#/) { |
| 182 | $end = $_; |
| 183 | last; |
| 184 | } |
| 185 | |
| 186 | $header .= $_; |
| 187 | } |
| 188 | |
| 189 | return if ($header eq $NOTICE_sh); |
| 190 | |
| 191 | $hashbang .= "\n" if ($hashbang); |
| 192 | |
| 193 | $header = '' if ($header =~ /copyright/im); |
| 194 | $header .= $end; |
| 195 | $header = "\n" . $header unless ($header =~ /^\n/); |
| 196 | |
| 197 | if ($start && !$end) { |
| 198 | print STDERR "$file: ERROR: initial comment not terminated.\n"; |
| 199 | return; |
| 200 | } |
| 201 | |
| 202 | addNotice($fh, $file, $hashbang . $NOTICE_sh . $header); |
| 203 | } |
| 204 | |
| 205 | sub notice_bat { |
| 206 | my $file = shift; |
| 207 | my $fh = new FileHandle($file); |
| 208 | my $header = undef; |
| 209 | my $atecho = undef; |
| 210 | my $end = ''; |
| 211 | my $start = ''; |
| 212 | |
| 213 | while (<$fh>) { |
| 214 | s/\r\n$/\n/; |
| 215 | if ($. == 1 && /^\@echo/) { |
| 216 | $atecho = $_; |
| 217 | next; |
| 218 | } |
| 219 | |
| 220 | if (!$start) { |
| 221 | unless (/^(::|\s*$)/) { |
| 222 | $header = $_; |
| 223 | last; |
| 224 | } |
| 225 | $start = 1; |
| 226 | next if (/^\s*$/); |
| 227 | } |
| 228 | |
| 229 | if (!/^::/) { |
| 230 | $end = $_; |
| 231 | last; |
| 232 | } |
| 233 | |
| 234 | $header .= $_; |
| 235 | } |
| 236 | |
| 237 | return if ($header eq $NOTICE_bat); |
| 238 | |
| 239 | $atecho .= "\n" if ($atecho); |
| 240 | |
| 241 | $header = '' if ($header =~ /copyright/im); |
| 242 | $header .= $end; |
| 243 | $header = "\n" . $header unless ($header =~ /^\n/); |
| 244 | |
| 245 | if ($start && !$end) { |
| 246 | print STDERR "$file: ERROR: initial comment not terminated.\n"; |
| 247 | return; |
| 248 | } |
| 249 | |
| 250 | $header = $atecho . $NOTICE_bat . $header; |
| 251 | $header =~ s/\n/\r\n/mg; |
| 252 | addNotice($fh, $file, $header); |
| 253 | } |
| 254 | |
| 255 | sub notice_unknown { |
| 256 | my $file = shift; |
| 257 | my $fh = new FileHandle($file); |
| 258 | |
| 259 | my $line = <$fh>; |
| 260 | |
| 261 | if ($line =~ /^#!/) { |
| 262 | notice_sh($file); |
| 263 | } |
| 264 | elsif ($line =~ /^\<\?xml/) { |
| 265 | notice_xml($file); |
| 266 | } |
| 267 | elsif (! $quiet) { |
| 268 | print STDERR "$file: unknown file type.\n"; |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | foreach my $f (@ARGV) { |
| 273 | if ($f eq '-n') { |
| 274 | $dryrun++; |
| 275 | } |
| 276 | elsif ($f eq '-q') { |
| 277 | $quiet++; |
| 278 | } |
| 279 | elsif ($f =~ /\.java$/) { |
| 280 | notice_java($f); |
| 281 | } |
| 282 | elsif ($f =~ /\.(xml|xsd|system|composite)$/) { |
| 283 | notice_xml($f); |
| 284 | } |
| 285 | elsif ($f =~ /\.(sh|app|ini|xargs)$/) { |
| 286 | notice_sh($f); |
| 287 | } |
| 288 | elsif ($f =~ /\.(bat)$/) { |
| 289 | notice_bat($f); |
| 290 | } |
| 291 | else { |
| 292 | notice_unknown($f); |
| 293 | } |
| 294 | } |
| 295 | |