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    }