001/*
002 * (C) Copyright 2006-2008 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     bstefanescu
018 *
019 * $Id$
020 */
021
022package org.nuxeo.ecm.webengine.security;
023
024import java.text.ParseException;
025import java.util.HashMap;
026import java.util.Map;
027
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030import org.nuxeo.common.xmap.annotation.XContent;
031import org.nuxeo.common.xmap.annotation.XNode;
032import org.nuxeo.common.xmap.annotation.XObject;
033import org.nuxeo.ecm.webengine.security.guards.And;
034import org.nuxeo.ecm.webengine.security.guards.FacetGuard;
035import org.nuxeo.ecm.webengine.security.guards.GroupGuard;
036import org.nuxeo.ecm.webengine.security.guards.IsAdministratorGuard;
037import org.nuxeo.ecm.webengine.security.guards.PermissionGuard;
038import org.nuxeo.ecm.webengine.security.guards.SchemaGuard;
039import org.nuxeo.ecm.webengine.security.guards.ScriptGuard;
040import org.nuxeo.ecm.webengine.security.guards.TypeGuard;
041import org.nuxeo.ecm.webengine.security.guards.UserGuard;
042import org.w3c.dom.DocumentFragment;
043import org.w3c.dom.NamedNodeMap;
044import org.w3c.dom.Node;
045
046/**
047 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
048 */
049@XObject("permission")
050public class GuardDescriptor {
051
052    private static final Log log = LogFactory.getLog(GuardDescriptor.class);
053
054    @XNode("@id")
055    protected String id;
056
057    @XNode("@expression")
058    protected String expression;
059
060    protected Map<String, Guard> guards;
061
062    public GuardDescriptor() {
063        this(null);
064    }
065
066    public GuardDescriptor(String name) {
067        id = name;
068        guards = new HashMap<String, Guard>();
069    }
070
071    public Map<String, Guard> getGuards() {
072        return guards;
073    }
074
075    /**
076     * @param expression the expression to set.
077     */
078    public void setExpression(String expression) {
079        this.expression = expression;
080    }
081
082    /**
083     * @return the expression.
084     */
085    public String getExpression() {
086        return expression;
087    }
088
089    @XContent
090    protected void setGuards(DocumentFragment content) {
091        Node node = content.getFirstChild();
092        while (node != null) {
093            if (node.getNodeType() == Node.ELEMENT_NODE) {
094                String name = node.getNodeName();
095                if ("guard".equals(name)) {
096                    NamedNodeMap map = node.getAttributes();
097                    Node aId = map.getNamedItem("id");
098                    Node aType = map.getNamedItem("type");
099                    if (aId == null) {
100                        throw new IllegalArgumentException("id is required");
101                    }
102                    String id = aId.getNodeValue();
103                    if (aType == null) {
104                        throw new IllegalArgumentException("type is required");
105                    } else {
106                        // String value = node.getTextContent().trim();
107                        // guards.put(id, new ScriptGuard(value));
108                        // TODO: compound guard
109                    }
110                    String type = aType.getNodeValue();
111                    if ("permission".equals(type)) {
112                        String value = node.getTextContent().trim();
113                        guards.put(id, new PermissionGuard(value));
114                    } else if ("isAdministrator".equals(type)) {
115                        String value = node.getTextContent().trim();
116                        guards.put(id, new IsAdministratorGuard(value));
117                    } else if ("facet".equals(type)) {
118                        String value = node.getTextContent().trim();
119                        guards.put(id, new FacetGuard(value));
120                    } else if ("type".equals(type)) {
121                        String value = node.getTextContent().trim();
122                        guards.put(id, new TypeGuard(value));
123                    } else if ("schema".equals(type)) {
124                        String value = node.getTextContent().trim();
125                        guards.put(id, new SchemaGuard(value));
126                    } else if ("user".equals(type)) {
127                        String value = node.getTextContent().trim();
128                        guards.put(id, new UserGuard(value));
129                    } else if ("group".equals(type)) {
130                        String value = node.getTextContent().trim();
131                        guards.put(id, new GroupGuard(value));
132                    } else if ("script".equals(type)) {
133                        Node engineNode = map.getNamedItem("engine");
134                        if (engineNode == null) {
135                            throw new IllegalArgumentException("Must specify an engine attribute on script guards");
136                        }
137                        String value = node.getTextContent().trim();
138                        guards.put(id, new ScriptGuard(engineNode.getNodeValue(), value));
139                    } else if ("expression".equals(type)) {
140                        String value = node.getTextContent().trim();
141                        try {
142                            guards.put(id, PermissionService.getInstance().parse(value, guards));
143                        } catch (ParseException e) {
144                            log.error(e, e);
145                        }
146                    } else { // the type should be a guard factory
147                        String value = node.getTextContent().trim();
148                        try {
149                            Class<?> factory = Class.forName(type);
150                            Guard guard = ((GuardFactory) factory.newInstance()).newGuard(value);
151                            guards.put(id, guard);
152                        } catch (ReflectiveOperationException e) {
153                            log.error(e, e); // TODO should throw a DeployException
154                        }
155                    }
156                }
157            }
158            node = node.getNextSibling();
159        }
160    }
161
162    public Guard getGuard() throws ParseException {
163        if (expression == null || expression.length() == 0) {
164            return new And(guards.values());
165        }
166        return PermissionService.getInstance().parse(expression, guards);
167    }
168
169    public String getId() {
170        return id;
171    }
172
173    public Permission getPermission() throws ParseException {
174        return new DefaultPermission(id, getGuard());
175    }
176
177}