You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2013/10/25 23:24:10 UTC

svn commit: r1535874 [3/9] - in /myfaces/shared/trunk/core/src: main/java/org/apache/myfaces/shared/application/ main/java/org/apache/myfaces/shared/config/ main/java/org/apache/myfaces/shared/context/flash/ main/java/org/apache/myfaces/shared/renderki...

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/JavascriptContext.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/JavascriptContext.java?rev=1535874&r1=1535873&r2=1535874&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/JavascriptContext.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/JavascriptContext.java Fri Oct 25 21:24:09 2013
@@ -1,160 +1,160 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.myfaces.shared.renderkit.html;
-
-/**
- * The ScriptContext offers methods and fields
- * to help with rendering out a script and keeping a
- * proper formatting.
- */
-public class JavascriptContext
-{
-    private static final String LINE_SEPARATOR = System.getProperty(
-            "line.separator", "\r\n");
-    private static final char TABULATOR = '\t';
-
-    private long currentIndentationLevel;
-    private StringBuilder buffer = new StringBuilder();
-    private boolean prettyPrint = false;
-    /**
-     * automatic formatting will render
-     * new-lines and indents if blocks are opened
-     * and closed - attention: you need to append
-     * opening and closing brackets of blocks separately in this case!
-     */
-    private boolean automaticFormatting = true;
-
-    public JavascriptContext()
-    {
-
-    }
-
-    public JavascriptContext(boolean prettyPrint)
-    {
-        this.prettyPrint = prettyPrint;
-    }
-
-    public JavascriptContext(StringBuilder buf, boolean prettyPrint)
-    {
-        this.prettyPrint = prettyPrint;
-        this.buffer = buf;
-    }
-
-    public void increaseIndent()
-    {
-        currentIndentationLevel++;
-    }
-
-    public void decreaseIndent()
-    {
-        currentIndentationLevel--;
-
-        if (currentIndentationLevel < 0)
-        {
-            currentIndentationLevel = 0;
-        }
-    }
-
-    public void prettyLine()
-    {
-        if (prettyPrint)
-        {
-            append(LINE_SEPARATOR);
-
-            for (int i = 0; i < getCurrentIndentationLevel(); i++)
-            {
-                append(TABULATOR);
-            }
-        }
-    }
-
-    public void prettyLineIncreaseIndent()
-    {
-        increaseIndent();
-        prettyLine();
-    }
-
-    public void prettyLineDecreaseIndent()
-    {
-        decreaseIndent();
-        prettyLine();
-    }
-
-    public long getCurrentIndentationLevel()
-    {
-        return currentIndentationLevel;
-    }
-
-    public void setCurrentIndentationLevel(long currentIndentationLevel)
-    {
-        this.currentIndentationLevel = currentIndentationLevel;
-    }
-
-    public JavascriptContext append(String str)
-    {
-
-        if (automaticFormatting && str.length() == 1)
-        {
-            boolean openBlock = str.equals("{");
-            boolean closeBlock = str.equals("}");
-
-            if (openBlock)
-            {
-                prettyLine();
-            }
-            else if (closeBlock)
-            {
-                prettyLineDecreaseIndent();
-            }
-
-            buffer.append(str);
-
-            if (openBlock)
-            {
-                prettyLineIncreaseIndent();
-            }
-            else if (closeBlock)
-            {
-                prettyLine();
-            }
-        }
-        else
-        {
-            buffer.append(str);
-        }
-        return this;
-    }
-
-    public JavascriptContext append(char c)
-    {
-        buffer.append(c);
-        return this;
-    }
-
-    public JavascriptContext append(int i)
-    {
-        buffer.append(i);
-        return this;
-    }
-
-    public String toString()
-    {
-        return buffer.toString();
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.shared.renderkit.html;
+
+/**
+ * The ScriptContext offers methods and fields
+ * to help with rendering out a script and keeping a
+ * proper formatting.
+ */
+public class JavascriptContext
+{
+    private static final String LINE_SEPARATOR = System.getProperty(
+            "line.separator", "\r\n");
+    private static final char TABULATOR = '\t';
+
+    private long currentIndentationLevel;
+    private StringBuilder buffer = new StringBuilder();
+    private boolean prettyPrint = false;
+    /**
+     * automatic formatting will render
+     * new-lines and indents if blocks are opened
+     * and closed - attention: you need to append
+     * opening and closing brackets of blocks separately in this case!
+     */
+    private boolean automaticFormatting = true;
+
+    public JavascriptContext()
+    {
+
+    }
+
+    public JavascriptContext(boolean prettyPrint)
+    {
+        this.prettyPrint = prettyPrint;
+    }
+
+    public JavascriptContext(StringBuilder buf, boolean prettyPrint)
+    {
+        this.prettyPrint = prettyPrint;
+        this.buffer = buf;
+    }
+
+    public void increaseIndent()
+    {
+        currentIndentationLevel++;
+    }
+
+    public void decreaseIndent()
+    {
+        currentIndentationLevel--;
+
+        if (currentIndentationLevel < 0)
+        {
+            currentIndentationLevel = 0;
+        }
+    }
+
+    public void prettyLine()
+    {
+        if (prettyPrint)
+        {
+            append(LINE_SEPARATOR);
+
+            for (int i = 0; i < getCurrentIndentationLevel(); i++)
+            {
+                append(TABULATOR);
+            }
+        }
+    }
+
+    public void prettyLineIncreaseIndent()
+    {
+        increaseIndent();
+        prettyLine();
+    }
+
+    public void prettyLineDecreaseIndent()
+    {
+        decreaseIndent();
+        prettyLine();
+    }
+
+    public long getCurrentIndentationLevel()
+    {
+        return currentIndentationLevel;
+    }
+
+    public void setCurrentIndentationLevel(long currentIndentationLevel)
+    {
+        this.currentIndentationLevel = currentIndentationLevel;
+    }
+
+    public JavascriptContext append(String str)
+    {
+
+        if (automaticFormatting && str.length() == 1)
+        {
+            boolean openBlock = str.equals("{");
+            boolean closeBlock = str.equals("}");
+
+            if (openBlock)
+            {
+                prettyLine();
+            }
+            else if (closeBlock)
+            {
+                prettyLineDecreaseIndent();
+            }
+
+            buffer.append(str);
+
+            if (openBlock)
+            {
+                prettyLineIncreaseIndent();
+            }
+            else if (closeBlock)
+            {
+                prettyLine();
+            }
+        }
+        else
+        {
+            buffer.append(str);
+        }
+        return this;
+    }
+
+    public JavascriptContext append(char c)
+    {
+        buffer.append(c);
+        return this;
+    }
+
+    public JavascriptContext append(int i)
+    {
+        buffer.append(i);
+        return this;
+    }
+
+    public String toString()
+    {
+        return buffer.toString();
+    }
+}

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/HTMLEncoder.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/HTMLEncoder.java?rev=1535874&r1=1535873&r2=1535874&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/HTMLEncoder.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/HTMLEncoder.java Fri Oct 25 21:24:09 2013
@@ -103,6 +103,14 @@ public abstract class HTMLEncoder
                     default:
                         break;
                 }
+                // http://www.w3.org/MarkUp/html3/specialchars.html
+                // From C0 extension U+0000-U+001F only U+0009, U+000A and
+                // U+000D are valid control characters
+                if (c <= 0x1F && c != 0x09 && c != 0x0A && c != 0x0D)
+                {
+                    // Ignore escape character
+                    app = "";
+                }
             }
             else if (encodeNonLatin && (int)c > 0x80)
             {
@@ -226,6 +234,14 @@ public abstract class HTMLEncoder
                     default:
                         break;
                 }
+                // http://www.w3.org/MarkUp/html3/specialchars.html
+                // From C0 extension U+0000-U+001F only U+0009, U+000A and
+                // U+000D are valid control characters
+                if (c <= 0x1F && c != 0x09 && c != 0x0A && c != 0x0D)
+                {
+                    // Ignore escape character
+                    app = "";
+                }
             }
             else if (encodeNonLatin && (int)c > 0x80)
             {
@@ -377,6 +393,14 @@ public abstract class HTMLEncoder
                     default:
                         break;
                 }
+                // http://www.w3.org/MarkUp/html3/specialchars.html
+                // From C0 extension U+0000-U+001F only U+0009, U+000A and
+                // U+000D are valid control characters
+                if (c <= 0x1F && c != 0x09 && c != 0x0A && c != 0x0D)
+                {
+                    // Ignore escape character
+                    app = "";
+                }
             }
             else if (encodeNonLatin && (int)c > 0x80)
             {
@@ -612,8 +636,8 @@ public abstract class HTMLEncoder
                 {
                     char c1 = string.charAt(i+1);
                     char c2 = string.charAt(i+2);
-                    if ((( c1 >= '0' && c1 <='9') || (c1 >='A' && c1 <='Z')) &&
-                        (( c2 >= '0' && c2 <='9') || (c2 >='A' && c2 <='Z')))
+                    if ((( c1 >= '0' && c1 <='9') || (c1 >='A' && c1 <='Z') || (c1 >='a' && c1 <='z')) &&
+                        (( c2 >= '0' && c2 <='9') || (c2 >='A' && c2 <='Z') || (c2 >='a' && c2 <='z')))
                     {
                         // do not percent encode, because it could be already encoded
                         // and we don't want encode it twice
@@ -771,8 +795,8 @@ public abstract class HTMLEncoder
                 {
                     char c1 = string.charAt(i+1);
                     char c2 = string.charAt(i+2);
-                    if ((( c1 >= '0' && c1 <='9') || (c1 >='A' && c1 <='Z')) &&
-                        (( c2 >= '0' && c2 <='9') || (c2 >='A' && c2 <='Z')))
+                    if ((( c1 >= '0' && c1 <='9') || (c1 >='A' && c1 <='Z') || (c1 >='a' && c1 <='z')) &&
+                        (( c2 >= '0' && c2 <='9') || (c2 >='A' && c2 <='Z') || (c2 >='a' && c2 <='z')))
                     {
                         // do not percent encode, because it could be already encoded
                     }
@@ -1010,8 +1034,8 @@ public abstract class HTMLEncoder
                 {
                     char c1 = string.charAt(i+1);
                     char c2 = string.charAt(i+2);
-                    if ((( c1 >= '0' && c1 <='9') || (c1 >='A' && c1 <='Z')) &&
-                        (( c2 >= '0' && c2 <='9') || (c2 >='A' && c2 <='Z')))
+                    if ((( c1 >= '0' && c1 <='9') || (c1 >='A' && c1 <='Z') || (c1 >='a' && c1 <='z')) &&
+                        (( c2 >= '0' && c2 <='9') || (c2 >='A' && c2 <='Z') || (c2 >='a' && c2 <='z')))
                     {
                         // do not percent encode, because it could be already encoded
                         // and we don't want encode it twice
@@ -1221,8 +1245,8 @@ public abstract class HTMLEncoder
                 {
                     char c1 = string.charAt(i+1);
                     char c2 = string.charAt(i+2);
-                    if ((( c1 >= '0' && c1 <='9') || (c1 >='A' && c1 <='Z')) &&
-                        (( c2 >= '0' && c2 <='9') || (c2 >='A' && c2 <='Z')))
+                    if ((( c1 >= '0' && c1 <='9') || (c1 >='A' && c1 <='Z') || (c1 >='a' && c1 <='z')) &&
+                        (( c2 >= '0' && c2 <='9') || (c2 >='A' && c2 <='Z') || (c2 >='a' && c2 <='z')))
                     {
                         // do not percent encode, because it could be already encoded
                     }

Added: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/HttpPartWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/HttpPartWrapper.java?rev=1535874&view=auto
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/HttpPartWrapper.java (added)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/HttpPartWrapper.java Fri Oct 25 21:24:09 2013
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.shared.renderkit.html.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+import javax.faces.FacesWrapper;
+import javax.faces.component.StateHolder;
+import javax.faces.context.FacesContext;
+import javax.servlet.http.Part;
+
+/**
+ *
+ * @author Leonardo Uribe
+ */
+public class HttpPartWrapper implements Part, FacesWrapper<Part>, StateHolder
+{
+    private Part delegate;
+
+    public HttpPartWrapper()
+    {
+    }
+    
+    public HttpPartWrapper(Part delegate)
+    {
+        this.delegate = delegate;
+    }
+
+    public void delete() throws IOException
+    {
+        getWrapped().delete();
+    }
+
+    public String getContentType()
+    {
+        return getWrapped().getContentType();
+    }
+
+    public String getHeader(String headerName)
+    {
+        return getWrapped().getHeader(headerName);
+    }
+
+    public Collection<String> getHeaderNames()
+    {
+        return getWrapped().getHeaderNames();
+    }
+
+    public Collection<String> getHeaders(String headerName)
+    {
+        return getWrapped().getHeaders(headerName);
+    }
+
+    public InputStream getInputStream() throws IOException
+    {
+        return getWrapped().getInputStream();
+    }
+
+    public String getName()
+    {
+        return getWrapped().getName();
+    }
+
+    public long getSize()
+    {
+        return getWrapped().getSize();
+    }
+
+    public void write(String fileName) throws IOException
+    {
+        getWrapped().write(fileName);
+    }
+
+    public Object saveState(FacesContext context)
+    {
+        return null;
+    }
+
+    public void restoreState(FacesContext context, Object state)
+    {
+    }
+
+    public boolean isTransient()
+    {
+        return true;
+    }
+
+    public void setTransient(boolean newTransientValue)
+    {
+    }
+
+    public Part getWrapped()
+    {
+        return delegate;
+    }
+    
+}

Added: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/OutcomeTargetUtils.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/OutcomeTargetUtils.java?rev=1535874&view=auto
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/OutcomeTargetUtils.java (added)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/OutcomeTargetUtils.java Fri Oct 25 21:24:09 2013
@@ -0,0 +1,285 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.shared.renderkit.html.util;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.faces.FacesException;
+import javax.faces.application.ConfigurableNavigationHandler;
+import javax.faces.application.NavigationCase;
+import javax.faces.application.NavigationHandler;
+import javax.faces.application.ProjectStage;
+import javax.faces.application.ViewHandler;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIOutcomeTarget;
+import javax.faces.component.UIParameter;
+import javax.faces.context.FacesContext;
+import javax.faces.flow.FlowHandler;
+import org.apache.myfaces.shared.application.NavigationUtils;
+import org.apache.myfaces.shared.renderkit.JSFAttr;
+import org.apache.myfaces.shared.renderkit.RendererUtils;
+import org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils;
+
+/**
+ * Utility methods for OutcomeTarget components.
+ *
+ * @author Leonardo Uribe
+ */
+public class OutcomeTargetUtils
+{
+    
+    private static final Logger log = Logger.getLogger(OutcomeTargetUtils.class
+            .getName());
+    
+    public static String getOutcomeTargetHref(FacesContext facesContext,
+            UIOutcomeTarget component) throws IOException
+    {
+        String outcome = component.getOutcome();
+        outcome = (outcome == null) ? facesContext.getViewRoot().getViewId()
+                : outcome;
+        outcome = ((outcome == null) ? HtmlRendererUtils.STR_EMPTY : outcome.trim());
+        // Get the correct URL for the outcome.
+        NavigationHandler nh = facesContext.getApplication().getNavigationHandler();
+        if (!(nh instanceof ConfigurableNavigationHandler))
+        {
+            throw new FacesException(
+                    "Navigation handler must be an instance of "
+                            + "ConfigurableNavigationHandler for using h:link or h:button");
+        }
+        ConfigurableNavigationHandler navigationHandler = (ConfigurableNavigationHandler) nh;
+        
+        // handle faces flow 
+        // 1. check to-flow-document-id
+        String toFlowDocumentId = (String) component.getAttributes().get(
+            JSFAttr.TO_FLOW_DOCUMENT_ID_ATTR);
+        
+        // fromAction is null because there is no action method that was called to get the outcome
+        NavigationCase navigationCase = null;
+        if (toFlowDocumentId == null)
+        {
+            navigationCase = navigationHandler.getNavigationCase(
+                facesContext, null, outcome);
+        }
+        else
+        {
+            navigationCase = navigationHandler.getNavigationCase(
+                facesContext, null, outcome, toFlowDocumentId);            
+        }
+        
+        // when navigation case is null, force the link or button to be disabled and log a warning
+        if (navigationCase == null)
+        {
+            // log a warning
+            log.warning("Could not determine NavigationCase for UIOutcomeTarget component "
+                    + RendererUtils.getPathToComponent(component));
+
+            return null;
+        }
+        Map<String, List<String>> parameters = null;
+        // handle URL parameters
+        if (component.getChildCount() > 0)
+        {
+            List<UIParameter> validParams = getValidUIParameterChildren(
+                    facesContext, component.getChildren(), true, false);
+            if (validParams.size() > 0)
+            {
+                parameters = new HashMap<String, List<String>>();
+            }
+            for (int i = 0, size = validParams.size(); i < size; i++)
+            {
+                UIParameter param = validParams.get(i);
+                String name = param.getName();
+                Object value = param.getValue();
+                if (parameters.containsKey(name))
+                {
+                    parameters.get(name).add(value.toString());
+                }
+                else
+                {
+                    List<String> list = new ArrayList<String>(1);
+                    list.add(value.toString());
+                    parameters.put(name, list);
+                }
+            }
+        }
+        
+        // From the navigation case, use getToFlowDocumentId() to identify when
+        // a navigation case is a flow call or a flow return.
+        if (navigationCase.getToFlowDocumentId() != null)
+        {
+            if (parameters == null)
+            {
+                parameters = new HashMap<String, List<String>>();
+            }
+            if (!parameters.containsKey(FlowHandler.TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME))
+            {
+                List<String> list = new ArrayList<String>(1);
+                list.add(navigationCase.getToFlowDocumentId());
+                parameters.put(FlowHandler.TO_FLOW_DOCUMENT_ID_REQUEST_PARAM_NAME, list);
+            }
+            if (!parameters.containsKey(FlowHandler.FLOW_ID_REQUEST_PARAM_NAME))
+            {
+                List<String> list2 = new ArrayList<String>(1);
+                list2.add(navigationCase.getFromOutcome());
+                parameters.put(FlowHandler.FLOW_ID_REQUEST_PARAM_NAME, list2);
+            }
+        }
+        
+        // handle NavigationCase parameters
+        Map<String, List<String>> navigationCaseParams = 
+            NavigationUtils.getEvaluatedNavigationParameters(facesContext,
+                navigationCase.getParameters());
+        if (navigationCaseParams != null)
+        {
+            if (parameters == null)
+            {
+                parameters = new HashMap<String, List<String>>();
+            }
+            //parameters.putAll(navigationCaseParams);
+            for (Map.Entry<String, List<String>> entry : navigationCaseParams
+                    .entrySet())
+            {
+                if (!parameters.containsKey(entry.getKey()))
+                {
+                    parameters.put(entry.getKey(), entry.getValue());
+                }
+            }
+        }
+        if (parameters == null)
+        {
+            parameters = Collections.emptyMap();
+        }
+        // In theory the precedence order to deal with params is this:
+        // component parameters, navigation-case parameters, view parameters
+        // getBookmarkableURL deal with this details.
+        ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
+        String href = viewHandler.getBookmarkableURL(facesContext,
+                navigationCase.getToViewId(facesContext),
+                parameters, navigationCase.isIncludeViewParams() || component.isIncludeViewParams());
+        // handle fragment (viewId#fragment)
+        String fragment = (String) component.getAttributes().get("fragment");
+        if (fragment != null)
+        {
+            fragment = fragment.trim();
+
+            if (fragment.length() > 0)
+            {
+                href += "#" + fragment;
+            }
+        }
+        return href;
+    }
+
+    /**
+     * Calls getValidUIParameterChildren(facesContext, children, skipNullValue, skipUnrendered, true);
+     *
+     * @param facesContext
+     * @param children
+     * @param skipNullValue
+     * @param skipUnrendered
+     * @return ArrayList size > 0 if any parameter found
+     */
+    public static List<UIParameter> getValidUIParameterChildren(
+            FacesContext facesContext, List<UIComponent> children,
+            boolean skipNullValue, boolean skipUnrendered)
+    {
+        return getValidUIParameterChildren(facesContext, children,
+                skipNullValue, skipUnrendered, true);
+    }
+    
+    
+    /**
+     * Returns a List of all valid UIParameter children from the given children.
+     * Valid means that the UIParameter is not disabled, its name is not null
+     * (if skipNullName is true), its value is not null (if skipNullValue is true)
+     * and it is rendered (if skipUnrendered is true). This method also creates a
+     * warning for every UIParameter with a null-name (again, if skipNullName is true)
+     * and, if ProjectStage is Development and skipNullValue is true, it informs the
+     * user about every null-value.
+     *
+     * @param facesContext
+     * @param children
+     * @param skipNullValue  should UIParameters with a null value be skipped
+     * @param skipUnrendered should UIParameters with isRendered() returning false be skipped
+     * @param skipNullName   should UIParameters with a null name be skipped
+     *                       (normally true, but in the case of h:outputFormat false)
+     * @return ArrayList size > 0 if any parameter found 
+     */
+    public static List<UIParameter> getValidUIParameterChildren(
+            FacesContext facesContext, List<UIComponent> children,
+            boolean skipNullValue, boolean skipUnrendered, boolean skipNullName)
+    {
+        List<UIParameter> params = null;
+        for (int i = 0, size = children.size(); i < size; i++)
+        {
+            UIComponent child = children.get(i);
+            if (child instanceof UIParameter)
+            {
+                UIParameter param = (UIParameter) child;
+                // check for the disable attribute (since 2.0)
+                // and the render attribute (only if skipUnrendered is true)
+                if (param.isDisable() || (skipUnrendered && !param.isRendered()))
+                {
+                    // ignore this UIParameter and continue
+                    continue;
+                }
+                // check the name
+                String name = param.getName();
+                if (skipNullName && (name == null || HtmlRendererUtils.STR_EMPTY.equals(name)))
+                {
+                    // warn for a null-name
+                    log.log(Level.WARNING, "The UIParameter " + RendererUtils.getPathToComponent(param)
+                                    + " has a name of null or empty string and thus will not be added to the URL.");
+                    // and skip it
+                    continue;
+                }
+                // check the value
+                if (skipNullValue && param.getValue() == null)
+                {
+                    if (facesContext.isProjectStage(ProjectStage.Development))
+                    {
+                        // inform the user about the null value when in Development stage
+                        log.log(Level.INFO, "The UIParameter " + RendererUtils.getPathToComponent(param)
+                                        + " has a value of null and thus will not be added to the URL.");
+                    }
+                    // skip a null-value
+                    continue;
+                }
+                // add the param
+                if (params == null)
+                {
+                    params = new ArrayList<UIParameter>();
+                }
+                params.add(param);
+            }
+        }
+        if (params == null)
+        {
+            params = Collections.emptyList();
+        }
+        return params;
+    }
+
+}

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/ResourceUtils.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/ResourceUtils.java?rev=1535874&r1=1535873&r2=1535874&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/ResourceUtils.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/util/ResourceUtils.java Fri Oct 25 21:24:09 2013
@@ -21,6 +21,7 @@ package org.apache.myfaces.shared.render
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;
+import javax.faces.FacesWrapper;
 
 import javax.faces.application.Resource;
 import javax.faces.component.UIComponent;
@@ -30,6 +31,7 @@ import javax.faces.context.ResponseWrite
 import org.apache.myfaces.shared.config.MyfacesConfig;
 import org.apache.myfaces.shared.renderkit.JSFAttr;
 import org.apache.myfaces.shared.renderkit.html.HTML;
+import org.apache.myfaces.shared.resource.ContractResource;
 
 /**
  * @author Leonardo Uribe (latest modification by $Author$)
@@ -189,7 +191,10 @@ public class ResourceUtils
 
         // Check if this is an ajax request. If so, we don't need to include it, because that was
         // already done and in the worst case, jsf script was already loaded on the page.
-        if (facesContext.getPartialViewContext() != null && facesContext.getPartialViewContext().isAjaxRequest())
+        if (facesContext.getPartialViewContext() != null && 
+                (facesContext.getPartialViewContext().isPartialRequest() ||
+                 facesContext.getPartialViewContext().isAjaxRequest() )
+            )
         {
             return;
         }
@@ -246,7 +251,10 @@ public class ResourceUtils
         //we only are allowed to do this on partial requests
         //because on normal requests a static viewroot still could mean that a full page refresh is performed
         //only in a ppr case this means we have the script already loaded and parsed
-        if (facesContext.getPartialViewContext() != null && facesContext.getPartialViewContext().isPartialRequest())
+        if (facesContext.getPartialViewContext() != null && 
+                (facesContext.getPartialViewContext().isPartialRequest() ||
+                 facesContext.getPartialViewContext().isAjaxRequest() )
+            )
         {
             return;
         }
@@ -297,4 +305,23 @@ public class ResourceUtils
         return;
     }
 
+    public static String getContractName(Resource resource)
+    {
+        while (resource != null)
+        {
+            if (resource instanceof ContractResource)
+            {
+                return ((ContractResource)resource).getContractName();
+            }
+            else if (resource instanceof FacesWrapper)
+            {
+                resource = (Resource)((FacesWrapper)resource).getWrapped();
+            }
+            else
+            {
+                resource = null;
+            }
+        }
+        return null;
+    }
 }

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/AliasResourceMetaImpl.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/AliasResourceMetaImpl.java?rev=1535874&r1=1535873&r2=1535874&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/AliasResourceMetaImpl.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/AliasResourceMetaImpl.java Fri Oct 25 21:24:09 2013
@@ -33,8 +33,16 @@ public class AliasResourceMetaImpl exten
     public AliasResourceMetaImpl(String prefix, String libraryName, String libraryVersion,
             String resourceName, String resourceVersion, String realResourceName, boolean couldContainValueExpressions)
     {
+        this(prefix, libraryName, libraryVersion, resourceName, resourceVersion, realResourceName, 
+            couldContainValueExpressions, null);
+    }
+    
+    public AliasResourceMetaImpl(String prefix, String libraryName, String libraryVersion,
+            String resourceName, String resourceVersion, String realResourceName, 
+            boolean couldContainValueExpressions, String contractName)
+    {
         super(prefix, libraryName, libraryVersion,
-            resourceName, resourceVersion);
+            resourceName, resourceVersion, contractName);
         _realResourceName = realResourceName;
         _couldContainValueExpressions = couldContainValueExpressions;
     }

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/BaseResourceHandlerSupport.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/BaseResourceHandlerSupport.java?rev=1535874&r1=1535873&r2=1535874&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/BaseResourceHandlerSupport.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/BaseResourceHandlerSupport.java Fri Oct 25 21:24:09 2013
@@ -64,6 +64,16 @@ public class BaseResourceHandlerSupport 
     {
         return null;
     }
+    
+    public ContractResourceLoader[] getContractResourceLoaders()
+    {
+        return null;
+    }
+    
+    public ResourceLoader[] getViewResourceLoaders()
+    {
+        return null;
+    }
 
     public String calculateResourceBasePath(FacesContext facesContext)
     {        

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ClassLoaderResourceLoader.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ClassLoaderResourceLoader.java?rev=1535874&r1=1535873&r2=1535874&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ClassLoaderResourceLoader.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ClassLoaderResourceLoader.java Fri Oct 25 21:24:09 2013
@@ -258,13 +258,13 @@ public class ClassLoaderResourceLoader e
         }
     }
 
-    @Override
-    public URL getResourceURL(ResourceMeta resourceMeta)
+    //@Override
+    public URL getResourceURL(String resourceId)
     {
         URL url = null;
         if (getPrefix() != null && !"".equals(getPrefix()))
         {
-            String name = getPrefix() + '/' + resourceMeta.getResourceIdentifier();
+            String name = getPrefix() + '/' + resourceId;
             url = getClassLoader().getResource(name);
             if (url == null)
             {
@@ -274,14 +274,20 @@ public class ClassLoaderResourceLoader e
         }
         else
         {
-            url = getClassLoader().getResource(resourceMeta.getResourceIdentifier());
+            url = getClassLoader().getResource(resourceId);
             if (url == null)
             {
-                url = this.getClass().getClassLoader().getResource(resourceMeta.getResourceIdentifier());
+                url = this.getClass().getClassLoader().getResource(resourceId);
             }
             return url;
         }
     }
+    
+    @Override
+    public URL getResourceURL(ResourceMeta resourceMeta)
+    {
+        return getResourceURL(resourceMeta.getResourceIdentifier());
+    }
 
     @Override
     public String getResourceVersion(String path)
@@ -484,7 +490,7 @@ public class ClassLoaderResourceLoader e
         }
         return false;
     }
-
+    
     /**
      * <p>Determines whether the given URL resource protocol refers to a JAR file. Note that
      * BEA WebLogic and IBM WebSphere don't use the "jar://" protocol for some reason even

Added: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ContractResource.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ContractResource.java?rev=1535874&view=auto
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ContractResource.java (added)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ContractResource.java Fri Oct 25 21:24:09 2013
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.shared.resource;
+
+/**
+ * Indicates if a resource has been served from a contract.
+ *
+ * @author Leonardo Uribe
+ */
+public interface ContractResource
+{
+    /**
+     * FacesContext attribute map that helps ResourceHandlerImpl to locate 
+     * a resource from an specified contract.
+     */
+    public static final String CONTRACT_SELECTED = "oam.contract.SELECTED";
+    
+    public boolean isContractResource();
+    
+    public String getContractName();
+}

Added: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ContractResourceLoader.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ContractResourceLoader.java?rev=1535874&view=auto
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ContractResourceLoader.java (added)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ContractResourceLoader.java Fri Oct 25 21:24:09 2013
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.shared.resource;
+
+/**
+ * ResourceLoaders that are able to handle contract aware resources
+ * must extends from this class.
+ *
+ * @author Leonardo Uribe
+ */
+public abstract class ContractResourceLoader extends ResourceLoader
+{
+    
+    public static final String VERSION_INVALID = "INVALID";
+    
+    public ContractResourceLoader(String prefix)
+    {
+        super(prefix);
+    }
+    
+    public String getResourceVersion(String path)
+    {
+        return null;
+    }
+
+    public String getLibraryVersion(String path)
+    {
+        return null;
+    }
+
+    public abstract String getResourceVersion(String path, String contractName);
+
+    /**
+     * Return the max available version found (if exists) or
+     * return null if no version available. 
+     */
+    public abstract String getLibraryVersion(String path, String contractName);
+
+    public ResourceMeta createResourceMeta(String prefix, String libraryName, 
+            String libraryVersion, String resourceName, String resourceVersion)
+    {
+        return null;
+    }
+    
+    public abstract ResourceMeta createResourceMeta(String prefix, String libraryName, 
+            String libraryVersion, String resourceName, String resourceVersion, String contractName);
+    
+    public boolean libraryExists(String libraryName)
+    {
+        return false;
+    }
+    
+    public abstract boolean libraryExists(String libraryName, String contractName);
+    
+}

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ExternalContextResourceLoader.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ExternalContextResourceLoader.java?rev=1535874&r1=1535873&r2=1535874&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ExternalContextResourceLoader.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ExternalContextResourceLoader.java Fri Oct 25 21:24:09 2013
@@ -142,19 +142,25 @@ public class ExternalContextResourceLoad
         return libraryVersion;
     }
 
-    @Override
-    public URL getResourceURL(ResourceMeta resourceMeta)
+    //@Override
+    public URL getResourceURL(String resourceId)
     {
         try
         {
             return FacesContext.getCurrentInstance().getExternalContext().getResource(
-                getPrefix() + '/' + resourceMeta.getResourceIdentifier());
+                getPrefix() + '/' + resourceId);
         }
         catch (MalformedURLException e)
         {
             return null;
         }
     }
+    
+    @Override
+    public URL getResourceURL(ResourceMeta resourceMeta)
+    {
+        return getResourceURL(resourceMeta.getResourceIdentifier());
+    }
 
     @Override
     public InputStream getResourceInputStream(ResourceMeta resourceMeta)

Added: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceCachedInfo.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceCachedInfo.java?rev=1535874&view=auto
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceCachedInfo.java (added)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceCachedInfo.java Fri Oct 25 21:24:09 2013
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.shared.resource;
+
+import java.net.URL;
+
+/**
+ * Holds the information that is static but can only be derived after
+ * a Resource instance is created.
+ *
+ * @author Leonardo Uribe
+ */
+public class ResourceCachedInfo
+{
+    private final URL url;
+
+    private final String requestPath;
+
+    public ResourceCachedInfo(URL url, String requestPath)
+    {
+        this.url = url;
+        this.requestPath = requestPath;
+    }
+
+    public URL getURL()
+    {
+        return url;
+    }
+
+    public String getRequestPath()
+    {
+        return requestPath;
+    }
+}

Added: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceELUtils.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceELUtils.java?rev=1535874&view=auto
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceELUtils.java (added)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceELUtils.java Fri Oct 25 21:24:09 2013
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.shared.resource;
+
+import java.util.regex.Pattern;
+
+import javax.faces.context.FacesContext;
+import javax.faces.view.Location;
+
+/**
+ * Utility class when used in EL Expressions --> #{resource}
+ * 
+ * @author Leonardo Uribe
+ */
+public class ResourceELUtils
+{
+
+    // TODO: check this expression, maybe we can make it simpler, because "resource" implicit object
+    // cannot be preceded by anything.
+    public static final Pattern RESOURCE_EXPRESSION_REGEX = Pattern.compile(".*[^\\w\\.]resource[^\\w].*");
+    
+    private static final String RESOURCE = "resource";
+    
+    public static final String RESOURCE_LOCATION_KEY = "org.apache.myfaces.view.facelets.resource.location";
+    
+    public static final String RESOURCE_THIS_LIBRARY = "oam.resource.library";
+    public static final String RESOURCE_THIS_CONTRACT = "oam.resource.contract";
+    
+    public static boolean isResourceExpression(String expression)
+    {
+        if (expression.contains(RESOURCE))
+        {
+            return RESOURCE_EXPRESSION_REGEX.matcher(expression).matches();
+        }
+        else
+        {
+            return false;
+        }
+    }
+
+    public static Location getResourceLocationForResolver(FacesContext facesContext)
+    {
+        return (Location) facesContext.getAttributes().get(RESOURCE_LOCATION_KEY);
+    }
+    
+    public static void saveResourceLocationForResolver(FacesContext facesContext, Location location)
+    {
+        facesContext.getAttributes().put(RESOURCE_LOCATION_KEY, location);
+    }
+    
+    public static void removeResourceLocationForResolver(FacesContext facesContext)
+    {
+        facesContext.getAttributes().remove(RESOURCE_LOCATION_KEY);
+    }
+
+    public static String getResourceContractForResolver(FacesContext facesContext)
+    {
+        return (String) facesContext.getAttributes().get(RESOURCE_THIS_CONTRACT);
+    }
+    
+    public static void saveResourceContractForResolver(FacesContext facesContext, String location)
+    {
+        facesContext.getAttributes().put(RESOURCE_THIS_CONTRACT, location);
+    }
+    
+    public static void removeResourceContractForResolver(FacesContext facesContext)
+    {
+        facesContext.getAttributes().remove(RESOURCE_THIS_CONTRACT);
+    }
+    
+    public static String getResourceLibraryForResolver(FacesContext facesContext)
+    {
+        return (String) facesContext.getAttributes().get(RESOURCE_THIS_LIBRARY);
+    }
+    
+    public static void saveResourceLibraryForResolver(FacesContext facesContext, String location)
+    {
+        facesContext.getAttributes().put(RESOURCE_THIS_LIBRARY, location);
+    }
+    
+    public static void removeResourceLibraryForResolver(FacesContext facesContext)
+    {
+        facesContext.getAttributes().remove(RESOURCE_THIS_LIBRARY);
+    }
+}

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceHandlerCache.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceHandlerCache.java?rev=1535874&r1=1535873&r2=1535874&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceHandlerCache.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceHandlerCache.java Fri Oct 25 21:24:09 2013
@@ -35,8 +35,10 @@ public class ResourceHandlerCache
             .getLogger(ResourceHandlerCache.class.getName());
 
     private Boolean _resourceCacheEnabled = null;
-    private volatile ConcurrentLRUCache<ResourceKey, ResourceValue> _resourceCacheMap = null;
+    private volatile ConcurrentLRUCache<Object, ResourceValue> _resourceCacheMap = null;
 
+    private volatile ConcurrentLRUCache<Object, ResourceValue> _viewResourceCacheMap = null;
+    
     /**
      * Controls the size of the cache used to check if a resource exists or not. 
      * 
@@ -62,6 +64,12 @@ public class ResourceHandlerCache
     public ResourceValue getResource(String resourceName, String libraryName,
             String contentType, String localePrefix)
     {
+        return getResource(resourceName, libraryName, contentType, localePrefix, null);
+    }
+    
+    public ResourceValue getResource(String resourceName, String libraryName,
+            String contentType, String localePrefix, String contractName)
+    {
         if (!isResourceCachingEnabled() || _resourceCacheMap == null)
         {
             return null;
@@ -73,12 +81,18 @@ public class ResourceHandlerCache
                     + resourceName);
         }
 
-        ResourceKey key = new ResourceKey(resourceName, libraryName, contentType, localePrefix);
+        ResourceKey key = new ResourceKey(resourceName, libraryName, contentType, localePrefix, contractName);
 
         return _resourceCacheMap.get(key);
+    }    
+
+    public boolean containsResource(String resourceName, String libraryName, String contentType, String localePrefix)
+    {
+        return containsResource(resourceName, libraryName, contentType, localePrefix, null);
     }
     
-    public boolean containsResource(String resourceName, String libraryName, String contentType, String localePrefix)
+    public boolean containsResource(String resourceName, String libraryName, String contentType, 
+        String localePrefix, String contractName)
     {
         if (!isResourceCachingEnabled() || _resourceCacheMap == null)
         {
@@ -92,6 +106,13 @@ public class ResourceHandlerCache
     public void putResource(String resourceName, String libraryName,
             String contentType, String localePrefix, ResourceMeta resource, ResourceLoader loader)
     {
+        putResource(resourceName, libraryName, contentType, localePrefix, null, resource, loader, null);
+    }
+    
+    public void putResource(String resourceName, String libraryName,
+            String contentType, String localePrefix, String contractName, ResourceMeta resource, ResourceLoader loader,
+            ResourceCachedInfo info)
+    {
         if (!isResourceCachingEnabled())
         {
             return;
@@ -110,12 +131,179 @@ public class ResourceHandlerCache
                 log.log(Level.FINE, "Initializing resource cache map");
             }
             int maxSize = getMaxSize();
-            _resourceCacheMap = new ConcurrentLRUCache<ResourceKey, ResourceValue>(
+            _resourceCacheMap = new ConcurrentLRUCache<Object, ResourceValue>(
                     (maxSize * 4 + 3) / 3, maxSize);
         }
 
         _resourceCacheMap.put(new ResourceKey(resourceName, libraryName,
-                contentType, localePrefix), new ResourceValue(resource, loader));
+                contentType, localePrefix, contractName), new ResourceValue(resource, loader, info));
+    }
+    
+    public ResourceValue getResource(String resourceId)
+    {
+        if (!isResourceCachingEnabled() || _resourceCacheMap == null)
+        {
+            return null;
+        }
+
+        if (log.isLoggable(Level.FINE))
+        {
+            log.log(Level.FINE, "Attemping to get resource from cache for "
+                    + resourceId);
+        }
+
+        return _resourceCacheMap.get(resourceId);
+    }
+
+    public ResourceValue getResource(String resourceId, String contractName)
+    {
+        if (!isResourceCachingEnabled() || _resourceCacheMap == null)
+        {
+            return null;
+        }
+
+        if (log.isLoggable(Level.FINE))
+        {
+            log.log(Level.FINE, "Attemping to get resource from cache for "
+                    + resourceId);
+        }
+
+        return _resourceCacheMap.get(contractName+':'+resourceId);
+    }
+    
+    public boolean containsResource(String resourceId, String contractName)
+    {
+        if (!isResourceCachingEnabled() || _resourceCacheMap == null)
+        {
+            return false;
+        }
+
+        return _resourceCacheMap.get(contractName+':'+resourceId) != null;
+    }
+    
+    public boolean containsResource(String resourceId)
+    {
+        if (!isResourceCachingEnabled() || _resourceCacheMap == null)
+        {
+            return false;
+        }
+
+        return _resourceCacheMap.get(resourceId) != null;
+    }
+
+    public void putResource(String resourceId, ResourceMeta resource, ResourceLoader loader, 
+        ResourceCachedInfo info)
+    {
+        if (!isResourceCachingEnabled())
+        {
+            return;
+        }
+
+        if (log.isLoggable(Level.FINE))
+        {
+            log.log(Level.FINE, "Attemping to put resource to cache for "
+                    + resourceId);
+        }
+
+        if (_resourceCacheMap == null)
+        {
+            if (log.isLoggable(Level.FINE))
+            {
+                log.log(Level.FINE, "Initializing resource cache map");
+            }
+            int maxSize = getMaxSize();
+            _resourceCacheMap = new ConcurrentLRUCache<Object, ResourceValue>(
+                    (maxSize * 4 + 3) / 3, maxSize);
+        }
+
+        if (resource.getContractName() != null)
+        {
+            _resourceCacheMap.put(resource.getContractName()+':'+resourceId, 
+                new ResourceValue(resource, loader));
+        }
+        else
+        {
+            _resourceCacheMap.put(resourceId, new ResourceValue(resource, loader, info));
+        }
+    }
+
+    public boolean containsViewResource(
+        String resourceName, String contentType, String localePrefix)
+    {
+        return containsViewResource(resourceName, contentType, localePrefix, null);
+    }
+    
+    public boolean containsViewResource(String resourceName, String contentType, 
+        String localePrefix, String contractName)
+    {
+        if (!isResourceCachingEnabled() || _viewResourceCacheMap == null)
+        {
+            return false;
+        }
+
+        ResourceKey key = new ResourceKey(resourceName, null, contentType, localePrefix, contractName);
+        return _viewResourceCacheMap.get(key) != null;
+    }
+    
+    public ResourceValue getViewResource(String resourceName,
+            String contentType, String localePrefix)
+    {
+        return getViewResource(resourceName, contentType, localePrefix, null);
+    }
+    
+    public ResourceValue getViewResource(String resourceName,
+            String contentType, String localePrefix, String contractName)
+    {
+        if (!isResourceCachingEnabled() || _viewResourceCacheMap == null)
+        {
+            return null;
+        }
+
+        if (log.isLoggable(Level.FINE))
+        {
+            log.log(Level.FINE, "Attemping to get resource from cache for "
+                    + resourceName);
+        }
+
+        ResourceKey key = new ResourceKey(resourceName, null, contentType, localePrefix, contractName);
+
+        return _viewResourceCacheMap.get(key);
+    }
+    
+    public void putViewResource(String resourceName, String contentType, 
+        String localePrefix, ResourceMeta resource, ResourceLoader loader, ResourceCachedInfo info)
+    {
+        putViewResource(resourceName, contentType, localePrefix, null, resource, loader, info);
+    }
+    
+    public void putViewResource(String resourceName, String contentType, 
+        String localePrefix, String contractName, ResourceMeta resource, ResourceLoader loader,
+        ResourceCachedInfo info)
+    {
+        if (!isResourceCachingEnabled())
+        {
+            return;
+        }
+
+        if (log.isLoggable(Level.FINE))
+        {
+            log.log(Level.FINE, "Attemping to put resource to cache for "
+                    + resourceName);
+        }
+
+        if (_viewResourceCacheMap == null)
+        {
+            if (log.isLoggable(Level.FINE))
+            {
+                log.log(Level.FINE, "Initializing resource cache map");
+            }
+            int maxSize = getMaxSize();
+            _viewResourceCacheMap = new ConcurrentLRUCache<Object, ResourceValue>(
+                    (maxSize * 4 + 3) / 3, maxSize);
+        }
+
+        _viewResourceCacheMap.put(new ResourceKey(resourceName, null,
+                contentType, localePrefix, contractName), new ResourceValue(resource, loader, info));
     }
 
     private boolean isResourceCachingEnabled()
@@ -162,18 +350,26 @@ public class ResourceHandlerCache
 
     public static class ResourceKey
     {
-        private String resourceName;
-        private String libraryName;
-        private String contentType;
-        private String localePrefix;
+        private final String resourceName;
+        private final String libraryName;
+        private final String contentType;
+        private final String localePrefix;
+        private final String contractName;
 
         public ResourceKey(String resourceName, String libraryName,
                 String contentType, String localePrefix)
         {
+            this(resourceName, libraryName, contentType, localePrefix, null);
+        }
+        
+        public ResourceKey(String resourceName, String libraryName,
+                String contentType, String localePrefix, String contractName)
+        {
             this.resourceName = resourceName;
             this.libraryName = libraryName;
             this.contentType = contentType;
             this.localePrefix = localePrefix;
+            this.contractName = contractName;
         }
 
         @Override
@@ -206,6 +402,10 @@ public class ResourceHandlerCache
             {
                 return false;
             }
+            if (contractName != null ? !contractName.equals(that.contractName) : that.contractName != null)
+            {
+                return false;
+            }
 
             return true;
         }
@@ -217,22 +417,35 @@ public class ResourceHandlerCache
             result = 31 * result + (libraryName != null ? libraryName.hashCode() : 0);
             result = 31 * result + (contentType != null ? contentType.hashCode() : 0);
             result = 31 * result + (localePrefix != null ? localePrefix.hashCode() : 0);
+            result = 31 * result + (contractName != null ? contractName.hashCode() : 0);
             return result;
         }
     }
 
     public static class ResourceValue
     {
-        private ResourceMeta resourceMeta;
+        private final ResourceMeta resourceMeta;
+        
+        private final ResourceLoader resourceLoader;
+        
+        private final ResourceCachedInfo info;
         
-        private ResourceLoader resourceLoader;
-
         public ResourceValue(ResourceMeta resourceMeta,
                 ResourceLoader resourceLoader)
         {
+            this.resourceMeta = resourceMeta;
+            this.resourceLoader = resourceLoader;
+            this.info = null;
+        }
+        
+        public ResourceValue(ResourceMeta resourceMeta,
+                ResourceLoader resourceLoader,
+                ResourceCachedInfo info)
+        {
             super();
             this.resourceMeta = resourceMeta;
             this.resourceLoader = resourceLoader;
+            this.info = info;
         }
 
         public ResourceMeta getResourceMeta()
@@ -244,6 +457,11 @@ public class ResourceHandlerCache
         {
             return resourceLoader;
         }
+        
+        public ResourceCachedInfo getCachedInfo()
+        {
+            return info;
+        }
     }
-
+        
 }

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceHandlerSupport.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceHandlerSupport.java?rev=1535874&r1=1535873&r2=1535874&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceHandlerSupport.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceHandlerSupport.java Fri Oct 25 21:24:09 2013
@@ -48,13 +48,32 @@ public abstract class ResourceHandlerSup
     public abstract String calculateResourceBasePath(FacesContext facesContext);
 
     /**
-     * Return an array of resource loaders used to find resources
-     * using the standard. The order of ResourceLoaders define
-     * its precedence. 
+     * Return an array of resource loaders used to find resources.
+     * The order of ResourceLoaders define its precedence. 
      * 
      * @return
      */
     public abstract ResourceLoader[] getResourceLoaders();
+
+    /**
+     * Return an array of resource loaders used to find resources 
+     * associated with a contract. The order of ContractResourceLoaders 
+     * define its precedence. 
+     * 
+     * @since 2.2
+     * @return 
+     */
+    public abstract ContractResourceLoader[] getContractResourceLoaders();
+
+    /**
+     * Return an array of resource loaders used to find resources
+     * that can be located using ResourceHandler.createViewResource().
+     * The order of ResourceLoaders define its precedence. 
+     * 
+     * @since 2.2
+     * @return 
+     */
+    public abstract ResourceLoader[] getViewResourceLoaders();
     
     /**
      * Check if the mapping used is done using extensions (.xhtml, .jsf)

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceImpl.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceImpl.java?rev=1535874&r1=1535873&r2=1535874&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceImpl.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceImpl.java Fri Oct 25 21:24:09 2013
@@ -35,7 +35,7 @@ import javax.faces.context.FacesContext;
  * @author Leonardo Uribe (latest modification by $Author$)
  * @version $Revision$ $Date$
  */
-public class ResourceImpl extends Resource
+public class ResourceImpl extends Resource implements ContractResource
 {
     protected final static String JAVAX_FACES_LIBRARY_NAME = "javax.faces";
     protected final static String JSF_JS_RESOURCE_NAME = "jsf.js";
@@ -44,7 +44,9 @@ public class ResourceImpl extends Resour
     private ResourceMeta _resourceMeta;
     private ResourceLoader _resourceLoader;
     private ResourceHandlerSupport _resourceHandlerSupport;
-    private URL _url; 
+    
+    private URL _url;
+    private String _requestPath;
     
     public ResourceImpl(ResourceMeta resourceMeta, 
             ResourceLoader resourceLoader, ResourceHandlerSupport support, String contentType)
@@ -57,6 +59,21 @@ public class ResourceImpl extends Resour
         setContentType(contentType);
     }
     
+    public ResourceImpl(ResourceMeta resourceMeta, 
+            ResourceLoader resourceLoader, ResourceHandlerSupport support, String contentType,
+            URL url, String requestPath)
+    {
+        
+        _resourceMeta = resourceMeta;
+        _resourceLoader = resourceLoader;
+        _resourceHandlerSupport = support;
+        _url = url;
+        _requestPath = requestPath;
+        setLibraryName(resourceMeta.getLibraryName());
+        setResourceName(resourceMeta.getResourceName());
+        setContentType(contentType);
+    }
+    
     public ResourceLoader getResourceLoader()
     {
         return _resourceLoader;
@@ -94,42 +111,51 @@ public class ResourceImpl extends Resour
     @Override
     public String getRequestPath()
     {
-        String path;
-        if (_resourceHandlerSupport.isExtensionMapping())
-        {
-            path = _resourceHandlerSupport.getResourceIdentifier() + '/' + 
-                getResourceName() + _resourceHandlerSupport.getMapping();
-        }
-        else
+        if (_requestPath == null)
         {
-            String mapping = _resourceHandlerSupport.getMapping(); 
-            path = _resourceHandlerSupport.getResourceIdentifier() + '/' + getResourceName();
-            path = (mapping == null) ? path : mapping + path;
-        }
- 
-        FacesContext facesContext = FacesContext.getCurrentInstance();
-        String metadata = null;
-        boolean useAmp = false;
-        if (getLibraryName() != null)
-        {
-            metadata = "?ln=" + getLibraryName();
-            path = path + metadata;
-            useAmp = true;
-            
-            if (!facesContext.isProjectStage(ProjectStage.Production)
-                    && JSF_JS_RESOURCE_NAME.equals(getResourceName()) 
-                    && JAVAX_FACES_LIBRARY_NAME.equals(getLibraryName()))
+            String path;
+            if (_resourceHandlerSupport.isExtensionMapping())
             {
-                // append &stage=?? for all ProjectStages except Production
-                path = path + "&stage=" + facesContext.getApplication().getProjectStage().toString();
+                path = _resourceHandlerSupport.getResourceIdentifier() + '/' + 
+                    getResourceName() + _resourceHandlerSupport.getMapping();
             }
+            else
+            {
+                String mapping = _resourceHandlerSupport.getMapping(); 
+                path = _resourceHandlerSupport.getResourceIdentifier() + '/' + getResourceName();
+                path = (mapping == null) ? path : mapping + path;
+            }
+
+            FacesContext facesContext = FacesContext.getCurrentInstance();
+            String metadata = null;
+            boolean useAmp = false;
+            if (getLibraryName() != null)
+            {
+                metadata = "?ln=" + getLibraryName();
+                path = path + metadata;
+                useAmp = true;
+
+                if (!facesContext.isProjectStage(ProjectStage.Production)
+                        && JSF_JS_RESOURCE_NAME.equals(getResourceName()) 
+                        && JAVAX_FACES_LIBRARY_NAME.equals(getLibraryName()))
+                {
+                    // append &stage=?? for all ProjectStages except Production
+                    path = path + "&stage=" + facesContext.getApplication().getProjectStage().toString();
+                }
+            }
+            if (_resourceMeta.getLocalePrefix() != null)
+            {
+                path = path + (useAmp ? '&' : '?') + "loc=" + _resourceMeta.getLocalePrefix();
+                useAmp = true;
+            }
+            if (_resourceMeta.getContractName() != null)
+            {
+                path = path + (useAmp ? '&' : '?') + "con=" + _resourceMeta.getContractName();
+                useAmp = true;
+            }
+            _requestPath = facesContext.getApplication().getViewHandler().getResourceURL(facesContext, path);
         }
-        if (_resourceMeta.getLocalePrefix() != null)
-        {
-            path = path + (useAmp ? '&' : '?') + "loc=" + _resourceMeta.getLocalePrefix();
-            useAmp = true;
-        }
-        return facesContext.getApplication().getViewHandler().getResourceURL(facesContext, path);
+        return _requestPath;
     }
 
     @Override
@@ -275,4 +301,14 @@ public class ResourceImpl extends Resour
     {
         return _resourceMeta;
     }
+
+    public boolean isContractResource()
+    {
+        return _resourceMeta.getContractName() != null;
+    }
+    
+    public String getContractName()
+    {
+        return _resourceMeta.getContractName();
+    }
 }

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceLoader.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceLoader.java?rev=1535874&r1=1535873&r2=1535874&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceLoader.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceLoader.java Fri Oct 25 21:24:09 2013
@@ -59,6 +59,12 @@ public abstract class ResourceLoader
     
     public abstract ResourceMeta createResourceMeta(String prefix, String libraryName, String libraryVersion,
             String resourceName, String resourceVersion);
+
+    public ResourceMeta createResourceMeta(String prefix, String libraryName, 
+            String libraryVersion, String resourceName, String resourceVersion, String contractName)
+    {
+        return createResourceMeta(prefix, libraryName, libraryVersion, resourceName, resourceVersion);
+    }
     
     public abstract boolean libraryExists(String libraryName);
     
@@ -66,6 +72,18 @@ public abstract class ResourceLoader
     {
         return (getResourceURL(resourceMeta) != null);
     }
+
+    /*
+    public URL getResourceURL(String resourceId)
+    {
+        throw new UnsupportedOperationException(
+            "An implementation for getResourceURL(String resourceId) method is required for JSF 2.2");
+    }
+    
+    public boolean resourceIdExists(String resourceId)
+    {
+        return (getResourceURL(resourceId) != null);
+    }*/
     
     private Comparator<String> _versionComparator = null;
 

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceLoaderWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceLoaderWrapper.java?rev=1535874&r1=1535873&r2=1535874&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceLoaderWrapper.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceLoaderWrapper.java Fri Oct 25 21:24:09 2013
@@ -1,100 +1,113 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.myfaces.shared.resource;
-
-import java.io.InputStream;
-import java.net.URL;
-import java.util.Comparator;
-
-import javax.faces.FacesWrapper;
-
-/**
- * 
- * @author Leonardo Uribe
- *
- */
-public abstract class ResourceLoaderWrapper extends ResourceLoader implements FacesWrapper<ResourceLoader>
-{
-    
-    public ResourceLoaderWrapper()
-    {
-        super(null);
-    }
-
-    public String getResourceVersion(String path)
-    {
-        return getWrapped().getResourceVersion(path);
-    }
-
-    public String getLibraryVersion(String path)
-    {
-        return getWrapped().getLibraryVersion(path);
-    }
-
-    public URL getResourceURL(ResourceMeta resourceMeta)
-    {
-        return getWrapped().getResourceURL(resourceMeta);
-    }
-
-    public InputStream getResourceInputStream(ResourceMeta resourceMeta)
-    {
-        return getWrapped().getResourceInputStream(resourceMeta);
-    }
-
-    public ResourceMeta createResourceMeta(String prefix, String libraryName,
-            String libraryVersion, String resourceName, String resourceVersion)
-    {
-        return getWrapped().createResourceMeta(prefix, libraryName, libraryVersion,
-                resourceName, resourceVersion);
-    }
-
-    public boolean libraryExists(String libraryName)
-    {
-        return getWrapped().libraryExists(libraryName);
-    }
-
-    public String getPrefix()
-    {
-        return getWrapped().getPrefix();
-    }
-
-    public void setPrefix(String prefix)
-    {
-        getWrapped().setPrefix(prefix);
-    }
-
-    @Override
-    public boolean resourceExists(ResourceMeta resourceMeta)
-    {
-        return getWrapped().resourceExists(resourceMeta);
-    }
-
-    @Override
-    protected Comparator<String> getVersionComparator()
-    {
-        return getWrapped().getVersionComparator();
-    }
-
-    @Override
-    protected void setVersionComparator(Comparator<String> versionComparator)
-    {
-        getWrapped().setVersionComparator(versionComparator);
-    }
-    
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.shared.resource;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Comparator;
+
+import javax.faces.FacesWrapper;
+
+/**
+ * 
+ * @author Leonardo Uribe
+ *
+ */
+public abstract class ResourceLoaderWrapper extends ResourceLoader implements FacesWrapper<ResourceLoader>
+{
+    
+    public ResourceLoaderWrapper()
+    {
+        super(null);
+    }
+
+    public String getResourceVersion(String path)
+    {
+        return getWrapped().getResourceVersion(path);
+    }
+
+    public String getLibraryVersion(String path)
+    {
+        return getWrapped().getLibraryVersion(path);
+    }
+
+    public URL getResourceURL(ResourceMeta resourceMeta)
+    {
+        return getWrapped().getResourceURL(resourceMeta);
+    }
+
+    public InputStream getResourceInputStream(ResourceMeta resourceMeta)
+    {
+        return getWrapped().getResourceInputStream(resourceMeta);
+    }
+
+    public ResourceMeta createResourceMeta(String prefix, String libraryName,
+            String libraryVersion, String resourceName, String resourceVersion)
+    {
+        return getWrapped().createResourceMeta(prefix, libraryName, libraryVersion,
+                resourceName, resourceVersion);
+    }
+
+    public boolean libraryExists(String libraryName)
+    {
+        return getWrapped().libraryExists(libraryName);
+    }
+
+    public String getPrefix()
+    {
+        return getWrapped().getPrefix();
+    }
+
+    public void setPrefix(String prefix)
+    {
+        getWrapped().setPrefix(prefix);
+    }
+
+    @Override
+    public boolean resourceExists(ResourceMeta resourceMeta)
+    {
+        return getWrapped().resourceExists(resourceMeta);
+    }
+
+    /*
+    @Override
+    public boolean resourceIdExists(String resourceId)
+    {
+        return getWrapped().resourceIdExists(resourceId);
+    }
+
+    @Override
+    public URL getResourceURL(String resourceId)
+    {
+        return getWrapped().getResourceURL(resourceId);
+    }*/
+
+    @Override
+    protected Comparator<String> getVersionComparator()
+    {
+        return getWrapped().getVersionComparator();
+    }
+
+    @Override
+    protected void setVersionComparator(Comparator<String> versionComparator)
+    {
+        getWrapped().setVersionComparator(versionComparator);
+    }
+    
+}

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceMeta.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceMeta.java?rev=1535874&r1=1535873&r2=1535874&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceMeta.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceMeta.java Fri Oct 25 21:24:09 2013
@@ -40,4 +40,13 @@ public abstract class ResourceMeta
     public abstract String getResourceIdentifier();
     
     public abstract boolean couldResourceContainValueExpressions();
+    
+    /**
+     * @since 2.2
+     * @return 
+     */
+    public String getContractName()
+    {
+        return null;
+    }
 }

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceMetaImpl.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceMetaImpl.java?rev=1535874&r1=1535873&r2=1535874&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceMetaImpl.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/resource/ResourceMetaImpl.java Fri Oct 25 21:24:09 2013
@@ -32,15 +32,23 @@ public class ResourceMetaImpl extends Re
     private final String _libraryVersion;
     private final String _resourceName;
     private final String _resourceVersion;
-    
+    private final String _contractName;
+
     public ResourceMetaImpl(String prefix, String libraryName, String libraryVersion,
             String resourceName, String resourceVersion)
     {
+        this(prefix, libraryName, libraryVersion, resourceName, resourceVersion, null);
+    }
+    
+    public ResourceMetaImpl(String prefix, String libraryName, String libraryVersion,
+            String resourceName, String resourceVersion, String contractName)
+    {
         _prefix = prefix;
         _libraryName = libraryName;
         _libraryVersion = libraryVersion;
         _resourceName = resourceName;
         _resourceVersion = resourceVersion;
+        _contractName = contractName;
     }
 
     public String getLibraryName()
@@ -67,6 +75,11 @@ public class ResourceMetaImpl extends Re
     {
         return _resourceVersion;
     }
+
+    public String getContractName()
+    {
+        return _contractName;
+    }
     
     @Override
     public String getResourceIdentifier()
@@ -125,4 +138,5 @@ public class ResourceMetaImpl extends Re
     {
         return false;
     }
+
 }