Merge Web Script framework extraction.

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@7455 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2007-11-27 19:45:50 +00:00
parent 7f8a4f0d5b
commit da5e6cface
4 changed files with 267 additions and 208 deletions

View File

@@ -0,0 +1,238 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.jscript;
import java.util.Iterator;
import java.util.Map;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.Wrapper;
/**
* Wrapper for exposing maps in Rhino scripts.
*
* @author davidc
*/
public class NativeMap implements Scriptable, Wrapper
{
private static final long serialVersionUID = 3664761893203964569L;
private Map<Object, Object> map;
private Scriptable parentScope;
private Scriptable prototype;
/**
* Construct
*
* @param scope
* @param map
* @return native map
*/
public static NativeMap wrap(Scriptable scope, Map<Object, Object> map)
{
return new NativeMap(scope, map);
}
/**
* Construct
*
* @param scope
* @param map
*/
public NativeMap(Scriptable scope, Map<Object, Object> map)
{
this.parentScope = scope;
this.map = map;
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Wrapper#unwrap()
*/
public Object unwrap()
{
return map;
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#getClassName()
*/
public String getClassName()
{
return "NativeMap";
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#get(java.lang.String, org.mozilla.javascript.Scriptable)
*/
public Object get(String name, Scriptable start)
{
// get the property from the underlying QName map
if ("length".equals(name))
{
return map.size();
}
else
{
return map.get(name);
}
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#get(int, org.mozilla.javascript.Scriptable)
*/
public Object get(int index, Scriptable start)
{
Object value = null;
int i=0;
Iterator itrValues = map.values().iterator();
while (i++ <= index && itrValues.hasNext())
{
value = itrValues.next();
}
return value;
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#has(java.lang.String, org.mozilla.javascript.Scriptable)
*/
public boolean has(String name, Scriptable start)
{
// locate the property in the underlying map
return map.containsKey(name);
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#has(int, org.mozilla.javascript.Scriptable)
*/
public boolean has(int index, Scriptable start)
{
return (index >= 0 && map.values().size() > index);
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#put(java.lang.String, org.mozilla.javascript.Scriptable, java.lang.Object)
*/
@SuppressWarnings("unchecked")
public void put(String name, Scriptable start, Object value)
{
map.put(name, value);
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#put(int, org.mozilla.javascript.Scriptable, java.lang.Object)
*/
public void put(int index, Scriptable start, Object value)
{
// TODO: implement?
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#delete(java.lang.String)
*/
public void delete(String name)
{
map.remove(name);
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#delete(int)
*/
public void delete(int index)
{
int i=0;
Iterator itrKeys = map.keySet().iterator();
while (i <= index && itrKeys.hasNext())
{
Object key = itrKeys.next();
if (i == index)
{
map.remove(key);
break;
}
}
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#getPrototype()
*/
public Scriptable getPrototype()
{
return this.prototype;
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#setPrototype(org.mozilla.javascript.Scriptable)
*/
public void setPrototype(Scriptable prototype)
{
this.prototype = prototype;
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#getParentScope()
*/
public Scriptable getParentScope()
{
return this.parentScope;
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#setParentScope(org.mozilla.javascript.Scriptable)
*/
public void setParentScope(Scriptable parent)
{
this.parentScope = parent;
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#getIds()
*/
public Object[] getIds()
{
return map.keySet().toArray();
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#getDefaultValue(java.lang.Class)
*/
public Object getDefaultValue(Class hint)
{
return null;
}
/* (non-Javadoc)
* @see org.mozilla.javascript.Scriptable#hasInstance(org.mozilla.javascript.Scriptable)
*/
public boolean hasInstance(Scriptable value)
{
if (!(value instanceof Wrapper))
return false;
Object instance = ((Wrapper)value).unwrap();
return Map.class.isInstance(instance);
}
}

View File

@@ -54,6 +54,7 @@ import org.apache.commons.logging.LogFactory;
import org.mozilla.javascript.Context; import org.mozilla.javascript.Context;
import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.ScriptableObject;
import org.mozilla.javascript.WrapFactory;
import org.springframework.util.FileCopyUtils; import org.springframework.util.FileCopyUtils;
/** /**
@@ -70,6 +71,9 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
private static final String PATH_CLASSPATH = "classpath:"; private static final String PATH_CLASSPATH = "classpath:";
private static final String SCRIPT_ROOT = "_root"; private static final String SCRIPT_ROOT = "_root";
/** Wrap Factory */
private static WrapFactory wrapFactory = new RhinoWrapFactory();
/** Base Value Converter */ /** Base Value Converter */
private ValueConverter valueConverter = new ValueConverter(); private ValueConverter valueConverter = new ValueConverter();
@@ -476,6 +480,7 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
// you need one. However, initStandardObjects is an expensive method to call and it // you need one. However, initStandardObjects is an expensive method to call and it
// allocates a fair amount of memory. // allocates a fair amount of memory.
Scriptable scope = cx.initStandardObjects(); Scriptable scope = cx.initStandardObjects();
cx.setWrapFactory(wrapFactory);
// there's always a model, if only to hold the util objects // there's always a model, if only to hold the util objects
if (model == null) if (model == null)
@@ -562,4 +567,23 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess
return newModel; return newModel;
} }
/**
* Rhino script value wraper
*/
private static class RhinoWrapFactory extends WrapFactory
{
/* (non-Javadoc)
* @see org.mozilla.javascript.WrapFactory#wrapAsJavaObject(org.mozilla.javascript.Context, org.mozilla.javascript.Scriptable, java.lang.Object, java.lang.Class)
*/
public Scriptable wrapAsJavaObject(Context cx, Scriptable scope, Object javaObject, Class staticType)
{
if (javaObject instanceof Map && !(javaObject instanceof ScriptableHashMap))
{
return new NativeMap(scope, (Map)javaObject);
}
return super.wrapAsJavaObject(cx, scope, javaObject, staticType);
}
}
} }

View File

@@ -70,6 +70,7 @@ import org.alfresco.service.cmr.version.VersionType;
import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.NamespaceService;
import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.QName;
import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.service.namespace.RegexQNamePattern;
import org.alfresco.util.Content;
import org.alfresco.util.GUID; import org.alfresco.util.GUID;
import org.alfresco.util.ParameterCheck; import org.alfresco.util.ParameterCheck;
import org.alfresco.util.URLEncoder; import org.alfresco.util.URLEncoder;
@@ -2159,62 +2160,10 @@ public class ScriptNode implements Serializable, Scopeable
// Inner Classes // Inner Classes
/**
* Inner class for representing content
*/
public static abstract class ScriptContent implements Serializable
{
/**
* @return the content stream as a string
*/
public abstract String getContent();
public String jsGet_content()
{
return getContent();
}
/**
* @return the content mimetype
*/
public abstract String getMimetype();
public String jsGet_mimetype()
{
return getMimetype();
}
/**
* @return the content encoding
*/
public abstract String getEncoding();
public String jsGet_encoding()
{
return getEncoding();
}
/**
* @return the content size
*/
public abstract long getSize();
public long jsGet_size()
{
return getSize();
}
/**
* @return input stream onto content
*/
/*package*/ abstract InputStream getInputStream();
}
/** /**
* Inner class wrapping and providing access to a ContentData property * Inner class wrapping and providing access to a ContentData property
*/ */
public class ScriptContentData extends ScriptContent implements Serializable public class ScriptContentData implements Content, Serializable
{ {
private static final long serialVersionUID = -7819328543933312278L; private static final long serialVersionUID = -7819328543933312278L;
@@ -2241,7 +2190,7 @@ public class ScriptNode implements Serializable, Scopeable
return (reader != null && reader.exists()) ? reader.getContentString() : ""; return (reader != null && reader.exists()) ? reader.getContentString() : "";
} }
/*package*/ InputStream getInputStream() public InputStream getInputStream()
{ {
ContentService contentService = services.getContentService(); ContentService contentService = services.getContentService();
ContentReader reader = contentService.getReader(nodeRef, property); ContentReader reader = contentService.getReader(nodeRef, property);
@@ -2275,7 +2224,7 @@ public class ScriptNode implements Serializable, Scopeable
* *
* @param content ScriptContent to set * @param content ScriptContent to set
*/ */
public void write(ScriptContent content) public void write(Content content)
{ {
ContentService contentService = services.getContentService(); ContentService contentService = services.getContentService();
ContentWriter writer = contentService.getWriter(nodeRef, this.property, true); ContentWriter writer = contentService.getWriter(nodeRef, this.property, true);
@@ -2371,79 +2320,6 @@ public class ScriptNode implements Serializable, Scopeable
private QName property; private QName property;
} }
/**
* Inner class wrapping and providing access to a Content stream
*/
public static class ScriptContentStream extends ScriptContent implements Serializable
{
private static final long serialVersionUID = -7819328543933312278L;
/**
* Constructor
*
* @param stream content input stream
* @param mimetype content mimetype
*/
public ScriptContentStream(InputStream stream, String mimetype, String encoding)
{
this.stream = stream;
this.mimetype = mimetype;
this.encoding = encoding;
}
/* (non-Javadoc)
* @see org.alfresco.repo.jscript.ScriptNode.ScriptContent#getContent()
*/
public String getContent()
{
try
{
ByteArrayOutputStream os = new ByteArrayOutputStream();
FileCopyUtils.copy(stream, os); // both streams are closed
byte[] bytes = os.toByteArray();
// get the encoding for the string
String encoding = getEncoding();
// create the string from the byte[] using encoding if necessary
String content = (encoding == null) ? new String(bytes) : new String(bytes, encoding);
// done
return content;
}
catch (IOException e)
{
throw new ContentIOException("Failed to copy content to string", e);
}
}
/*package*/ InputStream getInputStream()
{
return stream;
}
public long getSize()
{
return -1;
}
public String getMimetype()
{
return mimetype;
}
public String getEncoding()
{
return encoding;
}
private InputStream stream;
private String mimetype;
private String encoding;
}
/** /**
* Interface contract for simple anonymous classes that implement document transformations * Interface contract for simple anonymous classes that implement document transformations
*/ */

View File

@@ -1,79 +0,0 @@
/*
* Copyright (C) 2005-2007 Alfresco Software Limited.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
* As a special exception to the terms and conditions of version 2.0 of
* the GPL, you may redistribute this Program in connection with Free/Libre
* and Open Source Software ("FLOSS") applications as described in Alfresco's
* FLOSS exception. You should have recieved a copy of the text describing
* the FLOSS exception, and it is also available here:
* http://www.alfresco.com/legal/licensing"
*/
package org.alfresco.repo.template;
import java.util.List;
import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModelException;
import freemarker.template.TemplateScalarModel;
/**
* @author David Caruana
*
* Custom FreeMarker Template language method.
* <p>
* Render absolute url for the specified url (only if the url isn't already absolute).
* <p>
* Usage: absurl(String url)
*/
public final class AbsoluteUrlMethod implements TemplateMethodModelEx
{
private String basePath;
/**
* Construct
*
* @param basePath base path used to construct absolute url
*/
public AbsoluteUrlMethod(String basePath)
{
this.basePath = basePath;
}
/**
* @see freemarker.template.TemplateMethodModel#exec(java.util.List)
*/
public Object exec(List args) throws TemplateModelException
{
String result = "";
if (args.size() == 1)
{
Object arg0 = args.get(0);
if (arg0 instanceof TemplateScalarModel)
{
result = ((TemplateScalarModel)arg0).getAsString();
if (result.startsWith("/"))
{
result = basePath + result;
}
}
}
return result;
}
}