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 }