1 /* 2 * Copyright (C) 2010 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.doclava; 18 19 import com.google.clearsilver.jsilver.data.Data; 20 21 import java.io.*; 22 import java.util.regex.Pattern; 23 import java.util.regex.Matcher; 24 25 26 public class DocFile { 27 public static final Pattern LINE = Pattern.compile("(.*)[\r]?\n", Pattern.MULTILINE); 28 public static final Pattern PROP = Pattern.compile("([^=]+)=(.*)"); 29 readFile(String filename)30 public static String readFile(String filename) { 31 try { 32 File f = new File(filename); 33 int length = (int) f.length(); 34 FileInputStream is = new FileInputStream(f); 35 InputStreamReader reader = new InputStreamReader(is, "UTF-8"); 36 char[] buf = new char[length]; 37 int index = 0; 38 int amt; 39 while (true) { 40 amt = reader.read(buf, index, length - index); 41 42 if (amt < 1) { 43 break; 44 } 45 46 index += amt; 47 } 48 return new String(buf, 0, index); 49 } catch (IOException e) { 50 return null; 51 } 52 } 53 54 public static String[] DEVSITE_VALID_LANGS = {"en", "es", "in", "ja", "ko", 55 "ru", "vi", "zh-cn", "zh-tw", "pt-br"}; 56 getPathRoot(String filename)57 public static String getPathRoot(String filename) { 58 //look for a valid lang string in the file path. If found, 59 //snip the intl/lang from the path. 60 for (String t : DEVSITE_VALID_LANGS) { 61 int langStart = filename.indexOf("/" + t + "/"); 62 if (langStart > -1) { 63 int langEnd = filename.indexOf("/", langStart + 1); 64 filename = filename.substring(langEnd + 1); 65 break; 66 } 67 } 68 return filename; 69 } 70 getPageMetadata(String docfile, Data hdf)71 public static Data getPageMetadata (String docfile, Data hdf) { 72 //utility method for extracting metadata without generating file output. 73 if (hdf == null) { 74 hdf = Doclava.makeHDF(); 75 } 76 String filedata = readFile(docfile); 77 78 // The document is properties up until the line "@jd:body". 79 // Any blank lines are ignored. 80 int start = -1; 81 int lineno = 1; 82 Matcher lines = LINE.matcher(filedata); 83 String line = null; 84 while (lines.find()) { 85 line = lines.group(1); 86 if (line.length() > 0) { 87 if (line.equals("@jd:body")) { 88 start = lines.end(); 89 break; 90 } 91 Matcher prop = PROP.matcher(line); 92 if (prop.matches()) { 93 String key = prop.group(1); 94 String value = prop.group(2); 95 hdf.setValue(key, value); 96 } else { 97 break; 98 } 99 } 100 lineno++; 101 } 102 if (start < 0) { 103 System.err.println(docfile + ":" + lineno + ": error parsing docfile"); 104 if (line != null) { 105 System.err.println(docfile + ":" + lineno + ":" + line); 106 } 107 System.exit(1); 108 } 109 return hdf; 110 } 111 writePage(String docfile, String relative, String outfile, Data hdf)112 public static void writePage(String docfile, String relative, String outfile, Data hdf) { 113 114 /* 115 * System.out.println("docfile='" + docfile + "' relative='" + relative + "'" + "' outfile='" + 116 * outfile + "'"); 117 */ 118 if (hdf == null) { 119 hdf = Doclava.makeHDF(); 120 } 121 String filedata = readFile(docfile); 122 123 // The document is properties up until the line "@jd:body". 124 // Any blank lines are ignored. 125 int start = -1; 126 int lineno = 1; 127 Matcher lines = LINE.matcher(filedata); 128 String line = null; 129 while (lines.find()) { 130 line = lines.group(1); 131 if (line.length() > 0) { 132 if (line.equals("@jd:body")) { 133 start = lines.end(); 134 break; 135 } 136 Matcher prop = PROP.matcher(line); 137 if (prop.matches()) { 138 String key = prop.group(1); 139 String value = prop.group(2); 140 hdf.setValue(key, value); 141 } else { 142 break; 143 } 144 } 145 lineno++; 146 } 147 if (start < 0) { 148 System.err.println(docfile + ":" + lineno + ": error parsing docfile"); 149 if (line != null) { 150 System.err.println(docfile + ":" + lineno + ":" + line); 151 } 152 System.exit(1); 153 } 154 155 // if they asked to only be for a certain template, maybe skip it 156 String fromTemplate = hdf.getValue("template.which", ""); 157 String fromPage = hdf.getValue("page.onlyfortemplate", ""); 158 if (!"".equals(fromPage) && !fromTemplate.equals(fromPage)) { 159 return; 160 } 161 162 // and the actual text after that 163 String commentText = filedata.substring(start); 164 165 Comment comment = new Comment(commentText, null, new SourcePositionInfo(docfile, lineno, 1)); 166 TagInfo[] tags = comment.tags(); 167 168 TagInfo.makeHDF(hdf, "root.descr", tags); 169 170 hdf.setValue("commentText", commentText); 171 172 // write the page using the appropriate root template, based on the 173 // whichdoc value supplied by build 174 String fromWhichmodule = hdf.getValue("android.whichmodule", ""); 175 if (fromWhichmodule.equals("online-pdk")) { 176 // leaving this in just for temporary compatibility with pdk doc 177 hdf.setValue("online-pdk", "true"); 178 // add any conditional login for root template here (such as 179 // for custom left nav based on tab etc. 180 ClearPage.write(hdf, "docpage.cs", outfile); 181 } else { 182 String filename = outfile; 183 // Special case handling of samples files for devsite 184 // locale handling -- strip out the en/ root 185 if (Doclava.USE_DEVSITE_LOCALE_OUTPUT_PATHS) { 186 filename = filename.replaceFirst("^en/", ""); 187 } 188 // Strip out the intl and lang id substr and get back just the 189 // guide, design, distribute, etc. 190 filename = getPathRoot(filename); 191 192 if (Doclava.USE_UPDATED_TEMPLATES) { 193 //remap types to design, dev, distribute etc. 194 if (filename.indexOf("design") == 0) { 195 hdf.setValue("design", "true"); 196 hdf.setValue("page.type", "design"); 197 hdf.setValue("page.category", "design"); 198 } else if (filename.indexOf("develop") == 0) { 199 hdf.setValue("develop", "true"); 200 hdf.setValue("page.type", "develop"); 201 hdf.setValue("page.category", "develop"); 202 } else if (filename.indexOf("guide") == 0) { 203 hdf.setValue("guide", "true"); 204 hdf.setValue("page.type", "develop"); 205 if (filename.indexOf("guide/topics/manif") == 0) { 206 hdf.setValue("page.category", "app manifest"); 207 } else { 208 hdf.setValue("page.category", "guide"); 209 } 210 } else if (filename.indexOf("training") == 0) { 211 hdf.setValue("training", "true"); 212 hdf.setValue("page.type", "develop"); 213 hdf.setValue("page.category", "training"); 214 } else if (filename.indexOf("more") == 0) { 215 hdf.setValue("more", "true"); 216 } else if (filename.indexOf("google") == 0) { 217 hdf.setValue("google", "true"); 218 hdf.setValue("page.type", "develop"); 219 hdf.setValue("page.category", "google"); 220 } else if (filename.indexOf("samples") == 0) { 221 hdf.setValue("samples", "true"); 222 hdf.setValue("samplesDocPage", "true"); 223 hdf.setValue("page.type", "develop"); 224 hdf.setValue("page.category", "samples"); 225 if (Doclava.samplesNavTree != null) { 226 hdf.setValue("samples_toc_tree", Doclava.samplesNavTree.getValue("samples_toc_tree", "")); 227 } 228 } else if (filename.indexOf("topic/") == 0) { 229 hdf.setValue("topic", "true"); 230 hdf.setValue("page.type", "develop"); 231 if (filename.indexOf("topic/libraries") == 0) { 232 hdf.setValue("page.category", "libraries"); 233 hdf.setValue("page.type", "develop"); 234 hdf.setValue("libraries", "true"); 235 } else if (filename.indexOf("topic/instant-apps") == 0) { 236 hdf.setValue("instantapps", "true"); 237 hdf.setValue("page.type", "develop"); 238 hdf.setValue("page.category", "instant apps"); 239 } 240 } else if (filename.indexOf("distribute") == 0) { 241 hdf.setValue("distribute", "true"); 242 hdf.setValue("page.type", "distribute"); 243 hdf.setValue("page.category", "distribute"); 244 if (filename.indexOf("distribute/googleplay") == 0) { 245 hdf.setValue("page.category", "googleplay"); 246 hdf.setValue("page.type", "distribute"); 247 hdf.setValue("googleplay", "true"); 248 } else if (filename.indexOf("distribute/essentials") == 0) { 249 hdf.setValue("page.category", "essentials"); 250 hdf.setValue("essentials", "true"); 251 } else if (filename.indexOf("distribute/users") == 0) { 252 hdf.setValue("page.category", "users"); 253 hdf.setValue("users", "true"); 254 } else if (filename.indexOf("distribute/engage") == 0) { 255 hdf.setValue("page.category", "engage"); 256 hdf.setValue("engage", "true"); 257 } else if (filename.indexOf("distribute/monetize") == 0) { 258 hdf.setValue("page.category", "monetize"); 259 hdf.setValue("monetize", "true"); 260 } else if (filename.indexOf("distribute/analyze") == 0) { 261 hdf.setValue("page.category", "analyze"); 262 hdf.setValue("analyze", "true"); 263 } else if (filename.indexOf("distribute/tools") == 0) { 264 hdf.setValue("page.category", "essentials"); 265 hdf.setValue("essentials", "true"); 266 } else if (filename.indexOf("distribute/stories") == 0) { 267 hdf.setValue("page.category", "stories"); 268 hdf.setValue("stories", "true"); 269 } 270 } else if (filename.indexOf("about") == 0) { 271 hdf.setValue("about", "true"); 272 hdf.setValue("page.type", "about"); 273 hdf.setValue("page.category", "about"); 274 if ((filename.indexOf("about/versions") == 0)) { 275 hdf.setValue("versions", "true"); 276 hdf.setValue("page.category", "versions"); 277 //todo remove this because there's no file at this location 278 } else if ((filename.indexOf("wear") == 0)) { 279 hdf.setValue("wear", "true"); 280 hdf.setValue("page.category", "wear"); 281 } else if ((filename.indexOf("tv") == 0)) { 282 hdf.setValue("tv", "true"); 283 hdf.setValue("page.category", "tv"); 284 } else if ((filename.indexOf("auto") == 0)) { 285 hdf.setValue("auto", "true"); 286 hdf.setValue("page.category", "auto"); 287 } 288 } else if (filename.indexOf("wear/preview") == 0) { 289 hdf.setValue("wearpreview", "true"); 290 hdf.setValue("page.type", "about"); 291 hdf.setValue("page.category", "wear preview"); 292 } else if ((filename.indexOf("tools") == 0) || (filename.indexOf("sdk") == 0)) { 293 hdf.setValue("tools", "true"); 294 hdf.setValue("page.type", "develop"); 295 hdf.setValue("page.category", "tools"); 296 fromTemplate = hdf.getValue("page.template", ""); 297 } else if (filename.indexOf("devices") == 0) { 298 hdf.setValue("devices", "true"); 299 hdf.setValue("page.type", "devices"); 300 } else if (filename.indexOf("source") == 0) { 301 hdf.setValue("source", "true"); 302 } else if (filename.indexOf("accessories") == 0) { 303 hdf.setValue("accessories", "true"); 304 } else if (filename.indexOf("compatibility") == 0) { 305 hdf.setValue("compatibility", "true"); 306 } else if (filename.indexOf("wear") == 0) { 307 hdf.setValue("wear", "true"); 308 hdf.setValue("about", "true"); 309 hdf.setValue("page.type", "about"); 310 hdf.setValue("page.category", "wear"); 311 } else if (filename.indexOf("work") == 0) { 312 hdf.setValue("work", "true"); 313 hdf.setValue("page.type", "about"); 314 hdf.setValue("page.category", "work"); 315 } else if (filename.indexOf("preview") == 0) { 316 hdf.setValue("page.type", "develop"); 317 hdf.setValue("page.category", "preview"); 318 hdf.setValue("preview", "true"); 319 } else if (filename.indexOf("auto") == 0) { 320 hdf.setValue("auto", "true"); 321 hdf.setValue("about", "true"); 322 hdf.setValue("page.type", "about"); 323 hdf.setValue("page.category", "auto"); 324 } else if (filename.indexOf("tv") == 0) { 325 hdf.setValue("tv", "true"); 326 hdf.setValue("about", "true"); 327 hdf.setValue("page.type", "about"); 328 hdf.setValue("page.category", "tv"); 329 } else if (filename.indexOf("ndk") == 0) { 330 hdf.setValue("ndk", "true"); 331 hdf.setValue("page.type", "ndk"); 332 hdf.setValue("page.category", "ndk"); 333 if (filename.indexOf("ndk/guides") == 0) { 334 hdf.setValue("guide", "true"); 335 hdf.setValue("page.type", "ndk"); 336 hdf.setValue("page.category", "guide"); 337 } else if (filename.indexOf("ndk/reference") == 0) { 338 hdf.setValue("reference", "true"); 339 hdf.setValue("page.type", "ndk"); 340 hdf.setValue("page.category", "reference"); 341 } else if (filename.indexOf("ndk/samples") == 0) { 342 hdf.setValue("samples", "true"); 343 hdf.setValue("page.type", "ndk"); 344 hdf.setValue("page.category", "samples"); 345 hdf.setValue("samplesDocPage", "true"); 346 } else if (filename.indexOf("ndk/downloads") == 0) { 347 hdf.setValue("downloads", "true"); 348 hdf.setValue("page.type", "ndk"); 349 hdf.setValue("page.category", "downloads"); 350 fromTemplate = hdf.getValue("page.template", ""); 351 } 352 } 353 } else { 354 //support the old mappings 355 if (filename.indexOf("design") == 0) { 356 hdf.setValue("design", "true"); 357 hdf.setValue("page.type", "design"); 358 } else if (filename.indexOf("develop") == 0) { 359 hdf.setValue("develop", "true"); 360 hdf.setValue("page.type", "develop"); 361 } else if (filename.indexOf("guide") == 0) { 362 hdf.setValue("guide", "true"); 363 hdf.setValue("page.type", "guide"); 364 } else if (filename.indexOf("training") == 0) { 365 hdf.setValue("training", "true"); 366 hdf.setValue("page.type", "training"); 367 } else if (filename.indexOf("more") == 0) { 368 hdf.setValue("more", "true"); 369 } else if (filename.indexOf("google") == 0) { 370 hdf.setValue("google", "true"); 371 hdf.setValue("page.type", "google"); 372 } else if (filename.indexOf("samples") == 0) { 373 hdf.setValue("samples", "true"); 374 hdf.setValue("samplesDocPage", "true"); 375 hdf.setValue("page.type", "samples"); 376 if (Doclava.samplesNavTree != null) { 377 hdf.setValue("samples_toc_tree", Doclava.samplesNavTree.getValue("samples_toc_tree", "")); 378 } 379 } else if (filename.indexOf("distribute") == 0) { 380 hdf.setValue("distribute", "true"); 381 hdf.setValue("page.type", "distribute"); 382 if (filename.indexOf("distribute/googleplay") == 0) { 383 hdf.setValue("googleplay", "true"); 384 } else if (filename.indexOf("distribute/essentials") == 0) { 385 hdf.setValue("essentials", "true"); 386 } else if (filename.indexOf("distribute/users") == 0) { 387 hdf.setValue("users", "true"); 388 } else if (filename.indexOf("distribute/engage") == 0) { 389 hdf.setValue("engage", "true"); 390 } else if (filename.indexOf("distribute/monetize") == 0) { 391 hdf.setValue("monetize", "true"); 392 } else if (filename.indexOf("distribute/analyze") == 0) { 393 hdf.setValue("analyze", "true"); 394 } else if (filename.indexOf("distribute/tools") == 0) { 395 hdf.setValue("essentials", "true"); 396 } else if (filename.indexOf("distribute/stories") == 0) { 397 hdf.setValue("stories", "true"); 398 } 399 } else if (filename.indexOf("about") == 0) { 400 hdf.setValue("about", "true"); 401 hdf.setValue("page.type", "about"); 402 } else if ((filename.indexOf("tools") == 0) || (filename.indexOf("sdk") == 0)) { 403 hdf.setValue("tools", "true"); 404 hdf.setValue("page.type", "tools"); 405 fromTemplate = hdf.getValue("page.template", ""); 406 } else if (filename.indexOf("devices") == 0) { 407 hdf.setValue("devices", "true"); 408 hdf.setValue("page.type", "devices"); 409 } else if (filename.indexOf("source") == 0) { 410 hdf.setValue("source", "true"); 411 } else if (filename.indexOf("accessories") == 0) { 412 hdf.setValue("accessories", "true"); 413 } else if (filename.indexOf("compatibility") == 0) { 414 hdf.setValue("compatibility", "true"); 415 } else if (filename.indexOf("topic/") == 0) { 416 hdf.setValue("topic", "true"); 417 hdf.setValue("page.type", "develop"); 418 if (filename.indexOf("topic/libraries") == 0) { 419 hdf.setValue("page.category", "libraries"); 420 hdf.setValue("page.type", "develop"); 421 hdf.setValue("libraries", "true"); 422 } else if (filename.indexOf("topic/instant-apps") == 0) { 423 hdf.setValue("instantapps", "true"); 424 hdf.setValue("page.type", "develop"); 425 hdf.setValue("page.category", "instant apps"); 426 } 427 } else if (filename.indexOf("wear/preview") == 0) { 428 hdf.setValue("wearpreview", "true"); 429 hdf.setValue("page.type", "about"); 430 hdf.setValue("page.category", "wear preview"); 431 } else if (filename.indexOf("wear") == 0) { 432 hdf.setValue("wear", "true"); 433 } else if (filename.indexOf("work") == 0) { 434 hdf.setValue("work", "true"); 435 hdf.setValue("page.type", "about"); 436 hdf.setValue("page.category", "work"); 437 } else if (filename.indexOf("preview") == 0) { 438 hdf.setValue("page.type", "preview"); 439 hdf.setValue("page.category", "preview"); 440 hdf.setValue("preview", "true"); 441 } else if (filename.indexOf("auto") == 0) { 442 hdf.setValue("auto", "true"); 443 } else if (filename.indexOf("tv") == 0) { 444 hdf.setValue("tv", "true"); 445 } else if (filename.indexOf("ndk") == 0) { 446 hdf.setValue("ndk", "true"); 447 hdf.setValue("page.type", "ndk"); 448 if (filename.indexOf("ndk/guides") == 0) { 449 hdf.setValue("guide", "true"); 450 } else if (filename.indexOf("ndk/reference") == 0) { 451 hdf.setValue("reference", "true"); 452 } else if (filename.indexOf("ndk/samples") == 0) { 453 hdf.setValue("samples", "true"); 454 hdf.setValue("samplesDocPage", "true"); 455 } else if (filename.indexOf("ndk/downloads") == 0) { 456 hdf.setValue("downloads", "true"); 457 fromTemplate = hdf.getValue("page.template", ""); 458 } 459 } 460 } 461 //set metadata for this file in jd_lists_unified 462 PageMetadata.setPageMetadata(docfile, relative, outfile, hdf, Doclava.sTaglist); 463 464 //for devsite builds, remove 'intl/' from output paths for localized files 465 if (Doclava.USE_DEVSITE_LOCALE_OUTPUT_PATHS) { 466 outfile = outfile.replaceFirst("^intl/", ""); 467 } 468 469 if (fromTemplate.equals("sdk")) { 470 ClearPage.write(hdf, "sdkpage.cs", outfile); 471 } else { 472 ClearPage.write(hdf, "docpage.cs", outfile); 473 } 474 } 475 } // writePage 476 } 477