View Javadoc
1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.cpd;
5   
6   import java.io.File;
7   import java.io.FileInputStream;
8   import java.io.InputStreamReader;
9   import java.io.LineNumberReader;
10  import java.io.Reader;
11  import java.io.StringReader;
12  import java.lang.ref.SoftReference;
13  import java.util.ArrayList;
14  import java.util.List;
15  
16  import net.sourceforge.pmd.PMD;
17  
18  import org.apache.commons.io.IOUtils;
19  
20  public class SourceCode {
21  
22      public static abstract class CodeLoader {
23          private SoftReference<List<String>> code;
24  
25          public List<String> getCode() {
26              List<String> c = null;
27              if (code != null) {
28                  c = code.get();
29              }
30              if (c != null) {
31                  return c;
32              }
33              this.code = new SoftReference<>(load());
34              return code.get();
35          }
36  
37          public abstract String getFileName();
38  
39          protected abstract Reader getReader() throws Exception;
40  
41          protected List<String> load() {
42              LineNumberReader lnr = null;
43              try {
44                  lnr = new LineNumberReader(getReader());
45                  List<String> lines = new ArrayList<>();
46                  String currentLine;
47                  while ((currentLine = lnr.readLine()) != null) {
48                      lines.add(currentLine);
49                  }
50                  return lines;
51              } catch (Exception e) {
52                  e.printStackTrace();
53                  throw new RuntimeException("Problem while reading " + getFileName() + ":" + e.getMessage());
54              } finally {
55                  IOUtils.closeQuietly(lnr);
56              }
57          }
58      }
59  
60      public static class FileCodeLoader extends CodeLoader {
61          private File file;
62          private String encoding;
63  
64          public FileCodeLoader(File file, String encoding) {
65              this.file = file;
66              this.encoding = encoding;
67          }
68  
69          @Override
70          public Reader getReader() throws Exception {
71              return new InputStreamReader(new FileInputStream(file), encoding);
72          }
73  
74          @Override
75          public String getFileName() {
76              return file.getAbsolutePath();
77          }
78      }
79  
80      public static class StringCodeLoader extends CodeLoader {
81          public static final String DEFAULT_NAME = "CODE_LOADED_FROM_STRING";
82  
83          private String code;
84  
85          private String name;
86  
87          public StringCodeLoader(String code) {
88              this(code, DEFAULT_NAME);
89          }
90  
91          public StringCodeLoader(String code, String name) {
92              this.code = code;
93              this.name = name;
94          }
95  
96          @Override
97          public Reader getReader() {
98              return new StringReader(code);
99          }
100 
101         @Override
102         public String getFileName() {
103             return name;
104         }
105     }
106 
107     public static class ReaderCodeLoader extends CodeLoader {
108         public static final String DEFAULT_NAME = "CODE_LOADED_FROM_READER";
109 
110         private Reader code;
111 
112         private String name;
113 
114         public ReaderCodeLoader(Reader code) {
115             this(code, DEFAULT_NAME);
116         }
117 
118         public ReaderCodeLoader(Reader code, String name) {
119             this.code = code;
120             this.name = name;
121         }
122 
123         @Override
124         public Reader getReader() {
125             return code;
126         }
127 
128         @Override
129         public String getFileName() {
130             return name;
131         }
132     }
133 
134     private CodeLoader cl;
135 
136     public SourceCode(CodeLoader cl) {
137         this.cl = cl;
138     }
139 
140     public List<String> getCode() {
141         return cl.getCode();
142     }
143 
144     public StringBuilder getCodeBuffer() {
145         StringBuilder sb = new StringBuilder();
146         List<String> lines = cl.getCode();
147         for (String line : lines) {
148             sb.append(line).append(PMD.EOL);
149         }
150         return sb;
151     }
152 
153     public String getSlice(int startLine, int endLine) {
154         StringBuilder sb = new StringBuilder();
155         List<String> lines = cl.getCode();
156         for (int i = startLine == 0 ? startLine : startLine - 1; i < endLine && i < lines.size(); i++) {
157             if (sb.length() != 0) {
158                 sb.append(PMD.EOL);
159             }
160             sb.append(lines.get(i));
161         }
162         return sb.toString();
163     }
164 
165     public String getFileName() {
166         return cl.getFileName();
167     }
168 }