/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.hadoop.gateway.filter.rewrite.impl.xml;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.hadoop.gateway.filter.rewrite.api.*;
import org.apache.hadoop.gateway.filter.rewrite.i18n.UrlRewriteMessages;
import org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteRulesExporter;
import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
import org.apache.hadoop.gateway.util.XmlUtils;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.InvocationTargetException;
public class XmlUrlRewriteRulesExporter implements UrlRewriteRulesExporter, XmlRewriteRulesTags {
private static final UrlRewriteMessages LOG = MessagesFactory.get( UrlRewriteMessages.class );
@Override
public String getFormat() {
return "xml";
}
@Override
public void store( UrlRewriteRulesDescriptor descriptor, Writer writer ) throws IOException {
try {
Document document = XmlUtils.createDocument();
Element root = document.createElement( ROOT );
document.appendChild( root );
if( !descriptor.getFunctions().isEmpty() ) {
Element functionsElement = document.createElement( FUNCTIONS );
root.appendChild( functionsElement );
for( UrlRewriteFunctionDescriptor function : descriptor.getFunctions() ) {
Element functionElement = createElement( document, function.name(), function );
functionsElement.appendChild( functionElement );
}
}
if( !descriptor.getRules().isEmpty() ) {
for( UrlRewriteRuleDescriptor rule : descriptor.getRules() ) {
Element ruleElement = createRule( document, rule );
root.appendChild( ruleElement );
}
}
if( !descriptor.getFilters().isEmpty() ) {
for( UrlRewriteFilterDescriptor filter : descriptor.getFilters() ) {
Element filterElement = createFilter( document, filter );
root.appendChild( filterElement );
}
}
XmlUtils.writeXml( document, writer );
} catch( ParserConfigurationException e ) {
throw new IOException( e );
} catch( TransformerException e ) {
throw new IOException( e );
} catch( InvocationTargetException e ) {
LOG.failedToWriteRulesDescriptor( e );
} catch( NoSuchMethodException e ) {
LOG.failedToWriteRulesDescriptor( e );
} catch( IntrospectionException e ) {
LOG.failedToWriteRulesDescriptor( e );
} catch( IllegalAccessException e ) {
LOG.failedToWriteRulesDescriptor( e );
}
}
private Element createFilter( Document document, UrlRewriteFilterDescriptor parent )
throws IntrospectionException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
Element parentElement = createElement( document, FILTER, parent );
for( UrlRewriteFilterContentDescriptor child: parent.getContents() ) {
Element childElement = createFilterContent( document, child );
parentElement.appendChild( childElement );
}
return parentElement;
}
private Element createFilterContent( Document document, UrlRewriteFilterContentDescriptor parent )
throws IntrospectionException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
Element parentElement = createElement( document, CONTENT, parent );
for( UrlRewriteFilterPathDescriptor child: parent.getSelectors() ) {
Element childElement = createFilterSelector( document, child );
parentElement.appendChild( childElement );
}
return parentElement;
}
private Element createFilterSelector( Document document, UrlRewriteFilterPathDescriptor parent )
throws IntrospectionException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
Element parentElement = createElement( document, toTagName( parent ), parent );
if( parent instanceof UrlRewriteFilterGroupDescriptor ) {
for( UrlRewriteFilterPathDescriptor child: ((UrlRewriteFilterGroupDescriptor)parent).getSelectors() ) {
Element childElement = createFilterSelector( document, child );
parentElement.appendChild( childElement );
}
}
return parentElement;
}
private Element createRule( Document document, UrlRewriteRuleDescriptor rule )
throws IntrospectionException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
Element ruleElement = createElement( document, RULE, rule );
for( UrlRewriteStepDescriptor step: rule.steps() ) {
Element childElement = createStep( document, step );
ruleElement.appendChild( childElement );
}
return ruleElement;
}
private Element createStep( Document document, UrlRewriteStepDescriptor step )
throws IntrospectionException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
Element parentElement = createElement( document, step.type(), step );
if( step instanceof UrlRewriteFlowDescriptor ) {
UrlRewriteFlowDescriptor flow = (UrlRewriteFlowDescriptor)step;
for( Object child: flow.steps() ) {
UrlRewriteStepDescriptor childStep = (UrlRewriteStepDescriptor)child;
Element childElement = createStep( document, childStep );
parentElement.appendChild( childElement );
}
}
return parentElement;
}
private Element createElement( Document document, String name, Object bean )
throws IntrospectionException, InvocationTargetException, NoSuchMethodException, IllegalAccessException {
Element element = document.createElement( name );
BeanInfo beanInfo = Introspector.getBeanInfo( bean.getClass(), Object.class );
for( PropertyDescriptor propInfo: beanInfo.getPropertyDescriptors() ) {
String propName = propInfo.getName();
if( propInfo.getReadMethod() != null && String.class.isAssignableFrom( propInfo.getPropertyType() ) ) {
String propValue = BeanUtils.getProperty( bean, propName );
if( propValue != null && !propValue.isEmpty() ) {
// Doing it the hard way to avoid having the &'s in the query string escaped at &
Attr attr = document.createAttribute( propName );
attr.setValue( propValue );
element.setAttributeNode( attr );
//element.setAttribute( propName, propValue );
}
}
}
return element;
}
private static String toTagName( final UrlRewriteFilterPathDescriptor descriptor ) {
if( descriptor instanceof UrlRewriteFilterApplyDescriptor ) {
return APPLY;
} else if( descriptor instanceof UrlRewriteFilterDetectDescriptor ) {
return DETECT;
} else if( descriptor instanceof UrlRewriteFilterBufferDescriptor ) {
return BUFFER;
} else if( descriptor instanceof UrlRewriteFilterScopeDescriptor ) {
return SCOPE;
} else {
throw new IllegalArgumentException();
}
}
}