001    /*
002     * SonarQube, open source software quality management tool.
003     * Copyright (C) 2008-2014 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * SonarQube 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     * SonarQube 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 License
017     * along with this program; if not, write to the Free Software Foundation,
018     * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019     */
020    package org.sonar.api.web;
021    
022    import org.apache.commons.io.FileUtils;
023    import org.apache.commons.io.IOUtils;
024    import org.sonar.api.utils.SonarException;
025    
026    import java.io.File;
027    import java.io.FileNotFoundException;
028    import java.io.IOException;
029    import java.io.InputStream;
030    
031    /**
032     * It's useful in development environment to see browser rendering in real time while editing the template. To do that, just
033     * return an absolute path in the method getTemplatePath() :<br/>
034     * <pre>
035     * <code>
036     *   protected String getTemplatePath() {
037     *    return "/tmp/sample_dashboard_widget.erb";
038     *   }
039     * </code>
040     * </pre>
041     * Build and deploy the plugin in /extensions/plugins. The file /tmp/sample_dashboard_widget.erb will be reloaded on each request.
042     * <p/>
043     * <br/>
044     * In production environment, you have to return the classloader path, for example "/org/sonar/myplugin/sample_dashboard_widget.erb".
045     *
046     * @since 1.11
047     */
048    public abstract class AbstractRubyTemplate {
049    
050      private String cache = null;
051    
052      public String getTemplate() {
053        String result = loadTemplateFromCache();
054        try {
055          if (result == null) {
056            result = loadTemplateFromClasspath();
057          }
058          if (result == null) {
059            result = loadTemplateFromAbsolutePath();
060          }
061          return result;
062    
063        } catch (IOException e) {
064          throw new SonarException("Can not read the file " + getTemplatePath(), e);
065        }
066      }
067    
068      private String loadTemplateFromAbsolutePath() throws IOException {
069        File file = new File(getTemplatePath());
070        if (file.exists()) {
071          // the result is not cached
072          return FileUtils.readFileToString(file);
073        }
074        throw new FileNotFoundException(getTemplatePath());
075      }
076    
077      private String loadTemplateFromClasspath() throws IOException {
078        InputStream input = getClass().getResourceAsStream(getTemplatePath());
079        try {
080          if (input != null) {
081            cache = IOUtils.toString(input);
082            return cache;
083          }
084        } finally {
085          IOUtils.closeQuietly(input);
086        }
087        return null;
088      }
089    
090      protected String loadTemplateFromCache() {
091        return cache;
092      }
093    
094      /**
095       * the path of the template. In production environment, it's the classloader path (for example "/org/sonar/my_template.erb").
096       * In dev mode, it's useful to return an absolute path (for example C:/temp/my_template.erb). In such a case the result is not cached.
097       */
098      protected abstract String getTemplatePath();
099    
100    }