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