001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
019 */
020
021 /**
022 * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
023 */
024 package net.sourceforge.pmd.cpd;
025
026 import java.io.*;
027 import java.lang.ref.SoftReference;
028 import java.util.ArrayList;
029 import java.util.List;
030
031 /**
032 * <p>Not intended to be instantiated by clients.</p>
033 *
034 * @since 2.2
035 */
036 public class SourceCode {
037
038 public static final String EOL = System.getProperty("line.separator", "\n");
039
040 public abstract static class CodeLoader {
041 private SoftReference<List<String>> code;
042
043 public List<String> getCode() {
044 List<String> c = null;
045 if (code != null) {
046 c = code.get();
047 }
048 if (c != null) {
049 return c;
050 }
051 this.code = new SoftReference<List<String>>(load());
052 return code.get();
053 }
054
055 public abstract String getFileName();
056
057 protected abstract Reader getReader() throws Exception;
058
059 protected List<String> load() {
060 LineNumberReader lnr = null;
061 try {
062 lnr = new LineNumberReader(getReader());
063 List<String> lines = new ArrayList<String>();
064 String currentLine;
065 while ((currentLine = lnr.readLine()) != null) {
066 lines.add(currentLine);
067 }
068 return lines;
069 } catch (Exception e) {
070 throw new RuntimeException("Problem while reading " + getFileName() + ":" + e.getMessage(), e);
071 } finally {
072 try {
073 if (lnr != null) {
074 lnr.close();
075 }
076 } catch (Exception e) {
077 throw new RuntimeException("Problem while reading " + getFileName() + ":" + e.getMessage(), e);
078 }
079 }
080 }
081 }
082
083 public static class FileCodeLoader extends CodeLoader {
084 private File file;
085 private String encoding;
086
087 public FileCodeLoader(File file, String encoding) {
088 this.file = file;
089 this.encoding = encoding;
090 }
091
092 public Reader getReader() throws Exception {
093 return new InputStreamReader(new FileInputStream(file), encoding);
094 }
095
096 public String getFileName() {
097 return this.file.getAbsolutePath();
098 }
099 }
100
101 public static class StringCodeLoader extends CodeLoader {
102 public static final String DEFAULT_NAME = "CODE_LOADED_FROM_STRING";
103
104 private String source_code;
105
106 private String name;
107
108 public StringCodeLoader(String code) {
109 this(code, DEFAULT_NAME);
110 }
111
112 public StringCodeLoader(String code, String name) {
113 this.source_code = code;
114 this.name = name;
115 }
116
117 public Reader getReader() {
118 return new StringReader(source_code);
119 }
120
121 public String getFileName() {
122 return name;
123 }
124 }
125
126 private CodeLoader cl;
127
128 public SourceCode(CodeLoader cl) {
129 this.cl = cl;
130 }
131
132 public List<String> getCode() {
133 return cl.getCode();
134 }
135
136 public StringBuffer getCodeBuffer() {
137 StringBuffer sb = new StringBuffer();
138 List<String> lines = cl.getCode();
139 for (String line : lines) {
140 sb.append(line);
141 sb.append(EOL);
142 }
143 return sb;
144 }
145
146 public String getSlice(int startLine, int endLine) {
147 StringBuffer sb = new StringBuffer();
148 List lines = cl.getCode();
149 for (int i = (startLine == 0 ? startLine : startLine - 1); i < endLine && i < lines.size(); i++) {
150 if (sb.length() != 0) {
151 sb.append(EOL);
152 }
153 sb.append((String) lines.get(i));
154 }
155 return sb.toString();
156 }
157
158 /**
159 * Within Sonar Ecosystem - absolute path to file containing code,
160 * whereas in fact existence of such file not guaranteed - see {@link StringCodeLoader}.
161 */
162 public String getFileName() {
163 return cl.getFileName();
164 }
165 }