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 */ 024package net.sourceforge.pmd.cpd; 025 026import com.google.common.io.Closeables; 027 028import java.io.*; 029import java.lang.ref.SoftReference; 030import java.util.ArrayList; 031import java.util.List; 032 033/** 034 * <p>Not intended to be instantiated by clients.</p> 035 * 036 * @since 2.2 037 */ 038public class SourceCode { 039 040 public static final String EOL = System.getProperty("line.separator", "\n"); 041 042 public abstract static class CodeLoader { 043 private SoftReference<List<String>> code; 044 045 public List<String> getCode() { 046 List<String> c = null; 047 if (code != null) { 048 c = code.get(); 049 } 050 if (c != null) { 051 return c; 052 } 053 this.code = new SoftReference<List<String>>(load()); 054 return code.get(); 055 } 056 057 public abstract String getFileName(); 058 059 protected abstract Reader getReader() throws Exception; 060 061 protected List<String> load() { 062 LineNumberReader lnr = null; 063 try { 064 lnr = new LineNumberReader(getReader()); 065 List<String> lines = new ArrayList<String>(); 066 String currentLine; 067 while ((currentLine = lnr.readLine()) != null) { 068 lines.add(currentLine); 069 } 070 return lines; 071 } catch (Exception e) { 072 throw new RuntimeException("Problem while reading " + getFileName() + ":" + e.getMessage(), e); 073 } finally { 074 Closeables.closeQuietly(lnr); 075 } 076 } 077 } 078 079 public static class FileCodeLoader extends CodeLoader { 080 private File file; 081 private String encoding; 082 083 public FileCodeLoader(File file, String encoding) { 084 this.file = file; 085 this.encoding = encoding; 086 } 087 088 @Override 089 public Reader getReader() throws Exception { 090 return new InputStreamReader(new FileInputStream(file), encoding); 091 } 092 093 @Override 094 public String getFileName() { 095 return this.file.getAbsolutePath(); 096 } 097 } 098 099 public static class StringCodeLoader extends CodeLoader { 100 public static final String DEFAULT_NAME = "CODE_LOADED_FROM_STRING"; 101 102 private String source_code; 103 104 private String name; 105 106 public StringCodeLoader(String code) { 107 this(code, DEFAULT_NAME); 108 } 109 110 public StringCodeLoader(String code, String name) { 111 this.source_code = code; 112 this.name = name; 113 } 114 115 @Override 116 public Reader getReader() { 117 return new StringReader(source_code); 118 } 119 120 @Override 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}