001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.request.resource; 018 019import org.apache.wicket.request.IUrlRenderer; 020import org.apache.wicket.request.Url; 021import org.apache.wicket.request.UrlUtils; 022import org.apache.wicket.request.cycle.RequestCycle; 023import org.apache.wicket.util.lang.Args; 024 025/** 026 * A ResourceReference that can be used to point to a resource by using an Url. For example to a 027 * resource residing in a CDN (Content Delivering Network) or context relative one. 028 * 029 * @since 6.0 030 */ 031public class UrlResourceReference extends ResourceReference 032{ 033 /** 034 * An Url that knows how to render itself, so it doesn't need re-calculating in UrlRenderer. It 035 * should be rendered as is. 036 */ 037 private static class CalculatedUrl extends Url implements IUrlRenderer 038 { 039 private CalculatedUrl(Url original) 040 { 041 super(original); 042 } 043 044 @Override 045 public String renderFullUrl(Url url, Url baseUrl) 046 { 047 StringMode mode = getStringMode(url); 048 return url.toString(mode); 049 } 050 051 @Override 052 public String renderRelativeUrl(Url url, Url baseUrl) 053 { 054 return url.toString(); 055 } 056 } 057 058 /** 059 * The url to the resource. 060 */ 061 private final Url url; 062 063 private boolean contextRelative = false; 064 065 /** 066 * Constructor. 067 * 068 * @param url 069 * the url of the external resource 070 */ 071 public UrlResourceReference(final Url url) 072 { 073 super(asName(url)); 074 075 this.url = url; 076 } 077 078 private static String asName(Url externalUrl) 079 { 080 Args.notNull(externalUrl, "url"); 081 return externalUrl.toString(); 082 } 083 084 /** 085 * @return the url of the external resource 086 */ 087 public final Url getUrl() 088 { 089 CalculatedUrl _url; 090 091 if (contextRelative) 092 { 093 String contextRelative = UrlUtils.rewriteToContextRelative(url.toString(), 094 RequestCycle.get()); 095 _url = new CalculatedUrl(Url.parse(contextRelative, url.getCharset())); 096 } 097 else 098 { 099 _url = new CalculatedUrl(url); 100 } 101 102 return _url; 103 } 104 105 /** 106 * @return {@code null} because this ResourceReference won't use an IResource to deliver the 107 * content of the external resource. The browser will make a direct request to the 108 * external url. 109 */ 110 @Override 111 public final IResource getResource() 112 { 113 return null; 114 } 115 116 public UrlResourceReference setContextRelative(final boolean contextRelative) 117 { 118 if (contextRelative && (url.isFull() || url.isContextAbsolute())) 119 { 120 throw new IllegalStateException(String.format( 121 "An absolute url '%s' cannot be rendered as context relative", url)); 122 } 123 this.contextRelative = contextRelative; 124 return this; 125 } 126 127 public boolean isContextRelative() 128 { 129 return contextRelative; 130 } 131 132 @Override 133 public String toString() 134 { 135 return "UrlResourceReference{" + "url=" + url.toString(getStringMode(url)) + 136 ", contextRelative=" + contextRelative + '}'; 137 } 138 139 private static Url.StringMode getStringMode(Url url) 140 { 141 final Url.StringMode mode; 142 if (url.isFull()) 143 { 144 mode = Url.StringMode.FULL; 145 } 146 else 147 { 148 mode = Url.StringMode.LOCAL; 149 } 150 return mode; 151 } 152}