001/* 002 * Copyright 2017 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.cms.remote; 017 018import java.util.Collections; 019import java.util.HashMap; 020import java.util.Map; 021import java.util.regex.Matcher; 022import java.util.regex.Pattern; 023 024import org.apache.avalon.framework.context.Context; 025import org.apache.avalon.framework.context.ContextException; 026import org.apache.avalon.framework.context.Contextualizable; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.avalon.framework.service.Serviceable; 030import org.apache.cocoon.components.ContextHelper; 031import org.apache.cocoon.environment.Request; 032import org.apache.commons.lang.StringUtils; 033 034import org.ametys.cms.transformation.ConsistencyChecker.CHECK; 035import org.ametys.cms.transformation.URIResolver; 036import org.ametys.cms.transformation.URIResolverExtensionPoint; 037import org.ametys.cms.transformation.xslt.ResolveURIComponent; 038import org.ametys.runtime.config.Config; 039import org.ametys.runtime.i18n.I18nizableTextParameter; 040import org.ametys.runtime.i18n.I18nizableText; 041import org.ametys.runtime.workspace.WorkspaceMatcher; 042 043 044/** 045 * {@link URIResolver} for type "remote".<br> 046 * This resolver is a proxy to another type to be called from remote url. 047 * The resolved uri are necessary absolutes. 048 */ 049public class RemoteURIResolver implements URIResolver, Serviceable, Contextualizable 050{ 051 private static final Pattern __URI_PATTERN = Pattern.compile("([^;]*);(.*)"); 052 053 /** The context */ 054 protected Context _context; 055 056 /** The ametys uri resolver */ 057 protected URIResolverExtensionPoint _uriResolverEP; 058 059 @Override 060 public void service(ServiceManager manager) throws ServiceException 061 { 062 _uriResolverEP = (URIResolverExtensionPoint) manager.lookup(URIResolverExtensionPoint.ROLE); 063 } 064 065 @Override 066 public void contextualize(Context context) throws ContextException 067 { 068 _context = context; 069 } 070 071 @Override 072 public String getType() 073 { 074 return "remote"; 075 } 076 077 @Override 078 public String resolve(String uri, boolean download, boolean absolute, boolean internal) 079 { 080 Request request = ContextHelper.getRequest(_context); 081 082 ProxiedUri proxiedUri = getProxiedUri(uri); 083 084 return getAbsoluteRemoteUri(request, ResolveURIComponent.resolve(proxiedUri.getType(), proxiedUri.getUri(), download, false, false)); 085 } 086 087 @Override 088 public String resolveImage(String uri, int height, int width, boolean download, boolean absolute, boolean internal) 089 { 090 Request request = ContextHelper.getRequest(_context); 091 092 ProxiedUri proxiedUri = getProxiedUri(uri); 093 094 return getAbsoluteRemoteUri(request, ResolveURIComponent.resolveImage(proxiedUri.getType(), proxiedUri.getUri(), height, width, download, false, false)); 095 } 096 097 @Override 098 public String resolveImageAsBase64(String uri, int height, int width) 099 { 100 Request request = ContextHelper.getRequest(_context); 101 102 ProxiedUri proxiedUri = getProxiedUri(uri); 103 104 return getAbsoluteRemoteUri(request, ResolveURIComponent.resolveImage(proxiedUri.getType(), proxiedUri.getUri(), height, width)); 105 } 106 107 @Override 108 public String resolveBoundedImage(String uri, int maxHeight, int maxWidth, boolean download, boolean absolute, boolean internal) 109 { 110 Request request = ContextHelper.getRequest(_context); 111 112 ProxiedUri proxiedUri = getProxiedUri(uri); 113 114 return getAbsoluteRemoteUri(request, ResolveURIComponent.resolveBoundedImage(proxiedUri.getType(), proxiedUri.getUri(), maxHeight, maxWidth, download, false, false)); 115 } 116 117 @Override 118 public String resolveBoundedImageAsBase64(String uri, int maxHeight, int maxWidth) 119 { 120 Request request = ContextHelper.getRequest(_context); 121 122 ProxiedUri proxiedUri = getProxiedUri(uri); 123 124 return getAbsoluteRemoteUri(request, ResolveURIComponent.resolveBoundedImage(proxiedUri.getType(), proxiedUri.getUri(), maxHeight, maxWidth)); 125 } 126 127 @Override 128 public String resolveCroppedImage(String uri, int cropHeight, int cropWidth, boolean download, boolean absolute, boolean internal) 129 { 130 Request request = ContextHelper.getRequest(_context); 131 132 ProxiedUri proxiedUri = getProxiedUri(uri); 133 134 return getAbsoluteRemoteUri(request, ResolveURIComponent.resolveCroppedImage(proxiedUri.getType(), proxiedUri.getUri(), cropHeight, cropWidth, download, false, false)); 135 } 136 137 @Override 138 public String resolveCroppedImageAsBase64(String uri, int cropHeight, int cropWidth) 139 { 140 Request request = ContextHelper.getRequest(_context); 141 142 ProxiedUri proxiedUri = getProxiedUri(uri); 143 144 return getAbsoluteRemoteUri(request, ResolveURIComponent.resolveCroppedImage(proxiedUri.getType(), proxiedUri.getUri(), cropHeight, cropWidth)); 145 } 146 147 @Override 148 public CHECK checkLink(String uri, boolean shortTest) 149 { 150 ProxiedUri proxiedUri = getProxiedUri(uri); 151 152 URIResolver resolver = _uriResolverEP.getResolverForType(proxiedUri.getType()); 153 if (resolver != null) 154 { 155 return resolver.checkLink(proxiedUri.getUri(), shortTest); 156 } 157 158 return CHECK.NOT_FOUND; 159 } 160 161 @Override 162 public I18nizableText getLabel(String uri) 163 { 164 ProxiedUri proxiedUri = getProxiedUri(uri); 165 URIResolver resolver = _uriResolverEP.getResolverForType(proxiedUri.getType()); 166 if (resolver != null) 167 { 168 I18nizableText label = resolver.getLabel(proxiedUri.getUri()); 169 Map<String, I18nizableTextParameter> params = new HashMap<>(); 170 params.put("uri", label); 171 return new I18nizableText("plugin.cms", "PLUGINS_CMS_LINK_REMOTE_LABEL", params); 172 } 173 174 return new I18nizableText("plugin.cms", "PLUGINS_CMS_LINK_REMOTE_UNKNOWN_TYPE", Collections.singletonList(proxiedUri.getType())); 175 } 176 177 /** 178 * Get the absolute proxied uri 179 * @param request the request 180 * @param resolvedUri the resolved uri 181 * @return the absolute proxied url 182 */ 183 protected String getAbsoluteRemoteUri(Request request, String resolvedUri) 184 { 185 String uriPrefix = getUriPrefix(request); 186 return getAbsoluteRemoteUriPrefix() + (resolvedUri.startsWith(uriPrefix) ? StringUtils.substringAfter(resolvedUri, uriPrefix) : resolvedUri); 187 } 188 189 190 /** 191 * Get the absolute URI prefix 192 * @return the URI prefix 193 */ 194 protected String getAbsoluteRemoteUriPrefix() 195 { 196 StringBuilder result = new StringBuilder(); 197 198 String cmsUrl = Config.getInstance().getValue("cms.url"); 199 200 result.append(cmsUrl) 201 .append(cmsUrl.endsWith("/") ? "" : "/") 202 .append("_cms/remote"); 203 204 return result.toString(); 205 } 206 207 /** 208 * Get the URI prefix (non absolute) for resolved uri 209 * @param request The request 210 * @return the URI prefix 211 */ 212 protected String getUriPrefix(Request request) 213 { 214 String workspaceURI = (String) request.getAttribute(WorkspaceMatcher.WORKSPACE_URI); 215 return request.getContextPath() + workspaceURI; 216 } 217 218 /** 219 * Get the proxied uri 220 * @param uri The requested uri 221 * @return the proxied uri or null 222 * @throws IllegalArgumentException The uri does match the expected pattern 223 */ 224 protected ProxiedUri getProxiedUri(String uri) throws IllegalArgumentException 225 { 226 Matcher matcher = __URI_PATTERN.matcher(uri); 227 if (matcher.matches()) 228 { 229 String type = matcher.group(1); 230 String initialUri = matcher.group(2); 231 232 return new ProxiedUri(type, initialUri); 233 } 234 235 throw new IllegalArgumentException("The uri " + uri + " does not match the regular expression " + __URI_PATTERN.pattern()); 236 } 237 238 /** 239 * Proxied URI 240 * 241 */ 242 protected class ProxiedUri 243 { 244 private String _uri; 245 private String _type; 246 247 /** 248 * Constructor 249 * @param type The type 250 * @param uri The uri to proxy 251 */ 252 public ProxiedUri(String type, String uri) 253 { 254 _type = type; 255 _uri = uri; 256 } 257 258 /** 259 * Get the uri 260 * @return the uri 261 */ 262 public String getUri() 263 { 264 return _uri; 265 } 266 267 268 /** 269 * Get the object. 270 * @return the object 271 */ 272 public String getType() 273 { 274 return _type; 275 } 276 } 277 278}