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; 019 020import org.apache.avalon.framework.context.Context; 021import org.apache.avalon.framework.context.ContextException; 022import org.apache.avalon.framework.context.Contextualizable; 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.service.ServiceManager; 025import org.apache.cocoon.components.ContextHelper; 026import org.apache.cocoon.environment.Request; 027 028import org.ametys.cms.repository.Content; 029import org.ametys.cms.transformation.URIResolver; 030import org.ametys.odf.ProgramItem; 031import org.ametys.odf.course.Course; 032import org.ametys.odf.program.AbstractProgram; 033import org.ametys.odf.program.Program; 034import org.ametys.odf.program.SubProgram; 035import org.ametys.plugins.odfweb.repository.OdfPageHandler; 036import org.ametys.plugins.odfweb.repository.OdfPageResolver; 037import org.ametys.plugins.repository.AmetysObject; 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 private OdfPageHandler _odfPageHandler; 062 063 @Override 064 public void service(ServiceManager manager) throws ServiceException 065 { 066 super.service(manager); 067 _odfPageResolver = (OdfPageResolver) manager.lookup(OdfPageResolver.ROLE); 068 _odfPageHandler = (OdfPageHandler) manager.lookup(OdfPageHandler.ROLE); 069 _renderingContextHandler = (RenderingContextHandler) manager.lookup(RenderingContextHandler.ROLE); 070 _prefixHandler = (URIPrefixHandler) manager.lookup(URIPrefixHandler.ROLE); 071 _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE); 072 } 073 074 @Override 075 public void contextualize(Context context) throws ContextException 076 { 077 _context = context; 078 } 079 080 @Override 081 public String resolve(String uri, boolean download, boolean absolute, boolean internal) 082 { 083 Request request = ContextHelper.getRequest(_context); 084 String currentSite = (String) request.getAttribute(GetSiteAction.OVERRIDE_SITE_REQUEST_ATTR); 085 if (currentSite == null) 086 { 087 currentSite = (String) request.getAttribute("site"); 088 } 089 if (currentSite == null) 090 { 091 currentSite = (String) request.getAttribute("siteName"); 092 } 093 094 // Handle URI like content://UUID or 095 // courseContent://UUID;programContent://UUID or 096 // courseContent://UUID;courseContent://UUID;programContent://UUID 097 int i = uri.indexOf(';'); 098 String contentId = uri; 099 if (i != -1) 100 { 101 contentId = uri.substring(0, i); 102 } 103 104 Content content = _resolver.resolveById(contentId); 105 106 Page odfRootPage = _odfPageResolver.getOdfRootPage(currentSite, content.getLanguage(), ((ProgramItem) content).getCatalog()); 107 108 RenderingContext context = _renderingContextHandler.getRenderingContext(); 109 110 Page page = null; 111 String pagePath = null; 112 113 if (content instanceof Program) 114 { 115 page = _odfPageResolver.getProgramPage((Program) content, currentSite); 116 } 117 else if (content instanceof SubProgram) 118 { 119 page = _getSubProgramPage((SubProgram) content, odfRootPage, uri.split(";")); 120 } 121 else if (content instanceof Course) 122 { 123 page = _getCoursePage((Course) content, odfRootPage, uri.split(";")); 124 } 125 126 if (page == null) 127 { 128 // No page found, back to content URI 129 String siteName = Config.getInstance().getValue("odf.web.site.name"); 130 return _getContentURI(content, siteName, context, absolute, internal); 131 } 132 133 // We resolved a page either in the current site or in the ODF default 134 // site. 135 // The site is the page's site. 136 String siteName = page.getSiteName(); 137 138 pagePath = page.getSitemapName() + "/" + page.getPathInSitemap() + ".html"; 139 140 try 141 { 142 if (!siteName.equals(currentSite) && context == RenderingContext.FRONT) 143 { 144 String url = _siteManager.getSite(siteName).getUrl(); 145 return url + "/" + page.getSitemapName() + "/" + page.getPathInSitemap() + ".html"; 146 } 147 148 if (!(context == RenderingContext.BACK)) 149 { 150 StringBuilder result = new StringBuilder(); 151 152 if (internal) 153 { 154 result.append("cocoon://").append(siteName); 155 } 156 else if (absolute) 157 { 158 result.append(_prefixHandler.getAbsoluteUriPrefix(siteName)); 159 } 160 else 161 { 162 result.append(_prefixHandler.getUriPrefix(siteName)); 163 } 164 165 result.append("/").append(pagePath); 166 167 return new URI(null, null, result.toString(), null).toASCIIString(); 168 } 169 else // back 170 { 171 return "javascript:(function(){parent.Ametys.tool.ToolsManager.openTool('uitool-page', {id:'" + page.getId() + "'});})()"; 172 } 173 } 174 catch (Exception e) 175 { 176 throw new IllegalStateException(e); 177 } 178 } 179 180 private Page _getSubProgramPage(SubProgram subProgram, Page odfRootPage, String[] paths) 181 { 182 if (odfRootPage == null) 183 { 184 // There is no ODF root page 185 return null; 186 } 187 188 int index = paths.length - 1; 189 if (paths.length > 2) 190 { 191 // Possible paths are : 192 // [subprogramContent://UUID, subprogramContent://UUID, 193 // subprogramContent://UUID] 194 // [subprogramContent://UUID, subprogramContent://UUID, 195 // programContent://UUID] 196 197 AmetysObject lastParent = _resolver.resolveById(paths[index]); 198 199 Program rootProgram = null; 200 if (lastParent instanceof Program) 201 { 202 rootProgram = (Program) lastParent; 203 } 204 else 205 { 206 rootProgram = _odfPageResolver.getParentProgram((ProgramItem) lastParent, null); 207 } 208 209 if (rootProgram == null) 210 { 211 return null; 212 } 213 214 String pagePath = _odfPageResolver.getPathInProgram((ProgramItem) lastParent, null); 215 index -= 1; 216 217 while (index > 0) 218 { 219 ProgramItem parentItem = _resolver.resolveById(paths[index]); 220 if (parentItem instanceof AbstractProgram) 221 { 222 pagePath += '/' + _odfPageHandler.getPageName(parentItem); 223 index--; 224 } 225 } 226 227 return _resolver.resolveById("program://" + pagePath + "?rootId=" + odfRootPage.getId() + "&programId=" + subProgram.getId() + "&parentId=" + rootProgram.getId()); 228 } 229 else if (paths.length == 2) 230 { 231 // Possible paths are : 232 // [subProgramContent://UUID1, programContent://UUID1] 233 // [subProgramContent://UUID1, subProgramContent://UUID1] 234 235 AmetysObject parent = _resolver.resolveById(paths[index]); 236 if (parent instanceof AbstractProgram) 237 { 238 return _odfPageResolver.getSubProgramPage(odfRootPage, subProgram, (AbstractProgram) parent); 239 } 240 } 241 else 242 { 243 // [subProgramContent://UUID1] 244 return _odfPageResolver.getSubProgramPage(odfRootPage, subProgram, null); 245 } 246 247 // No page found 248 return null; 249 } 250 251 private Page _getCoursePage(Course course, Page odfRootPage, String[] paths) 252 { 253 if (odfRootPage == null) 254 { 255 // There is no ODF root page 256 return null; 257 } 258 259 int index = paths.length - 1; 260 if (paths.length > 2) 261 { 262 // Possible paths are : 263 // [courseContent://UUID1, courseContent://UUID2, ..., courseContent://UUID3, (sub)programContent://UUID] 264 // [courseContent://UUID1, courseContent://UUID2, ..., courseContent://UUID3] 265 // [courseContent://UUID1, subprogramContent://UUID2, ..., (sub)programContent://UUID3] 266 267 AmetysObject lastParent = _resolver.resolveById(paths[index]); 268 269 Program rootProgram = null; 270 if (lastParent instanceof Program) 271 { 272 rootProgram = (Program) lastParent; 273 } 274 else 275 { 276 rootProgram = _odfPageResolver.getParentProgram((ProgramItem) lastParent, null); 277 } 278 279 if (rootProgram == null) 280 { 281 return null; 282 } 283 284 String pagePath = _odfPageResolver.getPathInProgram((ProgramItem) lastParent, null); 285 index -= 1; 286 287 while (index > 0) 288 { 289 ProgramItem parentItem = _resolver.resolveById(paths[index]); 290 if (parentItem instanceof AbstractProgram || parentItem instanceof Course) 291 { 292 pagePath += '/' + _odfPageHandler.getPageName(parentItem); 293 index--; 294 } 295 } 296 297 return _resolver.resolveById("course://" + pagePath + "?rootId=" + odfRootPage.getId() + "&courseId=" + course.getId() + "&programId=" + rootProgram.getId()); 298 } 299 else if (paths.length == 2) 300 { 301 // Possible paths are : 302 // [courseContent://UUID1, courseContent://UUID1] 303 // [courseContent://UUID1, programContent://UUID1] 304 // [courseContent://UUID1, subProgramContent://UUID1] 305 306 AmetysObject parent = _resolver.resolveById(paths[index]); 307 if (parent instanceof AbstractProgram) 308 { 309 return _odfPageResolver.getCoursePage(odfRootPage, course, (AbstractProgram) parent); 310 } 311 else if (parent instanceof Course) 312 { 313 return _odfPageResolver.getCoursePage(odfRootPage, course, (Course) parent); 314 } 315 } 316 else 317 { 318 // [courseContent://UUID1] 319 return _odfPageResolver.getCoursePage(odfRootPage, course, (AbstractProgram) null); 320 } 321 322 // No page found 323 return null; 324 } 325 326 /** 327 * Get the content URI 328 * 329 * @param content The content 330 * @param siteName The site name 331 * @param context The rendering context 332 * @param absolute true if the url must be absolute 333 * @param internal true to get an internal URI. 334 * @return the content URI 335 */ 336 protected String _getContentURI(Content content, String siteName, RenderingContext context, boolean absolute, boolean internal) 337 { 338 try 339 { 340 if (context == RenderingContext.FRONT) 341 { 342 // In FO mode do not give the content URI 343 return ""; 344 } 345 else if (!(context == RenderingContext.BACK)) 346 { 347 StringBuilder result = new StringBuilder(); 348 349 if (internal) 350 { 351 result.append("cocoon://").append(siteName); 352 } 353 else if (absolute) 354 { 355 result.append(_prefixHandler.getAbsoluteUriPrefix()); 356 } 357 else 358 { 359 result.append(_prefixHandler.getUriPrefix()); 360 } 361 result.append("/").append("_wrapped-content.html"); 362 String query = "contentId=" + content.getId() + "&userLocale=" + content.getLanguage() + "&siteName=" + siteName; 363 return new URI(null, null, result.toString(), query, null).toASCIIString(); 364 } 365 else 366 { 367 return "javascript:(function(){parent.Ametys.tool.ToolsManager.openTool('uitool-content', {id:'" + content.getId() + "'});})()"; 368 } 369 } 370 catch (Exception e) 371 { 372 throw new IllegalStateException(e); 373 } 374 } 375}