Small patches to previously posted updates from OFBiz

David E Jones <[email protected]> Wed, 5 Mar 2003 13:24:05 -0800
Newsgroups gmane.comp.java.jpublish.devel
Organization The Open For Business Project
Message-ID <[email protected]>
Anthony and others,

Since sending out the last set of files there are two that I have made small 
changes to.

The RepositoryContent is now a bit more intelligent about handling 
lastModified times, and should be somewhat faster depending on how the 
repository is implemented.

The ScriptAction class now passes the "canonical" path as the source to BSF. 
This provides a more unique identifier to make is easier to cache and, when 
debugging, locate the script file you are working with.

Later,
-David Jones
RepositoryContent.java (text/x-java, 6.8 KB)
/*-- 

 Copyright (C) 2001-2003 Aetrion LLC.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:
 
 1. Redistributions of source code must retain the above copyright
    notice, this list of conditions, and the following disclaimer.
 
 2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions, and the disclaimer that follows 
    these conditions in the documentation and/or other materials 
    provided with the distribution.

 3. The name "JPublish" must not be used to endorse or promote products
    derived from this software without prior written permission.  For
    written permission, please contact [email protected].
 
 4. Products derived from this software may not be called "JPublish", nor
    may "JPublish" appear in their name, without prior written permission
    from Aetrion LLC ([email protected]).
 
 In addition, the authors of this software request (but do not require) 
 that you include in the end-user documentation provided with the 
 redistribution and/or in the software itself an acknowledgement equivalent 
 to the following:
     "This product includes software developed by
      Aetrion LLC (http://www.aetrion.com/)."

 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, 
 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 POSSIBILITY OF SUCH DAMAGE.

 For more information on JPublish, please see <http://www.jpublish.org/>.
 
 */

package org.jpublish.repository;

import java.io.Reader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.jpublish.Content;
import org.jpublish.Repository;

/** Interface which represents a single item of content.  This interface
    is read-only.
    
    @author Anthony Eden
    @since 2.0
*/

public class RepositoryContent implements Content{
    
    private static final Log log = LogFactory.getLog(RepositoryContent.class);
    
    private Repository repository = null;
    private String path = null;
    private String data = null;
    private long lastModified = -1;

    /** Construct a new RepositoryContent object.
    
        @param repository The Repository used to load the content
        @param path The path to the content in the repository
    */
    
    public RepositoryContent(Repository repository, String path) {
        this.repository = repository;
        this.path = path;
        this.data = null;
        this.lastModified = -1;
    }
    
    /** Construct a new RepositoryContent object.
    
        @param data The data
        @param lastModified The last modified time
    */
    
    public RepositoryContent(String data, long lastModified) {
        this.data = data;
        this.lastModified = lastModified;
    }
    
    /** Get the last-modified time of the content or -1 if it is not known.
    
        @return The last modified time
    */
    
    public long getLastModified(){
        this.snapLastModified(false);
        return lastModified;
    }
    
    private void snapLastModified(boolean forceFromRepository) {
        if ((forceFromRepository || this.lastModified == -1) && this.repository != null) {
            try {
                this.lastModified = this.repository.getLastModified(this.path);
            } catch (Exception e) {
                log.warn("Could not getLastModified time from repository (returning -1): " + e.toString());
            }
        }
    }
    
    /** Get an InputStream for reading the content data.
    
        @return The content InputStream
    */
    
    public InputStream getInputStream(){
        //doing an actual read, set the lastModified time
        this.snapLastModified(true);
        
        if (this.repository != null) {
            try {
                return this.repository.getInputStream(this.path);
            } catch (Exception e) {
                log.warn("Could not getInputStream from repository (returning null): " + e.toString());
                return null;
            }
        }
        return new ByteArrayInputStream(data.getBytes());
    }

    /** Get a Reader for reading the content data.
    
        @return The content Reader
    */
    
    public Reader getReader(){
        return getReader(null);
    }
    
    /** Get a Reader for reading the content data with the specified content
        encoding.
        
        @param encoding The content encoding
        @return The Reader
    */
    
    public Reader getReader(String encoding){
        //doing an actual read, set the lastModified time
        this.snapLastModified(true);
        
        InputStream repInputStrem = null;
        if (repository != null) {
            try {
                repInputStrem = repository.getInputStream(path);
            } catch (Exception e) {
                log.warn("Could not getInputStream from repository (returning null): " + e.toString());
                return null;
            }
        }
        
        if(encoding == null){
            if (repository != null) return new InputStreamReader(repInputStrem);
            return new StringReader(data);
        } else {
            try{
                if (repository != null) return new InputStreamReader(repInputStrem, encoding);
                return new StringReader(new String(data.getBytes(), encoding));
            } catch(UnsupportedEncodingException e){
                log.warn("Unsupported encoding " + encoding + "; using default encoding");
                if (repository != null) return new InputStreamReader(repInputStrem);
                return new StringReader(data);
            }
        }
    }

    public boolean equals(Object obj) {
        Content passed = (Content) obj;
        long thisLastModified = this.getLastModified();
        long passedLastModified = passed.getLastModified();
        if (thisLastModified == passedLastModified) {
            return true;
        }
        if (log.isDebugEnabled()) log.debug("Passed content not equal: thisLastModified=" + thisLastModified + ", passedLastModified=" + passedLastModified);
        return false;
    }
}
ScriptAction.java (text/x-java, 8.5 KB)
/*-- 

 Copyright (C) 2001-2003 Aetrion LLC.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions
 are met:
 
 1. Redistributions of source code must retain the above copyright
    notice, this list of conditions, and the following disclaimer.
 
 2. Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions, and the disclaimer that follows 
    these conditions in the documentation and/or other materials 
    provided with the distribution.

 3. The name "JPublish" must not be used to endorse or promote products
    derived from this software without prior written permission.  For
    written permission, please contact [email protected].
 
 4. Products derived from this software may not be called "JPublish", nor
    may "JPublish" appear in their name, without prior written permission
    from Aetrion LLC ([email protected]).
 
 In addition, the authors of this software request (but do not require) 
 that you include in the end-user documentation provided with the 
 redistribution and/or in the software itself an acknowledgement equivalent 
 to the following:
     "This product includes software developed by
      Aetrion LLC (http://www.aetrion.com/)."

 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, 
 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 POSSIBILITY OF SUCH DAMAGE.

 For more information on JPublish, please see <http://www.jpublish.org/>.
 
 */

package org.jpublish.action;

import java.io.File;
import java.io.FileReader;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ibm.bsf.BSFManager;
import com.ibm.bsf.BSFException;
import com.ibm.bsf.util.IOUtils;
import com.ibm.bsf.util.CodeBuffer;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.anthonyeden.lib.config.Configuration;

import org.jpublish.Page;
import org.jpublish.SiteContext;
import org.jpublish.JPublishContext;
import org.jpublish.util.CustomClassLoader;

/** An action which is implemented in a BSF supported scripting language.  
    Script actions have access to several varibles:
    
    <p>These are always available:</p>
    
    <p>
    <b>site</b> - The SiteContext<br>
    <b>syslog</b> - Standard logging stream (Log4J Category)<br>
    </p>
    
    <p>If there is a context defined when the action is executed (all
    actions excluding startup actions):</p>
    
    <p>
    <b>context</b> - The current context<br>
    <b>application</b> - The ServletContext<br>
    <b>request</b> - The HTTP request<br>
    <b>response</b> - The HTTP response<br>
    <b>session</b> - The HTTP session<br>
    <b>page</b> - The Page object<br>
    </p>

    @author Anthony Eden
*/

public class ScriptAction implements Action{
    
    private static Log log = LogFactory.getLog(ScriptAction.class);
    
    private SiteContext siteContext;
    private File script;
    private String scriptLang = null;
    private long timeLastLoaded = 0;
    private String scriptString = null;

    /** Construct a new ScriptAction for the given script.  The path to the
        script should be an absolute path.
    
        @param siteContext The SiteContext
        @param script The path to the script
    */

    public ScriptAction(SiteContext siteContext, String script){
        this(siteContext, new File(script));
    }
    
    /** Construct a new ScriptAction for the given script.
    
        @param siteContext The SiteContext
        @param script The file representing the script
    */

    public ScriptAction(SiteContext siteContext, File script){
        this.siteContext = siteContext;
        this.script = script;
        log.debug("Creating new ScriptAction for " + script.getName());
    }
    
    /** Execute the action script represented by this ScriptAction.
    
        @param context The current context
        @param configuration The configuration object
        @throws Exception
    */

    public void execute(JPublishContext context, Configuration configuration) 
    throws Exception{
        log.debug("Executing script: " + script);
        
        //ClassLoader cl = Thread.currentThread().getContextClassLoader();
        
        BSFManager bsfManager = new BSFManager();
        //bsfManager.setClassPath(siteContext.getActionManager().getClassPath());
        //bsfManager.setClassLoader(new CustomClassLoader(cl));
        
        // expose standard items in the context
        if(context != null){
            ServletContext application = 
                (ServletContext)context.get("application");
            HttpServletRequest request = 
                (HttpServletRequest)context.get("request");
            HttpServletResponse response = 
                (HttpServletResponse)context.get("response");
            HttpSession session = (HttpSession)context.get("session");
            Page page = (Page)context.get("page");
            
            // expose the context
            bsfManager.declareBean("context", context, JPublishContext.class);
            
            // expose the context.  The variable name vc should be considered
            // deprecated
            bsfManager.declareBean("vc", context, JPublishContext.class);
            
            // expose the page object.
            if(page == null){
                log.debug("Page request is null");
            } else {
                bsfManager.declareBean("page", page, Page.class);
            }
            
            // expose standard HttpServlet objects
            if(request == null){
                log.debug("HTTP request is null");
            } else {
                bsfManager.declareBean("request", request, 
                    HttpServletRequest.class);
            }
            
            if(response == null){
                log.debug("HTTP response is null");
            } else {
                bsfManager.declareBean("response", response, 
                    HttpServletResponse.class);
            }
            
            if(session == null){
                log.debug("HTTP session is null");
            } else {
                bsfManager.declareBean("session", session, HttpSession.class);
            }
            
            if(application == null){
                log.debug("ServletContext is null");
            } else {
                bsfManager.declareBean("application", application, 
                    ServletContext.class);
            }
        }
        
        // these objects are exposed regardless if there is a context
        // object or not.  In other words they are accesible to startup
        // actions
        bsfManager.declareBean("syslog", SiteContext.syslog, Log.class);
        
        if(siteContext == null){
            log.debug("SiteContext is null");
        } else {
            bsfManager.declareBean("site", siteContext, SiteContext.class);
        }
        
        if(configuration == null){
            log.debug("Configuration is null");
        } else {
            bsfManager.declareBean("configuration", configuration, 
                Configuration.class);
        }
        
        if (scriptLang == null) scriptLang = BSFManager.getLangFromFilename(script.getName());
        
        boolean reloadScript = false;
        long scriptLastModified = script.lastModified();
        if (scriptLastModified > timeLastLoaded) {
            log.debug("Loading updated or new script: " + script.getName());
            reloadScript = true;
        }
        
        if (reloadScript || scriptString == null) {
            synchronized (this) {
                if (reloadScript || scriptString == null) {
                    timeLastLoaded = System.currentTimeMillis();
                    scriptString = IOUtils.getStringFromReader(new FileReader(script));
                }
            }
        }
        
        bsfManager.exec(scriptLang, script.getCanonicalPath(), 0, 0, scriptString);
    }
}