/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved. * This code is licensed under the GPL 2.0 license, availible at the root * application directory. */ package org.geoserver.xacml.geoxacml; import java.io.File; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.geotools.xacml.geoxacml.config.GeoXACML; import org.vfny.geoserver.global.GeoserverDataDirectory; import com.sun.xacml.AbstractPolicy; import com.sun.xacml.EvaluationCtx; import com.sun.xacml.ParsingException; import com.sun.xacml.PolicyMetaData; import com.sun.xacml.VersionConstraints; import com.sun.xacml.finder.PolicyFinder; import com.sun.xacml.finder.PolicyFinderModule; import com.sun.xacml.finder.PolicyFinderResult; import com.sun.xacml.support.finder.PolicyCollection; import com.sun.xacml.support.finder.PolicyReader; import com.sun.xacml.support.finder.TopLevelPolicyException; /** * A PolicyFinderModule implementation reading policies form the GEOSERVER_DATA_DIR * * Assumptions: * * starting directory: geoxacml directory for policy matched against requests : geoxacml/byRequest * directory for policy referenced by ohter policieis : geoxacml/byReference * * Sub directories are searched recursively , all files with extension .xml or .XML are assumed to * be policy files. * * @author Christian Mueller * */ public class DataDirPolicyFinderModlule extends PolicyFinderModule { public static String BASE_DIR = "geoxacml"; public static String BY_REQUEST_DIR = "byRequest"; public static String BY_REFERENCE_DIR = "byReference"; protected PolicyCollection policiesByReference; protected PolicyCollection policiesByRequest; protected boolean validate; protected String baseDir; private static final Logger logger = Logger.getLogger(DataDirPolicyFinderModlule.class .getName()); /** * Constructor, policies are not validated against the XML schema * */ public DataDirPolicyFinderModlule() { this(false); } /** * Constructor * * @param validate * if true, perform a XML schema validation * */ public DataDirPolicyFinderModlule(boolean validate) { this.validate = validate; this.policiesByReference = new PolicyCollection(); this.policiesByRequest = new PolicyCollection(); } @Override public void init(PolicyFinder finder) { PolicyReader reader = null; try { if (validate) reader = new PolicyReader(finder, logger, new File(GeoXACML.getPolicyXMLSchemaURL() .toURI())); else reader = new PolicyReader(finder, logger); } catch (URISyntaxException e) { // should not happen } readPolicies(policiesByReference, BY_REFERENCE_DIR, reader); readPolicies(policiesByRequest, BY_REQUEST_DIR, reader); } private void readPolicies(PolicyCollection coll, String subdir, PolicyReader reader) { List<String> fileNames = getXMLFileNames(subdir); for (String fileName : fileNames) { try { AbstractPolicy policy = reader.readPolicy(new File(fileName)); if (!coll.addPolicy(policy)) { if (logger.isLoggable(Level.WARNING)) logger.log(Level.WARNING, "tried to load the same " + "policy multiple times: " + fileName); } else { logger.fine("Read policy(Set) " + policy.getId() + " from " + fileName.toString()); } } catch (ParsingException e) { if (logger.isLoggable(Level.WARNING)) logger.log(Level.WARNING, "Error reading policy: " + fileName, e); } } } private List<String> getXMLFileNames(String subdir) { File parentDir = null; if (baseDir == null) { String parent = "file:" + BASE_DIR + "/" + subdir; parentDir = GeoserverDataDirectory.findDataFile(parent); } else { parentDir = new File(baseDir, BASE_DIR + "/" + subdir); } List<String> fileNames = new ArrayList<String>(); collectXMLFiles(parentDir, fileNames); return fileNames; } private void collectXMLFiles(File f, List<String> fileNames) { if (f.isFile()) { if (f.getName().endsWith(".xml") || f.getName().endsWith(".XML")) fileNames.add(f.getAbsolutePath()); } if (f.isDirectory()) { File[] children = f.listFiles(); if (children == null) return; for (File child : children) { collectXMLFiles(child, fileNames); } } } @Override public PolicyFinderResult findPolicy(EvaluationCtx context) { try { AbstractPolicy policy = policiesByRequest.getPolicy(context); if (policy == null) return new PolicyFinderResult(); else return new PolicyFinderResult(policy); } catch (TopLevelPolicyException tlpe) { return new PolicyFinderResult(tlpe.getStatus()); } } @Override public PolicyFinderResult findPolicy(URI idReference, int type, VersionConstraints constraints, PolicyMetaData parentMetaData) { AbstractPolicy policy = policiesByReference.getPolicy(idReference.toString(), type, constraints); if (policy == null) return new PolicyFinderResult(); else return new PolicyFinderResult(policy); } @Override public void invalidateCache() { // TODO super.invalidateCache(); } @Override public boolean isIdReferenceSupported() { return true; } @Override public boolean isRequestSupported() { return true; } public String getBaseDir() { return baseDir; } public void setBaseDir(String baseDir) { this.baseDir = baseDir; } }