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", "id", "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 // map 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 } else if (filename.indexOf("topic/performance") == 0) { 240 hdf.setValue("perf", "true"); 241 hdf.setValue("page.type", "develop"); 242 hdf.setValue("page.category", "performance"); 243 } else if (filename.indexOf("topic/arc") == 0) { 244 hdf.setValue("arc", "true"); 245 hdf.setValue("page.type", "develop"); 246 hdf.setValue("page.category", "arc"); 247 } 248 } else if (filename.indexOf("distribute") == 0) { 249 hdf.setValue("distribute", "true"); 250 hdf.setValue("page.type", "distribute"); 251 hdf.setValue("page.category", "distribute"); 252 if (filename.indexOf("distribute/googleplay") == 0) { 253 hdf.setValue("page.category", "googleplay"); 254 hdf.setValue("page.type", "distribute"); 255 hdf.setValue("googleplay", "true"); 256 } else if (filename.indexOf("distribute/essentials") == 0) { 257 hdf.setValue("page.category", "essentials"); 258 hdf.setValue("essentials", "true"); 259 } else if (filename.indexOf("distribute/users") == 0) { 260 hdf.setValue("page.category", "users"); 261 hdf.setValue("users", "true"); 262 } else if (filename.indexOf("distribute/engage") == 0) { 263 hdf.setValue("page.category", "engage"); 264 hdf.setValue("engage", "true"); 265 } else if (filename.indexOf("distribute/monetize") == 0) { 266 hdf.setValue("page.category", "monetize"); 267 hdf.setValue("monetize", "true"); 268 } else if (filename.indexOf("distribute/analyze") == 0) { 269 hdf.setValue("page.category", "analyze"); 270 hdf.setValue("analyze", "true"); 271 } else if (filename.indexOf("distribute/tools") == 0) { 272 hdf.setValue("page.category", "essentials"); 273 hdf.setValue("essentials", "true"); 274 } else if (filename.indexOf("distribute/stories") == 0) { 275 hdf.setValue("page.category", "stories"); 276 hdf.setValue("stories", "true"); 277 } 278 } else if (filename.indexOf("about") == 0) { 279 hdf.setValue("about", "true"); 280 hdf.setValue("page.type", "about"); 281 hdf.setValue("page.category", "about"); 282 if ((filename.indexOf("about/versions") == 0)) { 283 hdf.setValue("versions", "true"); 284 hdf.setValue("page.category", "versions"); 285 //todo remove this because there's no file at this location 286 } else if ((filename.indexOf("wear") == 0)) { 287 hdf.setValue("wear", "true"); 288 hdf.setValue("page.category", "wear"); 289 } else if ((filename.indexOf("tv") == 0)) { 290 hdf.setValue("tv", "true"); 291 hdf.setValue("page.category", "tv"); 292 } else if ((filename.indexOf("auto") == 0)) { 293 hdf.setValue("auto", "true"); 294 hdf.setValue("page.category", "auto"); 295 } 296 } else if (filename.indexOf("wear/preview") == 0) { 297 hdf.setValue("wearpreview", "true"); 298 hdf.setValue("page.type", "about"); 299 hdf.setValue("page.category", "wear preview"); 300 } else if (filename.indexOf("devices") == 0) { 301 hdf.setValue("devices", "true"); 302 hdf.setValue("page.type", "devices"); 303 } else if (filename.indexOf("source") == 0) { 304 hdf.setValue("source", "true"); 305 } else if (filename.indexOf("security") == 0) { 306 hdf.setValue("security", "true"); 307 } else if (filename.indexOf("compatibility") == 0) { 308 hdf.setValue("compatibility", "true"); 309 } else if (filename.indexOf("wear") == 0) { 310 hdf.setValue("wear", "true"); 311 hdf.setValue("about", "true"); 312 hdf.setValue("page.type", "about"); 313 hdf.setValue("page.category", "wear"); 314 } else if (filename.indexOf("work") == 0) { 315 hdf.setValue("work", "true"); 316 hdf.setValue("page.type", "about"); 317 hdf.setValue("page.category", "work"); 318 } else if (filename.indexOf("preview") == 0) { 319 hdf.setValue("page.type", "develop"); 320 hdf.setValue("page.category", "preview"); 321 hdf.setValue("preview", "true"); 322 } else if (filename.indexOf("auto") == 0) { 323 hdf.setValue("auto", "true"); 324 hdf.setValue("about", "true"); 325 hdf.setValue("page.type", "about"); 326 hdf.setValue("page.category", "auto"); 327 } else if (filename.indexOf("tv") == 0) { 328 hdf.setValue("tv", "true"); 329 hdf.setValue("about", "true"); 330 hdf.setValue("page.type", "about"); 331 hdf.setValue("page.category", "tv"); 332 } else { 333 hdf.setValue("about", "true"); 334 hdf.setValue("page.type", "about"); 335 hdf.setValue("page.category", "about"); 336 } 337 338 //set metadata for this file in jd_lists_unified 339 PageMetadata.setPageMetadata(docfile, relative, outfile, hdf, Doclava.sTaglist); 340 341 //for devsite builds, remove 'intl/' from output paths for localized files 342 if (Doclava.USE_DEVSITE_LOCALE_OUTPUT_PATHS) { 343 outfile = outfile.replaceFirst("^intl/", ""); 344 } 345 346 ClearPage.write(hdf, "docpage.cs", outfile); 347 } 348 } // writePage 349 } 350