* Implement subskins
* Fix skin failmode levels * Add Resource.getOverloadedResource() * Implement ScriptingEngine.isTypedObject(Object) * Fix skin length bug with non-ASCII characters
This commit is contained in:
		
							parent
							
								
									0b363a4b96
								
							
						
					
					
						commit
						4531ef6e4b
					
				
					 9 changed files with 315 additions and 87 deletions
				
			
		|  | @ -324,10 +324,36 @@ public final class Prototype { | |||
|     /** | ||||
|      *  Get a skin for this prototype. This only works for skins | ||||
|      *  residing in the prototype directory, not for skins files in | ||||
|      *  other locations or database stored skins. | ||||
|      *  other locations or database stored skins. If parentName and | ||||
|      *  subName are defined, the skin may be a subskin of another skin. | ||||
|      */ | ||||
|     public Skin getSkin(String skinName) throws IOException { | ||||
|         return skinMap.getSkin(skinName); | ||||
|     public Skin getSkin(String skinName, String parentName, String subName) | ||||
|             throws IOException { | ||||
|         Skin skin = null; | ||||
|         Resource res = skinMap.getResource(skinName); | ||||
|         while (res != null) { | ||||
|             skin = Skin.getSkin(res, app); | ||||
|             if (skin.hasMainskin()) | ||||
|                 break; | ||||
|             res = res.getOverloadedResource(); | ||||
|         } | ||||
|         if (parentName != null) { | ||||
|             Skin parentSkin = null; | ||||
|             Resource parent = skinMap.getResource(parentName); | ||||
|             while (parent != null) { | ||||
|                 parentSkin = Skin.getSkin(parent, app); | ||||
|                 if (parentSkin.hasSubskin(subName)) | ||||
|                     break; | ||||
|                 parent = parent.getOverloadedResource(); | ||||
|             } | ||||
|             if (parent != null) { | ||||
|                 if (res != null && app.getResourceComparator().compare(res, parent) > 0) | ||||
|                     return skin; | ||||
|                 else | ||||
|                     return parentSkin.getSubskin(subName); | ||||
|             } | ||||
|         } | ||||
|         return skin; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | @ -494,6 +520,10 @@ public final class Prototype { | |||
|             } | ||||
|         } | ||||
| 
 | ||||
|         public Resource getResource(Object key) { | ||||
|             return (Resource) get(key); | ||||
|         } | ||||
| 
 | ||||
|         public Object get(Object key) { | ||||
|             checkForUpdates(); | ||||
|             return super.get(key); | ||||
|  | @ -559,7 +589,8 @@ public final class Prototype { | |||
|             // load Skins | ||||
|             for (Iterator i = skins.iterator(); i.hasNext();) { | ||||
|                 Resource res = (Resource) i.next(); | ||||
|                 super.put(res.getBaseName(), res); | ||||
|                 Resource prev = (Resource) super.put(res.getBaseName(), res); | ||||
|                 res.setOverloadedResource(prev); | ||||
|             } | ||||
| 
 | ||||
|             // if skinpath is not null, overload/add skins from there | ||||
|  | @ -594,7 +625,9 @@ public final class Prototype { | |||
|                 String name = skinNames[i].substring(0, skinNames[i].length() - 5); | ||||
|                 File file = new File(dir, skinNames[i]); | ||||
| 
 | ||||
|                 super.put(name, (new FileResource(file))); | ||||
|                 Resource res = new FileResource(file); | ||||
|                 Resource prev = (Resource) super.put(name, res); | ||||
|                 res.setOverloadedResource(prev); | ||||
|             } | ||||
| 
 | ||||
|         } | ||||
|  |  | |||
|  | @ -33,6 +33,15 @@ import java.io.IOException; | |||
|  * from the RequestEvaluator object to resolve Macro handlers by type name. | ||||
|  */ | ||||
| public final class Skin { | ||||
| 
 | ||||
|     private Macro[] macros; | ||||
|     private Application app; | ||||
|     private char[] source; | ||||
|     private int offset, length; // start and end index of skin content | ||||
|     private HashSet sandbox; | ||||
|     private HashMap subskins; | ||||
|     private Skin parentSkin = this; | ||||
| 
 | ||||
|     static private final int PARSE_MACRONAME = 0; | ||||
|     static private final int PARSE_PARAM = 1; | ||||
|     static private final int PARSE_DONE = 2; | ||||
|  | @ -52,20 +61,19 @@ public final class Skin { | |||
|     static private final int HANDLER_THIS = 5; | ||||
|     static private final int HANDLER_OTHER = 6; | ||||
| 
 | ||||
|     private Macro[] macros; | ||||
|     private Application app; | ||||
|     private char[] source; | ||||
|     private int sourceLength; | ||||
|     private HashSet sandbox; | ||||
|     static private final int FAIL_DEFAULT = 0; | ||||
|     static private final int FAIL_SILENT = 1; | ||||
|     static private final int FAIL_VERBOSE = 2; | ||||
| 
 | ||||
|     /** | ||||
|      * Create a skin without any restrictions on which macros are allowed to be called from it | ||||
|      */ | ||||
|     public Skin(String content, Application app) { | ||||
|         this.app = app; | ||||
|         sandbox = null; | ||||
|         source = content.toCharArray(); | ||||
|         sourceLength = source.length; | ||||
|         this.sandbox = null; | ||||
|         this.source = content.toCharArray(); | ||||
|         this.offset = 0; | ||||
|         this.length = source.length; | ||||
|         parse(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -75,8 +83,9 @@ public final class Skin { | |||
|     public Skin(String content, Application app, HashSet sandbox) { | ||||
|         this.app = app; | ||||
|         this.sandbox = sandbox; | ||||
|         source = content.toCharArray(); | ||||
|         sourceLength = source.length; | ||||
|         this.source = content.toCharArray(); | ||||
|         this.offset = 0; | ||||
|         length = source.length; | ||||
|         parse(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -86,8 +95,23 @@ public final class Skin { | |||
|     public Skin(char[] content, int length, Application app) { | ||||
|         this.app = app; | ||||
|         this.sandbox = null; | ||||
|         source = content; | ||||
|         sourceLength = length; | ||||
|         this.source = content; | ||||
|         this.offset = 0; | ||||
|         this.length = length; | ||||
|         parse(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      *  Subskin constructor. | ||||
|      */ | ||||
|     private Skin(Skin parentSkin, Macro anchorMacro) { | ||||
|         this.parentSkin = parentSkin; | ||||
|         this.app = parentSkin.app; | ||||
|         this.sandbox = parentSkin.sandbox; | ||||
|         this.source = parentSkin.source; | ||||
|         this.offset = anchorMacro.end; | ||||
|         this.length = parentSkin.length; | ||||
|         parentSkin.addSubskin(anchorMacro.name, this); | ||||
|         parse(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -113,7 +137,7 @@ public final class Skin { | |||
|         } finally { | ||||
|             reader.close(); | ||||
|         } | ||||
|         return new Skin(characterBuffer, length, app); | ||||
|         return new Skin(characterBuffer, read, app); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | @ -123,11 +147,17 @@ public final class Skin { | |||
|         ArrayList partBuffer = new ArrayList(); | ||||
| 
 | ||||
|         boolean escape = false; | ||||
|         for (int i = 0; i < (sourceLength - 1); i++) { | ||||
|         for (int i = offset; i < (length - 1); i++) { | ||||
|             if (source[i] == '<' && source[i + 1] == '%' && !escape) { | ||||
|                 // found macro start tag | ||||
|                 Macro macro = new Macro(i, 2); | ||||
|                 partBuffer.add(macro); | ||||
|                 if (macro.isSubskinMacro) { | ||||
|                     new Skin(parentSkin, macro); | ||||
|                     length = i; | ||||
|                     break; | ||||
|                 } else { | ||||
|                     partBuffer.add(macro); | ||||
|                 } | ||||
|                 i = macro.end - 1; | ||||
|             } else { | ||||
|                 escape = source[i] == '\\' && !escape; | ||||
|  | @ -138,11 +168,54 @@ public final class Skin { | |||
|         partBuffer.toArray(macros); | ||||
|     } | ||||
| 
 | ||||
|     private void addSubskin(String name, Skin subskin) { | ||||
|         if (subskins == null) { | ||||
|             subskins = new HashMap(); | ||||
|         } | ||||
|         subskins.put(name, subskin); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if this skin has a main skin, as opposed to consisting just of subskins | ||||
|      * @return true if this skin contains a main skin | ||||
|      */ | ||||
|     public boolean hasMainskin() { | ||||
|         return length - offset > 0; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if this skin contains a subskin with the given name | ||||
|      * @param name a subskin name | ||||
|      * @return true if the given subskin exists | ||||
|      */ | ||||
|     public boolean hasSubskin(String name) { | ||||
|         return subskins != null && subskins.containsKey(name); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get a subskin by name | ||||
|      * @param name the subskin name | ||||
|      * @return the subskin | ||||
|      */ | ||||
|     public Skin getSubskin(String name) { | ||||
|         return subskins == null ? null : (Skin) subskins.get(name); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Return an array of subskin names defined in this skin | ||||
|      * @return a string array containing this skin's substrings | ||||
|      */ | ||||
|     public String[] getSubskinNames() { | ||||
|         return subskins == null ? | ||||
|                 new String[0] : | ||||
|                 (String[]) subskins.keySet().toArray(new String[0]); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the raw source text this skin was parsed from | ||||
|      */ | ||||
|     public String getSource() { | ||||
|         return new String(source, 0, sourceLength); | ||||
|         return new String(source, offset, length - offset); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | @ -175,9 +248,8 @@ public final class Skin { | |||
|         ResponseTrans res = reval.getResponse(); | ||||
| 
 | ||||
|         if (macros == null) { | ||||
|             res.write(source, 0, sourceLength); | ||||
|             res.write(source, offset, length - offset); | ||||
|             reval.skinDepth--; | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|  | @ -186,7 +258,7 @@ public final class Skin { | |||
|         Object previousParam = handlers.put("param", paramObject); | ||||
| 
 | ||||
|         try { | ||||
|             int written = 0; | ||||
|             int written = offset; | ||||
|             Map handlerCache = null; | ||||
| 
 | ||||
|             if (macros.length > 3) { | ||||
|  | @ -202,8 +274,8 @@ public final class Skin { | |||
|                 written = macros[i].end; | ||||
|             } | ||||
| 
 | ||||
|             if (written < sourceLength) { | ||||
|                 res.write(source, written, sourceLength - written); | ||||
|             if (written < length) { | ||||
|                 res.write(source, written, length - written); | ||||
|             } | ||||
|         } finally { | ||||
|             reval.skinDepth--; | ||||
|  | @ -276,6 +348,8 @@ public final class Skin { | |||
| 
 | ||||
|         // comment macros are silently dropped during rendering | ||||
|         boolean isCommentMacro = false; | ||||
|         // subskin macros delimits the beginning of a new subskin | ||||
|         boolean isSubskinMacro = false; | ||||
| 
 | ||||
|         /** | ||||
|          * Create and parse a new macro. | ||||
|  | @ -293,7 +367,7 @@ public final class Skin { | |||
|             int i; | ||||
| 
 | ||||
|             loop: | ||||
|             for (i = start + offset; i < sourceLength - 1; i++) { | ||||
|             for (i = start + offset; i < length - 1; i++) { | ||||
| 
 | ||||
|                 switch (source[i]) { | ||||
| 
 | ||||
|  | @ -330,7 +404,7 @@ public final class Skin { | |||
|                         if (state == PARSE_MACRONAME && "//".equals(b.toString())) { | ||||
|                             isCommentMacro = true; | ||||
|                             // search macro end tag | ||||
|                             while (i < sourceLength - 1 && | ||||
|                             while (i < length - 1 && | ||||
|                                        (source[i] != '%' || source[i + 1] != '>')) { | ||||
|                                 i++; | ||||
|                             } | ||||
|  | @ -339,6 +413,16 @@ public final class Skin { | |||
|                         } | ||||
|                         break; | ||||
| 
 | ||||
|                     case '#': | ||||
| 
 | ||||
|                         if (state == PARSE_MACRONAME && b.length() == 0) { | ||||
|                             // this is a subskin/skinlet | ||||
|                             isSubskinMacro = true; | ||||
|                             break; | ||||
|                         } | ||||
|                         b.append(source[i]); | ||||
|                         escape = false; | ||||
| 
 | ||||
|                     case '|': | ||||
| 
 | ||||
|                         if (!escape && quotechar == '\u0000') { | ||||
|  | @ -431,7 +515,17 @@ public final class Skin { | |||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             this.end = Math.min(sourceLength, i + 2); | ||||
|             i += 2; | ||||
|             if (isSubskinMacro) { | ||||
|                 if (i + 1 < length && source[i] == '\r' && source[i + 1] == '\n') | ||||
|                     end = Math.min(length, i + 2); | ||||
|                 else if (i < length && (source[i] == '\r' || source[i] == '\n')) | ||||
|                     end = Math.min(length, i + 1); | ||||
|                 else | ||||
|                     end = Math.min(length, i); | ||||
|             } else { | ||||
|                 end = Math.min(length, i); | ||||
|             } | ||||
| 
 | ||||
|             if (b.length() > 0) { | ||||
|                 if (name == null) { | ||||
|  | @ -462,11 +556,6 @@ public final class Skin { | |||
|                     handler = HANDLER_PARAM; | ||||
|                 } | ||||
|             } | ||||
|             // Set default failmode unless explicitly set: | ||||
|             // silent for default handlers, verbose | ||||
|             if (namedParams == null || !namedParams.containsKey("failmode")) { | ||||
|                 standardParams.silentFailMode = (handler < HANDLER_GLOBAL); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private void addParameter(String name, Object value) { | ||||
|  | @ -607,8 +696,8 @@ public final class Skin { | |||
|                             } | ||||
|                         } | ||||
|                         // display error message unless silent failmode is on | ||||
|                         if (handlerObject == null || !hasProperty(handlerObject, propName, reval)) { | ||||
|                             if (!standardParams.silentFailMode) { | ||||
|                         if (handlerObject == null || !reval.scriptingEngine.hasProperty(handlerObject, propName)) { | ||||
|                             if (standardParams.verboseFailmode(handlerObject,  reval)) { | ||||
|                                 String msg = "[Macro unhandled: " + name + "]"; | ||||
|                                 reval.getResponse().write(" " + msg + " "); | ||||
|                                 app.logEvent(msg); | ||||
|  | @ -616,13 +705,13 @@ public final class Skin { | |||
|                                 writeResponse(null, reval, thisObject, handlerCache, standardParams, true); | ||||
|                             } | ||||
|                         } else { | ||||
|                             Object value = getProperty(handlerObject, propName, reval); | ||||
|                             Object value = reval.scriptingEngine.getProperty(handlerObject, propName); | ||||
|                             writeResponse(value, reval, thisObject, handlerCache, standardParams, true); | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
|                 } else { | ||||
|                     if (!standardParams.silentFailMode) { | ||||
|                     if (standardParams.verboseFailmode(handlerObject, reval)) { | ||||
|                         String msg = "[Macro unhandled: " + name + "]"; | ||||
|                         reval.getResponse().write(" " + msg + " "); | ||||
|                         app.logEvent(msg); | ||||
|  | @ -770,12 +859,12 @@ public final class Skin { | |||
|         } | ||||
| 
 | ||||
|         private Object resolvePath(Object handler, RequestEvaluator reval) { | ||||
|             if (!app.allowDeepMacros && path.length > 2) { | ||||
|             if (path.length > 2 && !app.allowDeepMacros) { | ||||
|                 throw new RuntimeException("allowDeepMacros property must be true " + | ||||
|                         "in order to enable deep macro paths."); | ||||
|             } | ||||
|             for (int i = 1; i < path.length - 1; i++) { | ||||
|                 handler = getProperty(handler, path[i], reval); | ||||
|                 handler = reval.scriptingEngine.getProperty(handler, path[i]); | ||||
|                 if (handler == null) { | ||||
|                     break; | ||||
|                 } | ||||
|  | @ -783,23 +872,6 @@ public final class Skin { | |||
|             return handler; | ||||
|         } | ||||
| 
 | ||||
|         private Object getProperty(Object obj, String name, | ||||
|                                    RequestEvaluator reval) { | ||||
|             if (obj instanceof Map) { | ||||
|                 return ((Map) obj).get(name); | ||||
|             } else { | ||||
|                 return reval.getScriptingEngine().getProperty(obj, name); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private boolean hasProperty(Object obj, String name, RequestEvaluator reval) { | ||||
|             if (obj instanceof Map) { | ||||
|                 return ((Map) obj).containsKey(name); | ||||
|             } else { | ||||
|                 return reval.getScriptingEngine().hasProperty(obj, name); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /** | ||||
|          * Utility method for writing text out to the response object. | ||||
|          */ | ||||
|  | @ -822,7 +894,7 @@ public final class Skin { | |||
|                     return; | ||||
|                 } | ||||
|             } else { | ||||
|                 text = reval.getScriptingEngine().toString(value); | ||||
|                 text = reval.scriptingEngine.toString(value); | ||||
|             } | ||||
| 
 | ||||
|             if ((text != null) && (text.length() > 0)) { | ||||
|  | @ -887,7 +959,7 @@ public final class Skin { | |||
|         Object prefix = null; | ||||
|         Object suffix = null; | ||||
|         Object defaultValue = null; | ||||
|         boolean silentFailMode = false; | ||||
|         int failmode = FAIL_DEFAULT; | ||||
| 
 | ||||
|         StandardParams() {} | ||||
| 
 | ||||
|  | @ -895,7 +967,6 @@ public final class Skin { | |||
|             prefix = map.get("prefix"); | ||||
|             suffix = map.get("suffix"); | ||||
|             defaultValue = map.get("default"); | ||||
|             silentFailMode = "silent".equals(map.get("failmode")); | ||||
|         } | ||||
| 
 | ||||
|         boolean containsMacros() { | ||||
|  | @ -906,13 +977,18 @@ public final class Skin { | |||
| 
 | ||||
|         void setFailMode(Object value) { | ||||
|             if ("silent".equals(value)) | ||||
|                 silentFailMode = true; | ||||
|                 failmode = FAIL_SILENT; | ||||
|             else if ("verbose".equals(value)) | ||||
|                 silentFailMode = false; | ||||
|             else | ||||
|                 failmode = FAIL_VERBOSE; | ||||
|             else if (value != null) | ||||
|                 app.logEvent("unrecognized failmode value: " + value); | ||||
|         } | ||||
| 
 | ||||
|         boolean verboseFailmode(Object handler, RequestEvaluator reval) { | ||||
|             return (failmode == FAIL_VERBOSE) || | ||||
|                    (failmode == FAIL_DEFAULT && reval.scriptingEngine.isTypedObject(handler)); | ||||
|         } | ||||
| 
 | ||||
|         StandardParams render(RequestEvaluator reval, Object thisObj, Map handlerCache) | ||||
|                 throws UnsupportedEncodingException { | ||||
|             if (!containsMacros()) | ||||
|  |  | |||
|  | @ -42,12 +42,22 @@ public final class SkinManager implements FilenameFilter { | |||
|         skinExtension = ".skin"; | ||||
|     } | ||||
| 
 | ||||
|     protected Skin getSkin(Prototype proto, String skinname, Object[] skinpath) throws IOException { | ||||
|         if (proto == null) { | ||||
|     protected Skin getSkin(Prototype prototype, String skinname, Object[] skinpath) | ||||
|             throws IOException { | ||||
|         if (prototype == null) { | ||||
|             return null; | ||||
|         } | ||||
| 
 | ||||
|         Skin skin = null; | ||||
|         Skin skin; | ||||
|         Prototype proto = prototype; | ||||
| 
 | ||||
|         // if name contains dot, this might be a substring of some other string | ||||
|         String parentName = null, subskinName = null; | ||||
|         int hash = skinname.indexOf('#'); | ||||
|         if (hash > -1) { | ||||
|             parentName = skinname.substring(0, hash); | ||||
|             subskinName = skinname.substring(hash + 1); | ||||
|         } | ||||
| 
 | ||||
|         // First check if the skin has been already used within the execution of this request | ||||
|         // check for skinsets set via res.skinpath property | ||||
|  | @ -55,16 +65,23 @@ public final class SkinManager implements FilenameFilter { | |||
|             if (skinpath != null) { | ||||
|                 for (int i = 0; i < skinpath.length; i++) { | ||||
|                     skin = getSkinInPath(skinpath[i], proto.getName(), skinname); | ||||
| 
 | ||||
|                     if (skin != null) { | ||||
|                     if (skin != null && skin.hasMainskin()) { | ||||
|                         // check if skin skin contains main skin | ||||
|                         return skin; | ||||
|                     } else if (parentName != null) { | ||||
|                         // get parent skin | ||||
|                         skin = getSkinInPath(skinpath[i], proto.getName(), parentName); | ||||
|                         // check if it contains subskin | ||||
|                         if (skin != null && skin.hasSubskin(subskinName)) { | ||||
|                             return skin.getSubskin(subskinName); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             // skin for this prototype wasn't found in the skinsets. | ||||
|             // the next step is to look if it is defined as skin file in the application directory | ||||
|             skin = proto.getSkin(skinname); | ||||
|             skin = proto.getSkin(skinname, parentName, subskinName); | ||||
| 
 | ||||
|             if (skin != null) { | ||||
|                 return skin; | ||||
|  | @ -78,7 +95,7 @@ public final class SkinManager implements FilenameFilter { | |||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     protected Skin getSkinInPath(Object skinset, String prototype, String skinname) throws IOException { | ||||
|     private Skin getSkinInPath(Object skinset, String prototype, String skinname) throws IOException { | ||||
|         if ((prototype == null) || (skinset == null)) { | ||||
|             return null; | ||||
|         } | ||||
|  |  | |||
							
								
								
									
										43
									
								
								src/helma/framework/repository/AbstractResource.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/helma/framework/repository/AbstractResource.java
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,43 @@ | |||
| /* | ||||
|  * Helma License Notice | ||||
|  * | ||||
|  * The contents of this file are subject to the Helma License | ||||
|  * Version 2.0 (the "License"). You may not use this file except in | ||||
|  * compliance with the License. A copy of the License is available at | ||||
|  * http://adele.helma.org/download/helma/license.txt | ||||
|  * | ||||
|  * Copyright 1998-2003 Helma Software. All Rights Reserved. | ||||
|  * | ||||
|  * $RCSfile$ | ||||
|  * $Author$ | ||||
|  * $Revision$ | ||||
|  * $Date$ | ||||
|  */ | ||||
| 
 | ||||
| package helma.framework.repository; | ||||
| 
 | ||||
| /** | ||||
|  * Abstract resource base class that implents get/setOverloadedResource. | ||||
|  */ | ||||
| public abstract class AbstractResource implements Resource { | ||||
| 
 | ||||
|     protected Resource overloaded = null; | ||||
| 
 | ||||
|     /** | ||||
|      * Method for registering a Resource this Resource is overloading | ||||
|      * | ||||
|      * @param res the overloaded resource | ||||
|      */ | ||||
|     public void setOverloadedResource(Resource res) { | ||||
|         overloaded = res; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get a Resource this Resource is overloading | ||||
|      * | ||||
|      * @return the overloaded resource | ||||
|      */ | ||||
|     public Resource getOverloadedResource() { | ||||
|         return overloaded; | ||||
|     } | ||||
| } | ||||
|  | @ -19,7 +19,7 @@ package helma.framework.repository; | |||
| import java.net.*; | ||||
| import java.io.*; | ||||
| 
 | ||||
| public class FileResource implements Resource { | ||||
| public class FileResource extends AbstractResource { | ||||
| 
 | ||||
|     File file; | ||||
|     Repository repository; | ||||
|  |  | |||
|  | @ -41,25 +41,29 @@ public interface Resource { | |||
|     /** | ||||
|      * Returns the lengh of the resource's content | ||||
|      * @return content length | ||||
|      * @throws IOException I/O related problem | ||||
|      */ | ||||
|     public long getLength() throws IOException; | ||||
| 
 | ||||
|     /** | ||||
|      * Returns an input stream to the content of the resource | ||||
|      * @return content input stream | ||||
|      * @throws IOException I/O related problem | ||||
|      */ | ||||
|     public InputStream getInputStream() throws IOException; | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the content of the resource in a given encoding | ||||
|      * @param encoding | ||||
|      * @param encoding the character encoding | ||||
|      * @return content | ||||
|      * @throws IOException I/O related problem | ||||
|      */ | ||||
|     public String getContent(String encoding) throws IOException; | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the content of the resource | ||||
|      * @return content | ||||
|      * @throws IOException I/O related problem | ||||
|      */ | ||||
|     public String getContent() throws IOException; | ||||
| 
 | ||||
|  | @ -88,9 +92,22 @@ public interface Resource { | |||
|      * Returns an url to the resource if the repository of this resource is | ||||
|      * able to provide urls | ||||
|      * @return url to the resource | ||||
|      * @throws UnsupportedOperationException if resource does not support URL schema | ||||
|      */ | ||||
|     public URL getUrl() throws UnsupportedOperationException; | ||||
| 
 | ||||
|     /** | ||||
|      * Get a Resource this Resource is overloading | ||||
|      * @return the overloaded resource | ||||
|      */ | ||||
|     public Resource getOverloadedResource(); | ||||
| 
 | ||||
|     /** | ||||
|      * Method for registering a Resource this Resource is overloading | ||||
|      * @param res the overloaded resource | ||||
|      */ | ||||
|     public void setOverloadedResource(Resource res); | ||||
| 
 | ||||
|     /** | ||||
|      * Returns the repository the resource does belong to | ||||
|      * @return upper repository | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ import java.net.URL; | |||
| import java.util.zip.ZipEntry; | ||||
| import java.util.zip.ZipFile; | ||||
| 
 | ||||
| public final class ZipResource implements Resource { | ||||
| public final class ZipResource extends AbstractResource { | ||||
| 
 | ||||
|     private String entryName; | ||||
|     private ZipRepository repository; | ||||
|  |  | |||
|  | @ -110,10 +110,10 @@ public interface ScriptingEngine { | |||
|     /** | ||||
|      * Get a property on an object | ||||
|      * @param thisObject the object | ||||
|      * @param key the property name | ||||
|      * @param propertyName the property name | ||||
|      * @return true the property value, or null | ||||
|      */ | ||||
|     public Object getProperty(Object thisObject, String key); | ||||
|     public Object getProperty(Object thisObject, String propertyName); | ||||
| 
 | ||||
|     /** | ||||
|      * Return true if a function by that name is defined for that object. | ||||
|  | @ -131,6 +131,13 @@ public interface ScriptingEngine { | |||
|      */ | ||||
|     public boolean hasProperty(Object thisObject, String propertyName); | ||||
| 
 | ||||
|     /** | ||||
|      * Determine if the given object is mapped to a type of the scripting engine | ||||
|      * @param obj an object | ||||
|      * @return true if the object is mapped to a type | ||||
|      */ | ||||
|     public boolean isTypedObject(Object obj); | ||||
| 
 | ||||
|     /** | ||||
|      * Return a string representation for the given object | ||||
|      * @param obj an object | ||||
|  |  | |||
|  | @ -346,28 +346,31 @@ public class RhinoEngine implements ScriptingEngine { | |||
|         // references/child objects just to check for function properties. | ||||
|         if (obj instanceof INode) { | ||||
|             String protoname = ((INode) obj).getPrototype(); | ||||
|             return core.hasFunction(protoname, fname); | ||||
|             if (protoname != null && core.hasFunction(protoname, fname)) | ||||
|                 return true; | ||||
|         } | ||||
| 
 | ||||
|         Scriptable op = obj == null ? global : Context.toObject(obj, global); | ||||
| 
 | ||||
|         Object func = ScriptableObject.getProperty(op, fname); | ||||
| 
 | ||||
|         return func instanceof Callable; | ||||
|         return ScriptableObject.getProperty(op, fname) instanceof Callable; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if an object has a value property defined with that name. | ||||
|      */ | ||||
|     public boolean hasProperty(Object obj, String propname) { | ||||
|         if ((obj == null) || (propname == null)) { | ||||
|         if (obj == null || propname == null) { | ||||
|             return false; | ||||
|         } else if (obj instanceof Map) { | ||||
|             return ((Map) obj).containsKey(propname); | ||||
|         } | ||||
| 
 | ||||
|         String prototypeName = app.getPrototypeName(obj); | ||||
| 
 | ||||
|         if ("user".equalsIgnoreCase(prototypeName) | ||||
|                 && "password".equalsIgnoreCase(propname)) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         // if this is a HopObject, check if the property is defined | ||||
|         // in the type.properties db-mapping. | ||||
|         if (obj instanceof INode && ! "hopobject".equalsIgnoreCase(prototypeName)) { | ||||
|  | @ -386,22 +389,36 @@ public class RhinoEngine implements ScriptingEngine { | |||
|      * is a java object) with that name. | ||||
|      */ | ||||
|     public Object getProperty(Object obj, String propname) { | ||||
|         if ((obj == null) || (propname == null)) | ||||
|         if (obj == null || propname == null) { | ||||
|             return null; | ||||
|         } else if (obj instanceof Map) { | ||||
|             Object prop = ((Map) obj).get(propname); | ||||
|             // Do not return functions as properties as this | ||||
|             // is a potential security problem | ||||
|             return (prop instanceof Function) ? null : prop; | ||||
|         } else if (obj instanceof INode) { | ||||
|             IProperty prop = ((INode) obj).get(propname); | ||||
|             if (prop == null) return null; | ||||
|             Object value = prop.getValue(); | ||||
|             return (value instanceof Function) ? null : value; | ||||
|         } | ||||
| 
 | ||||
|         // use Rhino wrappers and methods to get property | ||||
|         Scriptable so = Context.toObject(obj, global); | ||||
| 
 | ||||
|         try { | ||||
|             Object prop = so.get(propname, so); | ||||
| 
 | ||||
|             if ((prop == null) | ||||
|                     || (prop == Undefined.instance) | ||||
| 	                || (prop == ScriptableObject.NOT_FOUND)) { | ||||
|             if (prop == null | ||||
|                     || prop == Undefined.instance | ||||
| 	                || prop == ScriptableObject.NOT_FOUND) { | ||||
|                 return null; | ||||
|             } else if (prop instanceof Wrapper) { | ||||
|                 return ((Wrapper) prop).unwrap(); | ||||
|             } else { | ||||
|                 return prop; | ||||
|                 // Do not return functions as properties as this | ||||
|                 // is a potential security problem | ||||
|                 return (prop instanceof Function) ? null : prop; | ||||
|             } | ||||
|         } catch (Exception esx) { | ||||
|             app.logError("Error getting property " + propname + ": " + esx); | ||||
|  | @ -410,6 +427,22 @@ public class RhinoEngine implements ScriptingEngine { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     /** | ||||
|      * Determine if the given object is mapped to a type of the scripting engine | ||||
|      * @param obj an object | ||||
|      * @return true if the object is mapped to a type | ||||
|      */ | ||||
|     public boolean isTypedObject(Object obj) { | ||||
|         if (obj == null || obj instanceof Map || obj instanceof NativeObject) | ||||
|             return false; | ||||
|         if (obj instanceof INode) { | ||||
|             String protoName = app.getPrototypeName(obj); | ||||
|             return protoName != null && !"hopobject".equalsIgnoreCase(protoName); | ||||
|         } | ||||
|         // assume java object is typed | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Return a string representation for the given object | ||||
|      * @param obj an object | ||||
|  | @ -544,7 +577,9 @@ public class RhinoEngine implements ScriptingEngine { | |||
|      * Try to get a skin from the parameter object. | ||||
|      */ | ||||
|     public Skin toSkin(Object skinobj, String protoName) throws IOException { | ||||
|         if (skinobj instanceof Wrapper) { | ||||
|         if (skinobj == null) { | ||||
|             return null; | ||||
|         } else if (skinobj instanceof Wrapper) { | ||||
|             skinobj = ((Wrapper) skinobj).unwrap(); | ||||
|         } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue