001 /*
002 * Copyright 2007-2008 The Kuali Foundation
003 *
004 * Licensed under the Educational Community 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.opensource.org/licenses/ecl2.php
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 package org.kuali.rice.kew.xml;
017
018 import java.io.IOException;
019 import java.io.InputStream;
020 import java.util.ArrayList;
021 import java.util.List;
022
023 import javax.xml.bind.JAXBContext;
024 import javax.xml.bind.Unmarshaller;
025 import javax.xml.bind.UnmarshallerHandler;
026 import javax.xml.bind.util.ValidationEventCollector;
027 import javax.xml.parsers.SAXParserFactory;
028 import javax.xml.validation.Schema;
029
030 import org.apache.commons.lang.StringUtils;
031 import org.apache.log4j.Logger;
032 import org.kuali.rice.core.xml.CoreNamespaceConstants;
033 import org.kuali.rice.core.xml.dto.DataXmlDto;
034 import org.kuali.rice.core.xml.schema.RiceSchemaValidationEventCollector;
035 import org.kuali.rice.core.xml.schema.RiceXmlSchemaFactory;
036 import org.xml.sax.Attributes;
037 import org.xml.sax.InputSource;
038 import org.xml.sax.SAXException;
039 import org.xml.sax.XMLFilter;
040 import org.xml.sax.helpers.XMLFilterImpl;
041
042
043 /**
044 * Parses groups from XML using JAXB.
045 *
046 * @see KimGroups
047 *
048 * @author Kuali Rice Team (rice.collab@kuali.org)
049 *
050 */
051 public class GroupXmlJAXBParser implements XmlConstants {
052 private static final Logger LOG = Logger.getLogger(GroupXmlJAXBParser.class);
053 private static final String DEFAULT_GROUP_DESCRIPTION = "";
054 private static final String DEFAULT_GROUP_SCHEMA_NAME = "Groups-1.0.3.xsd";
055
056 public DataXmlDto parse(InputStream in) throws IOException {
057 DataXmlDto groupsXmlDto = new DataXmlDto();
058 JAXBContext jaxbContext;
059 Unmarshaller unmarshaller;
060
061 try {
062 jaxbContext = JAXBContext.newInstance(DataXmlDto.class);
063 unmarshaller = jaxbContext.createUnmarshaller();
064 }catch (Exception ex) {
065 throw new RuntimeException("Error creating JAXB unmarshaller", ex);
066 }
067
068 if (in == null) {
069 LOG.warn("###############################");
070 LOG.warn("#");
071 LOG.warn("# XML Import input stream not found!");
072 LOG.warn("#");
073 LOG.warn("###############################");
074 } else {
075 try {
076
077 groupsXmlDto = unmarshal(unmarshaller, in);
078
079 } catch (Exception ex) {
080 LOG.error(ex.getMessage());
081 throw new RuntimeException("Error parsing XML input stream", ex);
082 }
083
084 }
085 return groupsXmlDto;
086 }
087
088 /**
089 *
090 * This method returns a list of xmlfilters. The order here matters. The fist element gets processed
091 * first. FIFO.
092 *
093 * @return
094 */
095 public List<XMLFilter> getXMLFilterList(){
096
097 List<XMLFilter> lRet = new ArrayList<XMLFilter>();
098
099 lRet.add(new DataNamespaceURIFilter());
100 lRet.add(new GroupNamespaceURITransformationFilterPOC());
101 lRet.add(new GroupNamespaceURIMemberTransformationFilterPOC());
102 lRet.add(new GroupNamespaceURIFilter());
103
104 return lRet;
105 }
106
107 /**
108 *
109 * This method takes in a list of xml filters and appends them together via
110 * parent child relationships. The end result is one xml filter that can be applied to the parse.
111 *
112 * @param filters
113 * @return
114 * @throws Exception
115 */
116 public XMLFilter getXMLFilter(List<XMLFilter> filters) throws Exception{
117 SAXParserFactory spf = SAXParserFactory.newInstance();
118 spf.setNamespaceAware(true);
119 XMLFilter previous = null;
120 XMLFilter current = null;
121
122 for(int i=0; i< filters.size();i++)
123 {
124 if(i==0){
125 previous = filters.get(i);
126 previous.setParent(spf.newSAXParser().getXMLReader());
127 }else{
128 current = filters.get(i);
129 current.setParent(previous);
130 previous = current;
131 }
132 }
133 return current;
134 }
135
136 protected DataXmlDto unmarshal(Unmarshaller unmarshaller, InputStream in) throws Exception {
137
138 UnmarshallerHandler handler = unmarshaller.getUnmarshallerHandler();
139 Schema groupSchema = RiceXmlSchemaFactory.getSchema(DEFAULT_GROUP_SCHEMA_NAME);
140 unmarshaller.setSchema(groupSchema);
141 ValidationEventCollector vec = new RiceSchemaValidationEventCollector();
142 unmarshaller.setEventHandler(vec);
143
144 XMLFilter filter = this.getXMLFilter(this.getXMLFilterList());
145 filter.setContentHandler(handler);
146
147 filter.parse(new InputSource(in));
148
149
150 return (DataXmlDto)handler.getResult();
151 }
152
153 // protected GroupXmlDto unmarshalNew(Unmarshaller unmarshaller, InputStream in) throws Exception {
154 // SAXParserFactory spf = SAXParserFactory.newInstance();
155 // spf.setNamespaceAware(true);
156 //
157 // XMLFilter filter = new TestGroupNamespaceURIFilter();
158 // filter.setParent(spf.newSAXParser().getXMLReader());
159 //
160 // unmarshaller.setListener(new Unmarshaller.Listener() {
161 //
162 // public void afterUnmarshal(Object target, Object parent) {
163 // GroupXmlDto gxd = (GroupXmlDto)target;
164 // //super.afterUnmarshal(target, parent);
165 // }
166 // });
167 //
168 //
169 // UnmarshallerHandler handler = unmarshaller.getUnmarshallerHandler();
170 // filter.setContentHandler(handler);
171 //
172 // filter.parse(new InputSource(in));
173 //
174 // return (GroupXmlDto)handler.getResult();
175 // }
176 //
177 // protected GroupInfo generateGroupInfo(GroupXmlDto groupDto){
178 // IdentityManagementService identityManagementService = KIMServiceLocator.getIdentityManagementService();
179 //
180 // List<String> errors = new ArrayList<String>();
181 // GroupInfo gi = new GroupInfo();
182 // List<KimTypeAttributeInfo> typeAttributes = null;
183 //
184 // if(isBlank(groupDto.getNamespaceCode())){
185 // errors.add("Namespace must have a value.");
186 // }else{
187 // gi.setNamespaceCode(groupDto.getNamespaceCode());
188 // }
189 //
190 // if(groupDto.getKimType() != null){
191 // KimTypeInfo kimTypeInfo = null;
192 // if(!isBlank(groupDto.getKimType().getKimTypeId())){
193 // kimTypeInfo = KIMServiceLocator.getTypeInfoService().getKimType(groupDto.getKimType().getKimTypeId());
194 // }
195 // if(!isBlank(groupDto.getKimType().getName()) && !isBlank(groupDto.getKimType().getNamespaceCode())){
196 // kimTypeInfo = KIMServiceLocator.getTypeInfoService().getKimTypeByName(groupDto.getKimType().getNamespaceCode(), groupDto.getKimType().getName());
197 // }
198 //
199 // if (kimTypeInfo == null) {
200 // errors.add("Invalid typeId or type name and namespace specified.");
201 // } else {
202 // gi.setKimTypeId(kimTypeInfo.getKimTypeId());
203 // typeAttributes = kimTypeInfo.getAttributeDefinitions();
204 // }
205 // } else{
206 // KimTypeInfo kimTypeDefault = KIMServiceLocator.getTypeInfoService().getKimTypeByName(KimConstants.KIM_TYPE_DEFAULT_NAMESPACE, KimConstants.KIM_TYPE_DEFAULT_NAME);
207 // if (kimTypeDefault != null) {
208 // gi.setKimTypeId(kimTypeDefault.getKimTypeId());
209 // typeAttributes = kimTypeDefault.getAttributeDefinitions();
210 // } else {
211 // errors.add("Failed to locate the 'Default' group type! Please ensure that it's in your database.");
212 // }
213 // }
214 //
215 // //Active Indicator
216 // gi.setActive(groupDto.isActive());
217 //
218 // //Get list of attribute keys
219 // List<String> validAttributeKeys = new ArrayList<String>();
220 // for (KimTypeAttributeInfo attribute : typeAttributes) {
221 // validAttributeKeys.add(attribute.getAttributeName());
222 // }
223 // //Group attributes
224 // if (groupDto.getAttributes() != null) {
225 // AttributeSet attributeSet = new AttributeSet();
226 // for (String key : groupDto.getAttributes().keySet() ) {
227 // String value = groupDto.getAttributes().get(key);
228 // attributeSet.put(key, value);
229 // if (!validAttributeKeys.contains(key)) {
230 // errors.add("Invalid attribute specified.");
231 // }
232 // }
233 // if (attributeSet.size() > 0) {
234 // gi.setAttributes(attributeSet);
235 // }
236 // }
237 //
238 // // Group Members
239 // for(GroupMembershipXmlDto groupMember : groupDto.getMembers()){
240 //
241 // GroupMembershipInfo gmi = new GroupMembershipInfo(groupDto.getGroupId(), null, null, null, null, null);
242 // if(!isBlank(groupMember.getMemberId())){
243 // KimPrincipal principal = identityManagementService.getPrincipal(groupMember.getMemberId());
244 // gmi.setMemberId(principal.getPrincipalId());
245 // gmi.setMemberTypeCode(KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE);
246 // }
247 // if(!isBlank(groupMember.getMemberName())){
248 // KimPrincipal principal = identityManagementService.getPrincipalByPrincipalName(groupMember.getMemberName());
249 // gmi.setMemberId(principal.getPrincipalId());
250 // gmi.setMemberTypeCode(KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE);
251 // }
252 // if(groupMember.getGroupName() != null){
253 // Group group = identityManagementService.getGroupByName(groupMember.getGroupName().getNamespaceCode(),groupMember.getGroupName().getName());
254 // gmi.setMemberId(group.getGroupId());
255 // gmi.setMemberTypeCode(KimGroupMemberTypes.GROUP_MEMBER_TYPE);
256 // }
257 // if(groupMember.getGroupName() != null){
258 // Group group = identityManagementService.getGroupByName(groupMember.getGroupName().getNamespaceCode(),groupMember.getGroupName().getName());
259 // gmi.setMemberId(group.getGroupId());
260 // gmi.setMemberTypeCode(KimGroupMemberTypes.GROUP_MEMBER_TYPE);
261 // }
262 //
263 // /**
264 // if (principal != null) {
265 // addPrincipalToGroup(groupInfo.getNamespaceCode(), groupInfo.getGroupName(), principal.getPrincipalId());
266 // } else {
267 // throw new InvalidXmlException("Principal Name "+principalName+" cannot be found.");
268 // }
269 // **/
270 //
271 // }
272 //
273 // return gi;
274 // }
275 //
276 private boolean isBlank(Object o){
277 return (o == null || "".equals(o));
278 }
279
280
281 public class DataNamespaceURIFilter extends XMLFilterImpl {
282
283 public static final String DATA_URI=CoreNamespaceConstants.CORE;
284
285 public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
286 if("data".equals(localName)) {
287 uri = DATA_URI;
288 }
289
290 super.startElement(uri, localName, qName, atts);
291 }
292
293 public void endElement(String uri, String localName, String qName) throws SAXException {
294 if(StringUtils.isBlank(uri)) {
295 uri = DATA_URI;
296 }
297
298 super.endElement(uri, localName, qName);
299 }
300 }
301
302 }