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.JSilver;
20 import com.google.clearsilver.jsilver.data.Data;
21 
22 import java.io.BufferedWriter;
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.io.OutputStreamWriter;
28 import java.io.Writer;
29 import java.util.ArrayList;
30 import java.util.List;
31 import java.util.Arrays;
32 
33 public class ClearPage {
34   /*
35    * public ClearPage() { String templ = "templates/index.cs"; String filename = "docs/index.html";
36    *
37    * data.setValue("A.B.C", "1"); data.setValue("A.B.D", "2"); }
38    */
39 
40   private static ArrayList<String> mTemplateDirs = new ArrayList<String>();
41   private static boolean mTemplateDirSet = false;
42 
43   private static ArrayList<String> mBundledTemplateDirs = new ArrayList<String>();
44 
45   public static String outputDir = "docs";
46   public static List<String> htmlDirs = new ArrayList<String>();
47   public static String toroot = null;
48 
addTemplateDir(String dir)49   public static void addTemplateDir(String dir) {
50     mTemplateDirSet = true;
51     mTemplateDirs.add(dir);
52   }
53 
getTemplateDirs()54   public static List<String> getTemplateDirs() {
55     return mTemplateDirs;
56   }
57 
addBundledTemplateDir(String dir)58   public static void addBundledTemplateDir(String dir) {
59     mTemplateDirSet = true;
60     mBundledTemplateDirs.add(dir);
61   }
62 
getBundledTemplateDirs()63   public static List<String> getBundledTemplateDirs() {
64     return mBundledTemplateDirs;
65   }
66 
countSlashes(String s)67   private static int countSlashes(String s) {
68     final int N = s.length();
69     int slashcount = 0;
70     for (int i = 0; i < N; i++) {
71       if (s.charAt(i) == '/') {
72         slashcount++;
73       }
74     }
75     return slashcount;
76   }
77 
write(Data data, String templ, String filename, JSilver cs)78   public static void write(Data data, String templ, String filename, JSilver cs) {
79     write(data, templ, filename, false, cs);
80   }
81 
write(Data data, String templ, String filename)82   public static void write(Data data, String templ, String filename) {
83     write(data, templ, filename, false, Doclava.jSilver);
84   }
85 
write(Data data, String templ, String filename, boolean fullPath)86   public static void write(Data data, String templ, String filename, boolean fullPath) {
87     write(data, templ, filename, false, Doclava.jSilver);
88   }
89 
write(Data data, String templ, String filename, boolean fullPath, JSilver cs)90   public static void write(Data data, String templ, String filename, boolean fullPath, JSilver cs) {
91     if (!htmlDirs.isEmpty()) {
92       data.setValue("hasindex", "true");
93     }
94 
95     String toroot;
96     if (ClearPage.toroot != null) {
97       toroot = ClearPage.toroot;
98     } else {
99       int slashcount = countSlashes(filename);
100       if (slashcount > 0) {
101         toroot = "";
102         for (int i = 0; i < slashcount; i++) {
103           toroot += "../";
104         }
105       } else {
106         toroot = "./";
107       }
108     }
109     data.setValue("toroot", toroot);
110     if (Doclava.USE_UPDATED_TEMPLATES) {
111       data.setValue("useUpdatedTemplates", "true");
112     }
113     data.setValue("filename", filename);
114 
115     if (!fullPath) {
116       filename = outputDir + "/" + filename;
117     }
118 
119     int i = 0;
120     if (!htmlDirs.isEmpty()) {
121         for (String dir : htmlDirs) {
122           data.setValue("hdf.loadpaths." + i, dir);
123           i++;
124         }
125     }
126     if (mTemplateDirSet) {
127       for (String dir : mTemplateDirs) {
128         data.setValue("hdf.loadpaths." + i, dir);
129         i++;
130       }
131     } else {
132       data.setValue("hdf.loadpaths." + i, "templates");
133     }
134 
135     File file = new File(outputFilename(filename));
136 
137     ensureDirectory(file);
138     Writer stream = null;
139     try {
140       stream = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
141       String rendered = cs.render(templ, data);
142       stream.write(rendered, 0, rendered.length());
143     } catch (IOException e) {
144       System.out.println("error: " + e.getMessage() + "; when writing file: " + filename);
145     } finally {
146       if (stream != null) {
147         try {
148           stream.close();
149         } catch (IOException e) {}
150       }
151     }
152   }
153 
154   // recursively create the directories to the output
ensureDirectory(File f)155   public static void ensureDirectory(File f) {
156     File parent = f.getParentFile();
157     if (parent != null) {
158       parent.mkdirs();
159     }
160   }
161 
copyFile(boolean allowExcepted, File from, String toPath, Boolean append)162   public static void copyFile(boolean allowExcepted, File from, String toPath, Boolean append) {
163     File to = new File(outputDir + "/" + toPath);
164     FileInputStream in;
165     FileOutputStream out;
166     try {
167       if (!from.exists()) {
168         throw new IOException();
169       }
170       in = new FileInputStream(from);
171     } catch (IOException e) {
172       System.err.println(from.getAbsolutePath() + ": Error opening file");
173       return;
174     }
175     ensureDirectory(to);
176     try {
177       out = new FileOutputStream(to, append);
178     } catch (IOException e) {
179       System.err.println(to.getAbsolutePath() + ": Error opening file");
180       return;
181     }
182     if (!isValidContentType(allowExcepted, toPath, DROIDDOC_VALID_CONTENT_TYPES)) {
183         Errors.error(Errors.INVALID_CONTENT_TYPE, null, "Failed to process " + from
184                 + ": Invalid file type. Please move the file to frameworks/base/docs/image_sources/... or docs/downloads/...");
185         return;
186     }
187 
188     long sizel = from.length();
189     final int maxsize = 64 * 1024;
190     int size = sizel > maxsize ? maxsize : (int) sizel;
191     byte[] buf = new byte[size];
192     while (true) {
193       try {
194         size = in.read(buf);
195       } catch (IOException e) {
196         System.err.println(from.getAbsolutePath() + ": error reading file");
197         break;
198       }
199       if (size > 0) {
200         try {
201           out.write(buf, 0, size);
202         } catch (IOException e) {
203           System.err.println(from.getAbsolutePath() + ": error writing file");
204         }
205       } else {
206         break;
207       }
208     }
209     try {
210       in.close();
211     } catch (IOException e) {}
212     try {
213       out.close();
214     } catch (IOException e) {}
215   }
216 
217   /** Takes a string that ends w/ .html and changes the .html to htmlExtension */
outputFilename(String htmlFile)218   public static String outputFilename(String htmlFile) {
219     if (!Doclava.htmlExtension.equals(".html") && htmlFile.endsWith(".html")) {
220       return htmlFile.substring(0, htmlFile.length() - 5) + Doclava.htmlExtension;
221     } else {
222       return htmlFile;
223     }
224   }
225 
226   public static ArrayList<String> DROIDDOC_VALID_CONTENT_TYPES = new ArrayList<String>(Arrays.asList(".txt", ".css",
227     ".js", ".html", ".ico", ".png", ".jpg", ".gif", ".svg", ".webm", ".ogv","mp4", ".java", ".xml", ".aidl", ".rs",".zip", ".yaml"));
228   /* Setting excepted types to allow everything. Leaving it this way in in case we want to explicitly
229    * specify file types later. This adds unneeded checking though since it lets everything through
230    */
231   public static ArrayList<String> DROIDDOC_EXCEPTED_CONTENT_TYPES = new ArrayList<String>(Arrays.asList(""));
232 
isValidContentType(boolean allowExcepted, String s, ArrayList<String> list)233   public static boolean isValidContentType(boolean allowExcepted, String s, ArrayList<String> list) {
234     if(allowExcepted){
235       list.addAll(DROIDDOC_EXCEPTED_CONTENT_TYPES);
236     }
237     for (String t : list) {
238       if (s.endsWith(t)) {
239         return true;
240       }
241     }
242     return false;
243   }
244 }
245