/* * 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.wicket.resource; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.util.Locale; import org.apache.wicket.WicketRuntimeException; import org.apache.wicket.request.Url; import org.apache.wicket.request.resource.ResourceReference; import org.apache.wicket.util.io.IOUtils; import org.apache.wicket.util.lang.Args; import org.apache.wicket.util.resource.IResourceStream; import org.apache.wicket.util.resource.ResourceStreamNotFoundException; import org.apache.wicket.util.string.Strings; /** * Utilities for resources. * * @author Jeremy Thomerson */ public class ResourceUtil { /** * Reads resource reference attributes (style, locale, variation) encoded in the given string. * * @param encodedAttributes * the string containing the resource attributes * @return the encoded attributes * * @see ResourceReference.UrlAttributes */ public static ResourceReference.UrlAttributes decodeResourceReferenceAttributes(String encodedAttributes) { Locale locale = null; String style = null; String variation = null; if (Strings.isEmpty(encodedAttributes) == false) { String split[] = Strings.split(encodedAttributes, '-'); locale = parseLocale(split[0]); if (split.length == 2) { style = Strings.defaultIfEmpty(unescapeAttributesSeparator(split[1]), null); } else if (split.length == 3) { style = Strings.defaultIfEmpty(unescapeAttributesSeparator(split[1]), null); variation = Strings.defaultIfEmpty(unescapeAttributesSeparator(split[2]), null); } } return new ResourceReference.UrlAttributes(locale, style, variation); } /** * Reads resource reference attributes (style, locale, variation) encoded in the given URL. * * @param url * the url containing the resource attributes * @return the encoded attributes * * @see ResourceReference.UrlAttributes */ public static ResourceReference.UrlAttributes decodeResourceReferenceAttributes(Url url) { Args.notNull(url, "url"); if (url.getQueryParameters().size() > 0) { Url.QueryParameter param = url.getQueryParameters().get(0); if (Strings.isEmpty(param.getValue())) { return decodeResourceReferenceAttributes(param.getName()); } } return new ResourceReference.UrlAttributes(null, null, null); } /** * Encodes the given resource reference attributes returning the corresponding textual representation. * * @param attributes * the resource reference attributes to encode * @return the textual representation for the given attributes * * @see ResourceReference.UrlAttributes */ public static String encodeResourceReferenceAttributes(ResourceReference.UrlAttributes attributes) { if (attributes == null || (attributes.getLocale() == null && attributes.getStyle() == null && attributes.getVariation() == null)) { return null; } else { StringBuilder res = new StringBuilder(32); if (attributes.getLocale() != null) { res.append(attributes.getLocale()); } boolean styleEmpty = Strings.isEmpty(attributes.getStyle()); if (!styleEmpty) { res.append('-'); res.append(escapeAttributesSeparator(attributes.getStyle())); } if (!Strings.isEmpty(attributes.getVariation())) { if (styleEmpty) { res.append("--"); } else { res.append('-'); } res.append(escapeAttributesSeparator(attributes.getVariation())); } return res.toString(); } } /** * Encodes the attributes of the given resource reference in the specified url. * * @param url * the resource reference attributes to encode * @param reference * * @see ResourceReference.UrlAttributes * @see Url */ public static void encodeResourceReferenceAttributes(Url url, ResourceReference reference) { Args.notNull(url, "url"); Args.notNull(reference, "reference"); String encoded = encodeResourceReferenceAttributes(reference.getUrlAttributes()); if (!Strings.isEmpty(encoded)) { url.getQueryParameters().add(new Url.QueryParameter(encoded, "")); } } /** * Escapes any occurrences of <em>-</em> character in the style and variation * attributes with <em>~</em>. Any occurrence of <em>~</em> is encoded as <em>~~</em>. * * @param attribute * the attribute to escape * @return the attribute with escaped separator character */ public static CharSequence escapeAttributesSeparator(String attribute) { CharSequence tmp = Strings.replaceAll(attribute, "~", "~~"); return Strings.replaceAll(tmp, "-", "~"); } /** * Parses the string representation of a {@link java.util.Locale} (for example 'en_GB'). * * @param locale * the string representation of a {@link java.util.Locale} * @return the corresponding {@link java.util.Locale} instance */ public static Locale parseLocale(String locale) { if (Strings.isEmpty(locale)) { return null; } else { String parts[] = locale.toLowerCase().split("_", 3); if (parts.length == 1) { return new Locale(parts[0]); } else if (parts.length == 2) { return new Locale(parts[0], parts[1]); } else if (parts.length == 3) { return new Locale(parts[0], parts[1], parts[2]); } else { return null; } } } /** * read string with platform default encoding from resource stream * * @param resourceStream * @return string read from resource stream * * @see #readString(org.apache.wicket.util.resource.IResourceStream, java.nio.charset.Charset) */ public static String readString(IResourceStream resourceStream) { return readString(resourceStream, null); } /** * read string with specified encoding from resource stream * * @param resourceStream * string source * @param charset * charset for the string encoding (use <code>null</code> for platform default) * @return string read from resource stream */ public static String readString(IResourceStream resourceStream, Charset charset) { try { InputStream stream = resourceStream.getInputStream(); try { byte[] bytes = IOUtils.toByteArray(stream); if (charset == null) { charset = Charset.defaultCharset(); } return new String(bytes, charset.name()); } finally { resourceStream.close(); } } catch (IOException e) { throw new WicketRuntimeException("failed to read string from " + resourceStream, e); } catch (ResourceStreamNotFoundException e) { throw new WicketRuntimeException("failed to locate stream from " + resourceStream, e); } } /** * Reverts the escaping applied by {@linkplain #escapeAttributesSeparator(String)} - unescapes * occurrences of <em>~</em> character in the style and variation attributes with <em>-</em>. * * @param attribute * the attribute to unescape * @return the attribute with escaped separator character */ public static String unescapeAttributesSeparator(String attribute) { String tmp = attribute.replaceAll("(\\w)~(\\w)", "$1-$2"); return Strings.replaceAll(tmp, "~~", "~").toString(); } private ResourceUtil() { // no-op } }