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 net.sourceforge.pmd.PMD;
7
8 import java.io.File;
9 import java.io.LineNumberReader;
10 import java.io.Reader;
11 import java.io.StringReader;
12 import java.io.FileInputStream;
13 import java.io.InputStreamReader;
14 import java.lang.ref.SoftReference;
15 import java.util.ArrayList;
16 import java.util.List;
17
18 public class SourceCode {
19
20 public static abstract class CodeLoader {
21 private SoftReference<List<String>> code;
22
23 public List<String> getCode() {
24 List<String> c = null;
25 if (code != null) {
26 c = code.get();
27 }
28 if (c != null) {
29 return c;
30 }
31 this.code = new SoftReference<List<String>>(load());
32 return code.get();
33 }
34
35 public abstract String getFileName();
36
37 protected abstract Reader getReader() throws Exception;
38
39 protected List<String> load() {
40 LineNumberReader lnr = null;
41 try {
42 lnr = new LineNumberReader(getReader());
43 List<String> lines = new ArrayList<String>();
44 String currentLine;
45 while ((currentLine = lnr.readLine()) != null) {
46 lines.add(currentLine);
47 }
48 return lines;
49 } catch (Exception e) {
50 e.printStackTrace();
51 throw new RuntimeException("Problem while reading " + getFileName() + ":" + e.getMessage());
52 } finally {
53 try {
54 if (lnr != null)
55 lnr.close();
56 } catch (Exception e) {
57 throw new RuntimeException("Problem while reading " + getFileName() + ":" + e.getMessage());
58 }
59 }
60 }
61 }
62
63 public static class FileCodeLoader extends CodeLoader {
64 private File file;
65 private String encoding;
66
67 public FileCodeLoader(File file, String encoding) {
68 this.file = file;
69 this.encoding = encoding;
70 }
71
72 public Reader getReader() throws Exception {
73 return new InputStreamReader(new FileInputStream(file), encoding);
74 }
75
76 public String getFileName() {
77 return this.file.getAbsolutePath();
78 }
79 }
80
81 public static class StringCodeLoader extends CodeLoader {
82 public static final String DEFAULT_NAME = "CODE_LOADED_FROM_STRING";
83
84 private String source_code;
85
86 private String name;
87
88 public StringCodeLoader(String code) {
89 this(code, DEFAULT_NAME);
90 }
91
92 public StringCodeLoader(String code, String name) {
93 this.source_code = code;
94 this.name = name;
95 }
96
97 public Reader getReader() {
98 return new StringReader(source_code);
99 }
100
101 public String getFileName() {
102 return name;
103 }
104 }
105
106 private CodeLoader cl;
107
108 public SourceCode(CodeLoader cl) {
109 this.cl = cl;
110 }
111
112 public List<String> getCode() {
113 return cl.getCode();
114 }
115
116 public StringBuffer getCodeBuffer() {
117 StringBuffer sb = new StringBuffer();
118 List<String> lines = cl.getCode();
119 for ( String line : lines ) {
120 sb.append(line);
121 sb.append(PMD.EOL);
122 }
123 return sb;
124 }
125
126 public String getSlice(int startLine, int endLine) {
127 StringBuffer sb = new StringBuffer();
128 List lines = cl.getCode();
129 for (int i = (startLine == 0 ? startLine :startLine - 1); i < endLine && i < lines.size(); i++) {
130 if (sb.length() != 0) {
131 sb.append(PMD.EOL);
132 }
133 sb.append((String) lines.get(i));
134 }
135 return sb.toString();
136 }
137
138 public String getFileName() {
139 return cl.getFileName();
140 }
141 }