/* * JBoss, a division of Red Hat * Copyright 2010, Red Hat Middleware, LLC, and individual * contributors as indicated by the @authors tag. See the * copyright.txt in the distribution for a full listing of * individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.gatein.wsrp; import org.gatein.common.net.URLTools; import org.gatein.pc.api.Mode; import org.gatein.pc.api.OpaqueStateString; import org.gatein.pc.api.ResourceURL; import org.gatein.pc.api.StateString; import org.gatein.pc.api.WindowState; import org.gatein.pc.api.cache.CacheLevel; import org.gatein.wsrp.spec.v2.WSRP2RewritingConstants; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.Map; /** * @author <a href="mailto:chris.laprun@jboss.com">Chris Laprun</a> * @version $Revision: 13470 $ * @since 2.4 */ public class WSRPResourceURL extends WSRPPortletURL implements ResourceURL { public static final String DEFAULT_RESOURCE_ID = "_gtn_resid_"; private String resourceId; private StateString resourceState; private CacheLevel cacheability; private boolean requiresRewrite = false; private URL resourceURL; private boolean preferOperation = false; public WSRPResourceURL() { } public WSRPResourceURL(Mode mode, WindowState windowState, boolean secure, StateString navigationalState, StateString resourceState, String resourceId, CacheLevel cacheability, URLContext context) { super(mode, windowState, secure, navigationalState, context); if (resourceId == null) { // if the container didn't provide us with a resource id, fake one so that we can still build a correct WSRP URL. resourceId = DEFAULT_RESOURCE_ID; } else { // request operation if we have a proper resource id preferOperation = true; } if (context != null && !URLContext.EMPTY.equals(context)) { resourceURL = ResourceServingUtil.encode(mode, windowState, secure, navigationalState, resourceState, resourceId, cacheability, context); } else { resourceURL = null; } this.resourceId = resourceId; this.resourceState = resourceState; this.cacheability = cacheability; } protected String getURLType() { return WSRPRewritingConstants.URL_TYPE_RESOURCE; } protected void appendEnd(StringBuffer sb) { if (resourceURL != null) { createURLParameter(sb, WSRPRewritingConstants.RESOURCE_URL, URLTools.encodeXWWWFormURL(resourceURL.toExternalForm())); } createURLParameter(sb, WSRPRewritingConstants.RESOURCE_REQUIRES_REWRITE, requiresRewrite ? "true" : "false"); if (resourceId != null) { createURLParameter(sb, WSRP2RewritingConstants.RESOURCE_ID, URLTools.encodeXWWWFormURL(resourceId)); } // false is the default value, so we don't actually need to add it to the string if (preferOperation) { createURLParameter(sb, WSRP2RewritingConstants.RESOURCE_PREFER_OPERATION, Boolean.toString(preferOperation)); } if (resourceState != null) { createURLParameter(sb, WSRP2RewritingConstants.RESOURCE_STATE, resourceState.getStringValue()); } } @Override protected void dealWithSpecificParams(Map<String, String> params, String originalURL) { super.dealWithSpecificParams(params, originalURL); String requireRewrite = getRawParameterValueFor(params, WSRPRewritingConstants.RESOURCE_REQUIRES_REWRITE); if (requireRewrite != null) { requiresRewrite = Boolean.valueOf(requireRewrite); params.remove(WSRPRewritingConstants.RESOURCE_REQUIRES_REWRITE); } // navigational state String resourceState = getRawParameterValueFor(params, WSRP2RewritingConstants.RESOURCE_STATE); if (resourceState != null) { this.resourceState = new OpaqueStateString(resourceState); params.remove(WSRP2RewritingConstants.RESOURCE_STATE); } String url = getRawParameterValueFor(params, WSRPRewritingConstants.RESOURCE_URL); if (url != null) { try { url = URLTools.decodeXWWWFormURL(url); this.resourceURL = new URL(url); params.remove(WSRPRewritingConstants.RESOURCE_URL); } catch (MalformedURLException e) { throw new IllegalArgumentException("Malformed URL: " + url, e); } } String resourceIDParam = getRawParameterValueFor(params, WSRP2RewritingConstants.RESOURCE_ID); if (resourceIDParam != null) { resourceId = URLTools.decodeXWWWFormURL(resourceIDParam); params.remove(WSRP2RewritingConstants.RESOURCE_ID); } // GTNWSRP-103: if we don't have a resource id and wsrp-requiresRewrite has not been specified, set it to false for better compatibility if (resourceIDParam == null && requireRewrite == null) { requiresRewrite = false; } // we either need a resource Id or (requiredRewrite and url) if (resourceIDParam == null && url == null) { throw new IllegalArgumentException("The parsed parameters are not valid for a resource url. A resource URL must contain either a " + WSRP2RewritingConstants.RESOURCE_ID + " or " + WSRPRewritingConstants.RESOURCE_URL + " and " + WSRPRewritingConstants.RESOURCE_REQUIRES_REWRITE + " parameter in " + originalURL); } String preferOperationParam = getRawParameterValueFor(params, WSRP2RewritingConstants.RESOURCE_PREFER_OPERATION); if (preferOperationParam != null) { preferOperation = Boolean.valueOf(preferOperationParam); params.remove(WSRP2RewritingConstants.RESOURCE_PREFER_OPERATION); } String cacheabilityParam = getRawParameterValueFor(params, WSRP2RewritingConstants.RESOURCE_CACHEABILITY); if (cacheabilityParam != null) { cacheability = WSRPUtils.getCacheLevelFromResourceCacheability(cacheabilityParam); params.remove(WSRP2RewritingConstants.RESOURCE_CACHEABILITY); } if (resourceIDParam == null && url == null) { throw new IllegalArgumentException("The parsed parameters don't contain a value for " + WSRPRewritingConstants.RESOURCE_URL + " or for " + WSRP2RewritingConstants.RESOURCE_ID + " parameter in " + originalURL); } } /** * @return * @deprecated */ public URL getResourceURL() { return resourceURL; } public String getResourceId() { // we need to return a representation of the wsrp resource identification, this is not necessarily just // the wsrp-resourceID, we need to also consider the wsrp-url and other wsrp resource values. // This value returned by this method is used by the PC ResourceInvocation return encodeResource(resourceId, resourceURL, preferOperation); } public StateString getResourceState() { return resourceState; } public CacheLevel getCacheability() { return cacheability; } /** * @return * @deprecated */ public boolean requiresRewrite() { return requiresRewrite; } //TODO: figure out a more clean way to encode and decode the pc resource id (note: different from the wsrp resource id) //we should either use a Map<String, String> directly or pass an object back /** * Encodes the wsrp resource information into a single string. * * @param resourceId The original resource ID * @param resourceURL The originial resource url * @param preferedOperation The preferedOperation value * @return */ public static String encodeResource(String resourceId, URL resourceURL, boolean preferedOperation) { Map<String, String[]> parameters = new HashMap<String, String[]>(); if (resourceId != null) { parameters.put(WSRP2RewritingConstants.RESOURCE_ID, new String[]{resourceId}); } if (resourceURL != null) { parameters.put(WSRPRewritingConstants.RESOURCE_URL, new String[]{resourceURL.toString()}); } parameters.put(WSRP2RewritingConstants.RESOURCE_PREFER_OPERATION, new String[]{Boolean.toString(preferedOperation)}); return StateString.encodeAsOpaqueValue(parameters); } /** * Decodes the resource information specified by the encodeResource back into proper resource values todo: improve * * @param resourceInfo */ public static Map<String, String> decodeResource(String resourceInfo) { Map<String, String> resource = new HashMap<String, String>(); if (resourceInfo != null && resourceInfo.startsWith(StateString.JBPNS_PREFIX)) { Map<String, String[]> resourceParameters = StateString.decodeOpaqueValue(resourceInfo); for (Map.Entry<String, String[]> entry : resourceParameters.entrySet()) { if (entry.getValue() != null && entry.getValue().length > 0) { resource.put(entry.getKey(), entry.getValue()[0]); } } } else //we are not dealing with an encoded resource ID but an actual resource ID { resource.put(WSRP2RewritingConstants.RESOURCE_ID, resourceInfo); } return resource; } }