001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/portal/standard/security/control/StoreGroupsListener.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005       Department of Geography, University of Bonn
006     and
007       lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035    ----------------------------------------------------------------------------*/
036    package org.deegree.portal.standard.security.control;
037    
038    import java.util.ArrayList;
039    
040    import org.deegree.enterprise.control.AbstractListener;
041    import org.deegree.enterprise.control.FormEvent;
042    import org.deegree.enterprise.control.RPCException;
043    import org.deegree.enterprise.control.RPCMember;
044    import org.deegree.enterprise.control.RPCMethodCall;
045    import org.deegree.enterprise.control.RPCParameter;
046    import org.deegree.enterprise.control.RPCStruct;
047    import org.deegree.enterprise.control.RPCWebEvent;
048    import org.deegree.framework.log.ILogger;
049    import org.deegree.framework.log.LoggerFactory;
050    import org.deegree.i18n.Messages;
051    import org.deegree.security.GeneralSecurityException;
052    import org.deegree.security.UnauthorizedException;
053    import org.deegree.security.drm.SecurityAccessManager;
054    import org.deegree.security.drm.SecurityTransaction;
055    import org.deegree.security.drm.model.Group;
056    import org.deegree.security.drm.model.User;
057    
058    /**
059     * This <code>Listener</code> reacts on RPC-StoreGroups events, extracts the contained user/group
060     * relations and updates the <code>SecurityManager</code> accordingly.
061     *
062     * Access constraints:
063     * <ul>
064     * <li>only users that have the 'SEC_ADMIN'-role are allowed</li>
065     * </ul>
066     *
067     * @author <a href="mschneider@lat-lon.de">Markus Schneider </a>
068     * @author last edited by: $Author: mschneider $
069     *
070     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
071     */
072    public class StoreGroupsListener extends AbstractListener {
073    
074        private static final ILogger LOG = LoggerFactory.getLogger( StoreGroupsListener.class );
075    
076        @Override
077        public void actionPerformed( FormEvent event ) {
078    
079            SecurityAccessManager manager = null;
080            SecurityTransaction transaction = null;
081    
082            try {
083                RPCWebEvent ev = (RPCWebEvent) event;
084                RPCMethodCall rpcCall = ev.getRPCMethodCall();
085                RPCParameter[] params = rpcCall.getParameters();
086    
087                // values are Integers (groupIds) or Strings (groupNames)
088                Object[] groups = new Object[params.length];
089                // values of the ArrayLists are Integers (groupIds)
090                ArrayList[] userMembersIds = new ArrayList[params.length];
091                // values of the ArrayLists are Integers (userIds)
092                ArrayList[] groupMembersIds = new ArrayList[params.length];
093    
094                for ( int i = 0; i < params.length; i++ ) {
095                    ArrayList<Integer> userMemberList = new ArrayList<Integer>( 200 );
096                    ArrayList<Integer> groupMemberList = new ArrayList<Integer>( 200 );
097                    userMembersIds[i] = userMemberList;
098                    groupMembersIds[i] = groupMemberList;
099                    if ( !( params[0].getValue() instanceof RPCStruct ) ) {
100                        throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_MISSING_STRUCT" ) );
101                    }
102                    RPCStruct struct = (RPCStruct) params[i].getValue();
103    
104                    // extract group-id / group-name
105                    extractGroupInfo( groups, i, struct );
106    
107                    // extract user members
108                    extractUsers( userMemberList, struct );
109    
110                    // extract group members
111                    extractGroups( groupMemberList, struct );
112    
113                }
114    
115                // get Transaction and perform access check
116                manager = SecurityAccessManager.getInstance();
117                transaction = SecurityHelper.acquireTransaction( this );
118                SecurityHelper.checkForAdminRole( transaction );
119    
120                // remove deleted groups
121                removeDeletedGroups( transaction, groups );
122    
123                // save all submitted groups (and their members)
124                saveSubmittedGroups( transaction, groups, userMembersIds, groupMembersIds );
125                Group[] cycle = transaction.findGroupCycle();
126                manager.commitTransaction( transaction );
127                transaction = null;
128    
129                StringBuffer sb = new StringBuffer( 200 );
130                sb.append( Messages.getMessage( "IGEO_STD_SEC_SUCCESS_STOREGROUPS" ) );
131    
132                if ( cycle != null ) {
133                    sb.append( "<br><p><h4>" );
134                    sb.append( Messages.getMessage( "IGEO_STD_SEC_SUCCESS_STOREGROUPS_ADDTXT" ) );
135                    sb.append( "<br><code>" );
136                    for ( int i = 0; i < cycle.length; i++ ) {
137                        sb.append( cycle[i].getName() );
138                        if ( i != cycle.length - 1 ) {
139                            sb.append( " -> " );
140                        }
141                    }
142                    sb.append( "</code></h4></p>" );
143                }
144    
145                getRequest().setAttribute( "MESSAGE", sb.toString() );
146            } catch ( RPCException e ) {
147                getRequest().setAttribute( "SOURCE", this.getClass().getName() );
148                getRequest().setAttribute( "MESSAGE",
149                                           Messages.getMessage( "IGEO_STD_SEC_ERROR_CHANGE_REQ",
150                                                                e.getMessage() ) );
151                setNextPage( "error.jsp" );
152                LOG.logDebug( e.getMessage(), e );
153    
154            } catch ( GeneralSecurityException e ) {
155                getRequest().setAttribute( "SOURCE", this.getClass().getName() );
156                getRequest().setAttribute( "MESSAGE",
157                                           Messages.getMessage( "IGEO_STD_SEC_ERROR_CHANGE",
158                                                                e.getMessage() ) );
159                setNextPage( "error.jsp" );
160                LOG.logDebug( e.getMessage(), e );
161            } finally {
162                if ( manager != null && transaction != null ) {
163                    try {
164                        manager.abortTransaction( transaction );
165                    } catch ( GeneralSecurityException ex ) {
166                        LOG.logDebug( ex.getMessage(), ex );
167                    }
168                }
169            }
170        }
171    
172        private void saveSubmittedGroups( SecurityTransaction transaction, Object[] groups,
173                                         ArrayList[] userMembersIds, ArrayList[] groupMembersIds )
174                                throws GeneralSecurityException, UnauthorizedException {
175            for ( int i = 0; i < groups.length; i++ ) {
176                Group group;
177                if ( groups[i] instanceof Integer ) {
178                    group = transaction.getGroupById( ( (Integer) groups[i] ).intValue() );
179                } else {
180                    group = transaction.registerGroup( (String) groups[i], (String) groups[i] );
181                }
182    
183                // set user members
184                User[] userMembers = new User[userMembersIds[i].size()];
185                for ( int j = 0; j < userMembersIds[i].size(); j++ ) {
186                    int userId = ( (Integer) userMembersIds[i].get( j ) ).intValue();
187                    userMembers[j] = transaction.getUserById( userId );
188                }
189                transaction.setUsersInGroup( group, userMembers );
190    
191                // set group members
192                Group[] groupMembers = new Group[groupMembersIds[i].size()];
193                for ( int j = 0; j < groupMembersIds[i].size(); j++ ) {
194                    int groupId = ( (Integer) groupMembersIds[i].get( j ) ).intValue();
195                    groupMembers[j] = transaction.getGroupById( groupId );
196                }
197                transaction.setGroupsInGroup( group, groupMembers );
198            }
199        }
200    
201        private void removeDeletedGroups( SecurityTransaction transaction, Object[] groups )
202                                throws GeneralSecurityException, UnauthorizedException {
203            Group[] oldGroups = transaction.getAllGroups();
204            for ( int i = 0; i < oldGroups.length; i++ ) {
205                if ( oldGroups[i].getID() != Group.ID_SEC_ADMIN ) {
206                    boolean deleted = true;
207                    for ( int j = 0; j < groups.length; j++ ) {
208                        if ( groups[j] instanceof Integer ) {
209                            if ( ( (Integer) groups[j] ).intValue() == oldGroups[i].getID() ) {
210                                deleted = false;
211                            }
212                        }
213                    }
214                    if ( deleted ) {
215                        transaction.deregisterGroup( oldGroups[i] );
216                    }
217                }
218            }
219        }
220    
221        private void extractGroups( ArrayList<Integer> groupMemberList, RPCStruct struct )
222                                throws RPCException {
223            RPCMember groupMembers = struct.getMember( "groupMembers" );
224            if ( !( groupMembers.getValue() instanceof RPCParameter[] ) ) {
225                throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_MISSING_ARRAY",
226                                                             "groupMembers" ) );
227            }
228            RPCParameter[] memberArray = (RPCParameter[]) groupMembers.getValue();
229            for ( int j = 0; j < memberArray.length; j++ ) {
230                if ( !( memberArray[j].getValue() instanceof String ) ) {
231                    throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_MISSING_ARRAY_VALUES",
232                                                                 "groupMembers", "String" ) );
233                }
234                try {
235                    groupMemberList.add( new Integer( (String) memberArray[j].getValue() ) );
236                } catch ( NumberFormatException e ) {
237                    throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_INVALID_ARRAY_VALUES",
238                                                                 "groupMembers", "Integer" ) );
239                }
240            }
241        }
242    
243        private void extractUsers( ArrayList<Integer> userMemberList, RPCStruct struct )
244                                throws RPCException {
245            RPCMember userMembers = struct.getMember( "userMembers" );
246            if ( !( userMembers.getValue() instanceof RPCParameter[] ) ) {
247                throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_MISSING_ARRAY",
248                                                             "userMembers" ) );
249            }
250            RPCParameter[] memberArray = (RPCParameter[]) userMembers.getValue();
251            for ( int j = 0; j < memberArray.length; j++ ) {
252                if ( !( memberArray[j].getValue() instanceof String ) ) {
253                    throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_MISSING_ARRAY_VALUES",
254                                                                 "userMembers", "String" ) );
255                }
256                try {
257                    userMemberList.add( new Integer( (String) memberArray[j].getValue() ) );
258                } catch ( NumberFormatException e ) {
259                    throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_INVALID_ARRAY_VALUES",
260                                                                 "userMembers", "Integer" ) );
261                }
262            }
263        }
264    
265        private void extractGroupInfo( Object[] groups, int index, RPCStruct struct )
266                                throws RPCException {
267    
268            RPCMember groupId = struct.getMember( "groupId" );
269            RPCMember groupName = struct.getMember( "groupName" );
270            if ( ( groupId == null && groupName == null ) || ( groupId != null && groupName != null ) ) {
271                throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_MISSING_GROUPS" ) );
272            }
273            if ( groupId != null ) {
274                if ( !( groupId.getValue() instanceof String ) ) {
275                    throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_MISSING_GROUP_PARAM",
276                                                                 "groupId", "String" ) );
277                }
278                try {
279                    groups[index] = ( new Integer( (String) groupId.getValue() ) );
280                } catch ( NumberFormatException e ) {
281                    throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_MISSING_GROUP_PARAM",
282                                                                 "groupId", "Integer" ) );
283                }
284            } else {
285                if ( !( groupName.getValue() instanceof String ) ) {
286                    throw new RPCException( Messages.getMessage( "IGEO_STD_SEC_MISSING_GROUP_PARAM",
287                                                                 "groupName", "String" ) );
288                }
289    
290                groups[index] = groupName.getValue();
291            }
292        }
293    }