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: package org.apache.lenya.cms.usecase.gui.impl;
019:
020: import java.util.ArrayList;
021: import java.util.HashMap;
022: import java.util.List;
023: import java.util.Map;
024:
025: import org.apache.avalon.framework.configuration.Configurable;
026: import org.apache.avalon.framework.configuration.Configuration;
027: import org.apache.avalon.framework.configuration.ConfigurationException;
028: import org.apache.avalon.framework.context.Context;
029: import org.apache.avalon.framework.context.ContextException;
030: import org.apache.avalon.framework.context.Contextualizable;
031: import org.apache.avalon.framework.logger.AbstractLogEnabled;
032: import org.apache.avalon.framework.service.ServiceException;
033: import org.apache.avalon.framework.service.ServiceManager;
034: import org.apache.avalon.framework.service.ServiceSelector;
035: import org.apache.avalon.framework.service.Serviceable;
036: import org.apache.cocoon.components.ContextHelper;
037: import org.apache.cocoon.environment.Request;
038: import org.apache.lenya.ac.AccessControlException;
039: import org.apache.lenya.ac.AccessController;
040: import org.apache.lenya.ac.AccessControllerResolver;
041: import org.apache.lenya.ac.Authorizer;
042: import org.apache.lenya.ac.Role;
043: import org.apache.lenya.cms.ac.PolicyUtil;
044: import org.apache.lenya.cms.ac.usecase.UsecaseAuthorizer;
045: import org.apache.lenya.cms.cocoon.components.context.ContextUtility;
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.usecase.Usecase;
051: import org.apache.lenya.cms.usecase.UsecaseMessage;
052: import org.apache.lenya.cms.usecase.UsecaseResolver;
053: import org.apache.lenya.cms.usecase.gui.GUIManager;
054: import org.apache.lenya.cms.usecase.gui.Tab;
055: import org.apache.lenya.util.ServletHelper;
056:
057: /**
058: * GUI manager implementation.
059: */
060: public class GUIManagerImpl extends AbstractLogEnabled implements
061: GUIManager, Configurable, Serviceable, Contextualizable {
062:
063: protected static final String ELEMENT_PARAMETER = "parameter";
064: protected static final String ELEMENT_TAB_GROUP = "tab-group";
065: protected static final String ELEMENT_TAB = "tab";
066: protected static final String ATTRIBUTE_NAME = "name";
067: protected static final String ATTRIBUTE_VALUE = "value";
068: protected static final String ATTRIBUTE_LABEL = "label";
069: protected static final String ATTRIBUTE_USECASE = "usecase";
070:
071: private Map name2group = new HashMap();
072:
073: /**
074: * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
075: */
076: public void configure(Configuration config)
077: throws ConfigurationException {
078: Configuration[] tabGroupConfigs = config
079: .getChildren(ELEMENT_TAB_GROUP);
080: for (int i = 0; i < tabGroupConfigs.length; i++) {
081: String groupName = tabGroupConfigs[i]
082: .getAttribute(ATTRIBUTE_NAME);
083: List group = new ArrayList();
084: Configuration[] tabConfigs = tabGroupConfigs[i]
085: .getChildren(ELEMENT_TAB);
086: for (int j = 0; j < tabConfigs.length; j++) {
087: String name = tabConfigs[j]
088: .getAttribute(ATTRIBUTE_NAME);
089: String label = tabConfigs[j]
090: .getAttribute(ATTRIBUTE_LABEL);
091: String usecase = tabConfigs[j]
092: .getAttribute(ATTRIBUTE_USECASE);
093: TabImpl tab = new TabImpl(groupName, name, usecase,
094: label);
095: group.add(tab);
096:
097: Configuration[] paramConfigs = tabConfigs[j]
098: .getChildren(ELEMENT_PARAMETER);
099: for (int p = 0; p < paramConfigs.length; p++) {
100: String paramName = paramConfigs[p]
101: .getAttribute(ATTRIBUTE_NAME);
102: String paramValue = paramConfigs[p]
103: .getAttribute(ATTRIBUTE_VALUE);
104: tab.setParameter(paramName, paramValue);
105: }
106: }
107: name2group.put(groupName, group.toArray(new Tab[group
108: .size()]));
109: }
110: }
111:
112: /**
113: * @see org.apache.lenya.cms.usecase.gui.GUIManager#getActiveTabs(java.lang.String)
114: */
115: public Tab[] getActiveTabs(String group) {
116: Tab[] tabs = getTabs(group);
117: List activeTabs = new ArrayList();
118: for (int i = 0; i < tabs.length; i++) {
119: if (getErrorMessages(tabs[i]).length == 0) {
120: activeTabs.add(tabs[i]);
121: }
122: }
123: return (Tab[]) activeTabs.toArray(new Tab[activeTabs.size()]);
124: }
125:
126: protected Tab[] getTabs(String group) {
127: Tab[] tabs = (Tab[]) name2group.get(group);
128: return tabs;
129: }
130:
131: /**
132: * @see org.apache.lenya.cms.usecase.gui.GUIManager#getTab(java.lang.String, java.lang.String)
133: */
134: public Tab getTab(String group, String name) {
135: Tab[] tabs = getTabs(group);
136: for (int i = 0; i < tabs.length; i++) {
137: if (name.equals(tabs[i].getName())) {
138: return tabs[i];
139: }
140: }
141: throw new IllegalArgumentException("No tab [" + name
142: + "] in group [" + group + "]");
143: }
144:
145: /**
146: * Checks if a tab's usecase can be executed.
147: * @param tab The tab.
148: * @return An array of error messages.
149: */
150: protected UsecaseMessage[] getErrorMessages(Tab tab) {
151:
152: UsecaseMessage[] messages;
153:
154: ServiceSelector selector = null;
155: AccessControllerResolver acResolver = null;
156: AccessController accessController = null;
157: UsecaseResolver usecaseResolver = null;
158: UsecaseAuthorizer authorizer = null;
159: try {
160:
161: selector = (ServiceSelector) this .manager
162: .lookup(AccessControllerResolver.ROLE + "Selector");
163: acResolver = (AccessControllerResolver) selector
164: .select(AccessControllerResolver.DEFAULT_RESOLVER);
165: accessController = acResolver
166: .resolveAccessController(this .webappUrl);
167:
168: Authorizer[] authorizers = accessController
169: .getAuthorizers();
170: for (int i = 0; i < authorizers.length; i++) {
171: if (authorizers[i] instanceof UsecaseAuthorizer) {
172: authorizer = (UsecaseAuthorizer) authorizers[i];
173: }
174: }
175:
176: usecaseResolver = (UsecaseResolver) this .manager
177: .lookup(UsecaseResolver.ROLE);
178:
179: // filter item if usecase not allowed
180: if (tab.getUsecase() != null) {
181: if (getLogger().isDebugEnabled()) {
182: getLogger().debug(
183: "Found usecase [" + tab.getUsecase() + "]");
184: }
185:
186: DocumentFactory factory;
187: ContextUtility util = null;
188: try {
189: util = (ContextUtility) this .manager
190: .lookup(ContextUtility.ROLE);
191: Request request = util.getRequest();
192: factory = DocumentUtil.getDocumentFactory(
193: this .manager, request);
194: } finally {
195: if (util != null) {
196: this .manager.release(util);
197: }
198: }
199:
200: Publication pub = PublicationUtil
201: .getPublicationFromUrl(this .manager, factory,
202: this .webappUrl);
203: if (!authorizer.authorizeUsecase(tab.getUsecase(),
204: this .roles, pub)) {
205: if (getLogger().isDebugEnabled()) {
206: getLogger().debug("Usecase not authorized");
207: }
208: messages = new UsecaseMessage[1];
209: messages[0] = new UsecaseMessage("Access denied");
210: }
211: }
212:
213: if (usecaseResolver.isRegistered(this .webappUrl, tab
214: .getUsecase())) {
215: Usecase usecase = null;
216: try {
217: usecase = usecaseResolver.resolve(this .webappUrl,
218: tab.getUsecase());
219: usecase.setSourceURL(this .webappUrl);
220: usecase.setName(tab.getUsecase());
221: String[] keys = tab.getParameterNames();
222: for (int i = 0; i < keys.length; i++) {
223: usecase.setParameter(keys[i], tab
224: .getParameter(keys[i]));
225: }
226: usecase.checkPreconditions();
227: if (usecase.hasErrors()) {
228: if (getLogger().isDebugEnabled()) {
229: getLogger()
230: .debug(
231: "Usecase preconditions not complied");
232: }
233:
234: List msgs = usecase.getErrorMessages();
235: messages = (UsecaseMessage[]) msgs
236: .toArray(new UsecaseMessage[msgs.size()]);
237: } else {
238: messages = new UsecaseMessage[0];
239: }
240: } finally {
241: if (usecase != null) {
242: usecaseResolver.release(usecase);
243: }
244: }
245: } else {
246: messages = new UsecaseMessage[1];
247: messages[0] = new UsecaseMessage("Usecase ["
248: + tab.getUsecase() + "] is not registered!",
249: null);
250: }
251: } catch (final Exception e) {
252: throw new RuntimeException(e);
253: } finally {
254: if (usecaseResolver != null) {
255: this .manager.release(usecaseResolver);
256: }
257: if (selector != null) {
258: if (acResolver != null) {
259: if (accessController != null) {
260: acResolver.release(accessController);
261: }
262: selector.release(acResolver);
263: }
264: this .manager.release(selector);
265: }
266: }
267:
268: return messages;
269: }
270:
271: private ServiceManager manager;
272:
273: /**
274: * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
275: */
276: public void service(ServiceManager manager) throws ServiceException {
277: this .manager = manager;
278: }
279:
280: private String webappUrl;
281: private Role[] roles;
282:
283: /**
284: * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
285: */
286: public void contextualize(Context context) throws ContextException {
287: Request request = ContextHelper.getRequest(context);
288: try {
289: this .roles = PolicyUtil.getRoles(request);
290: } catch (AccessControlException e) {
291: throw new ContextException("Obtaining roles failed: ", e);
292: }
293: this.webappUrl = ServletHelper.getWebappURI(request);
294: }
295:
296: }
|