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