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 */
016
017package org.forgerock.opendj.config;
018
019import java.util.EnumSet;
020import java.util.regex.Pattern;
021
022import org.forgerock.util.Reject;
023
024/**
025 * ACI property definition.
026 */
027public final class ACIPropertyDefinition extends PropertyDefinition<String> {
028
029    /**
030     * An interface for incrementally constructing ACI property definitions.
031     */
032    public static final class Builder extends AbstractBuilder<String, ACIPropertyDefinition> {
033
034        /** Private constructor. */
035        private Builder(AbstractManagedObjectDefinition<?, ?> d, String propertyName) {
036            super(d, propertyName);
037        }
038
039        /** {@inheritDoc} */
040        @Override
041        protected ACIPropertyDefinition buildInstance(AbstractManagedObjectDefinition<?, ?> d,
042                String propertyName, EnumSet<PropertyOption> options,
043                AdministratorAction adminAction, DefaultBehaviorProvider<String> defaultBehavior) {
044            return new ACIPropertyDefinition(d, propertyName, options, adminAction, defaultBehavior);
045        }
046    }
047
048    /**
049     * Create a ACI property definition builder.
050     *
051     * @param d
052     *            The managed object definition associated with this property
053     *            definition.
054     * @param propertyName
055     *            The property name.
056     * @return Returns the new ACI property definition builder.
057     */
058    public static Builder createBuilder(AbstractManagedObjectDefinition<?, ?> d, String propertyName) {
059        return new Builder(d, propertyName);
060    }
061
062    /**
063     * Pattern used for performing basic ACI syntax validation. Taken from the
064     * Aci class in the server.
065     */
066    private static final Pattern ACI_REGEX =
067            Pattern.compile("^\\s*(\\(\\s*(\\w+)\\s*(!?=)\\s*\"([^\"]+)\"\\s*\\)\\s*)*\\s*\\"
068                    + "(\\s*(?i)version(?-i)\\s*(\\d\\.\\d)\\s*;\\s*(?i)acl(?-i)\\s*\"([^\"]*)"
069                    + "\"\\s*;\\s*\\s*(\\w+)\\s*\\(([^()]+)\\)\\s*(.+?\"[)]*)\\s*;\\s*\\s*\\)\\s*$");
070
071    /** Private constructor. */
072    private ACIPropertyDefinition(AbstractManagedObjectDefinition<?, ?> d, String propertyName,
073            EnumSet<PropertyOption> options, AdministratorAction adminAction,
074            DefaultBehaviorProvider<String> defaultBehavior) {
075        super(d, String.class, propertyName, options, adminAction, defaultBehavior);
076    }
077
078    /** {@inheritDoc} */
079    @Override
080    public void validateValue(String value) {
081        Reject.ifNull(value);
082
083        // No additional validation required.
084    }
085
086    /** {@inheritDoc} */
087    @Override
088    public String decodeValue(String value) {
089        Reject.ifNull(value);
090
091        /*
092         * We don't have access to the ACI class from the server so do
093         * best-effort using regular expressions. TODO: is it worth improving on
094         * this? We could use reflection to get the appropriate parser which
095         * would allow us to use full validation in OpenDJ whilst remaining
096         * decoupled in other applications.
097         */
098        if (ACI_REGEX.matcher(value).matches()) {
099            return value;
100        }
101        throw PropertyException.illegalPropertyValueException(this, value);
102    }
103
104    /** {@inheritDoc} */
105    @Override
106    public <R, P> R accept(PropertyDefinitionVisitor<R, P> v, P p) {
107        return v.visitACI(this, p);
108    }
109
110    /** {@inheritDoc} */
111    @Override
112    public <R, P> R accept(PropertyValueVisitor<R, P> v, String value, P p) {
113        return v.visitACI(this, value, p);
114    }
115
116    /** {@inheritDoc} */
117    @Override
118    public int compare(String o1, String o2) {
119        return o1.compareTo(o2);
120    }
121}