View Javadoc
1   /**
2    * Copyright 2014 Internet2
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package edu.internet2.middleware.grouper.scim;
17  
18  import edu.internet2.middleware.grouper.GroupFinder;
19  import edu.internet2.middleware.grouper.GrouperSession;
20  import edu.internet2.middleware.grouper.changeLog.ChangeLogConsumerBase;
21  import edu.internet2.middleware.grouper.changeLog.ChangeLogEntry;
22  import edu.internet2.middleware.grouper.changeLog.ChangeLogLabels;
23  import edu.internet2.middleware.grouper.changeLog.ChangeLogProcessorMetadata;
24  import edu.internet2.middleware.grouper.changeLog.ChangeLogType;
25  import edu.internet2.middleware.grouper.util.GrouperUtil;
26  import java.util.List;
27  import org.apache.commons.lang.builder.ToStringBuilder;
28  import org.apache.commons.lang.builder.ToStringStyle;
29  import org.apache.commons.logging.Log;
30  
31  /**
32   *
33   * @author davel
34   */
35  public class ScimChangeLogConsumer extends ChangeLogConsumerBase {
36  
37  	protected static final Log log = GrouperUtil.getLog(ScimChangeLogConsumer.class);
38  
39  	private ScimEmitter scim;
40  	private GrouperSession gs;
41  	
42  	/**
43  	 * The change log consumer name from the processor metadata.
44  	 */
45  	private String name;
46  
47  	private void processGroupAdd(ScimChangeLogConsumer consumer, ChangeLogEntry changeLogEntry) {
48  		scim.createGroup(GroupFinder.findByName(gs, changeLogEntry.retrieveValueForLabel(ChangeLogLabels.GROUP_ADD.name), true));
49  	}
50  
51  	private void processGroupDelete(ScimChangeLogConsumer consumer, ChangeLogEntry changeLogEntry) {
52  		scim.deleteGroup(GroupFinder.findByName(gs, changeLogEntry.retrieveValueForLabel(ChangeLogLabels.GROUP_DELETE.name), true));
53  	}
54  
55  	private void processGroupUpdate(ScimChangeLogConsumer consumer, ChangeLogEntry changeLogEntry) {
56  		scim.updateGroup(GroupFinder.findByName(gs,changeLogEntry.retrieveValueForLabel(ChangeLogLabels.GROUP_FIELD_UPDATE.name), true));
57  	}
58  
59  	private void processMembershipAdd(ScimChangeLogConsumer consumer, ChangeLogEntry changeLogEntry) {
60  		scim.updateGroup(GroupFinder.findByName(gs,changeLogEntry.retrieveValueForLabel(ChangeLogLabels.MEMBERSHIP_ADD.groupName), true));
61  	}
62  
63  	private void processMembershipDelete(ScimChangeLogConsumer consumer, ChangeLogEntry changeLogEntry) {
64  		scim.updateGroup(GroupFinder.findByName(gs,changeLogEntry.retrieveValueForLabel(ChangeLogLabels.MEMBERSHIP_DELETE.groupName), true));
65  	}
66  
67  	/**
68  	 * Maps change log entry category and action (change log type) to methods.
69  	 */
70  	enum ScimEventType {
71  
72  		/**
73  		 * Process the add group change log entry type.
74  		 */
75  		group__addGroup {
76  					public void process(ScimChangeLogConsumer consumer, ChangeLogEntry changeLogEntry) throws Exception {
77  						consumer.processGroupAdd(consumer, changeLogEntry);
78  					}
79  				},
80  		/**
81  		 * Process the delete group change log entry type.
82  		 */
83  		group__deleteGroup {
84  					public void process(ScimChangeLogConsumer consumer, ChangeLogEntry changeLogEntry) throws Exception {
85  						consumer.processGroupDelete(consumer, changeLogEntry);
86  					}
87  				},
88  		/**
89  		 * Process the update group change log entry type.
90  		 */
91  		group__updateGroup {
92  					public void process(ScimChangeLogConsumer consumer, ChangeLogEntry changeLogEntry) throws Exception {
93  						consumer.processGroupUpdate(consumer, changeLogEntry);
94  					}
95  				},
96  		/**
97  		 * Process the add membership change log entry type.
98  		 */
99  		membership__addMembership {
100 					public void process(ScimChangeLogConsumer consumer, ChangeLogEntry changeLogEntry) throws Exception {
101 						consumer.processMembershipAdd(consumer, changeLogEntry);
102 					}
103 				},
104 		/**
105 		 * Process the delete membership change log entry type.
106 		 */
107 		membership__deleteMembership {
108 					public void process(ScimChangeLogConsumer consumer, ChangeLogEntry changeLogEntry) throws Exception {
109 						consumer.processMembershipDelete(consumer, changeLogEntry);
110 					}
111 				},
112 		;
113 		 /**
114          * Process the change log entry.
115          * 
116          * @param consumer the scim change log consumer
117          * @param changeLogEntry the change log entry
118          * @throws Exception if any error occurs
119          */
120         public abstract void process(ScimChangeLogConsumer consumer, ChangeLogEntry changeLogEntry) throws Exception;
121 
122 	};
123 
124 	public ScimChangeLogConsumer() {
125 		scim = new ScimEmitter();
126 		gs = new GrouperSession();
127 	}
128 
129 	@Override
130 	public long processChangeLogEntries(List<ChangeLogEntry> changeLogEntryList, ChangeLogProcessorMetadata changeLogProcessorMetadata) {
131 		long currentId = -1;
132 
133 		// initialize this consumer's name from the change log metadata
134 		if (name == null) {
135 			name = changeLogProcessorMetadata.getConsumerName();
136 			log.trace("ScimChangeLog Consumer '" + name + "' - Setting name.");
137 		}
138 
139 		for (ChangeLogEntry entry : changeLogEntryList) {
140 			currentId = entry.getSequenceNumber();
141 			// find the method to run via the enum
142 			String enumKey = entry.getChangeLogType().getChangeLogCategory() + "__"
143 					+ entry.getChangeLogType().getActionName();
144 
145 			ScimEventType scimEventType = ScimEventType.valueOf(enumKey);
146 
147 			if (scimEventType == null) {
148 				log.debug("ScimChangeLog Consumer '" + name + "' - Change log entry '" + entry + "' Unsupported category and action.");
149 			} else {
150 				// process the change log event
151 				log.info("ScimChangeLog Consumer '" + name + "' - Change log entry '" + toStringDeep(entry) + "'");
152 				try{
153 					scimEventType.process(this, entry);
154 				}catch(Exception e){
155 					log.warn("ScimChangeLog Consumer '"+ name +"' exception "+e.getMessage(),e);
156 				}
157 				log.info("ScimChangeLog Consumer '" + name + "' - Change log entry '" + entry + "'");
158 			}
159 
160 		}
161 		return currentId;
162 	}
163 
164 	/**
165 	 * Return a string representing an {ChangeLogEntry}.
166 	 *
167 	 * Returns all labels (attributes).
168 	 *
169 	 * Uses {
170 	 *
171 	 * @ToStringBuilder}.
172 	 *
173 	 * @param changeLogEntry the change log entry
174 	 * @return the string representing the entire change log entry
175 	 */
176 	public static String toStringDeep(ChangeLogEntry changeLogEntry) {
177 		ToStringBuilder toStringBuilder = new ToStringBuilder(changeLogEntry, ToStringStyle.SHORT_PREFIX_STYLE);
178 		toStringBuilder.append("timestamp", changeLogEntry.getCreatedOn());
179 		toStringBuilder.append("sequence", changeLogEntry.getSequenceNumber());
180 		toStringBuilder.append("category", changeLogEntry.getChangeLogType().getChangeLogCategory());
181 		toStringBuilder.append("actionname", changeLogEntry.getChangeLogType().getActionName());
182 		toStringBuilder.append("contextId", changeLogEntry.getContextId());
183 
184 		ChangeLogType changeLogType = changeLogEntry.getChangeLogType();
185 
186 		for (String label : changeLogType.labels()) {
187 			toStringBuilder.append(label, changeLogEntry.retrieveValueForLabel(label));
188 		}
189 
190 		return toStringBuilder.toString();
191 	}
192 
193 }