All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.onetwo.boot.plugin.ftl.PluginTemplateLoader Maven / Gradle / Ivy

package org.onetwo.boot.plugin.ftl;

import java.io.IOException;
import java.io.Reader;
import java.util.Collections;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;

import org.onetwo.boot.plugin.core.PluginManager;
import org.onetwo.boot.plugin.core.PluginMeta;
import org.onetwo.boot.plugin.core.WebPlugin;
import org.onetwo.boot.plugin.mvc.PluginContextHolder;
import org.onetwo.boot.plugin.mvc.PluginThreadContext;
import org.onetwo.boot.utils.PathMatchers;
import org.onetwo.boot.utils.PathMatchers.PathMatcher;
import org.onetwo.common.file.FileUtils;
import org.onetwo.common.utils.StringUtils;

import freemarker.cache.StatefulTemplateLoader;
import freemarker.cache.TemplateLoader;

@SuppressWarnings({"unchecked", "rawtypes"})
public class PluginTemplateLoader implements StatefulTemplateLoader {
	
	private static final String CHINA_POSTFIX = "*"+Locale.CHINA.toString()+".*";
	private static final String CHINESE_POSTFIX = "*"+Locale.CHINESE.toString()+".*";
	private PathMatcher ignorePostfixMatcher = PathMatchers.anyPaths(CHINA_POSTFIX, CHINESE_POSTFIX);
	
//	public static final String ROOT_ACCESS = ":";

	private final PluginNameParser pluginNameParser;
	private final TemplateLoader[] loaders;
	private final Map lastLoaderForName = Collections.synchronizedMap(new HashMap());

	private Map pluginLoaders = new HashMap();
	final private PluginManager pluginManager;

	public PluginTemplateLoader(TemplateLoader[] loaders, PluginManager pluginManager) {
		this.loaders = (TemplateLoader[]) loaders.clone();
		this.pluginManager = pluginManager;
		this.pluginNameParser = pluginManager.getPluginNameParser();
	}

	public void putPluginTemplateLoader(WebPlugin plugin, TemplateLoader loader){
		this.pluginLoaders.put(plugin.getPluginMeta().getName(), loader);
	}
	/*public void addTemplateLoader(TemplateLoader loader) {
		loaders = (TemplateLoader[])ArrayUtils.add(loaders, loader);
	}*/

	public boolean containsPluginTemplateLoader(String name){
		return this.pluginLoaders.containsKey(name);
	}

	public Object findPluginTemplateSource(PluginMeta meta, String name) throws IOException {
		if(meta==null)
			return null;
		TemplateLoader loader = pluginLoaders.get(meta.getName());
		Object source = loader.findTemplateSource(name);
		if (source != null) {
			return new MultiSource(source, loader);
		}
		
		return null;
	}

	private PluginMeta getWebPluginMeta(String name){
		WebPlugin webplugin = pluginManager.getPlugin(name);
		if(webplugin==null)
			return null;
		return webplugin.getPluginMeta();
	}
	public Object findTemplateSource(String name) throws IOException {
		String fileName = FileUtils.getFileName(name);
		if(ignorePostfixMatcher.match(fileName)){
			return null;
		}
		
		String actualName = name;
		//for ftl view
		Object source = null;
		if(pluginNameParser.isPluginAccess(actualName)){
			String pname = pluginNameParser.getPluginName(actualName);
			if(pname!=null){
				PluginMeta meta = getWebPluginMeta(pname);
				actualName = actualName.substring(pname.length()+pluginNameParser.getLength());
				actualName = StringUtils.trimStartWith(actualName, "/");
				source = findPluginTemplateSource(meta, actualName);
			}
		}else{
			Optional context = PluginContextHolder.get();
			if (context.isPresent()) {//for controller
				source = findPluginTemplateSource(context.get().getPlugin().getPluginMeta(), actualName);
				if(source!=null){
					return source;
				}
			}
		}
		
		if(source!=null)
			return source;
		
		
		// Use soft affinity - give the loader that last found this
		// resource a chance to find it again first.
		TemplateLoader lastLoader = (TemplateLoader) lastLoaderForName.get(name);
		if (lastLoader != null) {
			source = lastLoader.findTemplateSource(name);
			if (source != null) {
				return new MultiSource(source, lastLoader);
			}
		}
		
		/*Object source = findPluginTemplateSource(name);
		if(source!=null)
			return source;*/
		
		

		// If there is no affine loader, or it could not find the resource
		// again, try all loaders in order of appearance. If any manages
		// to find the resource, then associate it as the new affine loader
		// for this resource.
		for (int i = 0; i < loaders.length; ++i) {
			TemplateLoader loader = loaders[i];
			source = loader.findTemplateSource(actualName);
			if (source != null) {
				lastLoaderForName.put(name, loader);
				return new MultiSource(source, loader);
			}
		}

		lastLoaderForName.remove(name);
		// Resource not found
		return null;
	}

	public long getLastModified(Object templateSource) {
		return ((MultiSource) templateSource).getLastModified();
	}

	public Reader getReader(Object templateSource, String encoding) throws IOException {
		return ((MultiSource) templateSource).getReader(encoding);
	}

	public void closeTemplateSource(Object templateSource) throws IOException {
		((MultiSource) templateSource).close();
	}

	public void resetState() {
		lastLoaderForName.clear();
		for (int i = 0; i < loaders.length; i++) {
			TemplateLoader loader = loaders[i];
			if (loader instanceof StatefulTemplateLoader) {
				((StatefulTemplateLoader) loader).resetState();
			}
		}
	}

	private static final class MultiSource {
		private final Object source;
		private final TemplateLoader loader;

		MultiSource(Object source, TemplateLoader loader) {
			this.source = source;
			this.loader = loader;
		}

		long getLastModified() {
			return loader.getLastModified(source);
		}

		Reader getReader(String encoding) throws IOException {
			return loader.getReader(source, encoding);
		}

		void close() throws IOException {
			loader.closeTemplateSource(source);
		}

		public boolean equals(Object o) {
			if (o instanceof MultiSource) {
				MultiSource m = (MultiSource) o;
				return m.loader.equals(loader) && m.source.equals(source);
			}
			return false;
		}

		public int hashCode() {
			return loader.hashCode() + 31 * source.hashCode();
		}

		public String toString() {
			return source.toString();
		}
	}

	public static void main(String[] args){
		PluginTemplateLoader j = new PluginTemplateLoader(new TemplateLoader[]{}, null);
		System.out.println(j.pluginNameParser.getPluginName("lib/test/test.ftl"));
		String path = "[codegen]/lib/test/test.ftl";
		String pname = j.pluginNameParser.getPluginName(path);
		System.out.println(pname);
		System.out.println(path.substring(pname.length()+j.pluginNameParser.getLength()));
		
		path = "[codegen]/test.ftl";
		pname = j.pluginNameParser.getPluginName(path);
		System.out.println(pname);
		System.out.println(path.substring(pname.length()+j.pluginNameParser.getLength()));
		
		path = "[[codegen-test";
		pname = j.pluginNameParser.getPluginName(path);
		System.out.println("[["+pname);
		System.out.println("[["+path.substring(pname.length()+j.pluginNameParser.getLength()));
		

	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy