Velocity: use resource loader that loads template content directly from FileTemplateManager instead of disk

This commit is contained in:
Eugene Zhuravlev
2011-04-21 14:30:50 +02:00
parent 88d7f3e04d
commit ccf0506983
3 changed files with 84 additions and 94 deletions
@@ -1,5 +1,6 @@
package com.intellij.ide.fileTemplates;
import com.intellij.ide.fileTemplates.impl.CustomFileTemplate;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.roots.ContentEntry;
@@ -17,41 +18,57 @@ import com.intellij.util.properties.EncodingAwareProperties;
import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.*;
@SuppressWarnings({"HardCodedStringLiteral"})
public class FileTemplatesTest extends IdeaTestCase {
public void testAllTemplates() throws Exception {
File testsDir = new File(PathManagerEx.getTestDataPath()+"/ide/fileTemplates");
FileTemplateUtil.addResourcesDir(testsDir);
final File testsDir = new File(PathManagerEx.getTestDataPath()+"/ide/fileTemplates");
final String txt = ".txt";
File[] children = testsDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".out"+txt);
final String includeTemplateName = "include1.inc";
final String includeTemplateExtension = "txt";
final String customIncludeFileName = includeTemplateName + "." + includeTemplateExtension;
final File customInclude = new File(testsDir, customIncludeFileName);
final String includeText = FileUtil.loadFile(customInclude, FileTemplate.ourEncoding);
final FileTemplateManager templateManager = FileTemplateManager.getInstance();
final ArrayList<FileTemplate> originalIncludes = new ArrayList<FileTemplate>(Arrays.asList(templateManager.getAllPatterns()));
try {
// configure custom include
final List<FileTemplate> allIncludes = new ArrayList<FileTemplate>(originalIncludes);
final CustomFileTemplate custom = new CustomFileTemplate(includeTemplateName, includeTemplateExtension);
custom.setText(includeText);
allIncludes.add(custom);
templateManager.setTemplates(FileTemplateManager.INCLUDES_TEMPLATES_CATEGORY, allIncludes);
final String txt = ".txt";
File[] children = testsDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".out"+txt);
}
});
assertTrue(children.length > 0);
for (File resultFile : children) {
String name = resultFile.getName();
String base = name.substring(0, name.length() - txt.length() - ".out".length());
File propFile = new File(resultFile.getParent(), base + ".prop" + txt);
File inFile = new File(resultFile.getParent(), base + txt);
String inputText = FileUtil.loadFile(inFile, FileTemplate.ourEncoding);
String outputText = FileUtil.loadFile(resultFile, FileTemplate.ourEncoding);
EncodingAwareProperties properties = new EncodingAwareProperties();
properties.load(propFile, FileTemplate.ourEncoding);
System.out.println(resultFile.getName());
doTestTemplate(inputText, properties, outputText, resultFile.getParent());
}
});
assertTrue(children.length > 0);
for (File resultFile : children) {
String name = resultFile.getName();
String base = name.substring(0, name.length() - txt.length() - ".out".length());
File propFile = new File(resultFile.getParent(), base + ".prop" + txt);
File inFile = new File(resultFile.getParent(), base + txt);
String inputText = FileUtil.loadFile(inFile, FileTemplate.ourEncoding);
String outputText = FileUtil.loadFile(resultFile, FileTemplate.ourEncoding);
EncodingAwareProperties properties = new EncodingAwareProperties();
properties.load(propFile, FileTemplate.ourEncoding);
System.out.println(resultFile.getName());
doTestTemplate(inputText, properties, outputText, resultFile.getParent());
}
finally {
templateManager.setTemplates(FileTemplateManager.INCLUDES_TEMPLATES_CATEGORY, originalIncludes);
}
}
@@ -18,7 +18,6 @@ package com.intellij.ide.fileTemplates;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
@@ -27,6 +26,7 @@ import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.fileTypes.ex.FileTypeManagerEx;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.ClassLoaderUtil;
import com.intellij.openapi.util.ThrowableComputable;
@@ -35,6 +35,7 @@ import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.util.ArrayUtil;
import org.apache.commons.collections.ExtendedProperties;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.ResourceNotFoundException;
@@ -48,15 +49,13 @@ import org.apache.velocity.runtime.parser.node.ASTReference;
import org.apache.velocity.runtime.parser.node.ASTSetDirective;
import org.apache.velocity.runtime.parser.node.Node;
import org.apache.velocity.runtime.parser.node.SimpleNode;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.apache.velocity.runtime.resource.loader.FileResourceLoader;
import org.apache.velocity.runtime.resource.Resource;
import org.apache.velocity.runtime.resource.loader.ResourceLoader;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import java.io.*;
import java.lang.reflect.Field;
import java.util.*;
/**
@@ -64,7 +63,6 @@ import java.util.*;
*/
public class FileTemplateUtil{
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.fileTemplates.FileTemplateUtil");
@NonNls private static final String FILE_RESOURCE_LOADER_INSTANCE = "file.resource.loader.instance";
private static final CreateFromTemplateHandler ourDefaultCreateFromTemplateHandler = new DefaultCreateFromTemplateHandler();
private FileTemplateUtil() {
@@ -72,9 +70,7 @@ public class FileTemplateUtil{
static {
try{
File modifiedPatternsPath = new File(PathManager.getConfigPath());
modifiedPatternsPath = new File(modifiedPatternsPath, "fileTemplates");
modifiedPatternsPath = new File(modifiedPatternsPath, "includes");
final FileTemplateManager templateManager = FileTemplateManager.getInstance();
LogSystem emptyLogSystem = new LogSystem() {
public void init(RuntimeServices runtimeServices) throws Exception {
@@ -85,13 +81,41 @@ public class FileTemplateUtil{
}
};
Velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, emptyLogSystem);
Velocity.setProperty(RuntimeConstants.RESOURCE_LOADER, "file,class");
//todo[myakovlev] implement my own Loader, with ability to load templates from classpath
Velocity.setProperty(FILE_RESOURCE_LOADER_INSTANCE, new FileResourceLoader());
Velocity.setProperty("class.resource.loader.class", MyClasspathResourceLoader.class.getName());
Velocity.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, modifiedPatternsPath.getAbsolutePath());
Velocity.setProperty(RuntimeConstants.INPUT_ENCODING, FileTemplate.ourEncoding);
Velocity.setProperty(RuntimeConstants.PARSER_POOL_SIZE, 3);
Velocity.setProperty(RuntimeConstants.RESOURCE_LOADER, "includes");
Velocity.setProperty("includes.resource.loader.instance", new ResourceLoader() {
public void init(ExtendedProperties configuration) {
}
public InputStream getResourceStream(String resourceName) throws ResourceNotFoundException {
final FileTemplate include = templateManager.getPattern(resourceName);
if (include == null) {
throw new ResourceNotFoundException("Template not found: " + resourceName);
}
final String lineSeparatorToUse = CodeStyleSettingsManager.getSettings(ProjectManagerEx.getInstanceEx().getDefaultProject()).getLineSeparator();
String text = include.getText();
if (!lineSeparatorToUse.equals("\n")){
text = StringUtil.convertLineSeparators(text, lineSeparatorToUse);
}
try {
return new ByteArrayInputStream(text.getBytes(FileTemplate.ourEncoding));
}
catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
public boolean isSourceModified(Resource resource) {
return true;
}
public long getLastModified(Resource resource) {
return 0L;
}
});
Velocity.init();
}
catch (Exception e){
@@ -223,20 +247,6 @@ public class FileTemplateUtil{
return stringWriter.toString();
}
@TestOnly
public static void addResourcesDir(File dir) {
final FileResourceLoader loader = (FileResourceLoader)Velocity.getProperty(FILE_RESOURCE_LOADER_INSTANCE);
try {
Field pathsField = FileResourceLoader.class.getDeclaredField("paths");
pathsField.setAccessible(true);
Collection<String> paths = (Collection)pathsField.get(loader);
paths.add(dir.getAbsolutePath());
}
catch (Exception e) {
LOG.error(e);
}
}
public static PsiElement createFromTemplate(@NotNull final FileTemplate template,
@NonNls @Nullable final String fileName,
@Nullable Properties props,
@@ -331,15 +341,6 @@ public class FileTemplateUtil{
}
public static class MyClasspathResourceLoader extends ClasspathResourceLoader{
private static final String INCLUDES_PATH = "fileTemplates/includes/";
private static final String FT_EXTENSION = ".ft";
public synchronized InputStream getResourceStream(String name) throws ResourceNotFoundException{
return super.getResourceStream(INCLUDES_PATH + name + FT_EXTENSION);
}
}
public static boolean canCreateFromTemplate (PsiDirectory[] dirs, FileTemplate template) {
FileType fileType = FileTypeManagerEx.getInstanceEx().getFileTypeByExtension(template.getExtension());
if (fileType.equals(FileTypes.UNKNOWN)) return false;
@@ -653,16 +653,6 @@ public class FileTemplateManagerImpl extends FileTemplateManager implements Expo
return myPatternsManager.findTemplateByName(name);
}
//public FileTemplate addPattern(@NotNull @NonNls String name, @NotNull @NonNls String extension) {
// LOG.assertTrue(myPatternsManager != null);
// return myPatternsManager.addTemplate(name, extension);
//}
//public void removePattern(@NotNull FileTemplate template, boolean fromDiskOnly) {
// LOG.assertTrue(myPatternsManager != null);
// myPatternsManager.removeTemplate(template, fromDiskOnly);
//}
@NotNull
public FileTemplate[] getAllCodeTemplates() {
final Collection<FileTemplateBase> templates = myCodeTemplatesManager.getAllTemplates(false);
@@ -675,24 +665,6 @@ public class FileTemplateManagerImpl extends FileTemplateManager implements Expo
return templates.toArray(new FileTemplate[templates.size()]);
}
//@NotNull
//public FileTemplate addCodeTemplate(@NotNull @NonNls String name, @NotNull @NonNls String extension) {
// return myCodeTemplatesManager.addTemplate(name, extension);
//}
//@NotNull
//public FileTemplate addJ2eeTemplate(@NotNull @NonNls String name, @NotNull @NonNls String extension) {
// return myJ2eeTemplatesManager.addTemplate(name, extension);
//}
//public void removeCodeTemplate(@NotNull FileTemplate template, boolean fromDiskOnly) {
// myCodeTemplatesManager.removeTemplate(template, fromDiskOnly);
//}
//
//public void removeJ2eeTemplate(@NotNull FileTemplate template, boolean fromDiskOnly) {
// myJ2eeTemplatesManager.removeTemplate(template, fromDiskOnly);
//}
public void setTemplates(@NotNull String templatesCategory, Collection<FileTemplate> templates) {
for (FTManager manager : myAllManagers) {
if (templatesCategory.equals(manager.getName())) {