001/* 002 * Copyright 2011 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.plugins.odfweb; 017 018import java.net.URI; 019import java.util.Arrays; 020 021import org.apache.avalon.framework.context.Context; 022import org.apache.avalon.framework.context.ContextException; 023import org.apache.avalon.framework.context.Contextualizable; 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.cocoon.components.ContextHelper; 027import org.apache.cocoon.environment.Request; 028 029import org.ametys.cms.repository.Content; 030import org.ametys.cms.transformation.URIResolver; 031import org.ametys.core.util.URIUtils; 032import org.ametys.odf.ProgramItem; 033import org.ametys.odf.course.Course; 034import org.ametys.odf.program.AbstractProgram; 035import org.ametys.odf.program.Program; 036import org.ametys.odf.program.SubProgram; 037import org.ametys.plugins.odfweb.repository.OdfPageResolver; 038import org.ametys.runtime.config.Config; 039import org.ametys.web.URIPrefixHandler; 040import org.ametys.web.content.GetSiteAction; 041import org.ametys.web.renderingcontext.RenderingContext; 042import org.ametys.web.renderingcontext.RenderingContextHandler; 043import org.ametys.web.repository.page.Page; 044import org.ametys.web.repository.site.SiteManager; 045 046/** 047 * {@link URIResolver} for a ODF Content. 048 */ 049public class OdfURIResolver extends org.ametys.odf.OdfURIResolver implements Contextualizable 050{ 051 private Context _context; 052 053 private SiteManager _siteManager; 054 055 private OdfPageResolver _odfPageResolver; 056 057 private RenderingContextHandler _renderingContextHandler; 058 059 private URIPrefixHandler _prefixHandler; 060 061 @Override 062 public void service(ServiceManager manager) throws ServiceException 063 { 064 super.service(manager); 065 _odfPageResolver = (OdfPageResolver) manager.lookup(OdfPageResolver.ROLE); 066 _renderingContextHandler = (RenderingContextHandler) manager.lookup(RenderingContextHandler.ROLE); 067 _prefixHandler = (URIPrefixHandler) manager.lookup(URIPrefixHandler.ROLE); 068 _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE); 069 } 070 071 @Override 072 public void contextualize(Context context) throws ContextException 073 { 074 _context = context; 075 } 076 077 @Override 078 public String resolve(String uri, boolean download, boolean absolute, boolean internal) 079 { 080 Request request = ContextHelper.getRequest(_context); 081 String currentSite = (String) request.getAttribute(GetSiteAction.OVERRIDE_SITE_REQUEST_ATTR); 082 if (currentSite == null) 083 { 084 currentSite = (String) request.getAttribute("site"); 085 } 086 if (currentSite == null) 087 { 088 currentSite = (String) request.getAttribute("siteName"); 089 } 090 091 // Handle URI like content://UUID or 092 // courseContent://UUID;programContent://UUID or 093 // courseContent://UUID;courseContent://UUID;programContent://UUID 094 int i = uri.indexOf(';'); 095 String contentId = uri; 096 if (i != -1) 097 { 098 contentId = uri.substring(0, i); 099 } 100 101 Content content = _resolver.resolveById(contentId); 102 103 Page odfRootPage = _odfPageResolver.getOdfRootPage(currentSite, content.getLanguage(), ((ProgramItem) content).getCatalog()); 104 105 RenderingContext context = _renderingContextHandler.getRenderingContext(); 106 107 Page page = null; 108 109 if (content instanceof Program) 110 { 111 page = _odfPageResolver.getProgramPage((Program) content, odfRootPage.getSiteName()); 112 } 113 else if (content instanceof SubProgram) 114 { 115 page = _getSubProgramPage((SubProgram) content, odfRootPage, uri.split(";")); 116 } 117 else if (content instanceof Course) 118 { 119 page = _getCoursePage((Course) content, odfRootPage, uri.split(";")); 120 } 121 122 if (page == null) 123 { 124 // No page found, back to content URI 125 String siteName = Config.getInstance().getValue("odf.web.site.name"); 126 return _getContentURI(content, siteName, context, absolute, internal); 127 } 128 129 // We resolved a page either in the current site or in the ODF default site. 130 // The site is the page's site. 131 String siteName = page.getSiteName(); 132 String pagePath = page.getSitemapName() + "/" + page.getPathInSitemap() + ".html"; 133 134 try 135 { 136 if (!siteName.equals(currentSite) && context == RenderingContext.FRONT) 137 { 138 String url = _siteManager.getSite(siteName).getUrl(); 139 return url + "/" + pagePath; 140 } 141 142 if (!(context == RenderingContext.BACK)) 143 { 144 StringBuilder result = new StringBuilder(); 145 146 if (internal) 147 { 148 result.append("cocoon://").append(siteName); 149 } 150 else if (absolute) 151 { 152 result.append(_prefixHandler.getAbsoluteUriPrefix(siteName)); 153 } 154 else 155 { 156 result.append(_prefixHandler.getUriPrefix(siteName)); 157 } 158 159 result.append("/").append(pagePath); 160 161 return URIUtils.encodePath(result.toString()); 162 } 163 else // back 164 { 165 return "javascript:(function(){parent.Ametys.tool.ToolsManager.openTool('uitool-page', {id:'" + page.getId() + "'});})()"; 166 } 167 } 168 catch (Exception e) 169 { 170 throw new IllegalStateException(e); 171 } 172 } 173 174 private Page _getSubProgramPage(SubProgram subProgram, Page odfRootPage, String[] paths) 175 { 176 if (odfRootPage == null) 177 { 178 // There is no ODF root page 179 return null; 180 } 181 182 if (paths.length > 2) 183 { 184 // Possible paths are : 185 // [subProgramContent://UUID1, programContent://UUID1] 186 // [subProgramContent://UUID1, subProgramContent://UUID1] 187 // [subprogramContent://UUID, subprogramContent://UUID, subprogramContent://UUID] 188 // [subprogramContent://UUID, subprogramContent://UUID, programContent://UUID] 189 190 return _odfPageResolver.getSubProgramPage(odfRootPage, subProgram, Arrays.asList(paths).reversed(), true); 191 } 192 else 193 { 194 // [subProgramContent://UUID1] 195 return _odfPageResolver.getSubProgramPage(odfRootPage, subProgram, null); 196 } 197 } 198 199 private Page _getCoursePage(Course course, Page odfRootPage, String[] paths) 200 { 201 if (odfRootPage == null) 202 { 203 // There is no ODF root page 204 return null; 205 } 206 207 if (paths.length >= 2) 208 { 209 // Possible paths are : 210 // [courseContent://UUID1, courseContent://UUID1] 211 // [courseContent://UUID1, programContent://UUID1] 212 // [courseContent://UUID1, subProgramContent://UUID1] 213 // [courseContent://UUID1, courseContent://UUID2, ..., courseContent://UUID3, (sub)programContent://UUID] 214 // [courseContent://UUID1, courseContent://UUID2, ..., courseContent://UUID3] 215 // [courseContent://UUID1, subprogramContent://UUID2, ..., (sub)programContent://UUID3] 216 217 return _odfPageResolver.getCoursePage(odfRootPage, course, Arrays.asList(paths).subList(1, paths.length).reversed(), true); 218 } 219 else 220 { 221 // [courseContent://UUID1] 222 return _odfPageResolver.getCoursePage(odfRootPage, course, (AbstractProgram) null); 223 } 224 } 225 226 /** 227 * Get the content URI 228 * 229 * @param content The content 230 * @param siteName The site name 231 * @param context The rendering context 232 * @param absolute true if the url must be absolute 233 * @param internal true to get an internal URI. 234 * @return the content URI 235 */ 236 protected String _getContentURI(Content content, String siteName, RenderingContext context, boolean absolute, boolean internal) 237 { 238 try 239 { 240 if (context == RenderingContext.FRONT) 241 { 242 // In FO mode do not give the content URI 243 return ""; 244 } 245 else if (!(context == RenderingContext.BACK)) 246 { 247 StringBuilder result = new StringBuilder(); 248 249 if (internal) 250 { 251 result.append("cocoon://").append(siteName); 252 } 253 else if (absolute) 254 { 255 result.append(_prefixHandler.getAbsoluteUriPrefix()); 256 } 257 else 258 { 259 result.append(_prefixHandler.getUriPrefix()); 260 } 261 result.append("/").append("_wrapped-content.html"); 262 String query = "contentId=" + content.getId() + "&userLocale=" + content.getLanguage() + "&siteName=" + siteName; 263 return new URI(null, null, result.toString(), query, null).toASCIIString(); 264 } 265 else 266 { 267 return "javascript:(function(){parent.Ametys.tool.ToolsManager.openTool('uitool-content', {id:'" + content.getId() + "'});})()"; 268 } 269 } 270 catch (Exception e) 271 { 272 throw new IllegalStateException(e); 273 } 274 } 275}