001: /*
002: * This file is part of PFIXCORE.
003: *
004: * PFIXCORE is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU Lesser General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * PFIXCORE is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public License
015: * along with PFIXCORE; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018:
019: package de.schlund.pfixxml.config.impl;
020:
021: import java.util.ArrayList;
022: import java.util.Collections;
023: import java.util.HashMap;
024: import java.util.Iterator;
025: import java.util.LinkedHashMap;
026: import java.util.LinkedHashSet;
027: import java.util.List;
028: import java.util.Map;
029: import java.util.Properties;
030: import java.util.Set;
031: import java.util.Map.Entry;
032:
033: import org.apache.log4j.Logger;
034: import org.xml.sax.SAXException;
035:
036: import de.schlund.pfixcore.auth.AuthConstraint;
037: import de.schlund.pfixcore.auth.Role;
038: import de.schlund.pfixcore.auth.RoleProvider;
039: import de.schlund.pfixcore.workflow.ContextInterceptor;
040: import de.schlund.pfixcore.workflow.ContextResource;
041: import de.schlund.pfixxml.config.ContextConfig;
042: import de.schlund.pfixxml.config.ContextResourceConfig;
043: import de.schlund.pfixxml.config.PageFlowConfig;
044:
045: /**
046: * Stores configuration for a Context
047: *
048: * @author Sebastian Marsching <sebastian.marsching@1und1.de>
049: */
050: public class ContextConfigImpl implements ContextConfig, RoleProvider {
051: // Caution: This implementation is not thread-safe. However, it
052: // does not have to be as a configuration is initialized only once.
053:
054: private final static Logger LOG = Logger
055: .getLogger(ContextConfigImpl.class);
056:
057: private String authPage = null;
058: private String defaultFlow = null;
059: private LinkedHashMap<Class<? extends ContextResource>, ContextResourceConfigImpl> resources = new LinkedHashMap<Class<? extends ContextResource>, ContextResourceConfigImpl>();
060: private List<ContextResourceConfigImpl> cacheResources = null;
061: protected HashMap<Class<? extends ContextResource>, ContextResourceConfigImpl> interfaceToResource = new HashMap<Class<? extends ContextResource>, ContextResourceConfigImpl>();
062: private HashMap<String, PageFlowConfigImpl> pageflows = new HashMap<String, PageFlowConfigImpl>();
063: private List<PageFlowConfigImpl> cachePageflows = null;
064: private HashMap<String, PageRequestConfigImpl> pagerequests = new HashMap<String, PageRequestConfigImpl>();
065: private List<PageRequestConfigImpl> cachePagerequests = null;
066: private ArrayList<Class<? extends ContextInterceptor>> startinterceptors = new ArrayList<Class<? extends ContextInterceptor>>();
067: private ArrayList<Class<? extends ContextInterceptor>> endinterceptors = new ArrayList<Class<? extends ContextInterceptor>>();
068: private String navigationFile = null;
069: private Properties props = new Properties();
070: private boolean synchronize = true;
071: private Map<String, Role> roles = new HashMap<String, Role>();
072: private List<Role> initialRoles = new ArrayList<Role>();
073: private Map<String, AuthConstraint> authConstraints = new HashMap<String, AuthConstraint>();
074: private AuthConstraint defaultAuthConstraint;
075: private boolean doLoadTimeChecks = false;
076:
077: public void setAuthPage(String page) {
078: this .authPage = page;
079: }
080:
081: public String getAuthPage() {
082: return this .authPage;
083: }
084:
085: public void setDefaultFlow(String flow) {
086: this .defaultFlow = flow;
087: }
088:
089: public String getDefaultFlow() {
090: return this .defaultFlow;
091: }
092:
093: public void addContextResource(ContextResourceConfigImpl config) {
094: if (resources.containsKey(config.getContextResourceClass())) {
095: LOG.warn("Overwriting configuration for context resource "
096: + config.getContextResourceClass().getName());
097: }
098: resources.put(config.getContextResourceClass(), config);
099: cacheResources = null;
100: }
101:
102: public List<ContextResourceConfigImpl> getContextResourceConfigs() {
103: List<ContextResourceConfigImpl> list = cacheResources;
104: if (list == null) {
105: list = new ArrayList<ContextResourceConfigImpl>();
106: for (Entry<Class<? extends ContextResource>, ContextResourceConfigImpl> e : this .resources
107: .entrySet()) {
108: list.add(e.getValue());
109: }
110: cacheResources = Collections.unmodifiableList(list);
111: }
112: return list;
113: }
114:
115: public ContextResourceConfig getContextResourceConfig(
116: Class<? extends ContextResource> clazz) {
117: return this .resources.get(clazz);
118: }
119:
120: public ContextResourceConfig getContextResourceConfigForInterface(
121: Class<? extends ContextResource> clazz) {
122: return interfaceToResource.get(clazz);
123: }
124:
125: public Map<Class<? extends ContextResource>, ContextResourceConfigImpl> getInterfaceToContextResourceMap() {
126: return Collections.unmodifiableMap(interfaceToResource);
127: }
128:
129: public void addPageFlow(PageFlowConfigImpl config) {
130: if (this .pageflows.containsKey(config.getFlowName())) {
131: LOG.warn("Overwriting configuration for pageflow "
132: + config.getFlowName());
133: }
134: this .pageflows.put(config.getFlowName(), config);
135: this .cachePageflows = null;
136: }
137:
138: public List<PageFlowConfigImpl> getPageFlowConfigs() {
139: List<PageFlowConfigImpl> list = this .cachePageflows;
140: if (list == null) {
141: list = new ArrayList<PageFlowConfigImpl>();
142: for (Entry<String, PageFlowConfigImpl> entry : this .pageflows
143: .entrySet()) {
144: list.add(entry.getValue());
145: }
146: this .cachePageflows = Collections.unmodifiableList(list);
147: }
148: return list;
149: }
150:
151: public PageFlowConfig getPageFlowConfig(String name) {
152: return this .pageflows.get(name);
153: }
154:
155: public void addPageRequest(PageRequestConfigImpl config) {
156: if (this .pagerequests.containsKey(config.getPageName())) {
157: LOG.warn("Overwriting configuration for pagerequest"
158: + config.getPageName());
159: }
160: this .pagerequests.put(config.getPageName(), config);
161: this .cachePagerequests = null;
162: }
163:
164: public List<PageRequestConfigImpl> getPageRequestConfigs() {
165: List<PageRequestConfigImpl> list = this .cachePagerequests;
166: if (list == null) {
167: list = new ArrayList<PageRequestConfigImpl>();
168: for (Iterator<Entry<String, PageRequestConfigImpl>> i = this .pagerequests
169: .entrySet().iterator(); i.hasNext();) {
170: Entry<String, PageRequestConfigImpl> entry = i.next();
171: list.add(entry.getValue());
172:
173: }
174: this .cachePagerequests = Collections.unmodifiableList(list);
175: }
176: return list;
177: }
178:
179: public PageRequestConfigImpl getPageRequestConfig(String name) {
180: return this .pagerequests.get(name);
181: }
182:
183: public void addStartInterceptor(
184: Class<? extends ContextInterceptor> clazz) {
185: if (this .startinterceptors.contains(clazz)) {
186: LOG.warn("Context interceptor " + clazz.getName()
187: + " not added - it is already present");
188: } else {
189: this .startinterceptors.add(clazz);
190: }
191: }
192:
193: public List<Class<? extends ContextInterceptor>> getStartInterceptors() {
194: return Collections.unmodifiableList(startinterceptors);
195: }
196:
197: public List<Class<? extends ContextInterceptor>> getEndInterceptors() {
198: return Collections.unmodifiableList(endinterceptors);
199: }
200:
201: public void addEndInterceptor(
202: Class<? extends ContextInterceptor> clazz) {
203: if (this .endinterceptors.contains(clazz)) {
204: LOG.warn("Context interceptor " + clazz.getName()
205: + " not added - it is already present");
206: } else {
207: this .endinterceptors.add(clazz);
208: }
209: }
210:
211: public void addRole(Role role) {
212: roles.put(role.getName(), role);
213: if (role.isInitial())
214: initialRoles.add(role);
215: }
216:
217: public Role getRole(String roleName) {
218: return roles.get(roleName);
219: }
220:
221: public Map<String, Role> getRoles() {
222: return Collections.unmodifiableMap(roles);
223: }
224:
225: public List<Role> getInitialRoles() {
226: return initialRoles;
227: }
228:
229: public RoleProvider getRoleProvider() {
230: return this ;
231: }
232:
233: public boolean hasRoles() {
234: return !roles.isEmpty();
235: }
236:
237: public void addAuthConstraint(String id,
238: AuthConstraint authConstraint) {
239: authConstraints.put(id, authConstraint);
240: }
241:
242: public AuthConstraint getAuthConstraint(String id) {
243: return authConstraints.get(id);
244: }
245:
246: public void setDefaultAuthConstraint(AuthConstraint authConstraint) {
247: defaultAuthConstraint = authConstraint;
248: }
249:
250: public AuthConstraint getDefaultAuthConstraint() {
251: return defaultAuthConstraint;
252: }
253:
254: public void setNavigationFile(String filename) {
255: this .navigationFile = filename;
256: }
257:
258: public String getNavigationFile() {
259: return this .navigationFile;
260: }
261:
262: public void setProperties(Properties properties) {
263: this .props = properties;
264: }
265:
266: public Properties getProperties() {
267: return this .props;
268: }
269:
270: public void setSynchronized(boolean sync) {
271: this .synchronize = sync;
272: }
273:
274: public boolean isSynchronized() {
275: return this .synchronize;
276: }
277:
278: public void doFinishing() throws SAXException {
279: // Handle page copies
280: HashMap<String, PageRequestConfigImpl> newPages = new HashMap<String, PageRequestConfigImpl>();
281:
282: for (String pagename : this .pagerequests.keySet()) {
283: PageRequestConfigImpl config = this .pagerequests
284: .get(pagename);
285: String copyfrom = config.getCopyFromPage();
286: if (copyfrom != null) {
287: // Find all variants for source page and copy them
288: for (String fullname : this .pagerequests.keySet()) {
289: if (fullname.startsWith(copyfrom + "::")) {
290: String variantname = fullname
291: .substring(fullname.indexOf("::"));
292: newPages.put(pagename + "::" + variantname,
293: copyPage(this .pagerequests
294: .get(fullname), pagename + "::"
295: + variantname));
296: } else if (fullname.equals(copyfrom)) {
297: newPages.put(pagename, copyPage(
298: this .pagerequests.get(fullname),
299: pagename));
300: }
301: }
302: }
303: }
304:
305: this .pagerequests.putAll(newPages);
306: this .cachePagerequests = null;
307:
308: if (doLoadTimeChecks)
309: checkAuthConstraints();
310: }
311:
312: private PageRequestConfigImpl copyPage(
313: PageRequestConfigImpl source, String newName) {
314: PageRequestConfigImpl newConfig;
315: try {
316: newConfig = (PageRequestConfigImpl) source.clone();
317: } catch (CloneNotSupportedException e) {
318: throw new RuntimeException(e);
319: }
320: newConfig.setPageName(newName);
321:
322: return newConfig;
323: }
324:
325: private void checkAuthConstraints() throws SAXException {
326: Set<String> authPages = new LinkedHashSet<String>();
327: List<PageRequestConfigImpl> pages = getPageRequestConfigs();
328: for (PageRequestConfigImpl page : pages) {
329: AuthConstraint authConstraint = page.getAuthConstraint();
330: if (authConstraint != null && getAuthPage() != null) {
331: if (getAuthPage().equals(authConstraint.getAuthPage()))
332: throw new SAXException(
333: "Authconstraint authpage isn't allowed to "
334: + "be equal to context authpage: "
335: + getAuthPage());
336: }
337: if (authConstraint == null)
338: authConstraint = getDefaultAuthConstraint();
339: if (authConstraint != null) {
340: authPages.clear();
341: authPages.add(page.getPageName());
342: checkAuthConstraint(authConstraint, authPages);
343: }
344: }
345: }
346:
347: private void checkAuthConstraint(AuthConstraint authConstraint,
348: Set<String> authPages) throws SAXException {
349: String authPage = authConstraint.getAuthPage();
350: if (authPage != null) {
351: if (authPages.contains(authPage)) {
352: StringBuilder sb = new StringBuilder();
353: for (String s : authPages)
354: sb.append(s + " -> ");
355: sb.append(authPage);
356: throw new SAXException(
357: "Circular authconstraint@authpage reference: "
358: + sb.toString());
359: }
360: PageRequestConfigImpl cfg = getPageRequestConfig(authPage);
361: if (cfg != null) {
362: AuthConstraint ac = cfg.getAuthConstraint();
363: if (ac == null)
364: ac = getDefaultAuthConstraint();
365: if (ac != null) {
366: authPages.add(authPage);
367: checkAuthConstraint(ac, authPages);
368: }
369: } else
370: throw new SAXException("Authpage not configured: "
371: + authPage);
372: }
373: }
374:
375: }
|