You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openaz.apache.org by pd...@apache.org on 2016/03/17 02:15:33 UTC
[11/23] incubator-openaz git commit: Ported original att source to
openaz This Closes #3
http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/648d0c0d/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/OnDemandFileDownloader.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/OnDemandFileDownloader.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/OnDemandFileDownloader.java
new file mode 100644
index 0000000..ba8cd82
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/OnDemandFileDownloader.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.openaz.xacml.admin.util;
+
+import java.io.IOException;
+
+import com.vaadin.server.FileDownloader;
+import com.vaadin.server.StreamResource;
+import com.vaadin.server.StreamResource.StreamSource;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.server.VaadinResponse;
+import com.vaadin.ui.UI;
+
+public class OnDemandFileDownloader extends FileDownloader {
+ private static final long serialVersionUID = 1L;
+ private final OnDemandStreamResource resource;
+
+ public interface OnDemandStreamResource extends StreamSource {
+ String getFilename ();
+ }
+
+ public OnDemandFileDownloader(OnDemandStreamResource resource) {
+ super(new StreamResource(resource, ""));
+ this.resource = resource;
+ if (this.resource == null) {
+ throw new NullPointerException("Can't send null resource");
+ }
+ }
+
+ @Override
+ public boolean handleConnectorRequest(VaadinRequest request,
+ VaadinResponse response, String path) throws IOException {
+ this.getResource().setFilename(this.resource.getFilename());
+ return super.handleConnectorRequest(request, response, path);
+ }
+
+ private StreamResource getResource() {
+ StreamResource resource = null;
+ UI.getCurrent().getSession().lock();
+ try {
+ resource = (StreamResource) this.getResource("dl");
+ } finally {
+ UI.getCurrent().getSession().unlock();
+ }
+ return resource;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/648d0c0d/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/RESTfulPAPEngine.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/RESTfulPAPEngine.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/RESTfulPAPEngine.java
new file mode 100644
index 0000000..3958100
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/RESTfulPAPEngine.java
@@ -0,0 +1,495 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.openaz.xacml.admin.util;
+
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.Set;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.openaz.xacml.api.pap.PAPEngine;
+import org.apache.openaz.xacml.api.pap.PAPException;
+import org.apache.openaz.xacml.api.pap.PDP;
+import org.apache.openaz.xacml.api.pap.PDPGroup;
+import org.apache.openaz.xacml.api.pap.PDPPolicy;
+import org.apache.openaz.xacml.api.pap.PDPStatus;
+import org.apache.openaz.xacml.rest.XACMLRestProperties;
+import org.apache.openaz.xacml.std.pap.StdPDP;
+import org.apache.openaz.xacml.std.pap.StdPDPGroup;
+import org.apache.openaz.xacml.std.pap.StdPDPItemSetChangeNotifier;
+import org.apache.openaz.xacml.std.pap.StdPDPPolicy;
+import org.apache.openaz.xacml.std.pap.StdPDPStatus;
+import org.apache.openaz.xacml.util.XACMLProperties;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.type.CollectionType;
+
+/**
+ * Implementation of the PAPEngine interface that communicates with a PAP engine in a remote servlet
+ * through a RESTful interface
+ *
+ * @author glenngriffin
+ *
+ */
+public class RESTfulPAPEngine extends StdPDPItemSetChangeNotifier implements PAPEngine {
+ private static final Log logger = LogFactory.getLog(RESTfulPAPEngine.class);
+
+ //
+ // URL of the PAP Servlet that this Admin Console talks to
+ //
+ private String papServletURLString;
+
+ /**
+ * Set up link with PAP Servlet and get our initial set of Groups
+ * @throws Exception
+ */
+ public RESTfulPAPEngine (String myURLString) throws PAPException, IOException {
+ //
+ // Get our URL to the PAP servlet
+ //
+ this.papServletURLString = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL);
+ if (this.papServletURLString == null || this.papServletURLString.length() == 0) {
+ String message = "The property 'POLICYENGINE_ADMIN_ACTIVE' was not set during installation. Admin Console cannot call PAP.";
+ logger.error(message);
+ throw new PAPException(message);
+ }
+
+ //
+ // register this Admin Console with the PAP Servlet to get updates
+ //
+ Object newURL = sendToPAP("PUT", null, null, null, "adminConsoleURL=" + myURLString);
+ if (newURL != null) {
+ // assume this was a re-direct and try again
+ logger.warn("Redirecting to '" + newURL + "'");
+ this.papServletURLString = (String)newURL;
+ newURL = sendToPAP("PUT", null, null, null, "adminConsoleURL=" + myURLString);
+ if (newURL != null) {
+ logger.error("Failed to redirect to " + this.papServletURLString);
+ throw new PAPException("Failed to register with PAP");
+ }
+ }
+ }
+
+
+ //
+ // High-level commands used by the Admin Console code through the PAPEngine Interface
+ //
+
+ @Override
+ public PDPGroup getDefaultGroup() throws PAPException {
+ PDPGroup newGroup = (PDPGroup)sendToPAP("GET", null, null, StdPDPGroup.class, "groupId=", "default=");
+ return newGroup;
+ }
+
+ @Override
+ public void SetDefaultGroup(PDPGroup group) throws PAPException {
+ sendToPAP("POST", null, null, null, "groupId=" + group.getId(), "default=true");
+ }
+
+ @Override
+ public Set<PDPGroup> getPDPGroups() throws PAPException {
+ Set<PDPGroup> newGroupSet;
+ newGroupSet = (Set<PDPGroup>) this.sendToPAP("GET", null, Set.class, StdPDPGroup.class, "groupId=");
+ return Collections.unmodifiableSet(newGroupSet);
+ }
+
+
+ @Override
+ public PDPGroup getGroup(String id) throws PAPException {
+ PDPGroup newGroup = (PDPGroup)sendToPAP("GET", null, null, StdPDPGroup.class, "groupId=" + id);
+ return newGroup;
+ }
+
+ @Override
+ public void newGroup(String name, String description)
+ throws PAPException, NullPointerException {
+ String escapedName = null;
+ String escapedDescription = null;
+ try {
+ escapedName = URLEncoder.encode(name, "UTF-8");
+ escapedDescription = URLEncoder.encode(description, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new PAPException("Unable to send name or description to PAP: " + e.getMessage());
+ }
+
+ this.sendToPAP("POST", null, null, null, "groupId=", "groupName="+escapedName, "groupDescription=" + escapedDescription);
+ }
+
+
+ /**
+ * Update the configuration on the PAP for a single Group.
+ *
+ * @param group
+ * @return
+ * @throws PAPException
+ */
+ public void updateGroup(PDPGroup group) throws PAPException {
+
+ try {
+
+ //
+ // ASSUME that all of the policies mentioned in this group are already located in the correct directory on the PAP!
+ //
+ // Whenever a Policy is added to the group, that file must be automatically copied to the PAP from the Workspace.
+ //
+
+
+// // Copy all policies from the local machine's workspace to the PAP's PDPGroup directory.
+// // This is not efficient since most of the policies will already exist there.
+// // However, the policy files are (probably!) not too huge, and this is a good way to ensure that any corrupted files on the PAP get refreshed.
+//
+//TODO WRONG!!!! The policy.getStream() is based on the location in the PAP directory, not the Workspace.
+//TODO
+// for (PDPPolicy policy : group.getPolicies()) {
+// try (InputStream is = policy.getStream()) {
+// copyFile(policy.getId(), group, is);
+// }
+// }
+
+ // now update the group object on the PAP
+
+ sendToPAP("PUT", group, null, null, "groupId=" + group.getId());
+ } catch (Exception e) {
+ String message = "Unable to PUT policy '" + group.getId() + "', e:" + e;
+ logger.error(message, e);
+ throw new PAPException(message);
+ }
+ }
+
+
+ @Override
+ public void removeGroup(PDPGroup group, PDPGroup newGroup)
+ throws PAPException, NullPointerException {
+ String moveToGroupString = null;
+ if (newGroup != null) {
+ moveToGroupString = "movePDPsToGroupId=" + newGroup.getId();
+ }
+ sendToPAP("DELETE", null, null, null, "groupId=" + group.getId(), moveToGroupString);
+ }
+
+ @Override
+ public PDPGroup getPDPGroup(PDP pdp) throws PAPException {
+ return getPDPGroup(pdp.getId());
+ }
+
+ @Override
+ public PDPGroup getPDPGroup(String pdpId) throws PAPException {
+ PDPGroup newGroup = (PDPGroup)sendToPAP("GET", null, null, StdPDPGroup.class, "groupId=", "pdpId=" + pdpId, "getPDPGroup=");
+ return newGroup;
+ }
+
+ @Override
+ public PDP getPDP(String pdpId) throws PAPException {
+ PDP newPDP = (PDP)sendToPAP("GET", null, null, StdPDP.class, "groupId=", "pdpId=" + pdpId);
+ return newPDP;
+ }
+
+ @Override
+ public void newPDP(String id, PDPGroup group, String name, String description) throws PAPException,
+ NullPointerException {
+ StdPDP newPDP = new StdPDP(id, name, description);
+ sendToPAP("PUT", newPDP, null, null, "groupId=" + group.getId(), "pdpId=" + id);
+ }
+
+
+ @Override
+ public void movePDP(PDP pdp, PDPGroup newGroup) throws PAPException {
+ sendToPAP("POST", null, null, null, "groupId=" + newGroup.getId(), "pdpId=" + pdp.getId());
+ }
+
+ @Override
+ public void updatePDP(PDP pdp) throws PAPException {
+ PDPGroup group = getPDPGroup(pdp);
+ sendToPAP("PUT", pdp, null, null, "groupId=" + group.getId(), "pdpId=" + pdp.getId());
+ }
+
+ @Override
+ public void removePDP(PDP pdp) throws PAPException {
+ PDPGroup group = getPDPGroup(pdp);
+ sendToPAP("DELETE", null, null, null, "groupId=" + group.getId(), "pdpId=" + pdp.getId());
+ }
+
+
+
+ @Override
+ public void publishPolicy(String id, String name, boolean isRoot,
+ InputStream policy, PDPGroup group) throws PAPException {
+
+//TODO - this method should take as input a Policy object, add it to the group, then call updateGroup
+//TODO - ?? Where does the Policy object (with the version info) get created?
+
+ // copy the (one) file into the target directory on the PAP servlet
+ copyFile(id, group, policy);
+
+ // adjust the local copy of the group to include the new policy
+ PDPPolicy pdpPolicy = new StdPDPPolicy(id, isRoot, name);
+ group.getPolicies().add(pdpPolicy);
+
+ // tell the PAP servlet to include the policy in the configuration
+ updateGroup(group);
+ }
+
+
+
+ /**
+ * Copy a single Policy file from the input stream to the PAP Servlet.
+ * Either this works (silently) or it throws an exception.
+ *
+ * @param policyId
+ * @param group
+ * @param policy
+ * @return
+ * @throws PAPException
+ */
+ public void copyFile(String policyId, PDPGroup group, InputStream policy) throws PAPException {
+ // send the policy file to the PAP Servlet
+ try {
+ sendToPAP("POST", policy, null, null, "groupId=" + group.getId(), "policyId="+policyId);
+ } catch (Exception e) {
+ String message = "Unable to PUT policy '" + policyId + "', e:" + e;
+ logger.error(message, e);
+ throw new PAPException(message);
+ }
+ }
+
+
+ @Override
+ public void copyPolicy(PDPPolicy policy, PDPGroup group) throws PAPException {
+ if (policy == null || group == null) {
+ throw new PAPException("Null input policy="+policy+" group="+group);
+ }
+ try (InputStream is = new FileInputStream(new File(policy.getLocation())) ) {
+ copyFile(policy.getId(), group, is );
+ } catch (Exception e) {
+ String message = "Unable to PUT policy '" + policy.getId() + "', e:" + e;
+ logger.error(message, e);
+ throw new PAPException(message);
+ }
+ }
+
+
+
+
+ @Override
+ public void removePolicy(PDPPolicy policy, PDPGroup group) throws PAPException {
+ throw new PAPException("NOT IMPLEMENTED");
+
+ }
+
+
+
+ /**
+ * Special operation - Similar to the normal PAP operations but this one contacts the PDP directly
+ * to get detailed status info.
+ *
+ * @param pdp
+ * @return
+ * @throws PAPException
+ */
+ @Override
+ public PDPStatus getStatus(PDP pdp) throws PAPException {
+ StdPDPStatus status = (StdPDPStatus)sendToPAP("GET", pdp, null, StdPDPStatus.class);
+ return status;
+ }
+
+
+
+
+ //
+ // Internal Operations called by the PAPEngine Interface methods
+ //
+
+ /**
+ * Send a request to the PAP Servlet and get the response.
+ *
+ * The content is either an InputStream to be copied to the Request OutputStream
+ * OR it is an object that is to be encoded into JSON and pushed into the Request OutputStream.
+ *
+ * The Request parameters may be encoded in multiple "name=value" sets, or parameters may be combined by the caller.
+ *
+ * @param method
+ * @param content - EITHER an InputStream OR an Object to be encoded in JSON
+ * @param collectionTypeClass
+ * @param responseContentClass
+ * @param parameters
+ * @return
+ * @throws Exception
+ */
+ private Object sendToPAP(String method, Object content, Class collectionTypeClass, Class responseContentClass, String... parameters ) throws PAPException {
+ HttpURLConnection connection = null;
+ try {
+ String fullURL = papServletURLString;
+ if (parameters != null && parameters.length > 0) {
+ String queryString = "";
+ for (String p : parameters) {
+ queryString += "&" + p;
+ }
+ fullURL += "?" + queryString.substring(1);
+ }
+
+ // special case - Status (actually the detailed status) comes from the PDP directly, not the PAP
+ if (method.equals("GET") &&
+ content instanceof PDP &&
+ responseContentClass == StdPDPStatus.class) {
+ // Adjust the url and properties appropriately
+ fullURL = ((PDP)content).getId() + "?type=Status";
+ content = null;
+ }
+
+
+ URL url = new URL(fullURL);
+
+ //
+ // Open up the connection
+ //
+ connection = (HttpURLConnection)url.openConnection();
+ //
+ // Setup our method and headers
+ //
+ connection.setRequestMethod(method);
+// connection.setRequestProperty("Accept", "text/x-java-properties");
+// connection.setRequestProperty("Content-Type", "text/x-java-properties");
+ connection.setUseCaches(false);
+ //
+ // Adding this in. It seems the HttpUrlConnection class does NOT
+ // properly forward our headers for POST re-direction. It does so
+ // for a GET re-direction.
+ //
+ // So we need to handle this ourselves.
+ //
+ connection.setInstanceFollowRedirects(false);
+ connection.setDoOutput(true);
+ connection.setDoInput(true);
+ if (content != null) {
+ if (content instanceof InputStream) {
+ try {
+ //
+ // Send our current policy configuration
+ //
+ try (OutputStream os = connection.getOutputStream()) {
+ int count = IOUtils.copy((InputStream)content, os);
+ if (logger.isDebugEnabled()) {
+ logger.debug("copied to output, bytes="+count);
+ }
+ }
+ } catch (Exception e) {
+ logger.error("Failed to write content in '" + method + "'", e);
+ throw e;
+ }
+ } else {
+ // The content is an object to be encoded in JSON
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.writeValue(connection.getOutputStream(), content);
+ }
+ }
+ //
+ // Do the connect
+ //
+ connection.connect();
+ if (connection.getResponseCode() == 204) {
+ logger.info("Success - no content.");
+ return null;
+ } else if (connection.getResponseCode() == 200) {
+ logger.info("Success. We have a return object.");
+
+ // get the response content into a String
+ String json = null;
+ // read the inputStream into a buffer (trick found online scans entire input looking for end-of-file)
+ java.util.Scanner scanner = new java.util.Scanner(connection.getInputStream());
+ scanner.useDelimiter("\\A");
+ json = scanner.hasNext() ? scanner.next() : "";
+ scanner.close();
+ logger.info("JSON response from PAP: " + json);
+
+ // convert Object sent as JSON into local object
+ ObjectMapper mapper = new ObjectMapper();
+
+ if (collectionTypeClass != null) {
+ // collection of objects expected
+ final CollectionType javaType =
+ mapper.getTypeFactory().constructCollectionType(collectionTypeClass, responseContentClass);
+
+ Object objectFromJSON = mapper.readValue(json, javaType);
+ return objectFromJSON;
+ } else {
+ // single value object expected
+ Object objectFromJSON = mapper.readValue(json, responseContentClass);
+ return objectFromJSON;
+ }
+
+ } else if (connection.getResponseCode() >= 300 && connection.getResponseCode() <= 399) {
+ // redirection
+ String newURL = connection.getHeaderField("Location");
+ if (newURL == null) {
+ logger.error("No Location header to redirect to when response code="+connection.getResponseCode());
+ throw new IOException("No redirect Location header when response code="+connection.getResponseCode());
+ }
+ int qIndex = newURL.indexOf("?");
+ if (qIndex > 0) {
+ newURL = newURL.substring(0, qIndex);
+ }
+ logger.info("Redirect seen. Redirecting " + fullURL + " to " + newURL);
+ return newURL;
+ } else {
+ logger.warn("Unexpected response code: " + connection.getResponseCode() + " message: " + connection.getResponseMessage());
+ throw new IOException("Server Response: " + connection.getResponseCode() + ": " + connection.getResponseMessage());
+ }
+
+ } catch (Exception e) {
+ logger.error("HTTP Request/Response to PAP: " + e,e);
+ throw new PAPException("Request/Response threw :" + e);
+ } finally {
+ // cleanup the connection
+ if (connection != null) {
+ try {
+ // For some reason trying to get the inputStream from the connection
+ // throws an exception rather than returning null when the InputStream does not exist.
+ InputStream is = null;
+ try {
+ is = connection.getInputStream();
+ } catch (Exception e1) { //NOPMD
+ // ignore this
+ }
+ if (is != null) {
+ is.close();
+ }
+
+ } catch (IOException ex) {
+ logger.error("Failed to close connection: " + ex, ex);
+ }
+ connection.disconnect();
+ }
+ }
+ }
+}
+
+
http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/648d0c0d/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/XACMLConstants.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/XACMLConstants.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/XACMLConstants.java
new file mode 100644
index 0000000..28bf377
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/XACMLConstants.java
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.openaz.xacml.admin.util;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.openaz.xacml.api.Identifier;
+import org.apache.openaz.xacml.api.XACML3;
+
+public class XACMLConstants {
+
+ public static final Set<Identifier> SUBJECT_CATEGORIES = new HashSet<Identifier>();
+ public static final Set<Identifier> ACTION_CATEGORIES = new HashSet<Identifier>();
+ public static final Set<Identifier> RESOURCE_CATEGORIES = new HashSet<Identifier>();
+ public static final Set<Identifier> ENVIRONMENT_CATEGORIES = new HashSet<Identifier>();
+
+ public static final Set<Identifier> CATEGORIES = new HashSet<Identifier>();
+ static {
+ SUBJECT_CATEGORIES.addAll(Arrays.asList(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT,
+ XACML3.ID_SUBJECT_CATEGORY_CODEBASE,
+ XACML3.ID_SUBJECT_CATEGORY_INTERMEDIARY_SUBJECT,
+ XACML3.ID_SUBJECT_CATEGORY_RECIPIENT_SUBJECT,
+ XACML3.ID_SUBJECT_CATEGORY_REQUESTING_MACHINE)
+ );
+
+ ACTION_CATEGORIES.addAll(Arrays.asList(
+ XACML3.ID_ATTRIBUTE_CATEGORY_ACTION)
+ );
+
+ RESOURCE_CATEGORIES.addAll(Arrays.asList(
+ XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE)
+ );
+
+ ENVIRONMENT_CATEGORIES.addAll(Arrays.asList(
+ XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT)
+ );
+
+ CATEGORIES.addAll(SUBJECT_CATEGORIES);
+ CATEGORIES.addAll(ACTION_CATEGORIES);
+ CATEGORIES.addAll(RESOURCE_CATEGORIES);
+ CATEGORIES.addAll(ENVIRONMENT_CATEGORIES);
+
+ }
+ public static final Set<Identifier> DATATYPES = new HashSet<Identifier>();
+ static {
+ DATATYPES.addAll(Arrays.asList(XACML3.ID_DATATYPE_STRING,
+ XACML3.ID_DATATYPE_BOOLEAN,
+ XACML3.ID_DATATYPE_INTEGER,
+ XACML3.ID_DATATYPE_DOUBLE,
+ XACML3.ID_DATATYPE_TIME,
+ XACML3.ID_DATATYPE_DATE,
+ XACML3.ID_DATATYPE_DATETIME,
+ XACML3.ID_DATATYPE_DAYTIMEDURATION,
+ XACML3.ID_DATATYPE_YEARMONTHDURATION,
+ XACML3.ID_DATATYPE_ANYURI,
+ XACML3.ID_DATATYPE_HEXBINARY,
+ XACML3.ID_DATATYPE_BASE64BINARY,
+ XACML3.ID_DATATYPE_RFC822NAME,
+ XACML3.ID_DATATYPE_X500NAME,
+ XACML3.ID_DATATYPE_IPADDRESS,
+ XACML3.ID_DATATYPE_DNSNAME));
+ }
+
+ public static final Set<Identifier> POLICY_ALGORITHMS = new HashSet<Identifier>();
+ static {
+ POLICY_ALGORITHMS.addAll(Arrays.asList(
+ XACML3.ID_POLICY_DENY_OVERRIDES,
+ XACML3.ID_POLICY_DENY_UNLESS_PERMIT,
+ XACML3.ID_POLICY_FIRST_APPLICABLE,
+ XACML3.ID_POLICY_ON_PERMIT_APPLY_SECOND,
+ XACML3.ID_POLICY_ONLY_ONE_APPLICABLE,
+ XACML3.ID_POLICY_ORDERED_DENY_OVERRIDES,
+ XACML3.ID_POLICY_ORDERED_PERMIT_OVERRIDES,
+ XACML3.ID_POLICY_PERMIT_OVERRIDES,
+ XACML3.ID_POLICY_PERMIT_UNLESS_DENY
+ ));
+ }
+
+ public static final Set<Identifier> RULE_ALGORITHMS = new HashSet<Identifier>();
+ static {
+ RULE_ALGORITHMS.addAll(Arrays.asList(
+ XACML3.ID_RULE_DENY_OVERRIDES,
+ XACML3.ID_RULE_DENY_UNLESS_PERMIT,
+ XACML3.ID_RULE_FIRST_APPLICABLE,
+ XACML3.ID_RULE_ONLY_ONE_APPLICABLE,
+ XACML3.ID_RULE_ORDERED_DENY_OVERRIDES,
+ XACML3.ID_RULE_ORDERED_PERMIT_OVERRIDES,
+ XACML3.ID_RULE_PERMIT_OVERRIDES,
+ XACML3.ID_RULE_PERMIT_UNLESS_DENY
+ ));
+ }
+
+ public static final Set<Identifier> STANDARD_ATTRIBUTES = new HashSet<Identifier>();
+ static {
+ STANDARD_ATTRIBUTES.addAll(Arrays.asList(
+ XACML3.ID_SUBJECT_SUBJECT_ID,
+ XACML3.ID_SUBJECT_SUBJECT_ID_QUALIFIER,
+ XACML3.ID_SUBJECT_KEY_INFO,
+ XACML3.ID_SUBJECT_AUTHENTICATION_TIME,
+ XACML3.ID_SUBJECT_AUTHENTICATION_METHOD,
+ XACML3.ID_SUBJECT_REQUEST_TIME,
+ XACML3.ID_SUBJECT_SESSION_START_TIME,
+ XACML3.ID_SUBJECT_AUTHN_LOCALITY_IP_ADDRESS,
+ XACML3.ID_SUBJECT_AUTHN_LOCALITY_DNS_NAME,
+ XACML3.ID_SUBJECT_ROLE,
+ XACML3.ID_ACTION_ACTION_ID,
+ XACML3.ID_ACTION_IMPLIED_ACTION,
+ XACML3.ID_RESOURCE_RESOURCE_ID,
+ XACML3.ID_RESOURCE_RESOURCE_LOCATION,
+ XACML3.ID_RESOURCE_SIMPLE_FILE_NAME,
+ XACML3.ID_ENVIRONMENT_CURRENT_DATE,
+ XACML3.ID_ENVIRONMENT_CURRENT_TIME,
+ XACML3.ID_ENVIRONMENT_CURRENT_DATETIME
+ ));
+ }
+
+ public static final Map<Identifier, Set<Identifier>> MAP_STANDARD_CATEGORIES = new HashMap<Identifier, Set<Identifier>>();
+ static {
+ MAP_STANDARD_CATEGORIES.put(XACML3.ID_SUBJECT_CATEGORY_ACCESS_SUBJECT, new HashSet<Identifier>(Arrays.asList(
+ XACML3.ID_SUBJECT_SUBJECT_ID,
+ XACML3.ID_SUBJECT_SUBJECT_ID_QUALIFIER,
+ XACML3.ID_SUBJECT_KEY_INFO,
+ XACML3.ID_SUBJECT_AUTHENTICATION_TIME,
+ XACML3.ID_SUBJECT_AUTHENTICATION_METHOD,
+ XACML3.ID_SUBJECT_REQUEST_TIME,
+ XACML3.ID_SUBJECT_SESSION_START_TIME,
+ XACML3.ID_SUBJECT_AUTHN_LOCALITY_IP_ADDRESS,
+ XACML3.ID_SUBJECT_AUTHN_LOCALITY_DNS_NAME,
+ XACML3.ID_SUBJECT_ROLE
+ )));
+ MAP_STANDARD_CATEGORIES.put(XACML3.ID_SUBJECT_CATEGORY_CODEBASE, new HashSet<Identifier>(Arrays.asList(
+ XACML3.ID_SUBJECT_SUBJECT_ID,
+ XACML3.ID_SUBJECT_SUBJECT_ID_QUALIFIER,
+ XACML3.ID_SUBJECT_KEY_INFO,
+ XACML3.ID_SUBJECT_AUTHENTICATION_TIME,
+ XACML3.ID_SUBJECT_AUTHENTICATION_METHOD,
+ XACML3.ID_SUBJECT_REQUEST_TIME,
+ XACML3.ID_SUBJECT_SESSION_START_TIME,
+ XACML3.ID_SUBJECT_AUTHN_LOCALITY_IP_ADDRESS,
+ XACML3.ID_SUBJECT_AUTHN_LOCALITY_DNS_NAME,
+ XACML3.ID_SUBJECT_ROLE
+ )));
+ MAP_STANDARD_CATEGORIES.put(XACML3.ID_SUBJECT_CATEGORY_INTERMEDIARY_SUBJECT, new HashSet<Identifier>(Arrays.asList(
+ XACML3.ID_SUBJECT_SUBJECT_ID,
+ XACML3.ID_SUBJECT_SUBJECT_ID_QUALIFIER,
+ XACML3.ID_SUBJECT_KEY_INFO,
+ XACML3.ID_SUBJECT_AUTHENTICATION_TIME,
+ XACML3.ID_SUBJECT_AUTHENTICATION_METHOD,
+ XACML3.ID_SUBJECT_REQUEST_TIME,
+ XACML3.ID_SUBJECT_SESSION_START_TIME,
+ XACML3.ID_SUBJECT_AUTHN_LOCALITY_IP_ADDRESS,
+ XACML3.ID_SUBJECT_AUTHN_LOCALITY_DNS_NAME,
+ XACML3.ID_SUBJECT_ROLE
+ )));
+ MAP_STANDARD_CATEGORIES.put(XACML3.ID_SUBJECT_CATEGORY_RECIPIENT_SUBJECT, new HashSet<Identifier>(Arrays.asList(
+ XACML3.ID_SUBJECT_SUBJECT_ID,
+ XACML3.ID_SUBJECT_SUBJECT_ID_QUALIFIER,
+ XACML3.ID_SUBJECT_KEY_INFO,
+ XACML3.ID_SUBJECT_AUTHENTICATION_TIME,
+ XACML3.ID_SUBJECT_AUTHENTICATION_METHOD,
+ XACML3.ID_SUBJECT_REQUEST_TIME,
+ XACML3.ID_SUBJECT_SESSION_START_TIME,
+ XACML3.ID_SUBJECT_AUTHN_LOCALITY_IP_ADDRESS,
+ XACML3.ID_SUBJECT_AUTHN_LOCALITY_DNS_NAME,
+ XACML3.ID_SUBJECT_ROLE
+ )));
+ MAP_STANDARD_CATEGORIES.put(XACML3.ID_SUBJECT_CATEGORY_REQUESTING_MACHINE, new HashSet<Identifier>(Arrays.asList(
+ XACML3.ID_SUBJECT_SUBJECT_ID,
+ XACML3.ID_SUBJECT_SUBJECT_ID_QUALIFIER,
+ XACML3.ID_SUBJECT_KEY_INFO,
+ XACML3.ID_SUBJECT_AUTHENTICATION_TIME,
+ XACML3.ID_SUBJECT_AUTHENTICATION_METHOD,
+ XACML3.ID_SUBJECT_REQUEST_TIME,
+ XACML3.ID_SUBJECT_SESSION_START_TIME,
+ XACML3.ID_SUBJECT_AUTHN_LOCALITY_IP_ADDRESS,
+ XACML3.ID_SUBJECT_AUTHN_LOCALITY_DNS_NAME,
+ XACML3.ID_SUBJECT_ROLE
+ )));
+ MAP_STANDARD_CATEGORIES.put(XACML3.ID_ATTRIBUTE_CATEGORY_ACTION, new HashSet<Identifier>(Arrays.asList(
+ XACML3.ID_ACTION_ACTION_ID,
+ XACML3.ID_ACTION_IMPLIED_ACTION
+ )));
+ MAP_STANDARD_CATEGORIES.put(XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE, new HashSet<Identifier>(Arrays.asList(
+ XACML3.ID_RESOURCE_RESOURCE_ID,
+ XACML3.ID_RESOURCE_RESOURCE_LOCATION,
+ XACML3.ID_RESOURCE_SIMPLE_FILE_NAME
+ )));
+ MAP_STANDARD_CATEGORIES.put(XACML3.ID_ATTRIBUTE_CATEGORY_ENVIRONMENT, new HashSet<Identifier>(Arrays.asList(
+ XACML3.ID_ENVIRONMENT_CURRENT_DATE,
+ XACML3.ID_ENVIRONMENT_CURRENT_TIME,
+ XACML3.ID_ENVIRONMENT_CURRENT_DATETIME
+ )));
+ }
+
+ public static String extractShortName(String xacmlID) {
+ if (xacmlID == null) {
+ return null;
+ }
+ if (xacmlID.startsWith("http:")) {
+ String [] parts = xacmlID.split("[#]");
+ if (parts != null && parts.length > 0) {
+ return parts[parts.length - 1];
+ }
+ return null;
+ }
+ if (xacmlID.startsWith("urn") || xacmlID.contains(":")) {
+ String[] parts = xacmlID.split("[:]");
+
+ if (parts != null && parts.length > 0) {
+ return parts[parts.length - 1];
+ }
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/648d0c0d/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/XACMLFunctionValidator.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/XACMLFunctionValidator.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/XACMLFunctionValidator.java
new file mode 100644
index 0000000..7ef7e60
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/XACMLFunctionValidator.java
@@ -0,0 +1,506 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.openaz.xacml.admin.util;
+
+import java.util.List;
+
+import javax.xml.bind.JAXBElement;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import org.apache.openaz.xacml.admin.jpa.Datatype;
+import org.apache.openaz.xacml.admin.jpa.FunctionArgument;
+import org.apache.openaz.xacml.admin.jpa.FunctionDefinition;
+import org.apache.openaz.xacml.api.XACML3;
+import org.apache.openaz.xacml.std.IdentifierImpl;
+
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.ApplyType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeAssignmentExpressionType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeDesignatorType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeSelectorType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AttributeValueType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.ConditionType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.FunctionType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableDefinitionType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.VariableReferenceType;
+
+public class XACMLFunctionValidator {
+ private static Log logger = LogFactory.getLog(XACMLFunctionValidator.class);
+
+ public static boolean validNumberOfArguments(ApplyType apply) {
+ try {
+ //
+ // Sanity check
+ //
+ if (apply == null) {
+ throw new IllegalArgumentException("Must supply a non-null apply object.");
+ }
+ //
+ // Get the function
+ //
+ FunctionDefinition function = JPAUtils.getFunctionIDMap().get(apply.getFunctionId());
+ if (function == null) {
+ throw new Exception("Invalid function id: " + apply.getFunctionId());
+ }
+ //
+ // Now check argument list, do we have the minimum?
+ //
+ List<JAXBElement<?>> applyArgs = apply.getExpression();
+ if (applyArgs.isEmpty()) {
+ //
+ // May not need any args
+ //
+ if (function.getArgLb() > 0) {
+ throw new Exception ("Number of Args mismatch, expecting at least " +
+ function.getArgLb() + " arguments but have zero.");
+ }
+ } else {
+ if (applyArgs.size() < function.getArgLb()) {
+ throw new Exception ("Number of Args mismatch, expecting at least " +
+ function.getArgLb() + " arguments but have " + applyArgs.size());
+ }
+ }
+ //
+ // Is there an upper bound?
+ //
+ if (function.getArgUb() != -1 && applyArgs.size() != function.getArgUb()) {
+ throw new Exception ("Number of Args mismatch, expecting at most " +
+ function.getArgUb() + " arguments but have " + applyArgs.size());
+ }
+ } catch (Exception e) {
+ logger.error("Number of arguments incorrect: " + e);
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean canHaveMoreArguments(ConditionType condition) {
+ if (condition.getExpression() == null || condition.getExpression().getValue() == null) {
+ return true;
+ }
+ Object expression = condition.getExpression().getValue();
+ if (expression instanceof ApplyType) {
+ return XACMLFunctionValidator.canHaveMoreArguments((ApplyType) expression);
+ }
+ return false;
+ }
+
+ public static boolean canHaveMoreArguments(VariableDefinitionType variable) {
+ if (variable.getExpression() == null || variable.getExpression().getValue() == null) {
+ return true;
+ }
+ Object expression = variable.getExpression().getValue();
+ if (expression instanceof ApplyType) {
+ return XACMLFunctionValidator.canHaveMoreArguments((ApplyType) expression);
+ }
+ return false;
+ }
+
+ public static boolean canHaveMoreArguments(AttributeAssignmentExpressionType assignment) {
+ if (assignment.getExpression() == null || assignment.getExpression().getValue() == null) {
+ return true;
+ }
+ Object expression = assignment.getExpression().getValue();
+ if (expression instanceof ApplyType) {
+ return XACMLFunctionValidator.canHaveMoreArguments((ApplyType) expression);
+ }
+ return false;
+ }
+
+ public static boolean canHaveMoreArguments(ApplyType apply) {
+ //
+ // Sanity check
+ //
+ if (apply == null) {
+ throw new IllegalArgumentException("Must supply a non-null apply object.");
+ }
+ //
+ // Get the function
+ //
+ FunctionDefinition function = JPAUtils.getFunctionIDMap().get(apply.getFunctionId());
+ if (function == null) {
+ throw new IllegalArgumentException("Invalid function id: " + apply.getFunctionId());
+ }
+ //
+ // Is there no upper bound?
+ //
+ if (function.getArgUb() == -1) {
+ //
+ // No limit to the number of arguments
+ //
+ return true;
+ }
+ //
+ // There is an upper bound - have we met it?
+ //
+ List<JAXBElement<?>> applyArgs = apply.getExpression();
+ if (applyArgs.size() < function.getArgUb()) {
+ //
+ // We have not met the upper bound, so yes we can
+ // add more arguments.
+ //
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isFunctionAvailable(FunctionDefinition function, ApplyType apply, FunctionArgument argument) {
+ //
+ // Does it return correct datatype?
+ //
+ if (argument != null) {
+ //
+ // Does it match?
+ //
+ if (function.getDatatypeBean().getXacmlId().equals(argument.getDatatypeBean().getXacmlId())) {
+ return false;
+ }
+ if (function.getIsBagReturn() != argument.getIsBag()) {
+ return false;
+ }
+ }
+ //
+ // Check each argument
+ //
+ int i;
+ for (i = 0; i < apply.getExpression().size(); i++) {
+ //
+ // Get the argument
+ //
+ JAXBElement<?> arg = apply.getExpression().get(i);
+ //
+ // Get what the argument should be
+ //
+ FunctionArgument functionArg = XACMLFunctionValidator.getFunctionArgument(i + 1, function);
+ //
+ // Sanity check
+ //
+ if (arg == null || arg.getValue() == null || functionArg == null) {
+ //
+ // Something screwy with the list, just return not available. They will have
+ // delete items that are bad.
+ //
+ return false;
+ }
+ //
+ // Does it match?
+ //
+ if (XACMLFunctionValidator.isArgumentValid(arg.getValue(), functionArg) == false) {
+ return false;
+ }
+ }
+ //
+ // Done checking, we don't care if there are more args needed. Just want to know if this
+ // function can fit with the existing arguments.
+ //
+ return true;
+ }
+
+ public static FunctionDefinition validateApply(ApplyType apply, FunctionArgument argument) {
+ //
+ // Sanity check
+ //
+ if (apply == null) {
+ throw new IllegalArgumentException("Must supply a non-null apply object.");
+ }
+ try {
+ //
+ // Get the function
+ //
+ FunctionDefinition function = JPAUtils.getFunctionIDMap().get(apply.getFunctionId());
+ if (function == null) {
+ throw new Exception("Invalid function id: " + apply.getFunctionId());
+ }
+ //
+ // Does it return correct datatype?
+ //
+ if (argument != null) {
+ //
+ // Does it match?
+ //
+ if (argument.getDatatypeBean() != null) {
+ if (! function.getDatatypeBean().getXacmlId().equals(argument.getDatatypeBean().getXacmlId())) {
+ throw new Exception("Function return datatype(" + function.getDatatypeBean() +
+ ") does not match expected argument datatype (" + argument.getDatatypeBean());
+ }
+ } else {
+ if (logger.isDebugEnabled()) {
+ logger.debug("Argument datatype bean is null - any datatype should work.");
+ }
+ }
+ if (function.getIsBagReturn() != argument.getIsBag()) {
+ throw new Exception("Function is bag (" + function.getIsBagReturn() +
+ ") does not match argument isBag(" + argument.getIsBag());
+ }
+ }
+ //
+ // Now check argument list, do we have the minimum?
+ //
+ List<JAXBElement<?>> applyArgs = apply.getExpression();
+ if (applyArgs == null) {
+ //
+ // May not need any args
+ //
+ if (function.getArgLb() > 0) {
+ throw new Exception ("Number of Args mismatch, expecting at least " +
+ function.getArgLb() + " arguments but have zero.");
+ }
+ } else {
+ if (applyArgs.size() < function.getArgLb()) {
+ throw new Exception ("Number of Args mismatch, expecting at least " +
+ function.getArgLb() + " arguments but have " + applyArgs.size());
+ }
+ }
+ //
+ // Is there an upper bound?
+ //
+ if (function.getArgUb() != -1 && applyArgs.size() != function.getArgUb()) {
+ throw new Exception ("Number of Args mismatch, expecting at most " +
+ function.getArgUb() + " arguments but have " + applyArgs.size());
+ }
+ //
+ // Check each argument
+ //
+ int i;
+ for (i = 0; i < applyArgs.size(); i++) {
+ //
+ // Get the argument
+ //
+ JAXBElement<?> arg = applyArgs.get(i);
+ //
+ // Get what the argument should be
+ //
+ FunctionArgument functionArg = XACMLFunctionValidator.getFunctionArgument(i + 1, function);
+ //
+ // Sanity check
+ //
+ if (arg == null || arg.getValue() == null || functionArg == null) {
+ throw new NullPointerException("An argument is null: Element" + arg + " Function Arg: " + functionArg);
+ }
+ //
+ // Does it match?
+ //
+ if (XACMLFunctionValidator.isArgumentValid(arg.getValue(), functionArg) == false) {
+ throw new Exception("Invalid Argument: " + arg.getValue());
+ }
+ }
+ //
+ // Done checking, just return the function which has the datatype
+ // and if it is a bag.
+ //
+ return function;
+ } catch(Exception e) {
+ logger.error("Function is not valid: " + apply.getFunctionId() + " argument: " + argument + " " + e);
+ return null;
+ }
+ }
+
+ private static boolean isArgumentValid(Object value, FunctionArgument functionArg) {
+ if (value instanceof ApplyType) {
+ //
+ // Recursively validate the Apply.
+ //
+ FunctionDefinition function = XACMLFunctionValidator.validateApply((ApplyType) value, functionArg);
+ if (functionArg.getDatatypeBean() == null || function.getDatatypeBean().getId() == functionArg.getDatatypeBean().getId()) {
+ if (function.getIsBagReturn() == functionArg.getIsBag()) {
+ return true;
+ }
+ logger.error("isBag does not match: " + function.getIsBagReturn() + " " + functionArg.getIsBag());
+ }
+ logger.error("Datatypes do not match: " + function.getDatatypeBean().getShortName() + " " + functionArg.getDatatypeBean().getShortName());
+ } else if (value instanceof AttributeValueType) {
+ AttributeValueType val = (AttributeValueType) value;
+ Datatype datatype = JPAUtils.findDatatype(new IdentifierImpl(val.getDataType()));
+ if (functionArg.getDatatypeBean() == null || datatype.getId() == functionArg.getDatatypeBean().getId()) {
+ //
+ // TODO Is bag?
+ //
+ return true;
+ }
+ logger.error("Datatypes do not match: " + datatype.getShortName() + " " + functionArg.getDatatypeBean().getShortName());
+ } else if (value instanceof AttributeDesignatorType) {
+ AttributeDesignatorType designator = (AttributeDesignatorType) value;
+ Datatype datatype = JPAUtils.findDatatype(new IdentifierImpl(designator.getDataType()));
+ if (functionArg.getDatatypeBean() == null || datatype.getId() == functionArg.getDatatypeBean().getId()) {
+ //
+ // TODO Is bag?
+ //
+ return true;
+ }
+ logger.error("Datatypes do not match: " + datatype.getShortName() + " " + functionArg.getDatatypeBean().getShortName());
+ } else if (value instanceof AttributeSelectorType) {
+ AttributeSelectorType selector = (AttributeSelectorType) value;
+ Datatype datatype = JPAUtils.findDatatype(new IdentifierImpl(selector.getDataType()));
+ if (functionArg.getDatatypeBean() == null || datatype.getId() == functionArg.getDatatypeBean().getId()) {
+ //
+ // TODO Is bag?
+ //
+ return true;
+ }
+ logger.error("Datatypes do not match: " + datatype.getShortName() + " " + functionArg.getDatatypeBean().getShortName());
+ } else if (value instanceof VariableReferenceType) {
+ //
+ // We can't verify this at this time.
+ // The user can define variables in other parts of the policy file
+ // or another policy file. This should be flagged if the user performs
+ // simulation and other testing on the policy before deployment.
+ //
+ return true;
+ } else if (value instanceof FunctionType) {
+ //
+ // Does this function exist?
+ //
+ FunctionDefinition function = JPAUtils.findFunction(((FunctionType) value).getFunctionId());
+ if (function == null) {
+ //
+ // Could not find function
+ //
+ logger.warn("Could not find function in our database: " + ((FunctionType) value).getFunctionId());
+ return false;
+ }
+ //
+ // Does this function return the correct data type?
+ //
+ if (functionArg.getDatatypeBean() == null || function.getDatatypeBean().getId() == functionArg.getDatatypeBean().getId()) {
+ return true;
+ }
+ logger.error("Datatypes do not match: " + function.getDatatypeBean().getShortName() + " " + functionArg.getDatatypeBean().getShortName());
+ }
+ return false;
+ }
+
+ public static FunctionArgument getFunctionArgument(int index, FunctionDefinition function) {
+ if (index < 1) {
+ throw new IllegalArgumentException("The index must be 1-based");
+ }
+ //
+ // Setup what the actual lower bound and upper bounds are
+ // within the list.
+ //
+// int lowerBound = function.getArgLb();
+// if (lowerBound == 0) {
+// lowerBound = 1;
+// }
+ int upperBound = function.getArgUb();
+ if (upperBound == -1) {
+ upperBound = function.getFunctionArguments().size();
+ }
+ //
+ // The list may not be sorted, so make sure we find
+ // the actual argument index
+ //
+ int argumentIndex = index;
+ if (index >= upperBound) {
+ argumentIndex = upperBound;
+ }
+ for (FunctionArgument arg : function.getFunctionArguments()) {
+ if (arg.getArgIndex() == argumentIndex) {
+ return arg;
+ }
+ }
+ return null;
+ }
+
+ public static boolean validateCondition(ConditionType condition) {
+ if (condition.getExpression() == null) {
+ return false;
+ }
+ Object expression = condition.getExpression().getValue();
+ if (expression instanceof ApplyType) {
+ FunctionDefinition function = XACMLFunctionValidator.validateApply((ApplyType) expression, null);
+ if (function == null) {
+ return false;
+ }
+ if (function.isBagReturn()) {
+ return false;
+ }
+ if (function.getDatatypeBean() == null) {
+ return false;
+ }
+ return function.getDatatypeBean().getXacmlId().equals(XACML3.ID_DATATYPE_BOOLEAN.stringValue());
+ }
+ if (expression instanceof AttributeDesignatorType) {
+ return ((AttributeDesignatorType) expression).getDataType().equals(XACML3.ID_DATATYPE_BOOLEAN.stringValue());
+ }
+ if (expression instanceof AttributeSelectorType) {
+ return ((AttributeSelectorType) expression).getDataType().equals(XACML3.ID_DATATYPE_BOOLEAN.stringValue());
+ }
+ if (expression instanceof AttributeValueType) {
+ return ((AttributeValueType) expression).getDataType().equals(XACML3.ID_DATATYPE_BOOLEAN.stringValue());
+ }
+ if (expression instanceof VariableReferenceType) {
+ //
+ // Really unknown - the variable may or may not have been defined
+ //
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean validateVariable(VariableDefinitionType variable) {
+ if (variable.getExpression() == null) {
+ return false;
+ }
+ Object expression = variable.getExpression().getValue();
+ if (expression instanceof ApplyType) {
+ FunctionDefinition function = XACMLFunctionValidator.validateApply((ApplyType) expression, null);
+ if (function == null) {
+ return false;
+ }
+ return true;
+ }
+ if (expression instanceof AttributeDesignatorType) {
+ return true;
+ }
+ if (expression instanceof AttributeSelectorType) {
+ return true;
+ }
+ if (expression instanceof AttributeValueType) {
+ return true;
+ }
+ if (expression instanceof VariableReferenceType) {
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean validateAssignment(AttributeAssignmentExpressionType assignmentExpression) {
+ if (assignmentExpression.getExpression() == null) {
+ return false;
+ }
+ Object expression = assignmentExpression.getExpression().getValue();
+ if (expression instanceof ApplyType) {
+ FunctionDefinition function = XACMLFunctionValidator.validateApply((ApplyType) expression, null);
+ if (function == null) {
+ return false;
+ }
+ //
+ // TODO
+ //
+ }
+ //
+ // TODO
+ //
+ return true;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/648d0c0d/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/XACMLPolicyImporter.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/XACMLPolicyImporter.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/XACMLPolicyImporter.java
new file mode 100644
index 0000000..8a7c714
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/util/XACMLPolicyImporter.java
@@ -0,0 +1,495 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.openaz.xacml.admin.util;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.AdviceExpressionType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.EffectType;
+import oasis.names.tc.xacml._3_0.core.schema.wd_17.ObligationExpressionType;
+
+import org.apache.openaz.xacml.admin.XacmlAdminUI;
+import org.apache.openaz.xacml.admin.jpa.Attribute;
+import org.apache.openaz.xacml.admin.jpa.Category;
+import org.apache.openaz.xacml.admin.jpa.ConstraintType;
+import org.apache.openaz.xacml.admin.jpa.ConstraintValue;
+import org.apache.openaz.xacml.admin.jpa.Datatype;
+import org.apache.openaz.xacml.admin.jpa.Obadvice;
+import org.apache.openaz.xacml.api.Advice;
+import org.apache.openaz.xacml.api.AttributeValue;
+import org.apache.openaz.xacml.api.Identifier;
+import org.apache.openaz.xacml.api.Obligation;
+import org.apache.openaz.xacml.api.XACML3;
+import org.apache.openaz.xacml.util.XACMLObjectCopy;
+import org.apache.openaz.xacml.util.XACMLPolicyAggregator;
+import org.apache.openaz.xacml.util.XACMLPolicyScanner.CallbackResult;
+import com.vaadin.addon.jpacontainer.JPAContainer;
+import com.vaadin.addon.jpacontainer.provider.CachingMutableLocalEntityProvider;
+import com.vaadin.data.Buffered.SourceException;
+import com.vaadin.data.Validator.InvalidValueException;
+import com.vaadin.ui.UI;
+
+public class XACMLPolicyImporter extends XACMLPolicyAggregator {
+ private static Log logger = LogFactory.getLog(XACMLPolicyImporter.class);
+
+ public enum OPTION {
+ /*
+ * Overwrite any existing ID
+ */
+ OVERWRITE_EXISTING,
+ /*
+ * Update an existing ID - only ADDs information
+ */
+ UPDATE_EXISTING,
+ /*
+ * Does not change an existing ID
+ */
+ DONOTCHANGE_EXISTING
+ }
+
+ public boolean importAttributes = true;
+ public boolean ignoreStandardAttributes = true;
+ public boolean addConstraints = true;
+ public OPTION attributeOption = OPTION.OVERWRITE_EXISTING;
+ public boolean importObligations = true;
+ public OPTION obligationOption = OPTION.OVERWRITE_EXISTING;
+ public boolean importAdvice = true;
+ public OPTION adviceOption = OPTION.OVERWRITE_EXISTING;
+
+ public XACMLPolicyImporter() {
+ }
+
+ public boolean isImportAttributes() {
+ return importAttributes;
+ }
+
+ public void setImportAttributes(boolean importAttributes) {
+ this.importAttributes = importAttributes;
+ }
+
+ public boolean isIgnoreStandardAttributes() {
+ return ignoreStandardAttributes;
+ }
+
+ public void setIgnoreStandardAttributes(boolean ignoreStandardAttributes) {
+ this.ignoreStandardAttributes = ignoreStandardAttributes;
+ }
+
+ public boolean isAddConstraints() {
+ return addConstraints;
+ }
+
+ public void setAddConstraints(boolean addConstraints) {
+ this.addConstraints = addConstraints;
+ }
+
+ public OPTION getAttributeOption() {
+ return attributeOption;
+ }
+
+ public void setAttributeOption(OPTION attributeOption) {
+ this.attributeOption = attributeOption;
+ }
+
+ public boolean isImportObligations() {
+ return importObligations;
+ }
+
+ public void setImportObligations(boolean importObligations) {
+ this.importObligations = importObligations;
+ }
+
+ public OPTION getObligationOption() {
+ return obligationOption;
+ }
+
+ public void setObligationOption(OPTION obligationOption) {
+ this.obligationOption = obligationOption;
+ }
+
+ public boolean isImportAdvice() {
+ return importAdvice;
+ }
+
+ public void setImportAdvice(boolean importAdvice) {
+ this.importAdvice = importAdvice;
+ }
+
+ public OPTION getAdviceOption() {
+ return adviceOption;
+ }
+
+ public void setAdviceOption(OPTION adviceOption) {
+ this.adviceOption = adviceOption;
+ }
+ @Override
+ public CallbackResult onObligation(Object parent, ObligationExpressionType expression, Obligation obligation) {
+ if (importObligations) {
+ super.onObligation(parent, expression, obligation);
+ }
+ return CallbackResult.CONTINUE;
+ }
+
+ @Override
+ public CallbackResult onAttribute(Object parent, Object container, org.apache.openaz.xacml.api.Attribute attribute) {
+ if (importAttributes) {
+ super.onAttribute(parent, container, attribute);
+ }
+ return CallbackResult.CONTINUE;
+ }
+
+ @Override
+ public CallbackResult onAdvice(Object parent, AdviceExpressionType expression, Advice advice) {
+ if (importAdvice) {
+ super.onAdvice(parent, expression, advice);
+ }
+ return CallbackResult.CONTINUE;
+ }
+
+ @Override
+ public void onFinishScan(Object root) {
+ if (this.importAttributes && this.doImportAttributes() > 0) {
+ ((XacmlAdminUI)UI.getCurrent()).refreshAttributes();
+ }
+ int changes = 0;
+ if (this.importObligations) {
+ changes += this.doImportObligations();
+ }
+ if (this.importAdvice) {
+ changes += this.doImportAdvice();
+ }
+ //
+ // If changes were made, we need to tell the UI so the
+ // dictionary can refresh.
+ //
+ if (changes > 0) {
+ ((XacmlAdminUI)UI.getCurrent()).refreshObadvice();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ protected int doImportAttributes() {
+ int changes = 0;
+ //
+ // Get our attributes. This container is modifiable.
+ //
+ JPAContainer<Attribute> attributes = ((XacmlAdminUI)UI.getCurrent()).getAttributes();
+ //
+ // Get mutable entity providers for these.
+ //
+ JPAContainer<Category> categories = new JPAContainer<Category>(Category.class);
+ categories.setEntityProvider(new CachingMutableLocalEntityProvider<Category>(Category.class, ((XacmlAdminUI)UI.getCurrent()).getEntityManager()));
+
+ JPAContainer<Datatype> datatypes = new JPAContainer<Datatype>(Datatype.class);
+ datatypes.setEntityProvider(new CachingMutableLocalEntityProvider<Datatype>(Datatype.class, ((XacmlAdminUI)UI.getCurrent()).getEntityManager()));
+ //
+ // Work the map
+ //
+ for (Identifier cat : this.attributeMap.keySet()) {
+ //
+ // Does category exist?
+ //
+ Category category = JPAUtils.findCategory(cat);
+ if (category == null) {
+ //
+ // This should rarely happen, but is possible since XACML 3.0
+ // you can define your own categories.
+ //
+ logger.warn("New category: " + cat);
+ category = new Category(cat, Category.CUSTOM);
+ String shortName = XACMLConstants.extractShortName(cat.stringValue());
+ if (shortName != null) {
+ category.setShortName(shortName);
+ } else {
+ category.setShortName(category.getXacmlId());
+ }
+ //
+ // Make sure the grouping is ok
+ //
+ if (category.getGrouping() == null) {
+ category.setGrouping(category.getShortName());
+ }
+ //
+ // Add it in
+ //
+ categories.addEntity(category);
+ //
+ // Tell the RO to update itself.
+ //
+ ((XacmlAdminUI)UI.getCurrent()).getCategories().refresh();
+ }
+ Map<Identifier, Map<Identifier, Set<AttributeValue<?>>>> map = this.attributeMap.get(cat);
+ for (Identifier dt : map.keySet()) {
+ //
+ // Does datatype exist?
+ //
+ Datatype datatype = JPAUtils.findDatatype(dt);
+ if (datatype == null) {
+ //
+ // This should rarely happen, but is possible since XACML 3.0
+ // you can define new datatypes.
+ //
+ logger.warn("New datatype: " + dt);
+ datatype = new Datatype(dt, Datatype.CUSTOM);
+ String shortName = XACMLConstants.extractShortName(dt.stringValue());
+ if (shortName != null) {
+ datatype.setShortName(shortName);
+ } else {
+ datatype.setShortName(datatype.getXacmlId());
+ }
+ //
+ // Add it in
+ //
+ datatypes.addEntity(datatype);
+ //
+ // Tell the Read-Only property to update itself.
+ //
+ ((XacmlAdminUI)UI.getCurrent()).getDatatypes().refresh();
+ }
+ //
+ // Iterate the attributes
+ //
+ for (Identifier id : map.get(dt).keySet()) {
+ //
+ // Do we ignore it if its standard?
+ //
+ if (! this.ignoreStandardAttributes ||
+ XACMLConstants.STANDARD_ATTRIBUTES.contains(id) == false) {
+ //
+ // Does it already exist?
+ //
+ Attribute newAttribute = null;
+ Attribute currentAttribute = JPAUtils.findAttribute(category, datatype, id.stringValue());
+ //
+ // Support for an existing attribute
+ //
+ if (currentAttribute != null) {
+ if (this.attributeOption == OPTION.OVERWRITE_EXISTING) {
+ newAttribute = currentAttribute;
+ newAttribute.setConstraintType(null);
+ newAttribute.removeAllConstraintValues();
+ } else if (this.attributeOption == OPTION.DONOTCHANGE_EXISTING) {
+ logger.info("Do not change existing: " + currentAttribute);
+ continue;
+ } else if (this.attributeOption == OPTION.UPDATE_EXISTING) {
+ newAttribute = currentAttribute;
+ }
+ } else {
+ //
+ // Create our new attribute
+ //
+ newAttribute = new Attribute(id.stringValue(), ((XacmlAdminUI)UI.getCurrent()).getUserid());
+ newAttribute.setCategoryBean(category);
+ newAttribute.setDatatypeBean(datatype);
+ }
+ //
+ // Get all the values
+ //
+ Set<AttributeValue<?>> values = map.get(dt).get(id);
+ //
+ // Do we have more than 1? Also, omit boolean datatype which
+ // doesn't make any sense to enumerate.
+ //
+ if (values.size() > 1 && dt.equals(XACML3.ID_DATATYPE_BOOLEAN) == false) {
+ //
+ // We have a lot of possible values, add as an enumeration
+ //
+ newAttribute.setConstraintType(JPAUtils.findConstraintType(ConstraintType.ENUMERATION_TYPE));
+ for (AttributeValue<?> value : values) {
+ Object val = value.getValue();
+ String content;
+ if (val instanceof Collection) {
+ content = XACMLObjectCopy.getContent((List<Object>) value.getValue());
+ } else {
+ content = val.toString();
+ }
+ //
+ // Check if we should add it in
+ //
+ boolean add = true;
+ //
+ // If we are updating an existing, we can really only do this for enumerations,
+ // its impossible to resolve a regular expression or range.
+ //
+ if (currentAttribute != null && this.attributeOption == OPTION.UPDATE_EXISTING &&
+ newAttribute.getConstraintType().getConstraintType().equals(ConstraintType.ENUMERATION_TYPE)) {
+ //
+ // Make sure it isn't there already, no duplicates.
+ //
+ for (ConstraintValue currentConstraintValue : newAttribute.getConstraintValues()) {
+ if (currentConstraintValue.getValue().equals(content)) {
+ add = false;
+ break;
+ }
+ }
+ }
+ if (add && content.isEmpty() == false) {
+ ConstraintValue newValue = new ConstraintValue("Enumeration", content);
+ newValue.setAttribute(newAttribute);
+ newAttribute.addConstraintValue(newValue);
+ }
+ }
+ }
+ //
+ // Add it
+ //
+ if (newAttribute != null) {
+ if (newAttribute.getId() == 0) {
+ logger.info("Adding new attribute");
+ if (attributes.addEntity(newAttribute) == null) {
+ logger.error("Failed to add new attribute: " + newAttribute);
+ } else {
+ changes++;
+ }
+ } else {
+ logger.info("Updating attribute " + newAttribute);
+ try {
+ attributes.commit();
+ changes++;
+ } catch (SourceException | InvalidValueException e) {
+ logger.error("Update failed: " + e.getLocalizedMessage());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return changes;
+ }
+
+ protected int doImportObligations() {
+ int changes = 0;
+ JPAContainer<Obadvice> oa = ((XacmlAdminUI)UI.getCurrent()).getObadvice();
+ for (Identifier id : this.obligationMap.keySet()) {
+ for (EffectType effect : this.obligationMap.get(id).keySet()) {
+ for (Obligation obligation : this.obligationMap.get(id).get(effect)) {
+ Obadvice newObligation = null;
+ Obadvice currentObligation = JPAUtils.findObligation(obligation.getId(), effect);
+ //
+ // Does it exist?
+ //
+ if (currentObligation != null) {
+ if (this.obligationOption == OPTION.OVERWRITE_EXISTING) {
+ newObligation = currentObligation;
+ newObligation.removeAllExpressions();
+ } else if (this.obligationOption == OPTION.DONOTCHANGE_EXISTING) {
+ continue;
+ } else if (this.obligationOption == OPTION.UPDATE_EXISTING) {
+ newObligation = currentObligation;
+ }
+ } else {
+ //
+ // Create new one
+ //
+ newObligation = new Obadvice(obligation.getId(), ((XacmlAdminUI)UI.getCurrent()).getUserid());
+ newObligation.setFulfillOn((effect == EffectType.PERMIT ? Obadvice.EFFECT_PERMIT : Obadvice.EFFECT_DENY));
+ }
+ //
+ // TODO add the expressions
+ //
+
+ //
+ // Add it in
+ //
+ if (newObligation != null) {
+ if (newObligation.getId() == 0) {
+ logger.info("Adding obligation " + newObligation);
+ oa.addEntity(newObligation);
+ changes++;
+ } else {
+ logger.info("Updating obligation " + newObligation);
+ try {
+ oa.commit();
+ changes++;
+ } catch (SourceException | InvalidValueException e) {
+ logger.error("Update obligation failed " + e.getLocalizedMessage());
+ }
+ }
+ }
+ }
+ }
+ }
+ return changes;
+ }
+
+ protected int doImportAdvice() {
+ int changes = 0;
+ JPAContainer<Obadvice> oa = ((XacmlAdminUI)UI.getCurrent()).getObadvice();
+ for (Identifier id : this.adviceMap.keySet()) {
+ for (EffectType effect : this.adviceMap.get(id).keySet()) {
+ for (Advice advice : this.adviceMap.get(id).get(effect)) {
+ Obadvice newAdvice = null;
+ Obadvice currentAdvice = JPAUtils.findAdvice(advice.getId(), effect);
+ //
+ // Does it exist?
+ //
+ if (currentAdvice != null) {
+ if (this.adviceOption == OPTION.OVERWRITE_EXISTING) {
+ newAdvice = currentAdvice;
+ newAdvice.removeAllExpressions();
+ } else if (this.adviceOption == OPTION.DONOTCHANGE_EXISTING) {
+ continue;
+ } else if (this.adviceOption == OPTION.UPDATE_EXISTING) {
+ newAdvice = currentAdvice;
+ }
+ } else {
+ //
+ // Create new one
+ //
+ newAdvice = new Obadvice(advice.getId(), ((XacmlAdminUI)UI.getCurrent()).getUserid());
+ newAdvice.setType(Obadvice.ADVICE);
+ newAdvice.setFulfillOn((effect == EffectType.PERMIT ? Obadvice.EFFECT_PERMIT : Obadvice.EFFECT_DENY));
+ }
+ //
+ // TODO add the expressions
+ //
+
+ //
+ // Add it in
+ //
+ if (newAdvice != null) {
+ if (newAdvice.getId() == 0) {
+ logger.info("Adding advice " + newAdvice);
+ oa.addEntity(newAdvice);
+ changes++;
+ } else {
+ logger.info("Updating advice " + newAdvice);
+ try {
+ oa.commit();
+ changes++;
+ } catch (SourceException | InvalidValueException e) {
+ logger.error("Update advice failed " + e.getLocalizedMessage());
+ }
+ }
+ }
+ }
+ }
+ }
+ return changes;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-openaz/blob/648d0c0d/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/view/components/AttributeDictionarySelectorComponent.java
----------------------------------------------------------------------
diff --git a/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/view/components/AttributeDictionarySelectorComponent.java b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/view/components/AttributeDictionarySelectorComponent.java
new file mode 100644
index 0000000..0dd7f32
--- /dev/null
+++ b/openaz-xacml-pap-admin/src/main/java/org/apache/openaz/xacml/admin/view/components/AttributeDictionarySelectorComponent.java
@@ -0,0 +1,290 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.openaz.xacml.admin.view.components;
+
+import org.apache.openaz.xacml.admin.XacmlAdminUI;
+import org.apache.openaz.xacml.admin.components.AttributeDictionary;
+import org.apache.openaz.xacml.admin.jpa.Attribute;
+import org.apache.openaz.xacml.admin.jpa.Category;
+import org.apache.openaz.xacml.admin.jpa.Datatype;
+import org.apache.openaz.xacml.admin.view.events.AttributeChangedEventListener;
+import org.apache.openaz.xacml.admin.view.events.AttributeChangedEventNotifier;
+import com.vaadin.addon.jpacontainer.JPAContainer;
+import com.vaadin.addon.jpacontainer.provider.CachingLocalEntityProvider;
+import com.vaadin.annotations.AutoGenerated;
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.data.util.filter.Compare;
+import com.vaadin.ui.AbstractSelect.ItemCaptionMode;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.ComboBox;
+import com.vaadin.ui.CustomComponent;
+import com.vaadin.ui.HorizontalLayout;
+import com.vaadin.ui.ListSelect;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+
+public class AttributeDictionarySelectorComponent extends CustomComponent implements AttributeChangedEventNotifier {
+
+ /*- VaadinEditorProperties={"grid":"RegularGrid,20","showGrid":true,"snapToGrid":true,"snapToObject":true,"movingGuides":false,"snappingDistance":10} */
+
+ @AutoGenerated
+ private VerticalLayout mainLayout;
+ @AutoGenerated
+ private ListSelect listSelectAttribute;
+ @AutoGenerated
+ private HorizontalLayout horizontalLayout_2;
+ @AutoGenerated
+ private Button buttonNewAttribute;
+ @AutoGenerated
+ private ComboBox comboBoxCategoryFilter;
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private final AttributeDictionarySelectorComponent self = this;
+ private final Datatype datatype;
+ private final Attribute initialAttribute;
+ private final BasicNotifier notifier = new BasicNotifier();
+ private static final JPAContainer<Category> categories = new JPAContainer<Category>(Category.class);
+ private static final JPAContainer<Attribute> attributes = new JPAContainer<Attribute>(Attribute.class);
+ static {
+ attributes.setEntityProvider(new CachingLocalEntityProvider<Attribute>(Attribute.class, ((XacmlAdminUI)UI.getCurrent()).getEntityManager()));
+ categories.setEntityProvider(new CachingLocalEntityProvider<Category>(Category.class, ((XacmlAdminUI)UI.getCurrent()).getEntityManager()));
+ attributes.sort(new String[]{"xacmlId"}, new boolean[]{true});
+ categories.sort(new String[]{"xacmlId"}, new boolean[]{true});
+ }
+ /**
+ * The constructor should first build the main layout, set the
+ * composition root and then do any custom initialization.
+ *
+ * The constructor will not be automatically regenerated by the
+ * visual editor.
+ */
+ public AttributeDictionarySelectorComponent(Datatype datatype, Attribute initialAttribute) {
+ buildMainLayout();
+ setCompositionRoot(mainLayout);
+ //
+ // Save pointer and finish container initialization
+ //
+ this.datatype = datatype;
+ this.initialAttribute = initialAttribute;
+ //
+ // Initialize
+ //
+ this.initializeCategoryFilter();
+ this.initializeAttributes();
+ this.initializeButtons();
+ //
+ // Set our focus
+ //
+ this.listSelectAttribute.focus();
+ }
+
+ protected void initializeCategoryFilter() {
+ //
+ // Remove any filters
+ //
+ AttributeDictionarySelectorComponent.categories.removeAllContainerFilters();
+ //
+ // Initialize data source and GUI properties
+ //
+ this.comboBoxCategoryFilter.setContainerDataSource(AttributeDictionarySelectorComponent.categories);
+ this.comboBoxCategoryFilter.setItemCaptionMode(ItemCaptionMode.PROPERTY);
+ this.comboBoxCategoryFilter.setItemCaptionPropertyId("xacmlId");
+ this.comboBoxCategoryFilter.setImmediate(true);
+ //
+ // Respond to events
+ //
+ this.comboBoxCategoryFilter.addValueChangeListener(new ValueChangeListener() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ //
+ // Clear any existing filters
+ //
+ AttributeDictionarySelectorComponent.attributes.removeAllContainerFilters();
+ //
+ // Get the current selection
+ //
+ Object id = self.comboBoxCategoryFilter.getValue();
+ //
+ // Is anything currently selected?
+ //
+ if (id != null) {
+ //
+ // Yes - add the new filter into the container
+ //
+ AttributeDictionarySelectorComponent.attributes.addContainerFilter(new Compare.Equal("categoryBean", AttributeDictionarySelectorComponent.categories.getItem(id).getEntity()));
+ }
+ }
+ });
+ }
+
+ protected void initializeAttributes() {
+ //
+ // Remove any filters
+ //
+ AttributeDictionarySelectorComponent.attributes.removeAllContainerFilters();
+ //
+ // Initialize data source and GUI properties
+ //
+ this.listSelectAttribute.setContainerDataSource(AttributeDictionarySelectorComponent.attributes);
+ this.listSelectAttribute.setItemCaptionMode(ItemCaptionMode.PROPERTY);
+ this.listSelectAttribute.setItemCaptionPropertyId("xacmlId");
+ this.listSelectAttribute.setImmediate(true);
+ this.listSelectAttribute.setHeight(7, Unit.EM);
+ //
+ // Filter by datatype
+ //
+ if (this.datatype != null) {
+ AttributeDictionarySelectorComponent.attributes.addContainerFilter(new Compare.Equal("datatypeBean", this.datatype));
+ }
+ //
+ // Is there a default selection? Is there an id?
+ //
+ if (this.initialAttribute != null && this.initialAttribute.getId() != 0) {
+ this.listSelectAttribute.select(this.initialAttribute.getId());
+ }
+ //
+ // Respond to events
+ //
+ this.listSelectAttribute.addValueChangeListener(new ValueChangeListener() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void valueChange(ValueChangeEvent event) {
+ self.fireAttributeChanged(self.getAttribute());
+ }
+ });
+ }
+
+ protected void initializeButtons() {
+ this.buttonNewAttribute.addClickListener(new ClickListener() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ AttributeDictionary.createNewAttributeWindow();
+ }
+ });
+ }
+
+ @Override
+ public void commit() {
+ this.listSelectAttribute.commit();
+ }
+
+ @Override
+ public Attribute getAttribute() {
+ Object id = this.listSelectAttribute.getValue();
+ if (id == null) {
+ return null;
+ }
+ return AttributeDictionarySelectorComponent.attributes.getItem(id).getEntity();
+ }
+
+ @Override
+ public boolean addListener(AttributeChangedEventListener listener) {
+ return this.notifier.addListener(listener);
+ }
+
+ @Override
+ public boolean removeListener(AttributeChangedEventListener listener) {
+ return this.notifier.removeListener(listener);
+ }
+
+ @Override
+ public void fireAttributeChanged(Attribute attribute) {
+ this.notifier.fireAttributeChanged(attribute);
+ }
+
+ @AutoGenerated
+ private VerticalLayout buildMainLayout() {
+ // common part: create layout
+ mainLayout = new VerticalLayout();
+ mainLayout.setImmediate(false);
+ mainLayout.setWidth("-1px");
+ mainLayout.setHeight("-1px");
+ mainLayout.setMargin(true);
+ mainLayout.setSpacing(true);
+
+ // top-level component properties
+ setWidth("-1px");
+ setHeight("-1px");
+
+ // horizontalLayout_2
+ horizontalLayout_2 = buildHorizontalLayout_2();
+ mainLayout.addComponent(horizontalLayout_2);
+
+ // listSelectAttribute
+ listSelectAttribute = new ListSelect();
+ listSelectAttribute.setCaption("Dictionary Attributes");
+ listSelectAttribute.setImmediate(false);
+ listSelectAttribute.setWidth("100.0%");
+ listSelectAttribute.setHeight("-1px");
+ listSelectAttribute.setInvalidAllowed(false);
+ listSelectAttribute.setRequired(true);
+ mainLayout.addComponent(listSelectAttribute);
+ mainLayout.setExpandRatio(listSelectAttribute, 1.0f);
+
+ return mainLayout;
+ }
+
+ @AutoGenerated
+ private HorizontalLayout buildHorizontalLayout_2() {
+ // common part: create layout
+ horizontalLayout_2 = new HorizontalLayout();
+ horizontalLayout_2.setImmediate(false);
+ horizontalLayout_2.setWidth("-1px");
+ horizontalLayout_2.setHeight("-1px");
+ horizontalLayout_2.setMargin(false);
+ horizontalLayout_2.setSpacing(true);
+
+ // comboBoxCategoryFilter
+ comboBoxCategoryFilter = new ComboBox();
+ comboBoxCategoryFilter.setCaption("Filter Category");
+ comboBoxCategoryFilter.setImmediate(false);
+ comboBoxCategoryFilter.setWidth("-1px");
+ comboBoxCategoryFilter.setHeight("-1px");
+ horizontalLayout_2.addComponent(comboBoxCategoryFilter);
+ horizontalLayout_2.setExpandRatio(comboBoxCategoryFilter, 1.0f);
+
+ // buttonNewAttribute
+ buttonNewAttribute = new Button();
+ buttonNewAttribute.setCaption("New Attribute");
+ buttonNewAttribute.setImmediate(true);
+ buttonNewAttribute
+ .setDescription("Click to create a new attribute in the dictionary.");
+ buttonNewAttribute.setWidth("-1px");
+ buttonNewAttribute.setHeight("-1px");
+ horizontalLayout_2.addComponent(buttonNewAttribute);
+ horizontalLayout_2.setComponentAlignment(buttonNewAttribute,
+ new Alignment(10));
+
+ return horizontalLayout_2;
+ }
+
+}