/* * JBoss, Home of Professional Open Source * Copyright 2013, Red Hat, Inc. and individual contributors * 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.richfaces.resource.mapping; import java.net.URI; import java.net.URISyntaxException; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.faces.application.Resource; import javax.faces.context.FacesContext; import org.richfaces.application.ServiceTracker; import org.richfaces.resource.ResourceKey; import org.richfaces.webapp.ResourceServlet; import com.google.common.base.Strings; /** * Maps resource with given key to RichFaces {@link ResourceServlet}. * * @author Lukas Fryc */ public class ResourceServletMapping implements ResourceMapping { private static final Pattern LN_PATTERN = Pattern.compile("(.*(?:^|&))ln=([^&]*)((?:$|&).*)"); private static final Pattern AMP_CLEANUP_PATTERN = Pattern.compile("(.*)(?:^&|&$|&+(&))(.*)"); private final ResourceKey resourceKey; private final ResourcePath resourcePath; public ResourceServletMapping(ResourceKey resourceKey) { if (resourceKey == null) { throw new NullPointerException("resourceKey can't be null"); } this.resourceKey = resourceKey; this.resourcePath = null; } public ResourceServletMapping(ResourcePath resourcePath) { if (resourcePath == null) { throw new NullPointerException("resourceKey can't be null"); } this.resourceKey = null; this.resourcePath = resourcePath; } @Override public ResourcePath getResourcePath(FacesContext context) { ResourceMappingConfiguration service = ServiceTracker.getService(ResourceMappingConfiguration.class); String location = service.getLocation(); String mappedPath = getMappedPath(context); return new ResourcePath(location + mappedPath); } private String getMappedPath(FacesContext context) { if (resourcePath != null) { return resourcePath.toExternalForm(); } else { Resource resource = context.getApplication().getResourceHandler() .createResource(resourceKey.getResourceName(), resourceKey.getLibraryName()); if (resource == null) { return "RESOURCE_NOT_FOUND"; } return getResourcePath(resource); } } static String getResourcePath(Resource resource) { final StringBuffer buffer = new StringBuffer(); String ln = Strings.nullToEmpty(resource.getLibraryName()); if (!ln.isEmpty()) { buffer.append(ln).append("/"); } buffer.append(resource.getResourceName()); try { URI originalRequestPath = new URI("path://" + resource.getRequestPath()); String query = originalRequestPath.getQuery(); Matcher matcher = LN_PATTERN.matcher(query); if (matcher.matches()) { ln = matcher.group(2); query = matcher.replaceFirst("$1$3"); matcher = AMP_CLEANUP_PATTERN.matcher(query); if (matcher.matches()) { query = matcher.replaceAll("$1$2$3"); } } if (!query.isEmpty()) { buffer.append("?").append(query); } return buffer.toString(); } catch (URISyntaxException e) { throw new IllegalStateException(String.format("Failed to parse requestPath '%s' for resource '%s': %s", resource.getRequestPath(), ResourceKey.create(resource), e.getMessage()), e); } } }