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);
}
}