001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: /* $Id: DocumentPolicyManagerWrapper.java 566248 2007-08-15 16:30:23Z andreas $ */
020:
021: package org.apache.lenya.cms.ac;
022:
023: import org.apache.avalon.framework.activity.Disposable;
024: import org.apache.avalon.framework.configuration.Configurable;
025: import org.apache.avalon.framework.configuration.Configuration;
026: import org.apache.avalon.framework.configuration.ConfigurationException;
027: import org.apache.avalon.framework.logger.AbstractLogEnabled;
028: import org.apache.avalon.framework.parameters.ParameterException;
029: import org.apache.avalon.framework.service.ServiceException;
030: import org.apache.avalon.framework.service.ServiceManager;
031: import org.apache.avalon.framework.service.ServiceSelector;
032: import org.apache.avalon.framework.service.Serviceable;
033: import org.apache.cocoon.environment.Request;
034: import org.apache.lenya.ac.AccessControlException;
035: import org.apache.lenya.ac.Accreditable;
036: import org.apache.lenya.ac.AccreditableManager;
037: import org.apache.lenya.ac.Credential;
038: import org.apache.lenya.ac.Identity;
039: import org.apache.lenya.ac.InheritingPolicyManager;
040: import org.apache.lenya.ac.Policy;
041: import org.apache.lenya.ac.PolicyManager;
042: import org.apache.lenya.ac.Role;
043: import org.apache.lenya.ac.impl.DefaultAccessController;
044: import org.apache.lenya.cms.cocoon.components.context.ContextUtility;
045: import org.apache.lenya.cms.publication.Document;
046: import org.apache.lenya.cms.publication.DocumentFactory;
047: import org.apache.lenya.cms.publication.DocumentUtil;
048: import org.apache.lenya.cms.publication.Publication;
049: import org.apache.lenya.cms.publication.PublicationUtil;
050: import org.apache.lenya.cms.publication.URLInformation;
051: import org.apache.lenya.cms.repository.RepositoryUtil;
052: import org.apache.lenya.cms.repository.Session;
053:
054: /**
055: * A PolicyManager which is capable of mapping all URLs of a document to the
056: * appropriate canonical URL, e.g. <code>/foo/bar_de.print.html</code> is
057: * mapped to <code>/foo/bar</code>.
058: */
059: public class DocumentPolicyManagerWrapper extends AbstractLogEnabled
060: implements InheritingPolicyManager, Serviceable, Configurable,
061: Disposable {
062:
063: /**
064: * Ctor.
065: */
066: public DocumentPolicyManagerWrapper() {
067: // do nothing
068: }
069:
070: private InheritingPolicyManager policyManager;
071: private ServiceSelector policyManagerSelector;
072:
073: /**
074: * Returns the URI which is used to obtain the policy for a webapp URL.
075: * @param webappUrl The web application URL.
076: * @return A string.
077: * @throws AccessControlException when something went wrong.
078: */
079: protected String getPolicyURL(String webappUrl)
080: throws AccessControlException {
081: return getPolicyUrlCorrect(webappUrl);
082: }
083:
084: /**
085: * Returns the URI which is used to obtain the policy for a webapp URL.
086: * @param webappUrl The web application URL.
087: * @return A string.
088: * @throws AccessControlException when something went wrong.
089: */
090: protected String getPolicyUrlCorrect(String webappUrl)
091: throws AccessControlException {
092:
093: if (getLogger().isDebugEnabled()) {
094: getLogger().debug(
095: "Resolving policy for webapp URL [" + webappUrl
096: + "]");
097: }
098:
099: String url = null;
100: ContextUtility contextUtility = null;
101: try {
102: contextUtility = (ContextUtility) serviceManager
103: .lookup(ContextUtility.ROLE);
104: Session session = RepositoryUtil.getSession(
105: this .serviceManager, contextUtility.getRequest());
106: DocumentFactory map = DocumentUtil.createDocumentFactory(
107: this .serviceManager, session);
108:
109: // always check for authoring URL since the live document doesn't
110: // have to exist
111:
112: URLInformation info = new URLInformation(webappUrl);
113: // Danger, Will Robinson! If area or pubId is null, webappUrl.substring()
114: // will be out of bounds, because null becomes "null" in string concatenation
115: String pubId = info.getPublicationId();
116: String area = info.getArea();
117: String prefix = "/" + ((pubId != null) ? pubId + "/" : "");
118: // String prefix = "/" + pubId + "/";
119: String prefixWithArea = prefix
120: + ((area != null) ? area : "");
121: // String prefixWithArea = prefix + area;
122: String authoringUrl = prefix
123: + Publication.AUTHORING_AREA
124: + ((webappUrl.length() > prefixWithArea.length()) ? webappUrl
125: .substring(prefixWithArea.length())
126: : "/");
127:
128: if (map.isDocument(authoringUrl)) {
129: Document authoringDoc = map.getFromURL(authoringUrl);
130: url = "/" + authoringDoc.getPublication().getId() + "/"
131: + area + authoringDoc.getPath();
132: if (getLogger().isDebugEnabled()) {
133: getLogger().debug(" Document exists");
134: getLogger().debug(
135: " Document path: ["
136: + authoringDoc.getPath() + "]");
137: }
138: }
139: } catch (ServiceException e) {
140: throw new AccessControlException(
141: "Error looking up ContextUtility component", e);
142: } catch (Exception e) {
143: throw new AccessControlException(e);
144: } finally {
145: if (contextUtility != null) {
146: serviceManager.release(contextUtility);
147: }
148: }
149:
150: if (url == null) {
151: if (getLogger().isDebugEnabled()) {
152: getLogger().debug(" Document does not exist.");
153: }
154: url = webappUrl;
155: }
156:
157: if (getLogger().isDebugEnabled()) {
158: getLogger().debug(" Using URL: [" + url + "]");
159: }
160: return url;
161: }
162:
163: protected String getPolicyUrlFast(String webappUrl)
164: throws AccessControlException {
165: String strippedUrl = strip(strip(webappUrl, '.'), '_');
166: return strippedUrl;
167: }
168:
169: protected String strip(String strippedUrl, char delimiter) {
170: int lastDotIndex = strippedUrl.lastIndexOf(delimiter);
171: if (lastDotIndex != -1) {
172: strippedUrl = strippedUrl.substring(0, lastDotIndex);
173: }
174: return strippedUrl;
175: }
176:
177: /**
178: * Returns the publication for a certain URL.
179: * @param url The webapp url.
180: * @return A publication.
181: * @throws AccessControlException when the publication could not be created.
182: */
183: protected Publication getPublication(String url)
184: throws AccessControlException {
185: getLogger().debug("Building publication");
186:
187: ContextUtility util = null;
188: try {
189: util = (ContextUtility) this .serviceManager
190: .lookup(ContextUtility.ROLE);
191: Request request = util.getRequest();
192: DocumentFactory factory = DocumentUtil.getDocumentFactory(
193: this .serviceManager, request);
194: return PublicationUtil.getPublicationFromUrl(
195: this .serviceManager, factory, url);
196: } catch (Exception e) {
197: throw new AccessControlException(e);
198: } finally {
199: if (util != null) {
200: this .serviceManager.release(util);
201: }
202: }
203: }
204:
205: private ServiceManager serviceManager;
206:
207: /**
208: * Returns the service manager.
209: * @return A service manager.
210: */
211: protected ServiceManager getServiceManager() {
212: return this .serviceManager;
213: }
214:
215: /**
216: * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
217: */
218: public void service(ServiceManager manager) throws ServiceException {
219: this .serviceManager = manager;
220: }
221:
222: /**
223: * @return Returns the policyManager.
224: */
225: public InheritingPolicyManager getPolicyManager() {
226: return this .policyManager;
227: }
228:
229: /**
230: * @param _policyManager The policyManager to set.
231: */
232: public void setPolicyManager(InheritingPolicyManager _policyManager) {
233: this .policyManager = _policyManager;
234: }
235:
236: public Policy buildSubtreePolicy(AccreditableManager controller,
237: String url) throws AccessControlException {
238: return getPolicyManager().buildSubtreePolicy(controller,
239: getPolicyURL(url));
240: }
241:
242: public Policy[] getPolicies(AccreditableManager controller,
243: String url) throws AccessControlException {
244: return getPolicyManager().getPolicies(controller,
245: getPolicyURL(url));
246: }
247:
248: public void saveSubtreePolicy(String url, Policy policy)
249: throws AccessControlException {
250: getPolicyManager().saveSubtreePolicy(getPolicyURL(url), policy);
251: }
252:
253: /**
254: * @see org.apache.lenya.ac.PolicyManager#getPolicy(org.apache.lenya.ac.AccreditableManager,
255: * java.lang.String)
256: */
257: public Policy getPolicy(AccreditableManager controller, String url)
258: throws AccessControlException {
259: return getPolicyManager().getPolicy(controller,
260: getPolicyURL(url));
261: }
262:
263: /**
264: * @see org.apache.lenya.ac.PolicyManager#accreditableRemoved(org.apache.lenya.ac.AccreditableManager,
265: * org.apache.lenya.ac.Accreditable)
266: */
267: public void accreditableRemoved(AccreditableManager manager,
268: Accreditable accreditable) throws AccessControlException {
269: getPolicyManager().accreditableRemoved(manager, accreditable);
270:
271: }
272:
273: String ELEMENT_POLICY_MANAGER = "policy-manager";
274: String ATTRIBUTE_TYPE = "type";
275:
276: /**
277: * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
278: */
279: public void configure(Configuration configuration)
280: throws ConfigurationException {
281: Configuration policyManagerConfiguration = configuration
282: .getChild(this .ELEMENT_POLICY_MANAGER, false);
283: if (policyManagerConfiguration != null) {
284: String type = null;
285: try {
286: type = policyManagerConfiguration
287: .getAttribute(this .ATTRIBUTE_TYPE);
288:
289: this .policyManagerSelector = (ServiceSelector) getServiceManager()
290: .lookup(PolicyManager.ROLE + "Selector");
291:
292: PolicyManager _policyManager = (PolicyManager) this .policyManagerSelector
293: .select(type);
294:
295: if (!(_policyManager instanceof InheritingPolicyManager)) {
296: throw new AccessControlException("The "
297: + getClass().getName()
298: + " can only be used with an "
299: + InheritingPolicyManager.class.getName()
300: + ".");
301: }
302:
303: DefaultAccessController.configureOrParameterize(
304: _policyManager, policyManagerConfiguration);
305: setPolicyManager((InheritingPolicyManager) _policyManager);
306: } catch (final ConfigurationException e1) {
307: throw new ConfigurationException(
308: "Obtaining policy manager for type [" + type
309: + "] failed: ", e1);
310: } catch (final ServiceException e1) {
311: throw new ConfigurationException(
312: "Obtaining policy manager for type [" + type
313: + "] failed: ", e1);
314: } catch (final ParameterException e1) {
315: throw new ConfigurationException(
316: "Obtaining policy manager for type [" + type
317: + "] failed: ", e1);
318: } catch (final AccessControlException e1) {
319: throw new ConfigurationException(
320: "Obtaining policy manager for type [" + type
321: + "] failed: ", e1);
322: }
323: }
324: }
325:
326: /**
327: * @see org.apache.avalon.framework.activity.Disposable#dispose()
328: */
329: public void dispose() {
330: if (this .policyManagerSelector != null) {
331: if (getPolicyManager() != null) {
332: this .policyManagerSelector.release(getPolicyManager());
333: }
334: getServiceManager().release(this .policyManagerSelector);
335: }
336: if (getLogger().isDebugEnabled()) {
337: getLogger().debug("Disposing [" + this + "]");
338: }
339:
340: }
341:
342: /**
343: * @see org.apache.lenya.ac.PolicyManager#accreditableAdded(org.apache.lenya.ac.AccreditableManager,
344: * org.apache.lenya.ac.Accreditable)
345: */
346: public void accreditableAdded(AccreditableManager manager,
347: Accreditable accreditable) throws AccessControlException {
348: getPolicyManager().accreditableAdded(manager, accreditable);
349: }
350:
351: public Credential[] getCredentials(AccreditableManager controller,
352: String url) throws AccessControlException {
353: return getPolicyManager().getCredentials(controller,
354: getPolicyURL(url));
355: }
356:
357: public Role[] getGrantedRoles(
358: AccreditableManager accreditableManager, Identity identity,
359: String url) throws AccessControlException {
360: return getPolicyManager().getGrantedRoles(accreditableManager,
361: identity, getPolicyURL(url));
362: }
363: }
|