[ 
http://issues.apache.org/struts/browse/SHALE-183?page=comments#action_37925 ] 
            
Ed Burns commented on SHALE-183:
--------------------------------

Here is a snapshot of a diff to fix this issue.  I have added a unit test to 
the MappingImplTest to exercise this much of the feature:

parse the shale-remoting-resource-library.json for each such file in the webapp 
classloader into a session scoped in memory data structure.  It could be app 
scoped really, but session is safer for thread safety reasons due to its lazy 
initialization status.

To make it app scoped, we'd need some way to parse the files before the app is 
placed into service, and currently shale remoting doesn't seem to have that 
hook.

I  will attach a tarbal of changed files as well.

This feature is in progress.

Index: src/test/java/org/apache/shale/remoting/impl/MappingImplTestCase.java
===================================================================
--- src/test/java/org/apache/shale/remoting/impl/MappingImplTestCase.java       
(revision 428935)
+++ src/test/java/org/apache/shale/remoting/impl/MappingImplTestCase.java       
(working copy)
@@ -244,8 +244,22 @@
                      mapping.mapResourceId(facesContext, resourceId));
 
     }
+    
+    // Test that initialize creates a Map in application scope.
+    public void testInitialize() throws Exception {
 
+        String resourceId = "/foo/bar.baz";
 
+        // FacesServlet=prefix Mapping=prefix
+        mappings.setPatterns(new String[] { "/faces/*" });
+        mapping.setPattern("/bop/*");
+        assertEquals("/webapp/faces/bop/foo/bar.baz",
+                     mapping.mapResourceId(facesContext, resourceId));
+
+        
assertTrue(facesContext.getExternalContext().getSessionMap().containsKey("org.apache.shale.remoting.RESOURCE_LIBRARIES"));
+    }
+
+
     // --------------------------------------------------------- Support 
Methods
 
 
Index: src/test/resources/META-INF/shale-remoting-resource-library.json
===================================================================
--- src/test/resources/META-INF/shale-remoting-resource-library.json    
(revision 0)
+++ src/test/resources/META-INF/shale-remoting-resource-library.json    
(revision 0)
@@ -0,0 +1 @@
+{ resourceIds: [ "prototype" ],  prototype: { versions: [ "1.4.0", "1.2.0" ], 
"1.4.0": [ "1.4.0/prototype.js", "1.4.0/effects.js", "1.4.0/dragdrop.js", 
"1.4.0/controls.js" ], "1.2.0": [ "1.2.0/prototype.js", "1.2.0/effects.js", 
"1.2.0/dragdrop.js", "1.2.0/controls.js" ]  } };
Index: src/test/resources/META-INF/shale-remoting-resource-library.json
===================================================================
--- src/test/resources/META-INF/shale-remoting-resource-library.json    
(revision 0)
+++ src/test/resources/META-INF/shale-remoting-resource-library.json    
(revision 0)
@@ -0,0 +1 @@
+{ resourceIds: [ "prototype" ],  prototype: { versions: [ "1.4.0", "1.2.0" ], 
"1.4.0": [ "1.4.0/prototype.js", "1.4.0/effects.js", "1.4.0/dragdrop.js", 
"1.4.0/controls.js" ], "1.2.0": [ "1.2.0/prototype.js", "1.2.0/effects.js", 
"1.2.0/dragdrop.js", "1.2.0/controls.js" ]  } };
Index: src/main/java/org/apache/shale/remoting/impl/MappingImpl.java
===================================================================
--- src/main/java/org/apache/shale/remoting/impl/MappingImpl.java       
(revision 428935)
+++ src/main/java/org/apache/shale/remoting/impl/MappingImpl.java       
(working copy)
@@ -16,7 +16,25 @@
 
 package org.apache.shale.remoting.impl;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import javax.faces.FacesException;
 import javax.faces.context.FacesContext;
+import net.sf.json.JSONArray;
+import net.sf.json.JSONObject;
 import org.apache.shale.remoting.Mapping;
 import org.apache.shale.remoting.Mappings;
 import org.apache.shale.remoting.Mechanism;
@@ -178,6 +196,8 @@
 
     /** [EMAIL PROTECTED] */
     public String mapResourceId(FacesContext context, String resourceId) {
+        
+        initialize(context);
 
         // Acquire the servlet mapping to be used for FacesServlet (if any --
         // there will not be such a mapping in a portlet environment)
@@ -327,5 +347,167 @@
         return viewId;
 
     }
+    
+    private static final String RESOURCE_LIBRARIES_KEY = 
+            "org.apache.shale.remoting.RESOURCE_LIBRARIES";
+    private static final String RESOURCE_LIBRARY_METAFILE = 
+            "META-INF/shale-remoting-resource-library.json";
+    
+    private void initialize(FacesContext context) {
+        Map sessionMap = context.getExternalContext().getSessionMap();
+        if (sessionMap.containsKey(RESOURCE_LIBRARIES_KEY)) {
+            return;
+        }
 
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        Iterator resources;
+        SortedMap sortedJarMap = new TreeMap();
+        List unsortedResourceList = new ArrayList();
+        String jarName = null, jarUrl = null;
+        URL nextElement = null;
+        int sepIndex, resourceIndex = 0;
+        char sep = ' ';
+        try {
+            Enumeration items = cl.getResources(RESOURCE_LIBRARY_METAFILE);
+            while (items.hasMoreElements()) {
+                nextElement = (URL) items.nextElement();
+                jarUrl = nextElement.toString();
+                jarName = null;
+                // If this resource has a RESOURCE_LIBRARY_METAFILE file 
inside of it
+                if (-1 != (resourceIndex =
+                        jarUrl.indexOf(RESOURCE_LIBRARY_METAFILE))) {
+                    // Search backwards for the previous occurrence of 
File.SEPARATOR
+                    sepIndex = resourceIndex - 2;
+                    while (0 < sepIndex) {
+                        sep = jarUrl.charAt(sepIndex);
+                        if ('/' == sep) {
+                            break;
+                        }
+                        sepIndex--;
+                    }
+                    if ('/' == sep) {
+                        jarName =
+                                jarUrl.substring(sepIndex + 1, resourceIndex);
+                    }
+                }
+                if (null != jarName) {
+                    sortedJarMap.put(jarName, nextElement);
+                } else {
+                    unsortedResourceList.add(0, nextElement);
+                }
+            }
+        } catch (IOException e) {
+            throw new FacesException(e);
+        }
+        Map resourceLibs = new HashMap();
+        sessionMap.put(RESOURCE_LIBRARIES_KEY, resourceLibs);
+        // Load the sorted resources first:
+        Iterator sortedResources =
+                sortedJarMap.entrySet().iterator();
+        while (sortedResources.hasNext()) {
+            nextElement = (URL) ((Map.Entry)sortedResources.next()).getValue();
+            parseResourceMetafile(nextElement, resourceLibs);
+        }
+        // Then load the unsorted resources
+        resources = unsortedResourceList.iterator();
+        while (resources.hasNext()) {
+            nextElement = (URL) resources.next();
+            parseResourceMetafile(nextElement, resourceLibs);
+        }
+
+    }
+    
+    private void parseResourceMetafile(URL url, Map cur_resourceLibs) {
+        URLConnection conn = null;
+        BufferedReader reader = null;
+        StringBuffer buf = new StringBuffer();
+        final String message = "Cannot read resource library metafile for " +
+                    url.toString();
+        try {
+            conn = url.openConnection();
+            conn.setUseCaches(false);
+            reader = new BufferedReader(new 
InputStreamReader(conn.getInputStream()));
+            String line = null;
+            while (null != (line = reader.readLine())) {
+                buf.append(line);
+            }
+        } 
+        catch (Exception e) {
+            throw new FacesException(message, e);
+        } finally {
+            if (reader != null) {
+                try {
+                    reader.close();
+                } catch (Exception e) {
+                    ;
+                }
+            }
+            reader = null;
+        }
+        
+        // The JSON file currently being parsed is referred to as the 
+        // "metafile", for discussion.  Local variables prefixed with
+        // mf_ represent information from the metafile.  Local variables
+        // prefixed with cur_ represent informatino from the in memory
+        // data structure.
+        
+        // Parse the contents of the metafile into a JSONObject.
+        JSONObject mf_jsonObj = new JSONObject(buf.toString()),
+                   mf_resourceLib = null;
+        List cur_versionsList = null,
+             mf_versionsList = null, 
+             // Extract the metafile's top level "resourceIds" key, 
+             // which is a JSON Array.
+             mf_resourceIdsList = 
JSONArray.toList(mf_jsonObj.getJSONArray("resourceIds"),
+                String.class);
+        Iterator mf_versionsIter = null, 
+                mf_resourceIdsIter = mf_resourceIdsList.iterator();
+        Map cur_versions = null, cur_resourceLib = null;
+        
+        String mf_resourceLibName, mf_version = null;
+        try {
+            // For each element in the "resourceIds" JSON Array in the 
metafile...
+            while (mf_resourceIdsIter.hasNext()) {
+                // Get the next resourceLibName from the metafile.
+                mf_resourceLibName = mf_resourceIdsIter.next().toString();
+                // Get the corresponding JSONObject for this resource library 
in the metafile.
+                mf_resourceLib = mf_jsonObj.getJSONObject(mf_resourceLibName);
+                mf_versionsList = 
JSONArray.toList(mf_resourceLib.getJSONArray("versions"),
+                        String.class);
+                mf_versionsIter = mf_versionsList.iterator();
+                // Check if already have a resource library with this name in 
our
+                // data structure.
+                cur_resourceLib = (Map) 
cur_resourceLibs.get(mf_resourceLibName);
+                if (null == cur_resourceLib) {
+                    // If not, create a new resourceLib Map for this 
mf_resourceLibName.
+                    cur_resourceLib = new HashMap();
+                    // Put it into the in memory data structure
+                    cur_resourceLibs.put(mf_resourceLibName, cur_resourceLib);
+                }
+                // For each version of mf_resourceLibName in the metafile...
+                while (mf_versionsIter.hasNext()) {
+                    mf_version = mf_versionsIter.next().toString();
+                    // see if we already have this version of 
mf_resourceLibName
+                    // in memory.
+                    cur_versionsList = (List) cur_resourceLib.get(mf_version);
+                    if (null != cur_versionsList) {
+                        // If so, log a message and replace the current
+                        // versionList with the content of the mf_versionList,
+                        // PENDING(edburns): log message
+                    }
+                    // In any case, get the contents of this version of
+                    // mf_resourceLibName of the metafile as a list...
+                    cur_versionsList =
+                            
JSONArray.toList(mf_resourceLib.getJSONArray(mf_version));
+                    // and put into cur_resourceLib under the key mf_version
+                    cur_resourceLib.put(mf_version, cur_versionsList);
+                }
+            }
+        }
+        catch (Exception e) {
+            throw new FacesException(message, e);
+        }
+
+    }
+
 }
Index: pom.xml
===================================================================
--- pom.xml     (revision 428935)
+++ pom.xml     (working copy)
@@ -33,7 +33,34 @@
     <artifactId>shale-remoting</artifactId>
     <packaging>jar</packaging>
     <name>Shale Remoting Support</name>
+    <version>1.0.3a-SNAPSHOT</version>
 
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                 <argLine>-Xdebug 
-Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y</argLine>
+               </configuration>            
+           </plugin>
+
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.4</source>
+                    <target>1.4</target>
+                    <debug>true</debug>
+                </configuration>
+             </plugin>
+
+        </plugins>
+
+    </build>
+
+
 <!--
     <build>
         <plugins>
@@ -69,6 +96,12 @@
         </dependency>
 
         <dependency>
+            <groupId>net.sf.json</groupId>
+            <artifactId>json-lib</artifactId>
+            <version>0.6</version>
+        </dependency>
+
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>
@@ -77,7 +110,7 @@
         <dependency>
             <groupId>org.apache.shale</groupId>
             <artifactId>shale-test</artifactId>
-            <version>${version}</version>
+            <version>${parent.version}</version>
             <scope>test</scope>
         </dependency>
 


> Shale Remoting doesn't support linking Javascript of popular javascript 
> libraries.
> ----------------------------------------------------------------------------------
>
>                 Key: SHALE-183
>                 URL: http://issues.apache.org/struts/browse/SHALE-183
>             Project: Shale
>          Issue Type: Improvement
>          Components: Remoting
>            Reporter: Ed Burns
>
> I would like to have an enhancement to XhtmlHelper.linkJavascript() that 
> supported many different popular JavaScript libraries.  For example, I'd like 
> to do something like:
> getXhtmlHelper().linkJavascript(context, component, writer,
>                         Mechanism.CLASS_RESOURCE, "dojo", "0.3.0");
> getXhtmlHelper().linkJavascript(context, component, writer,
>                         Mechanism.CLASS_RESOURCE, "prototype", "1.4.0");
> getXhtmlHelper().linkJavascript(context, component, writer,
>                         Mechanism.CLASS_RESOURCE, "scriptaculous", "1.6.1");
> And rest assured in the knowledge that the proper script elemnets will be 
> rendered out iff no-one else on this request has asked for these scripts to 
> be rendered.  
> If we make jMaki and jsf-extensions use this, then we can save a lot of code 
> and bandwidth.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
http://issues.apache.org/struts/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to