1
2
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<List<String>>(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<String>();
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
108
109 public static class ReaderCodeLoader extends CodeLoader {
110 public static final String DEFAULT_NAME = "CODE_LOADED_FROM_READER";
111
112 private Reader code;
113
114 private String name;
115
116 public ReaderCodeLoader(Reader code) {
117 this(code, DEFAULT_NAME);
118 }
119
120 public ReaderCodeLoader(Reader code, String name) {
121 this.code = code;
122 this.name = name;
123 }
124
125 @Override
126 public Reader getReader() {
127 return code;
128 }
129
130 @Override
131 public String getFileName() {
132 return name;
133 }
134 }
135
136
137
138 private CodeLoader cl;
139
140 public SourceCode(CodeLoader cl) {
141 this.cl = cl;
142 }
143
144 public List<String> getCode() {
145 return cl.getCode();
146 }
147
148 public StringBuilder getCodeBuffer() {
149 StringBuilder sb = new StringBuilder();
150 List<String> lines = cl.getCode();
151 for (String line : lines) {
152 sb.append(line).append(PMD.EOL);
153 }
154 return sb;
155 }
156
157 public String getSlice(int startLine, int endLine) {
158 StringBuilder sb = new StringBuilder();
159 List<String> lines = cl.getCode();
160 for (int i = startLine == 0 ? startLine :startLine - 1; i < endLine && i < lines.size(); i++) {
161 if (sb.length() != 0) {
162 sb.append(PMD.EOL);
163 }
164 sb.append(lines.get(i));
165 }
166 return sb.toString();
167 }
168
169 public String getFileName() {
170 return cl.getFileName();
171 }
172 }