1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.apache.maven.jxr;
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  import java.io.BufferedReader;
52  import java.io.FileInputStream;
53  import java.io.FileOutputStream;
54  import java.io.FileReader;
55  import java.io.FileWriter;
56  import java.io.IOException;
57  import java.io.InputStreamReader;
58  import java.io.ObjectInputStream;
59  import java.io.ObjectOutputStream;
60  import java.io.OutputStreamWriter;
61  import java.io.PrintWriter;
62  import java.io.Reader;
63  import java.io.Serializable;
64  import java.io.Writer;
65  import java.nio.file.Files;
66  import java.nio.file.Path;
67  import java.util.Collections;
68  import java.util.HashSet;
69  import java.util.Hashtable;
70  import java.util.List;
71  import java.util.Locale;
72  import java.util.Map;
73  import java.util.Set;
74  
75  import org.apache.maven.jxr.pacman.ClassType;
76  import org.apache.maven.jxr.pacman.FileManager;
77  import org.apache.maven.jxr.pacman.ImportType;
78  import org.apache.maven.jxr.pacman.JavaFile;
79  import org.apache.maven.jxr.pacman.PackageManager;
80  import org.apache.maven.jxr.pacman.PackageType;
81  import org.apache.maven.jxr.util.SimpleWordTokenizer;
82  import org.apache.maven.jxr.util.StringEntry;
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100 
101 
102 
103 
104 
105 
106 
107 
108 
109 
110 
111 public class JavaCodeTransform implements Serializable {
112     
113     
114     
115 
116     
117 
118 
119     private static final boolean LINE_NUMBERS = true;
120 
121     
122 
123 
124     private static final String COMMENT_START = "<em class=\"jxr_comment\">";
125 
126     
127 
128 
129     private static final String COMMENT_END = "</em>";
130 
131     
132 
133 
134     private static final String JAVADOC_COMMENT_START = "<em class=\"jxr_javadoccomment\">";
135 
136     
137 
138 
139     private static final String JAVADOC_COMMENT_END = "</em>";
140 
141     
142 
143 
144     private static final String STRING_START = "<span class=\"jxr_string\">";
145 
146     
147 
148 
149     private static final String STRING_END = "</span>";
150 
151     
152 
153 
154     private static final String RESERVED_WORD_START = "<strong class=\"jxr_keyword\">";
155 
156     
157 
158 
159     private static final String RESERVED_WORD_END = "</strong>";
160 
161     
162 
163 
164     private static final String STYLESHEET_FILENAME = "stylesheet.css";
165 
166     private static final String[] VALID_URI_SCHEMES = {"http://", "https://", "mailto:"};
167 
168     
169 
170 
171 
172     private static final char[] VALID_URI_CHARS = {
173         '?', '+', '%', '&', ':', '/', '.', '@', '_', ';', '=', '$', ',', '-', '!', '~', '*', '\'', '(', ')'
174     };
175 
176     
177     
178     
179 
180     
181 
182 
183     private Map<String, String> reservedWords = new Hashtable<>();
184 
185     
186 
187 
188     private boolean inMultiLineComment = false;
189 
190     
191 
192 
193     private boolean inJavadocComment = false;
194 
195     
196 
197 
198     private Path currentFilename = null;
199 
200     
201 
202 
203     private String revision = null;
204 
205     
206 
207 
208     private String outputEncoding = null;
209 
210     
211 
212 
213     private Locale locale = null;
214 
215     
216 
217 
218     private Path javadocLinkDir;
219 
220     
221 
222 
223     private final PackageManager packageManager;
224 
225     
226 
227 
228     private final FileManager fileManager;
229 
230     {
231         reservedWords.put("abstract", "abstract");
232         reservedWords.put("do", "do");
233         reservedWords.put("inner", "inner");
234         reservedWords.put("public", "public");
235         reservedWords.put("var", "var");
236         reservedWords.put("boolean", "boolean");
237         reservedWords.put("continue", "continue");
238         reservedWords.put("int", "int");
239         reservedWords.put("return", "return");
240         reservedWords.put("void", "void");
241         reservedWords.put("break", "break");
242         reservedWords.put("else", "else");
243         reservedWords.put("interface", "interface");
244         reservedWords.put("short", "short");
245         reservedWords.put("volatile", "volatile");
246         reservedWords.put("byvalue", "byvalue");
247         reservedWords.put("extends", "extends");
248         reservedWords.put("long", "long");
249         reservedWords.put("static", "static");
250         reservedWords.put("while", "while");
251         reservedWords.put("case", "case");
252         reservedWords.put("final", "final");
253         reservedWords.put("native", "native");
254         reservedWords.put("super", "super");
255         reservedWords.put("transient", "transient");
256         reservedWords.put("cast", "cast");
257         reservedWords.put("float", "float");
258         reservedWords.put("new", "new");
259         reservedWords.put("rest", "rest");
260         reservedWords.put("catch", "catch");
261         reservedWords.put("for", "for");
262         reservedWords.put("null", "null");
263         reservedWords.put("synchronized", "synchronized");
264         reservedWords.put("char", "char");
265         reservedWords.put("finally", "finally");
266         reservedWords.put("operator", "operator");
267         reservedWords.put("this", "this");
268         reservedWords.put("class", "class");
269         reservedWords.put("generic", "generic");
270         reservedWords.put("outer", "outer");
271         reservedWords.put("switch", "switch");
272         reservedWords.put("const", "const");
273         reservedWords.put("goto", "goto");
274         reservedWords.put("package", "package");
275         reservedWords.put("throw", "throw");
276         reservedWords.put("double", "double");
277         reservedWords.put("if", "if");
278         reservedWords.put("private", "private");
279         reservedWords.put("true", "true");
280         reservedWords.put("default", "default");
281         reservedWords.put("import", "import");
282         reservedWords.put("protected", "protected");
283         reservedWords.put("try", "try");
284         reservedWords.put("throws", "throws");
285         reservedWords.put("implements", "implements");
286     }
287 
288     public JavaCodeTransform(PackageManager packageManager, FileManager fileManager) {
289         this.packageManager = packageManager;
290         this.fileManager = fileManager;
291     }
292 
293     
294     
295     
296 
297     
298 
299 
300 
301 
302 
303     private String syntaxHighlight(String line) {
304         return htmlFilter(line);
305     }
306 
307     
308 
309 
310 
311 
312     private void appendHeader(PrintWriter out) {
313         String outputEncoding = this.outputEncoding;
314         if (outputEncoding == null) {
315             outputEncoding = "ISO-8859-1";
316         }
317 
318         
319         out.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" "
320                 + "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
321         out.print("<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"");
322         out.print(locale);
323         out.print("\" lang=\"");
324         out.print(locale);
325         out.println("\">");
326         out.print("<head>");
327         out.print("<meta http-equiv=\"content-type\" content=\"text/html; charset=");
328         out.print(outputEncoding);
329         out.println("\" />");
330 
331         
332         out.print("<title>");
333         try {
334             JavaFile javaFile = fileManager.getFile(this.getCurrentFilename());
335             
336             if (javaFile.getClassType() != null && javaFile.getClassType().getFilename() != null) {
337                 out.print(javaFile.getClassType().getFilename());
338             } else {
339                 out.print(javaFile.getFilename());
340             }
341             out.print(' ');
342         } catch (IOException e) {
343             e.printStackTrace();
344         } finally {
345             out.println("xref</title>");
346         }
347 
348         
349         out.print("<link type=\"text/css\" rel=\"stylesheet\" href=\"");
350         out.print(this.getPackageRoot());
351         out.print(STYLESHEET_FILENAME);
352         out.println("\" />");
353 
354         out.println("</head>");
355         out.println("<body>");
356         out.print(this.getFileOverview());
357 
358         
359         out.println("<pre>");
360     }
361 
362     
363 
364 
365 
366 
367 
368     private void appendFooter(PrintWriter out, String bottom) {
369         out.println("</pre>");
370         out.println("<hr/>");
371         out.print("<div id=\"footer\">");
372         out.print(bottom);
373         out.println("</div>");
374         out.println("</body>");
375         out.println("</html>");
376     }
377 
378     
379 
380 
381 
382 
383 
384 
385 
386 
387 
388 
389 
390     private void transform(
391             Reader sourceReader,
392             Writer destWriter,
393             Locale locale,
394             String outputEncoding,
395             Path javadocLinkDir,
396             String revision,
397             String bottom)
398             throws IOException {
399         this.locale = locale;
400         this.outputEncoding = outputEncoding;
401         this.javadocLinkDir = javadocLinkDir;
402         this.revision = revision;
403 
404         BufferedReader in = new BufferedReader(sourceReader);
405 
406         PrintWriter out = new PrintWriter(destWriter);
407 
408         String line;
409 
410         appendHeader(out);
411 
412         int linenumber = 1;
413         while ((line = in.readLine()) != null) {
414             if (LINE_NUMBERS) {
415                 out.print("<a class=\"jxr_linenumber\" name=\"L" + linenumber + "\" " + "href=\"#L" + linenumber + "\">"
416                         + linenumber + "</a>" + getLineWidth(linenumber));
417             }
418 
419             out.println(this.syntaxHighlight(line));
420 
421             ++linenumber;
422         }
423 
424         appendFooter(out, bottom);
425 
426         out.flush();
427     }
428 
429     
430 
431 
432 
433 
434 
435 
436 
437 
438 
439 
440 
441 
442     public final void transform(
443             Path sourcefile,
444             Path destfile,
445             Locale locale,
446             String inputEncoding,
447             String outputEncoding,
448             Path javadocLinkDir,
449             String revision,
450             String bottom)
451             throws IOException {
452         this.setCurrentFilename(sourcefile);
453 
454         
455         Files.createDirectories(destfile.getParent());
456 
457         try (Reader fr = getReader(sourcefile, inputEncoding);
458                 Writer fw = getWriter(destfile, outputEncoding)) {
459             transform(fr, fw, locale, outputEncoding, javadocLinkDir, revision, bottom);
460         } catch (RuntimeException e) {
461             System.out.println("Unable to processPath " + sourcefile + " => " + destfile);
462             throw e;
463         }
464     }
465 
466     private Writer getWriter(Path destfile, String outputEncoding) throws IOException {
467         Writer fw;
468         if (outputEncoding != null) {
469             fw = new OutputStreamWriter(new FileOutputStream(destfile.toFile()), outputEncoding);
470         } else {
471             fw = new FileWriter(destfile.toFile());
472         }
473         return fw;
474     }
475 
476     private Reader getReader(Path sourcefile, String inputEncoding) throws IOException {
477         Reader fr;
478         if (inputEncoding != null) {
479             fr = new InputStreamReader(new FileInputStream(sourcefile.toFile()), inputEncoding);
480         } else {
481             fr = new FileReader(sourcefile.toFile());
482         }
483         return fr;
484     }
485 
486     
487 
488 
489 
490 
491     private Path getCurrentFilename() {
492         return this.currentFilename;
493     }
494 
495     
496 
497 
498 
499 
500     private void setCurrentFilename(Path filename) {
501         this.currentFilename = filename;
502     }
503 
504     
505 
506 
507 
508 
509     private String getPackageRoot() {
510         StringBuilder buff = new StringBuilder();
511 
512         JavaFile jf;
513 
514         try {
515             jf = fileManager.getFile(this.getCurrentFilename());
516         } catch (IOException e) {
517             e.printStackTrace();
518             return null;
519         }
520 
521         String current = jf.getPackageType().getName();
522 
523         int count = this.getPackageCount(current);
524 
525         for (int i = 0; i < count; ++i) {
526             buff.append("../");
527         }
528 
529         return buff.toString();
530     }
531 
532     
533 
534 
535 
536 
537 
538     private String uriFilter(String line) {
539         for (String scheme : VALID_URI_SCHEMES) {
540             int index = line.indexOf(scheme);
541 
542             if (index != -1) {
543                 int start = index;
544                 int end = -1;
545 
546                 for (int j = start; j < line.length(); ++j) {
547                     char current = line.charAt(j);
548 
549                     if (!Character.isLetterOrDigit(current) && isInvalidURICharacter(current)) {
550                         end = j;
551                         break;
552                     }
553 
554                     end = j;
555                 }
556 
557                 
558                 
559 
560                 if (end != -1) {
561                     String uri = (end + 1 == line.length()) ? line.substring(start) : line.substring(start, end);
562 
563                     line = line.replace(uri, "<a href=\"" + uri + "\" target=\"alexandria_uri\">" + uri + "</a>");
564                 }
565             }
566         }
567 
568         
569         if (!inMultiLineComment && !inJavadocComment) {
570             return jxrFilter(line);
571         }
572 
573         return line;
574     }
575 
576     
577 
578 
579 
580 
581     public final String getRevision() {
582         return this.revision;
583     }
584 
585     
586 
587 
588 
589 
590 
591 
592 
593     private String xrLine(String line, String packageName, ClassType classType) {
594         StringBuilder buff = new StringBuilder(line);
595 
596         String link;
597         String find;
598         String href;
599 
600         if (classType != null) {
601             href = this.getHREF(packageName, classType);
602             find = classType.getName();
603 
604             
605             link = "<a name=\"" + find + "\" href=\"" + href + "\">" + find + "</a>";
606         } else {
607             href = this.getHREF(packageName);
608             find = packageName;
609 
610             
611             link = "<a href=\"" + href + "\">" + find + "</a>";
612         }
613 
614         
615         
616 
617         
618 
619         String replace = link;
620         List<StringEntry> tokens = SimpleWordTokenizer.tokenize(buff.toString(), find);
621 
622         
623         
624         
625         
626         Collections.reverse(tokens);
627 
628         for (StringEntry token : tokens) {
629             int start = token.getIndex();
630             int end = token.getIndex() + find.length();
631 
632             buff.replace(start, end, replace);
633         }
634 
635         return buff.toString();
636     }
637 
638     
639     
640     
641 
642     
643 
644 
645 
646 
647 
648     private String htmlFilter(String line) {
649         if (line == null || line.equals("")) {
650             return "";
651         }
652         line = line.replace("&", "&")
653                 .replace("<", "<")
654                 .replace(">", ">")
655                 .replace("\\\\", "\\")
656                 .replace("\\\"", "\\"")
657                 .replace("'\"'", "'"'");
658         return ongoingMultiLineCommentFilter(line);
659     }
660 
661     
662 
663 
664 
665 
666 
667 
668 
669     private String ongoingMultiLineCommentFilter(String line) {
670         if (line == null || line.equals("")) {
671             return "";
672         }
673         final String[] tags = inJavadocComment
674                 ? new String[] {JAVADOC_COMMENT_START, JAVADOC_COMMENT_END}
675                 : inMultiLineComment ? new String[] {COMMENT_START, COMMENT_END} : null;
676 
677         if (tags == null) {
678             
679             return inlineCommentFilter(line);
680         }
681 
682         int index = line.indexOf("*/");
683         
684         
685         String comment = uriFilter(index < 0 ? line : line.substring(0, index));
686         if (index >= 0) {
687             inJavadocComment = false;
688             inMultiLineComment = false;
689         }
690         StringBuilder buf = new StringBuilder(tags[0]).append(comment);
691 
692         if (index >= 0) {
693             buf.append("*/");
694         }
695         buf.append(tags[1]);
696 
697         if (index >= 0 && line.length() > index + 2) {
698             buf.append(inlineCommentFilter(line.substring(index + 2)));
699         }
700         return buf.toString();
701     }
702 
703     
704 
705 
706 
707 
708 
709 
710 
711 
712     private String inlineCommentFilter(String line) {
713         
714         
715 
716         if (line == null || line.equals("")) {
717             return "";
718         }
719         int index = line.indexOf("//");
720         if ((index >= 0) && !isInsideString(line, index)) {
721             return beginMultiLineCommentFilter(line.substring(0, index))
722                     + COMMENT_START
723                     + line.substring(index)
724                     + COMMENT_END;
725         }
726 
727         return beginMultiLineCommentFilter(line);
728     }
729 
730     
731 
732 
733 
734 
735 
736 
737     private String beginMultiLineCommentFilter(String line) {
738         
739         
740 
741         if (line == null || line.equals("")) {
742             return "";
743         }
744 
745         int index = line.indexOf("/*");
746         
747         if ((index > -1) && !isInsideString(line, index)) {
748             String fromIndex = line.substring(index);
749             if (fromIndex.startsWith("/**") && !(fromIndex.startsWith("/**/"))) {
750                 inJavadocComment = true;
751             } else {
752                 inMultiLineComment = true;
753             }
754             
755             
756             
757             
758             return stringFilter(line.substring(0, index)) + ongoingMultiLineCommentFilter(fromIndex);
759         }
760 
761         
762         
763         else {
764             return stringFilter(line);
765         }
766     }
767 
768     
769 
770 
771 
772 
773 
774     private String stringFilter(String line) {
775         if (line == null || line.equals("")) {
776             return "";
777         }
778         StringBuilder buf = new StringBuilder();
779         if (line.indexOf('"') <= -1) {
780             return keywordFilter(line);
781         }
782         int start = 0;
783         int startStringIndex = -1;
784         int endStringIndex = -1;
785         int tempIndex;
786         
787         while ((tempIndex = line.indexOf('"')) > -1) {
788             
789             if (startStringIndex == -1) {
790                 startStringIndex = 0;
791                 buf.append(stringFilter(line.substring(start, tempIndex)));
792                 buf.append(STRING_START).append('"');
793                 line = line.substring(tempIndex + 1);
794             }
795             
796             else {
797                 startStringIndex = -1;
798                 endStringIndex = tempIndex;
799                 buf.append(line, 0, endStringIndex + 1);
800                 buf.append(STRING_END);
801                 line = line.substring(endStringIndex + 1);
802             }
803         }
804 
805         buf.append(keywordFilter(line));
806 
807         return buf.toString();
808     }
809 
810     
811 
812 
813 
814 
815 
816     private String keywordFilter(String line) {
817         final String classKeyword = "class";
818 
819         if (line == null || line.equals("")) {
820             return "";
821         }
822         StringBuilder buf = new StringBuilder();
823         int i = 0;
824         char ch;
825         StringBuilder temp = new StringBuilder();
826         while (i < line.length()) {
827             temp.setLength(0);
828             ch = line.charAt(i);
829             while (i < line.length() && ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))) {
830                 temp.append(ch);
831                 i++;
832                 if (i < line.length()) {
833                     ch = line.charAt(i);
834                 }
835             }
836             String tempString = temp.toString();
837 
838             
839             if (classKeyword.equals(tempString) && ch == '=') {
840                 i++;
841             } else if (reservedWords.containsKey(tempString)) {
842                 line = line.substring(0, i - tempString.length())
843                         + RESERVED_WORD_START
844                         + tempString
845                         + RESERVED_WORD_END
846                         + line.substring(i);
847                 i += (RESERVED_WORD_START.length() + RESERVED_WORD_END.length());
848             } else {
849                 i++;
850             }
851         }
852         buf.append(line);
853 
854         return uriFilter(buf.toString());
855     }
856 
857     
858 
859 
860 
861 
862 
863 
864 
865     private boolean isInsideString(String line, int position) {
866         if (line.indexOf('"') < 0) {
867             return false;
868         }
869         int index;
870         String left = line.substring(0, position);
871         String right = line.substring(position);
872         int leftCount = 0;
873         int rightCount = 0;
874         while ((index = left.indexOf('"')) > -1) {
875             leftCount++;
876             left = left.substring(index + 1);
877         }
878         while ((index = right.indexOf('"')) > -1) {
879             rightCount++;
880             right = right.substring(index + 1);
881         }
882         return (rightCount % 2 != 0 && leftCount % 2 != 0);
883     }
884 
885     
886 
887 
888 
889     final void writeObject(ObjectOutputStream oos) throws IOException {
890         oos.defaultWriteObject();
891     }
892 
893     
894 
895 
896 
897 
898     final void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
899         ois.defaultReadObject();
900     }
901 
902     
903 
904 
905 
906 
907     private String getFileOverview() {
908         StringBuilder overview = new StringBuilder();
909 
910         
911         if (javadocLinkDir != null) {
912             overview.append("<div id=\"overview\">");
913             
914             Path javadocURI;
915 
916             try {
917                 JavaFile jf = fileManager.getFile(this.getCurrentFilename());
918 
919                 javadocURI =
920                         javadocLinkDir.resolve(jf.getPackageType().getName().replace('.', '/'));
921                 
922                 String fileName;
923                 if (jf.getClassType() != null && jf.getClassType().getFilename() != null) {
924                     fileName = jf.getClassType().getFilename();
925                 } else {
926                     fileName = jf.getFilename();
927                 }
928                 javadocURI = javadocURI.resolve(fileName + ".html");
929 
930                 String javadocHREF = "<a href=\"" + javadocURI.toString().replace('\\', '/') + "\">View Javadoc</a>";
931 
932                 
933                 overview.append(javadocHREF);
934             } catch (IOException e) {
935                 e.printStackTrace();
936             }
937 
938             overview.append("</div>");
939         }
940 
941         return overview.toString();
942     }
943 
944     
945 
946 
947 
948 
949 
950     private String getLineWidth(int linenumber) {
951         if (linenumber < 10) {
952             return "   ";
953         } else if (linenumber < 100) {
954             return "  ";
955         } else {
956             return " ";
957         }
958     }
959 
960     
961 
962 
963 
964 
965 
966     private String jxrFilter(String line) {
967         JavaFile jf;
968 
969         try {
970             
971             if (this.getCurrentFilename() == null) {
972                 return line;
973             }
974 
975             jf = fileManager.getFile(this.getCurrentFilename());
976         } catch (IOException e) {
977             e.printStackTrace();
978             return line;
979         }
980 
981         Set<String> packages = new HashSet<>();
982 
983         
984         for (ImportType importType : jf.getImportTypes()) {
985             packages.add(importType.getPackage());
986         }
987 
988         
989         packages.add(jf.getPackageType().getName());
990 
991         List<StringEntry> words = SimpleWordTokenizer.tokenize(line);
992 
993         
994         for (StringEntry word : words) {
995             for (String pkg : packages) {
996                 
997                 
998 
999                 PackageType currentImport = packageManager.getPackageType(pkg);
1000 
1001                 
1002                 
1003                 
1004 
1005                 if (currentImport == null) {
1006                     continue;
1007                 }
1008 
1009                 
1010 
1011                 
1012                 
1013 
1014                 String wordName = word.toString();
1015 
1016                 if (wordName.indexOf('.') != -1) {
1017                     
1018                     
1019 
1020                     String fqpnPackage = wordName.substring(0, wordName.lastIndexOf('.'));
1021                     String fqpnClass = wordName.substring(wordName.lastIndexOf('.') + 1);
1022 
1023                     
1024                     
1025                     
1026 
1027                     PackageType pt = packageManager.getPackageType(fqpnPackage);
1028 
1029                     if (pt != null) {
1030                         ClassType ct = pt.getClassType(fqpnClass);
1031 
1032                         if (ct != null) {
1033                             
1034                             
1035                             
1036 
1037                             line = xrLine(line, pt.getName(), ct);
1038                         }
1039                     }
1040 
1041                     if (fqpnPackage.equals(currentImport.getName()) && currentImport.getClassType(fqpnClass) != null) {
1042                         
1043                         
1044                         line = xrLine(line, pkg, currentImport.getClassType(fqpnClass));
1045                     }
1046                 } else if (currentImport.getClassType(wordName) != null) {
1047                     line = xrLine(line, pkg, currentImport.getClassType(wordName));
1048                 }
1049             }
1050         }
1051 
1052         return importFilter(line);
1053     }
1054 
1055     
1056 
1057 
1058 
1059 
1060 
1061 
1062     private String getHREF(String dest, ClassType jc) {
1063         StringBuilder href = new StringBuilder();
1064 
1065         
1066         href.append(this.getPackageRoot());
1067 
1068         
1069         dest = dest.replace(".*", "").replace('.', '/');
1070 
1071         href.append(dest);
1072 
1073         
1074         if (jc != null) {
1075             href.append('/');
1076             href.append(jc.getFilename());
1077             href.append(".html");
1078             href.append('#');
1079             href.append(jc.getName());
1080         }
1081 
1082         return href.toString();
1083     }
1084 
1085     
1086 
1087 
1088 
1089 
1090 
1091     private String getHREF(String dest) {
1092         return getHREF(dest, null);
1093     }
1094 
1095     
1096 
1097 
1098 
1099 
1100 
1101 
1102 
1103 
1104 
1105 
1106     private int getPackageCount(String packageName) {
1107         if (packageName == null) {
1108             return 0;
1109         }
1110 
1111         int count = 0;
1112         int index = 0;
1113 
1114         while (true) {
1115             index = packageName.indexOf('.', index);
1116 
1117             if (index == -1) {
1118                 break;
1119             }
1120             ++index;
1121             ++count;
1122         }
1123 
1124         
1125         ++count;
1126 
1127         return count;
1128     }
1129 
1130     
1131 
1132 
1133 
1134 
1135 
1136     private String importFilter(String line) {
1137         int start = -1;
1138 
1139         
1140 
1141 
1142 
1143 
1144         boolean isPackage = line.trim().startsWith("package ");
1145         boolean isImport = line.trim().startsWith("import ");
1146 
1147         if (isImport || isPackage) {
1148             start = line.trim().indexOf(' ');
1149         }
1150 
1151         if (start != -1) {
1152             
1153             String pkg = line.substring(start).trim();
1154 
1155             
1156             String classname = null;
1157 
1158             if (pkg.contains(".*")) {
1159                 pkg = pkg.replace(".*", "");
1160             } else if (!isPackage) {
1161                 
1162 
1163                 String packageLine = pkg;
1164 
1165                 
1166                 
1167                 
1168                 
1169                 
1170                 
1171                 
1172 
1173                 int a = packageLine.lastIndexOf('.') + 1;
1174                 int b = packageLine.length() - 1;
1175 
1176                 if (a > b + 1) {
1177                     classname = packageLine.substring(packageLine.lastIndexOf('.') + 1, packageLine.length() - 1);
1178 
1179                     int end = pkg.lastIndexOf('.');
1180                     if (end == -1) {
1181                         end = pkg.length() - 1;
1182                     }
1183 
1184                     pkg = pkg.substring(0, end);
1185                 }
1186             }
1187 
1188             pkg = pkg.replace(";", "");
1189             String pkgHREF = getHREF(pkg);
1190             
1191 
1192             if (packageManager.getPackageType(pkg) != null || isPackage) {
1193                 
1194                 if (classname != null) {
1195                     line = line.replace(
1196                             classname, "<a href=\"" + pkgHREF + '/' + classname + ".html" + "\">" + classname + "</a>");
1197                 }
1198 
1199                 
1200                 line = line.replace(pkg, "<a href=\"" + pkgHREF + '/' + DirectoryIndexer.INDEX + "\">" + pkg + "</a>");
1201             }
1202         }
1203 
1204         return line;
1205     }
1206 
1207     
1208 
1209 
1210 
1211 
1212 
1213     private boolean isInvalidURICharacter(char c) {
1214         for (char validUriChar : VALID_URI_CHARS) {
1215             if (validUriChar == c) {
1216                 return false;
1217             }
1218         }
1219 
1220         return true;
1221     }
1222 }