Remove static initialization of Velocity

Use a RuntimeInstance that is passed through Guice, rather than
relying on the static singleton. This makes configuration easier
as we could later work with different templates that aren't in the
mail directory/namespace by setting up a different RuntimeInstance.

Change-Id: Ib198a40bfe0f8028f7e65e8e021ae1f7d544d608
This commit is contained in:
Shawn O. Pearce
2011-10-07 18:25:11 -07:00
parent 4ec33a2138
commit b92b81371b
4 changed files with 91 additions and 54 deletions

View File

@@ -17,7 +17,6 @@ package com.google.gerrit.server.config;
import static com.google.inject.Scopes.SINGLETON;
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.lifecycle.LifecycleListener;
import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.reviewdb.AuthType;
import com.google.gerrit.rules.PrologModule;
@@ -51,6 +50,7 @@ import com.google.gerrit.server.git.TagCache;
import com.google.gerrit.server.git.TransferConfig;
import com.google.gerrit.server.mail.FromAddressGenerator;
import com.google.gerrit.server.mail.FromAddressGeneratorProvider;
import com.google.gerrit.server.mail.VelocityRuntimeProvider;
import com.google.gerrit.server.patch.PatchListCacheImpl;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.project.AccessControlModule;
@@ -65,51 +65,14 @@ import com.google.gerrit.server.util.IdGenerator;
import com.google.gerrit.server.workflow.FunctionState;
import com.google.inject.Inject;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.RuntimeInstance;
import org.eclipse.jgit.lib.Config;
import java.util.Properties;
/** Starts global state with standard dependencies. */
public class GerritGlobalModule extends FactoryModule {
private final AuthType loginType;
public static class VelocityLifecycle implements LifecycleListener {
private final SitePaths site;
@Inject
VelocityLifecycle(final SitePaths site) {
this.site = site;
}
@Override
public void start() {
String rl = "resource.loader";
String pkg = "org.apache.velocity.runtime.resource.loader";
Properties p = new Properties();
p.setProperty(rl, "file, class");
p.setProperty("file." + rl + ".class", pkg + ".FileResourceLoader");
p.setProperty("file." + rl + ".path", site.mail_dir.getAbsolutePath());
p.setProperty("class." + rl + ".class", pkg + ".ClasspathResourceLoader");
p.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
"org.apache.velocity.runtime.log.SimpleLog4JLogSystem" );
p.setProperty("runtime.log.logsystem.log4j.category", "velocity");
try {
Velocity.init(p);
} catch(Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void stop() {
}
}
@Inject
GerritGlobalModule(final AuthConfig authConfig,
@GerritServerConfig final Config config) {
@@ -172,6 +135,9 @@ public class GerritGlobalModule extends FactoryModule {
bind(MergeQueue.class).to(ChangeMergeQueue.class).in(SINGLETON);
factory(ReloadSubmitQueueOp.Factory.class);
bind(RuntimeInstance.class)
.toProvider(VelocityRuntimeProvider.class)
.in(SINGLETON);
bind(FromAddressGenerator.class).toProvider(
FromAddressGeneratorProvider.class).in(SINGLETON);
@@ -186,7 +152,6 @@ public class GerritGlobalModule extends FactoryModule {
@Override
protected void configure() {
listener().to(CachePool.Lifecycle.class);
listener().to(VelocityLifecycle.class);
}
});
}

View File

@@ -21,7 +21,6 @@ import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.GroupCache;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
@@ -31,6 +30,8 @@ import com.google.gerrit.server.query.change.ChangeQueryRewriter;
import com.google.inject.Inject;
import com.google.inject.Provider;
import org.apache.velocity.runtime.RuntimeInstance;
import javax.annotation.Nullable;
class EmailArguments {
@@ -49,7 +50,7 @@ class EmailArguments {
final ChangeQueryBuilder.Factory queryBuilder;
final Provider<ChangeQueryRewriter> queryRewriter;
final Provider<ReviewDb> db;
final SitePaths site;
final RuntimeInstance velocityRuntime;
@Inject
EmailArguments(GitRepositoryManager server, ProjectCache projectCache,
@@ -61,7 +62,7 @@ class EmailArguments {
AllProjectsName allProjectsName,
ChangeQueryBuilder.Factory queryBuilder,
Provider<ChangeQueryRewriter> queryRewriter, Provider<ReviewDb> db,
SitePaths site) {
RuntimeInstance velocityRuntime) {
this.server = server;
this.projectCache = projectCache;
this.groupCache = groupCache;
@@ -76,6 +77,6 @@ class EmailArguments {
this.queryBuilder = queryBuilder;
this.queryRewriter = queryRewriter;
this.db = db;
this.site = site;
this.velocityRuntime = velocityRuntime;
}
}

View File

@@ -20,8 +20,9 @@ import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.mail.EmailHeader.AddressList;
import org.apache.commons.lang.StringUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.runtime.RuntimeInstance;
import org.eclipse.jgit.util.SystemReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -346,23 +347,30 @@ public abstract class OutgoingEmail {
protected String velocify(String template) throws EmailException {
try {
StringWriter w = new StringWriter();
Velocity.evaluate(velocityContext, w, "OutgoingEmail", template);
args.velocityRuntime.evaluate(velocityContext, w, "OutgoingEmail", template);
return w.toString();
} catch(Exception e) {
throw new EmailException("Velocity template " + template, e);
} catch (Exception e) {
throw new EmailException("Cannot format velocity template: " + template, e);
}
}
protected String velocifyFile(String name) throws EmailException {
if (!Velocity.resourceExists(name)) {
name = "com/google/gerrit/server/mail/" + name;
}
try {
RuntimeInstance runtime = args.velocityRuntime;
Template template;
try {
template = runtime.getTemplate(name, "UTF-8");
} catch (org.apache.velocity.exception.ResourceNotFoundException notFound) {
name = "com/google/gerrit/server/mail/" + name;
template = runtime.getTemplate(name, "UTF-8");
}
StringWriter w = new StringWriter();
Velocity.mergeTemplate(name, "UTF-8", velocityContext, w);
template.merge(velocityContext, w);
return w.toString();
} catch(Exception e) {
throw new EmailException("Velocity template " + name + ".\n", e);
} catch (EmailException e) {
throw e;
} catch (Exception e) {
throw new EmailException("Cannot format velocity template " + name, e);
}
}
}

View File

@@ -0,0 +1,63 @@
// Copyright (C) 2011 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.gerrit.server.mail;
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.ProvisionException;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.RuntimeInstance;
import java.util.Properties;
/** Configures Velocity template engine for sending email. */
public class VelocityRuntimeProvider implements Provider<RuntimeInstance> {
private final SitePaths site;
@Inject
VelocityRuntimeProvider(SitePaths site) {
this.site = site;
}
public RuntimeInstance get() {
String rl = "resource.loader";
String pkg = "org.apache.velocity.runtime.resource.loader";
Properties p = new Properties();
p.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
"org.apache.velocity.runtime.log.SimpleLog4JLogSystem" );
p.setProperty("runtime.log.logsystem.log4j.category", "velocity");
if (site.mail_dir.isDirectory()) {
p.setProperty(rl, "file, class");
p.setProperty("file." + rl + ".class", pkg + ".FileResourceLoader");
p.setProperty("file." + rl + ".path", site.mail_dir.getAbsolutePath());
p.setProperty("class." + rl + ".class", pkg + ".ClasspathResourceLoader");
} else {
p.setProperty(rl, "class");
p.setProperty("class." + rl + ".class", pkg + ".ClasspathResourceLoader");
}
RuntimeInstance ri = new RuntimeInstance();
try {
ri.init(p);
} catch (Exception err) {
throw new ProvisionException("Cannot configure Velocity templates", err);
}
return ri;
}
}