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 */
020package org.sonar.api.web;
021
022import org.apache.commons.io.FileUtils;
023import org.apache.commons.io.IOUtils;
024import org.sonar.api.utils.SonarException;
025
026import java.io.File;
027import java.io.FileNotFoundException;
028import java.io.IOException;
029import 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 */
048public 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}