001: /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
002: * This code is licensed under the GPL 2.0 license, availible at the root
003: * application directory.
004: */
005: package org.geoserver.security;
006:
007: import org.acegisecurity.ConfigAttributeDefinition;
008: import org.acegisecurity.ConfigAttributeEditor;
009: import org.acegisecurity.intercept.ObjectDefinitionSource;
010: import org.geoserver.platform.Operation;
011: import org.vfny.geoserver.global.GeoserverDataDirectory;
012: import java.io.File;
013: import java.util.Collections;
014: import java.util.HashMap;
015: import java.util.Iterator;
016: import java.util.Map;
017: import java.util.Properties;
018: import java.util.logging.Level;
019: import java.util.logging.Logger;
020:
021: /**
022: * Returns security attributes (roles) for an OWS {@link Operation} based on the
023: * contents of a property file
024: *
025: * @author Andrea Aime - TOPP
026: *
027: */
028: public class OperationDefinitionSource implements
029: ObjectDefinitionSource {
030: /** logger */
031: static Logger LOGGER = org.geotools.util.logging.Logging
032: .getLogger("org.geoserver.security");
033: Map definitions;
034: PropertyFileWatcher operationDefinitionFile;
035:
036: public ConfigAttributeDefinition getAttributes(Object object)
037: throws IllegalArgumentException {
038: if (!(object instanceof Operation)) {
039: throw new IllegalArgumentException(
040: "Only Operation objects are supported by the OperationDefinitionSource");
041: }
042:
043: // check if we have config attributes in the map
044: Operation op = (Operation) object;
045: checkDefinitions();
046:
047: OperationKey key = new OperationKey(op.getService().getId(), op
048: .getId());
049: ConfigAttributeDefinition result = (ConfigAttributeDefinition) definitions
050: .get(key);
051:
052: if (result == null) {
053: // try to fall back on some service definitions
054: key.operation = null;
055: result = (ConfigAttributeDefinition) definitions.get(key);
056: }
057:
058: return result;
059: }
060:
061: public Iterator getConfigAttributeDefinitions() {
062: checkDefinitions();
063:
064: if (definitions != null) {
065: return definitions.values().iterator();
066: }
067:
068: return Collections.EMPTY_SET.iterator();
069: }
070:
071: public boolean supports(Class clazz) {
072: return Operation.class.isAssignableFrom(clazz);
073: }
074:
075: void checkDefinitions() {
076: if ((definitions == null)
077: || ((operationDefinitionFile != null) && operationDefinitionFile
078: .isStale())) {
079: try {
080: definitions = new HashMap();
081:
082: if (operationDefinitionFile == null) {
083: File dd = GeoserverDataDirectory
084: .getGeoserverDataDirectory();
085: File securityDir = GeoserverDataDirectory
086: .findConfigDir(dd, "security");
087: File securityDefinitions = new File(securityDir,
088: "service.properties");
089: operationDefinitionFile = new PropertyFileWatcher(
090: securityDefinitions);
091: }
092:
093: ConfigAttributeEditor editor = new ConfigAttributeEditor();
094: Properties p = operationDefinitionFile.getProperties();
095:
096: for (Iterator it = p.keySet().iterator(); it.hasNext();) {
097: try {
098: String key = (String) it.next();
099: OperationKey okey = new OperationKey(key);
100: editor.setAsText(p.getProperty(key));
101:
102: ConfigAttributeDefinition cad = (ConfigAttributeDefinition) editor
103: .getValue();
104: definitions.put(okey, cad);
105: } catch (IllegalArgumentException e) {
106: LOGGER
107: .log(
108: Level.SEVERE,
109: "Skipping invalid operation security configuration element",
110: e);
111: }
112: }
113: } catch (Exception e) {
114: LOGGER
115: .log(
116: Level.SEVERE,
117: "An error occurred loading service security definitions ",
118: e);
119: }
120: }
121: }
122:
123: private class OperationKey {
124: String service;
125: String operation;
126:
127: public OperationKey(String service, String operation) {
128: this .service = service;
129: this .operation = operation;
130: }
131:
132: public OperationKey(String key) throws IllegalArgumentException {
133: if (key.indexOf('.') != -1) {
134: String[] elements = key.split("\\.");
135:
136: if (elements.length > 2) {
137: throw new IllegalArgumentException(
138: "A valid operation key is made of 'service.method', or just 'service'. ");
139: }
140:
141: service = elements[0].trim();
142: operation = elements[1].trim();
143: } else {
144: service = key;
145: operation = null;
146: }
147:
148: if ("".equals(service)) {
149: throw new IllegalArgumentException(
150: "Service must be specified");
151: }
152:
153: if ("".equals(operation)) {
154: operation = null;
155: }
156: }
157:
158: public int hashCode() {
159: final int PRIME = 31;
160: int result = 1;
161: result = (PRIME * result)
162: + ((operation == null) ? 0 : operation.hashCode());
163: result = (PRIME * result)
164: + ((service == null) ? 0 : service.hashCode());
165:
166: return result;
167: }
168:
169: public boolean equals(Object obj) {
170: if (this == obj) {
171: return true;
172: }
173:
174: if (obj == null) {
175: return false;
176: }
177:
178: if (getClass() != obj.getClass()) {
179: return false;
180: }
181:
182: final OperationKey other = (OperationKey) obj;
183:
184: if (operation == null) {
185: if (other.operation != null) {
186: return false;
187: }
188: } else if (!operation.equals(other.operation)) {
189: return false;
190: }
191:
192: if (service == null) {
193: if (other.service != null) {
194: return false;
195: }
196: } else if (!service.equals(other.service)) {
197: return false;
198: }
199:
200: return true;
201: }
202: }
203: }
|