001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2008 Sun Microsystems, Inc.
015 * Portions Copyright 2016 ForgeRock AS.
016 */
017package org.forgerock.opendj.config;
018
019import java.util.EnumSet;
020import java.util.regex.Pattern;
021
022import org.forgerock.util.Reject;
023
024/** ACI property definition. */
025public final class ACIPropertyDefinition extends PropertyDefinition<String> {
026
027    /** An interface for incrementally constructing ACI property definitions. */
028    public static final class Builder extends AbstractBuilder<String, ACIPropertyDefinition> {
029
030        /** Private constructor. */
031        private Builder(AbstractManagedObjectDefinition<?, ?> d, String propertyName) {
032            super(d, propertyName);
033        }
034
035        @Override
036        protected ACIPropertyDefinition buildInstance(AbstractManagedObjectDefinition<?, ?> d,
037                String propertyName, EnumSet<PropertyOption> options,
038                AdministratorAction adminAction, DefaultBehaviorProvider<String> defaultBehavior) {
039            return new ACIPropertyDefinition(d, propertyName, options, adminAction, defaultBehavior);
040        }
041    }
042
043    /**
044     * Create a ACI property definition builder.
045     *
046     * @param d
047     *            The managed object definition associated with this property
048     *            definition.
049     * @param propertyName
050     *            The property name.
051     * @return Returns the new ACI property definition builder.
052     */
053    public static Builder createBuilder(AbstractManagedObjectDefinition<?, ?> d, String propertyName) {
054        return new Builder(d, propertyName);
055    }
056
057    /**
058     * Pattern used for performing basic ACI syntax validation. Taken from the
059     * Aci class in the server.
060     */
061    private static final Pattern ACI_REGEX =
062            Pattern.compile("^\\s*(\\(\\s*(\\w+)\\s*(!?=)\\s*\"([^\"]+)\"\\s*\\)\\s*)*\\s*\\"
063                    + "(\\s*(?i)version(?-i)\\s*(\\d\\.\\d)\\s*;\\s*(?i)acl(?-i)\\s*\"([^\"]*)"
064                    + "\"\\s*;\\s*\\s*(\\w+)\\s*\\(([^()]+)\\)\\s*(.+?\"[)]*)\\s*;\\s*\\s*\\)\\s*$");
065
066    /** Private constructor. */
067    private ACIPropertyDefinition(AbstractManagedObjectDefinition<?, ?> d, String propertyName,
068            EnumSet<PropertyOption> options, AdministratorAction adminAction,
069            DefaultBehaviorProvider<String> defaultBehavior) {
070        super(d, String.class, propertyName, options, adminAction, defaultBehavior);
071    }
072
073    @Override
074    public void validateValue(String value) {
075        Reject.ifNull(value);
076
077        // No additional validation required.
078    }
079
080    @Override
081    public String decodeValue(String value) {
082        Reject.ifNull(value);
083
084        /*
085         * We don't have access to the ACI class from the server so do
086         * best-effort using regular expressions. TODO: is it worth improving on
087         * this? We could use reflection to get the appropriate parser which
088         * would allow us to use full validation in OpenDJ whilst remaining
089         * decoupled in other applications.
090         */
091        if (ACI_REGEX.matcher(value).matches()) {
092            return value;
093        }
094        throw PropertyException.illegalPropertyValueException(this, value);
095    }
096
097    @Override
098    public <R, P> R accept(PropertyDefinitionVisitor<R, P> v, P p) {
099        return v.visitACI(this, p);
100    }
101
102    @Override
103    public <R, P> R accept(PropertyValueVisitor<R, P> v, String value, P p) {
104        return v.visitACI(this, value, p);
105    }
106
107    @Override
108    public int compare(String o1, String o2) {
109        return o1.compareTo(o2);
110    }
111}