1 17 package org.apache.lenya.cms.cocoon.transformation; 18 19 import java.io.IOException ; 20 import java.util.Map ; 21 import org.apache.avalon.framework.parameters.Parameters; 22 import org.apache.avalon.framework.activity.Disposable; 23 import org.apache.avalon.framework.service.ServiceSelector; 24 import org.apache.cocoon.ProcessingException; 25 import org.apache.cocoon.environment.ObjectModelHelper; 26 import org.apache.cocoon.environment.Request; 27 import org.apache.cocoon.environment.SourceResolver; 28 import org.apache.cocoon.transformation.AbstractSAXTransformer; 29 import org.apache.lenya.ac.AccessControlException; 30 import org.apache.lenya.ac.AccessController; 31 import org.apache.lenya.ac.AccessControllerResolver; 32 import org.apache.lenya.ac.AccreditableManager; 33 import org.apache.lenya.ac.Authorizer; 34 import org.apache.lenya.ac.Policy; 35 import org.apache.lenya.ac.PolicyManager; 36 import org.apache.lenya.ac.impl.DefaultAccessController; 37 import org.apache.lenya.ac.impl.PolicyAuthorizer; 38 import org.apache.lenya.cms.publication.Document; 39 import org.apache.lenya.cms.publication.DocumentBuilder; 40 import org.apache.lenya.cms.publication.PageEnvelope; 41 import org.apache.lenya.cms.publication.PageEnvelopeFactory; 42 import org.apache.lenya.cms.publication.Proxy; 43 import org.apache.lenya.cms.publication.Publication; 44 import org.apache.lenya.cms.publication.PublicationException; 45 import org.apache.lenya.util.ServletHelper; 46 import org.xml.sax.Attributes ; 47 import org.xml.sax.SAXException ; 48 import org.xml.sax.helpers.AttributesImpl ; 49 50 73 public class LinkRewritingTransformer extends AbstractSAXTransformer implements Disposable { 74 75 private boolean ignoreAElement = false; 76 private ServiceSelector serviceSelector; 77 private PolicyManager policyManager; 78 private AccessControllerResolver acResolver; 79 private AccreditableManager accreditableManager; 80 81 private Document currentDocument; 82 83 88 public void setup(SourceResolver resolver, Map objectModel, String source, Parameters parameters) 89 throws ProcessingException, SAXException , IOException { 90 super.setup(resolver, objectModel, source, parameters); 91 92 try { 93 PageEnvelope envelope = PageEnvelopeFactory.getInstance().getPageEnvelope(objectModel); 94 this.currentDocument = envelope.getDocument(); 95 96 } catch (Exception e) { 97 throw new ProcessingException(e); 98 } 99 100 if (getLogger().isDebugEnabled()) { 101 getLogger().debug("Setting up transformer"); 102 getLogger().debug(" Processed version: [" + getCurrentDocument() + "]"); 103 } 104 105 Request request = ObjectModelHelper.getRequest(objectModel); 106 107 this.serviceSelector = null; 108 this.acResolver = null; 109 this.policyManager = null; 110 111 try { 112 this.serviceSelector = (ServiceSelector) this.manager 113 .lookup(AccessControllerResolver.ROLE + "Selector"); 114 this.acResolver = (AccessControllerResolver) this.serviceSelector 115 .select(AccessControllerResolver.DEFAULT_RESOLVER); 116 117 if (getLogger().isDebugEnabled()) { 118 getLogger().debug(" Resolved AC resolver [" + this.acResolver + "]"); 119 } 120 String webappUrl = ServletHelper.getWebappURI(request); 121 AccessController accessController = this.acResolver.resolveAccessController(webappUrl); 122 if (accessController instanceof DefaultAccessController) { 123 DefaultAccessController defaultAccessController = (DefaultAccessController) accessController; 124 this.accreditableManager = defaultAccessController.getAccreditableManager(); 125 Authorizer[] authorizers = defaultAccessController.getAuthorizers(); 126 for (int i = 0; i < authorizers.length; i++) { 127 if (authorizers[i] instanceof PolicyAuthorizer) { 128 PolicyAuthorizer policyAuthorizer = (PolicyAuthorizer) authorizers[i]; 129 this.policyManager = policyAuthorizer.getPolicyManager(); 130 } 131 } 132 } 133 if (getLogger().isDebugEnabled()) { 134 getLogger().debug(" Using policy manager [" + this.policyManager + "]"); 135 } 136 } catch (Exception e) { 137 throw new ProcessingException(e); 138 } 139 } 140 141 146 protected Document getCurrentDocument() { 147 return this.currentDocument; 148 } 149 150 153 public static final String ATTRIBUTE_HREF = "href"; 154 155 private String indent = ""; 156 157 163 public void startElement(String uri, String name, String qname, Attributes attrs) 164 throws SAXException { 165 166 if (getLogger().isDebugEnabled()) { 167 getLogger().debug(this.indent + "<" + qname + "> (ignoreAElement = " 168 + isIgnoreAElement() + ")"); 169 this.indent += " "; 170 } 171 172 AttributesImpl newAttrs = null; 173 if (lookingAtLinkElement(name)) { 174 175 setIgnoreAElement(false); 176 177 String href = attrs.getValue(ATTRIBUTE_HREF); 178 if (href != null) { 179 180 Publication publication = getCurrentDocument().getPublication(); 181 DocumentBuilder builder = publication.getDocumentBuilder(); 182 183 try { 184 185 newAttrs = new AttributesImpl (attrs); 186 187 if (getLogger().isDebugEnabled()) { 188 getLogger().debug(this.indent + "href URL: [" + href + "]"); 189 } 190 191 String context = this.request.getContextPath(); 192 193 if (href.startsWith(context + "/" + publication.getId())) { 194 195 final String webappUrlWithQueryString = href.substring(context.length()); 196 String webappUrlWithAnchor; 197 198 String queryString = null; 199 int queryStringIndex = webappUrlWithQueryString.indexOf("?"); 200 if (queryStringIndex > -1) { 201 webappUrlWithAnchor = webappUrlWithQueryString.substring(0, queryStringIndex); 202 queryString = webappUrlWithQueryString.substring(queryStringIndex + 1); 203 } 204 else { 205 webappUrlWithAnchor = webappUrlWithQueryString; 206 } 207 208 String anchor = null; 209 String webappUrl = null; 210 211 int anchorIndex = webappUrlWithAnchor.indexOf("#"); 212 if (anchorIndex > -1) { 213 webappUrl = webappUrlWithAnchor.substring(0, anchorIndex); 214 anchor = webappUrlWithAnchor.substring(anchorIndex + 1); 215 } 216 else { 217 webappUrl = webappUrlWithAnchor; 218 } 219 220 if (getLogger().isDebugEnabled()) { 221 getLogger().debug(this.indent + "webapp URL: [" + webappUrl + "]"); 222 getLogger().debug(this.indent + "anchor: [" + anchor + "]"); 223 } 224 if (builder.isDocument(publication, webappUrl)) { 225 226 Document targetDocument = builder.buildDocument(publication, webappUrl); 227 228 if (getLogger().isDebugEnabled()) { 229 getLogger().debug(this.indent + "Resolved target document: [" 230 + targetDocument + "]"); 231 } 232 233 String currentAreaUrl = builder.buildCanonicalUrl(publication, 234 getCurrentDocument().getArea(), 235 targetDocument.getId(), 236 targetDocument.getLanguage()); 237 targetDocument = builder.buildDocument(publication, currentAreaUrl); 238 239 if (targetDocument.exists()) { 240 rewriteLink(newAttrs, targetDocument, anchor, queryString); 241 } else { 242 setIgnoreAElement(true); 243 } 244 } 245 } 246 } catch (Exception e) { 247 getLogger().error("startElement failed: ", e); 248 throw new SAXException (e); 249 } 250 } 251 252 } 253 254 if (getLogger().isDebugEnabled()) { 255 getLogger().debug(this.indent + "ignoreAElement: " + isIgnoreAElement()); 256 } 257 258 if (!(lookingAtAElement(name) && isIgnoreAElement())) { 259 if (newAttrs != null) { 260 attrs = newAttrs; 261 } 262 super.startElement(uri, name, qname, attrs); 263 if (getLogger().isDebugEnabled()) { 264 getLogger().debug(this.indent + "<" + qname + "> sent"); 265 } 266 } 267 } 268 269 279 protected void rewriteLink(AttributesImpl newAttrs, Document targetDocument, String anchor, String queryString) 280 throws AccessControlException, PublicationException { 281 String webappUrl = targetDocument.getCompleteURL(); 282 Policy policy = this.policyManager.getPolicy(this.accreditableManager, webappUrl); 283 284 Proxy proxy = targetDocument.getPublication().getProxy(targetDocument, policy.isSSLProtected()); 285 286 String rewrittenURL; 287 if (proxy == null) { 288 rewrittenURL = this.request.getContextPath() + webappUrl; 289 } else { 290 rewrittenURL = proxy.getURL(targetDocument); 291 } 292 293 if (anchor != null) { 294 rewrittenURL += "#" + anchor; 295 } 296 297 if (queryString != null) { 298 rewrittenURL += "?" + queryString; 299 } 300 301 if (getLogger().isDebugEnabled()) { 302 getLogger().debug(this.indent + "SSL protection: [" + policy.isSSLProtected() + "]"); 303 getLogger().debug(this.indent + "Resolved proxy: [" + proxy + "]"); 304 getLogger().debug(this.indent + "Rewriting URL to: [" + rewrittenURL + "]"); 305 } 306 307 setHrefAttribute(newAttrs, rewrittenURL); 308 } 309 310 318 protected void setHrefAttribute(AttributesImpl attr, String value) { 319 int position = attr.getIndex(ATTRIBUTE_HREF); 320 if (position == -1) { 321 throw new IllegalArgumentException ("The href attribute is not available!"); 322 } 323 attr.setValue(position, value); 324 } 325 326 332 public void endElement(String uri, String name, String qname) throws SAXException { 333 if (getLogger().isDebugEnabled()) { 334 this.indent = this.indent.substring(2); 335 getLogger().debug(this.indent + "</" + qname + ">"); 336 } 337 if (lookingAtAElement(name) && isIgnoreAElement()) { 338 setIgnoreAElement(false); 339 } else { 340 if (getLogger().isDebugEnabled()) { 341 getLogger().debug(this.indent + "</" + qname + "> sent"); 342 } 343 super.endElement(uri, name, qname); 344 } 345 } 346 347 354 protected boolean lookingAtLinkElement(String name) { 355 return lookingAtAElement(name); 356 } 357 358 protected boolean lookingAtAElement(String name) { 359 return name.equals("a"); 360 } 361 362 365 public void dispose() { 366 if (getLogger().isDebugEnabled()) { 367 getLogger().debug("Disposing transformer"); 368 } 369 if (this.serviceSelector != null) { 370 if (this.acResolver != null) { 371 this.serviceSelector.release(this.acResolver); 372 } 373 this.manager.release(this.serviceSelector); 374 } 375 } 376 377 381 public void recycle() { 382 this.ignoreAElement = false; 383 } 384 387 protected boolean isIgnoreAElement() { 388 return ignoreAElement; 389 } 390 393 protected void setIgnoreAElement(boolean ignoreAElement) { 394 this.ignoreAElement = ignoreAElement; 395 } 396 } | Popular Tags |