Java tutorial
/* ========================================================================== * Copyright 2002-2005 Cyclops Group Community * * Licensed under the Open Software License, Version 2.1 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://opensource.org/licenses/osl-2.1.php * * 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.cyclopsgroup.waterview.jelly; import java.net.URL; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Properties; import org.apache.avalon.framework.activity.Initializable; import org.apache.avalon.framework.context.Context; import org.apache.avalon.framework.context.ContextException; import org.apache.avalon.framework.context.Contextualizable; import org.apache.avalon.framework.logger.AbstractLogEnabled; import org.apache.avalon.framework.service.ServiceException; import org.apache.avalon.framework.service.ServiceManager; import org.apache.avalon.framework.service.Serviceable; import org.apache.commons.jelly.JellyContext; import org.apache.commons.jelly.JellyException; import org.apache.commons.jelly.JellyTagException; import org.apache.commons.jelly.Script; import org.apache.commons.jelly.XMLOutput; import org.apache.commons.lang.StringUtils; import com.cyclopsgroup.waterview.Path; import com.cyclopsgroup.waterview.Waterview; import com.cyclopsgroup.waterview.spi.CacheService; import com.cyclopsgroup.waterview.spi.DynaViewFactory; import com.cyclopsgroup.waterview.spi.ModuleService; import com.cyclopsgroup.waterview.spi.View; import com.cyclopsgroup.waterview.utils.TagLibrary; import com.cyclopsgroup.waterview.utils.TagPackage; import com.cyclopsgroup.waterview.utils.TagSupport; /** * Jelly engine for jelly processing * * @author <a href="mailto:jiaqi.guo@gmail.com">Jiaqi Guo </a> */ public class JellyEngine extends AbstractLogEnabled implements Initializable, Contextualizable, Serviceable, DynaViewFactory { /** Class name of definition tag package */ private static final String DEFINITION_TAG_PACKAGE = "com.cyclopsgroup.waterview.jelly.deftaglib.DefinitionTagPackage"; /** Definition taglib url */ public static final String DEFINITION_TAGLIB_URL = "http://waterview.cyclopsgroup.com/definition"; /** Stupid dummy script */ public static final Script DUMMY_SCRIPT = new Script() { /** * Override or implement method of parent class or interface * * @see org.apache.commons.jelly.Script#compile() */ public Script compile() throws JellyException { return this; } /** * Override or implement method of parent class or interface * * @see org.apache.commons.jelly.Script#run(org.apache.commons.jelly.JellyContext, org.apache.commons.jelly.XMLOutput) */ public void run(JellyContext jellyContext, XMLOutput output) throws JellyTagException { //doing nothing } }; /** Role name of this class */ public static final String ROLE = JellyEngine.class.getName(); /** Name of service manager */ public static final String SERVICE_MANAGER = ServiceManager.class.getName(); private CacheService cacheManager; private JellyContext globalContext; private Properties initProperties = new Properties(); private ModuleService moduleManager; private ServiceManager serviceManager; private Hashtable tagLibraries = new Hashtable(); /** * Override or implement method of parent class or interface * * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context) */ public void contextualize(Context context) throws ContextException { try { Properties waterviewProperties = (Properties) context.get(Waterview.INIT_PROPERTIES); initProperties.putAll(waterviewProperties); } catch (Exception e) { getLogger().debug("Can not add init properties", e); } } /** * Create new Jelly context with all variables in given context * * @param context Given clib context * @return JellyContext object */ public JellyContext createJellyContext(com.cyclopsgroup.waterview.Context context) { JellyContext jc = new JellyContext(getGlobalContext()); for (Iterator i = context.keys(); i.hasNext();) { String name = (String) i.next(); Object value = context.get(name); jc.setVariable(name, value); } jc.setVariable(com.cyclopsgroup.waterview.Context.NAME, context); return jc; } /** * Overwrite or implement method createView() * * @see com.cyclopsgroup.waterview.spi.DynaViewFactory#createView(com.cyclopsgroup.waterview.Path) */ public View createView(Path path) throws Exception { Script script = getScript(path.getPackage(), path.getPath()); return new JellyView(script, path.getFullPath()); } /** * Getter method for cacheManager * * @return Returns the cacheManager. */ public CacheService getCacheManager() { return cacheManager; } /** * Getter method for globalContext * * @return Returns the globalContext. */ public JellyContext getGlobalContext() { return globalContext; } /** * Getter method for initProperties * * @return Returns the initProperties. */ public Properties getInitProperties() { return initProperties; } /** * Get script with given path * * @param path Path * @return Script object * @throws JellyException Throw it out */ public Script getScript(String path) throws JellyException { Path p = moduleManager.parsePath(path); return getScript(p.getPackage(), p.getPath()); } /** * Get script with given path and default script * * @param path Script path * @param defaultScript Default script * @return Script object * @throws JellyException Throw it out */ public Script getScript(String path, Script defaultScript) throws JellyException { Path p = moduleManager.parsePath(path); return getScript(p.getPackage(), p.getPath(), defaultScript); } /** * Get script with give path and package name * * @param scriptPath Script path * @param packageName Look for it in this package * @return Script object * @throws JellyException Throw it out */ public Script getScript(String packageName, String scriptPath) throws JellyException { return getScript(packageName, scriptPath, DUMMY_SCRIPT); } /** * Get script with give path and package name * * @param scriptPath Script path * @param packageName Look for it in this package * @param defaultScript Return as default value * @return Script object * @throws JellyException Throw it out */ public Script getScript(String packageName, String scriptPath, Script defaultScript) throws JellyException { String fullPath = scriptPath; String pkg = moduleManager.getPackageName(packageName); if (StringUtils.isNotEmpty(pkg)) { fullPath = pkg.replace('.', '/') + scriptPath; } Script script = null; synchronized (this) { if (getCacheManager().contains(this, fullPath)) { script = (Script) getCacheManager().get(this, fullPath); } else { final URL resource = getClass().getClassLoader().getResource(fullPath); if (resource == null) { script = DUMMY_SCRIPT; } else { JellyContext jc = new JellyContext(getGlobalContext()); final Script s = jc.compileScript(resource); script = new Script() { public Script compile() throws JellyException { return this; } public void run(JellyContext context, XMLOutput output) throws JellyTagException { TagSupport.addScriptResource(resource, context); try { s.run(context, output); } catch (JellyTagException e) { throw e; } finally { TagSupport.removeScriptResource(resource, context); } } }; } getCacheManager().put(this, fullPath, script); } } return script == DUMMY_SCRIPT ? defaultScript : script; } /** * Init global context * * @throws Exception Throw it out */ private void initGlobalContext() throws Exception { JellyContext jc = new JellyContext(); jc.setVariable(SERVICE_MANAGER, serviceManager); jc.setVariable(ROLE, this); TagLibrary deftaglib = new TagLibrary(); deftaglib.registerPackage((TagPackage) Class.forName(DEFINITION_TAG_PACKAGE).newInstance()); jc.registerTagLibrary(DEFINITION_TAGLIB_URL, deftaglib); Enumeration e = getClass().getClassLoader().getResources("META-INF/cyclopsgroup/waterview.xml"); while (e.hasMoreElements()) { URL resource = (URL) e.nextElement(); getLogger().info("Load definition from " + resource); jc.runScript(resource, XMLOutput.createDummyXMLOutput()); } globalContext = new JellyContext(); globalContext.setVariables(initProperties); for (Iterator i = tagLibraries.keySet().iterator(); i.hasNext();) { String uri = (String) i.next(); TagLibrary taglib = (TagLibrary) tagLibraries.get(uri); globalContext.registerTagLibrary(uri, taglib); } globalContext.setVariable(SERVICE_MANAGER, serviceManager); globalContext.setVariable(ROLE, this); } /** * Override or implement method of parent class or interface * * @see org.apache.avalon.framework.activity.Initializable#initialize() */ public void initialize() throws Exception { initGlobalContext(); } /** * Register tag package into jelly engine * * @param uri Name space uri * @param tagPackage TagPackage object */ public synchronized void registerTagPackage(String uri, TagPackage tagPackage) { TagLibrary ctl = (TagLibrary) tagLibraries.get(uri); if (ctl == null) { ctl = new TagLibrary(); tagLibraries.put(uri, ctl); } ctl.registerPackage(tagPackage); } /** * Override or implement method of parent class or interface * * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager) */ public void service(ServiceManager serviceManager) throws ServiceException { this.serviceManager = serviceManager; cacheManager = (CacheService) serviceManager.lookup(CacheService.ROLE); moduleManager = (ModuleService) serviceManager.lookup(ModuleService.ROLE); String pattern = ".+\\.jelly"; moduleManager.registerDynaViewFactory(pattern, this); } }