/* * 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.asual.summer.core.faces; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.lang.reflect.Method; import java.net.URI; import java.util.Arrays; import java.util.HashMap; import javax.el.FunctionMapper; import javax.tools.FileObject; import javax.tools.ForwardingJavaFileManager; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.JavaFileObject.Kind; import javax.tools.SimpleJavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * * @author Rostislav Hristov * */ public class FacesFunctionMapper extends FunctionMapper { private final Log logger = LogFactory.getLog(getClass()); private static HashMap<String, JavaFileObject> classes = new HashMap<String, JavaFileObject>(); private static ClassLoader classLoader = new ClassLoader() { protected Class<?> findClass(String name) throws ClassNotFoundException { if (classes.containsKey(name)) { byte[] bytes = ((MemoryJavaFileObject) classes.get(name)).baos.toByteArray(); return defineClass(name, bytes, 0, bytes.length); } return Class.forName(name, true, getClass().getClassLoader()); } }; private class JavaObjectFromString extends SimpleJavaFileObject { private String contents = null; public JavaObjectFromString(String className, String contents) throws Exception{ super(new URI(className + Kind.SOURCE.extension), Kind.SOURCE); this.contents = contents; } public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return contents; } } private class MemoryJavaFileObject extends SimpleJavaFileObject { ByteArrayOutputStream baos; MemoryJavaFileObject(String name, Kind kind) { super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension), kind); } public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException, IllegalStateException, UnsupportedOperationException { throw new UnsupportedOperationException(); } public InputStream openInputStream() throws IOException, IllegalStateException, UnsupportedOperationException { return new ByteArrayInputStream(baos.toByteArray()); } public OutputStream openOutputStream() throws IOException, IllegalStateException, UnsupportedOperationException { return baos = new ByteArrayOutputStream(); } } private class MemoryFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> { MemoryFileManager (JavaCompiler compiler){ super(compiler.getStandardFileManager(null,null,null)); } public JavaFileObject getJavaFileForOutput(Location location, String name, Kind kind, FileObject sibling) throws java.io.IOException { JavaFileObject jfo = new MemoryJavaFileObject(name, kind); classes.put(name, jfo); return jfo; } } public Method resolveFunction(String namespace, final String fn) { try { String className = fn + "Script"; if (!classes.containsKey(className)) { StringBuilder out = new StringBuilder(); out.append("public class " + className + " {"); out.append(" private static String fn = \"" + fn + "\";"); out.append(" public static Object call(Object... args) throws Exception {"); out.append(" return Class.forName(\"com.asual.summer.core.util.ScriptUtils\")"); out.append(" .getDeclaredMethod(\"call\", String.class, Object[].class).invoke(null, fn, args);"); out.append(" }"); out.append("}"); JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); JavaFileManager jfm = new MemoryFileManager(compiler); JavaFileObject file = new JavaObjectFromString(className, out.toString()); compiler.getTask(null, jfm, null, null, null, Arrays.asList(file)).call(); } return Class.forName(className, true, classLoader).getDeclaredMethod("call", Object[].class); } catch (Exception e) { logger.error(e.getMessage(), e); } return null; } }