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