001/* 002 * Copyright 2010 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.site; 017 018import java.util.HashMap; 019import java.util.Iterator; 020import java.util.List; 021import java.util.Map; 022 023import org.apache.avalon.framework.parameters.Parameters; 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.thread.ThreadSafe; 026import org.apache.cocoon.acting.ServiceableAction; 027import org.apache.cocoon.environment.ObjectModelHelper; 028import org.apache.cocoon.environment.PermanentRedirector; 029import org.apache.cocoon.environment.Redirector; 030import org.apache.cocoon.environment.Request; 031import org.apache.cocoon.environment.Response; 032import org.apache.cocoon.environment.SourceResolver; 033import org.apache.commons.lang3.StringUtils; 034import org.apache.excalibur.source.SourceNotFoundException; 035 036import org.ametys.core.util.URIUtils; 037import org.ametys.plugins.site.Site; 038import org.ametys.plugins.site.SiteInformationCache; 039import org.ametys.plugins.site.SiteUrl; 040 041/** 042 * Get the site from server path, port and path. 043 */ 044public class GetSiteAction extends ServiceableAction implements ThreadSafe 045{ 046 /** 047 * sub_path in the uri to indicate the edition mode, and parameter passed to back 048 */ 049 public static final String EDITION_URI = "edition"; 050 051 private SiteInformationCache _siteCache; 052 053 /** 054 * Get the site information cache 055 * @return the SiteInformationCache 056 */ 057 protected SiteInformationCache _getSiteInformationCache() 058 { 059 if (_siteCache == null) 060 { 061 try 062 { 063 _siteCache = (SiteInformationCache) manager.lookup(SiteInformationCache.ROLE); 064 } 065 catch (ServiceException e) 066 { 067 throw new IllegalStateException("Cannot get SiteInformationCache", e); 068 } 069 } 070 return _siteCache; 071 } 072 073 @Override 074 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 075 { 076 Request request = ObjectModelHelper.getRequest(objectModel); 077 Response response = ObjectModelHelper.getResponse(objectModel); 078 079 String frontServer = request.getServerName(); 080 String frontPort = String.valueOf(request.getServerPort()); 081 String frontPath = request.getRequestURI(); 082 083 frontPath = frontPath.endsWith("/") ? frontPath.substring(0, frontPath.length() - 1) : frontPath; 084 085 Map<SiteUrl, Site> sites = _getSiteInformationCache().getSites(); 086 Iterator<SiteUrl> it = sites.keySet().iterator(); 087 088 Site result = null; 089 String pathInSite = null; 090 String path = null; 091 HashMap<String, String> map = new HashMap<>(); 092 093 while (result == null && it.hasNext()) 094 { 095 SiteUrl url = it.next(); 096 Site site = sites.get(url); 097 String serverName = url.getServerName(); 098 String port = url.getServerPort(); 099 path = url.getServerPath(); 100 path = path.endsWith("/") ? path.substring(0, path.length() - 1) : path; 101 102 if (serverName.equals(frontServer) && frontPort.equals(port) && frontPath.startsWith(path)) 103 { 104 // same server and port, the path starts with the configured context, the current site is eligible 105 result = site; 106 pathInSite = frontPath.equals(path) ? "" : frontPath.substring(path.length() + 1); 107 108 if (frontPath.equals(path) || "index.html".equals(pathInSite)) 109 { 110 // root was requested 111 List<String> languages = site.getLanguages(); 112 113 String language = _findLanguage(request, languages); 114 115 String redirectURI = url.getServerPath() + "/" + language + "/index.html"; 116 117 if (redirector instanceof PermanentRedirector) 118 { 119 ((PermanentRedirector) redirector).permanentRedirect(false, redirectURI); 120 response.setHeader("Cache-Control", "no-cache"); 121 } 122 else 123 { 124 redirector.redirect(false, redirectURI); 125 } 126 127 return null; 128 } 129 130 if (pathInSite.startsWith(EDITION_URI + "/")) 131 { 132 url = new SiteUrl(url.getServerName(), url.getServerPort(), url.getServerPath() + "/" + EDITION_URI); 133 path += "/" + EDITION_URI; 134 pathInSite = pathInSite.substring(EDITION_URI.length() + 1); 135 136 request.setAttribute(EDITION_URI, "true"); 137 } 138 139 // per spec, request.getRequestURI() is not decoded, so we have to do it here 140 pathInSite = URIUtils.decode(pathInSite); 141 142 request.setAttribute("site", result); 143 request.setAttribute("url", url); 144 request.setAttribute("path", pathInSite); 145 request.setAttribute("requestedURI", request.getRequestURI()); 146 } 147 } 148 149 if (result == null) 150 { 151 throw new SourceNotFoundException("There's no site registered in the cms for url http(s)://" + frontServer + ":" + frontPort + frontPath + "/"); 152 } 153 154 map.put("site", result.getName()); 155 map.put("path", pathInSite); 156 157 String p = path; 158 p = StringUtils.removeStart(p, request.getContextPath()); 159 p = StringUtils.removeStart(p, "/"); 160 p = StringUtils.isBlank(p) ? "" : (p + "/"); 161 map.put("sitePath", p); 162 request.setAttribute("sitePath", p); 163 164 return map; 165 } 166 167 private String _findLanguage(Request request, List<String> availableLanguages) 168 { 169 String requestLanguage = request.getLocale().getLanguage(); 170 171 return availableLanguages.contains(requestLanguage) ? requestLanguage : availableLanguages.contains("en") ? "en" : availableLanguages.get(0); 172 } 173}