From da5e6cfaceb2f61ba2c406f033e2cd7b0b41f224 Mon Sep 17 00:00:00 2001 From: David Caruana Date: Tue, 27 Nov 2007 19:45:50 +0000 Subject: [PATCH] Merge Web Script framework extraction. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@7455 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../org/alfresco/repo/jscript/NativeMap.java | 238 ++++++++++++++++++ .../repo/jscript/RhinoScriptProcessor.java | 26 +- .../org/alfresco/repo/jscript/ScriptNode.java | 132 +--------- .../repo/template/AbsoluteUrlMethod.java | 79 ------ 4 files changed, 267 insertions(+), 208 deletions(-) create mode 100644 source/java/org/alfresco/repo/jscript/NativeMap.java delete mode 100644 source/java/org/alfresco/repo/template/AbsoluteUrlMethod.java diff --git a/source/java/org/alfresco/repo/jscript/NativeMap.java b/source/java/org/alfresco/repo/jscript/NativeMap.java new file mode 100644 index 0000000000..d66a794933 --- /dev/null +++ b/source/java/org/alfresco/repo/jscript/NativeMap.java @@ -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 map; + private Scriptable parentScope; + private Scriptable prototype; + + + /** + * Construct + * + * @param scope + * @param map + * @return native map + */ + public static NativeMap wrap(Scriptable scope, Map map) + { + return new NativeMap(scope, map); + } + + /** + * Construct + * + * @param scope + * @param map + */ + public NativeMap(Scriptable scope, Map 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); + } + +} diff --git a/source/java/org/alfresco/repo/jscript/RhinoScriptProcessor.java b/source/java/org/alfresco/repo/jscript/RhinoScriptProcessor.java index 6d0145cb1f..7510c30ebc 100644 --- a/source/java/org/alfresco/repo/jscript/RhinoScriptProcessor.java +++ b/source/java/org/alfresco/repo/jscript/RhinoScriptProcessor.java @@ -54,6 +54,7 @@ import org.apache.commons.logging.LogFactory; import org.mozilla.javascript.Context; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; +import org.mozilla.javascript.WrapFactory; 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 SCRIPT_ROOT = "_root"; + /** Wrap Factory */ + private static WrapFactory wrapFactory = new RhinoWrapFactory(); + /** Base Value Converter */ 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 // allocates a fair amount of memory. Scriptable scope = cx.initStandardObjects(); + cx.setWrapFactory(wrapFactory); // there's always a model, if only to hold the util objects if (model == null) @@ -561,5 +566,24 @@ public class RhinoScriptProcessor extends BaseProcessor implements ScriptProcess } 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); + } + } + } diff --git a/source/java/org/alfresco/repo/jscript/ScriptNode.java b/source/java/org/alfresco/repo/jscript/ScriptNode.java index 351467e6e2..9f29f65134 100644 --- a/source/java/org/alfresco/repo/jscript/ScriptNode.java +++ b/source/java/org/alfresco/repo/jscript/ScriptNode.java @@ -70,6 +70,7 @@ import org.alfresco.service.cmr.version.VersionType; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; +import org.alfresco.util.Content; import org.alfresco.util.GUID; import org.alfresco.util.ParameterCheck; import org.alfresco.util.URLEncoder; @@ -2159,62 +2160,10 @@ public class ScriptNode implements Serializable, Scopeable // 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 */ - public class ScriptContentData extends ScriptContent implements Serializable + public class ScriptContentData implements Content, Serializable { private static final long serialVersionUID = -7819328543933312278L; @@ -2241,7 +2190,7 @@ public class ScriptNode implements Serializable, Scopeable return (reader != null && reader.exists()) ? reader.getContentString() : ""; } - /*package*/ InputStream getInputStream() + public InputStream getInputStream() { ContentService contentService = services.getContentService(); ContentReader reader = contentService.getReader(nodeRef, property); @@ -2275,7 +2224,7 @@ public class ScriptNode implements Serializable, Scopeable * * @param content ScriptContent to set */ - public void write(ScriptContent content) + public void write(Content content) { ContentService contentService = services.getContentService(); ContentWriter writer = contentService.getWriter(nodeRef, this.property, true); @@ -2371,79 +2320,6 @@ public class ScriptNode implements Serializable, Scopeable 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 */ diff --git a/source/java/org/alfresco/repo/template/AbsoluteUrlMethod.java b/source/java/org/alfresco/repo/template/AbsoluteUrlMethod.java deleted file mode 100644 index c7ea810323..0000000000 --- a/source/java/org/alfresco/repo/template/AbsoluteUrlMethod.java +++ /dev/null @@ -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. - *

- * Render absolute url for the specified url (only if the url isn't already absolute). - *

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