View Javadoc

1   /* This file is part of COPAL (COntext Provisioning for All).
2    *
3    * COPAL is a part of SM4All (Smart hoMes for All) project.
4    *
5    * COPAL is free software: you can redistribute it and/or modify
6    * it under the terms of the GNU Lesser General Public License as published by
7    * the Free Software Foundation, either version 3 of the License, or
8    * (at your option) any later version.
9    *
10   * COPAL is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU Lesser General Public License for more details.
14   *
15   * You should have received a copy of the GNU Lesser General Public License
16   * along with COPAL. If not, see <http://www.gnu.org/licenses/>.
17   */
18  package at.ac.tuwien.infosys.sm4all.copal.core.internal;
19  
20  import java.text.MessageFormat;
21  import java.util.Collections;
22  import java.util.HashMap;
23  import java.util.Map;
24  import java.util.concurrent.atomic.AtomicBoolean;
25  import java.util.concurrent.locks.ReadWriteLock;
26  import java.util.concurrent.locks.ReentrantReadWriteLock;
27  import org.apache.log4j.Level;
28  import org.apache.log4j.Logger;
29  import at.ac.tuwien.infosys.sm4all.copal.api.event.ContextEvent;
30  import at.ac.tuwien.infosys.sm4all.copal.api.listener.ContextListener;
31  import at.ac.tuwien.infosys.sm4all.copal.api.osgi.GenericActivator;
32  import at.ac.tuwien.infosys.sm4all.copal.api.security.Authorization;
33  import at.ac.tuwien.infosys.sm4all.copal.api.security.AuthorizationMethod;
34  import at.ac.tuwien.infosys.sm4all.copal.api.security.HasClassName;
35  import at.ac.tuwien.infosys.sm4all.copal.api.security.HasToken;
36  import at.ac.tuwien.infosys.sm4all.copal.api.security.InPackage;
37  import at.ac.tuwien.infosys.sm4all.copal.api.service.ContextSecurityManager;
38  import at.ac.tuwien.infosys.sm4all.copal.api.util.Attribute;
39  import static at.ac.tuwien.infosys.sm4all.copal.api.security.AuthorizationResult.Deny;
40  
41  /**
42   * Implementation of the {@link ContextSecurityManager} interface.
43   * 
44   * @author sanjin
45   */
46  public class ContextSecurityManagerImpl extends GenericActivator implements
47          ContextSecurityManager {
48  
49      private static final Logger LOGGER = Logger.getLogger(ContextSecurityManager.class);
50  
51      private final ReadWriteLock lock = new ReentrantReadWriteLock();
52      private final Map<String, AuthorizationMethod> authorizations = new HashMap<String, AuthorizationMethod>();
53      private final AtomicBoolean started = new AtomicBoolean(false);
54  
55      {
56          add(new InPackage());
57          add(new HasClassName());
58          add(new HasToken());
59      }
60  
61      /**
62       * Returns if this {@link ContextSecurityManager} has been started by an
63       * OSGi framework.
64       * 
65       * @return if this {@link ContextSecurityManager} has been started by an
66       *         OSGi framework.
67       */
68      public boolean isStarted() {
69          return this.started.get();
70      }
71  
72      @Override
73      protected void start() {
74          if (!this.started.getAndSet(true)) {
75              if (register(ContextSecurityManager.class, this)) {
76                  if (LOGGER.isInfoEnabled()) {
77                      LOGGER.info("Successfully registered ContextSecurityManager service.");
78                  }
79              } else {
80                  if (LOGGER.isEnabledFor(Level.ERROR)) {
81                      LOGGER.error("Failed to register ContextSecurityManager service!");
82                  }
83              }
84          }
85      }
86  
87      @Override
88      protected void stop() {
89          if (this.started.getAndSet(false)) {
90              if (unregister(ContextSecurityManager.class)) {
91                  if (LOGGER.isInfoEnabled()) {
92                      LOGGER.info("Successfully unregistered ContextSecurityManager service.");
93                  }
94              }
95          }
96      }
97  
98      @Override
99      public void add(final AuthorizationMethod method) {
100         final String name = method.getName();
101 
102         this.lock.writeLock().lock();
103         try {
104             if (!this.authorizations.containsKey(name)) {
105                 this.authorizations.put(name, method);
106             }
107         } finally {
108             this.lock.writeLock().unlock();
109         }
110     }
111 
112     @Override
113     public boolean authorized(final ContextListener listener,
114             final ContextEvent event) {
115         boolean result = true;
116 
117         if (event.hasAuthorizations()) {
118             this.lock.readLock().lock();
119             try {
120                 for (final Authorization authorization : event.getAuthorizations()) {
121                     final String method = authorization.getMethod();
122                     if ((!this.authorizations.containsKey(method))
123                             || (this.authorizations.get(method).authorize(
124                                     listener, event,
125                                     toMap(authorization.getAttributes())) == Deny)) {
126                         result = false;
127                         if (LOGGER.isInfoEnabled()) {
128                             LOGGER.info(MessageFormat.format(
129                                     "Authorization ''{0}'' for event ''{1}'' on listener ''{2}'' failed.",
130                                     method, event.getType().getName(),
131                                     listener.getName()));
132                         }
133                         break;
134                     }
135                 }
136             } finally {
137                 this.lock.readLock().unlock();
138             }
139         }
140 
141         return result;
142     }
143 
144     private static Map<String, String> toMap(final Attribute... attributes) {
145         final Map<String, String> result = new HashMap<String, String>();
146 
147         for (final Attribute attribute : attributes) {
148             result.put(attribute.getName(), attribute.getValue());
149         }
150 
151         return Collections.unmodifiableMap(result);
152     }
153 }