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 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 }