/* * 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.cocoon.transformation.helpers; import java.util.Map; import java.util.StringTokenizer; import org.apache.avalon.framework.configuration.SAXConfigurationHandler; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; /** * A SAX ContentHandler that builds Avalon <code>Configuration</code> objects, * but also replaces variables of the form {var} with values from a map. * * @see VariableConfiguration * @author <a href="jefft@apache.org">Jeff Turner</a> * @version CVS $Id$ */ public class InterpolatingConfigurationHandler extends SAXConfigurationHandler { final private Map vars; final private String location; /** Constructor. * @param vars The mappings from variable name to value. */ public InterpolatingConfigurationHandler(Map vars) { this.vars = vars; this.location = "Unknown"; } /** Constructor. * @param vars The mappings from variable name to value. * @param location The origin of this configuration info. */ public InterpolatingConfigurationHandler(Map vars, String location) { this.vars = vars; this.location = location; } /** Replace {vars} in attributes. */ public void startElement(String uri, String localName, String qName, Attributes attr) throws SAXException { AttributesImpl newAttr = new AttributesImpl(attr); for (int i=0; i<attr.getLength(); i++) { newAttr.setValue(i, interp(attr.getValue(i))); } super.startElement(uri, localName, qName, newAttr); } /** Replace {vars} in element bodies. */ public void characters( final char[] ch, int start, int len ) throws SAXException { StringBuffer buf = new StringBuffer(); if (start!=0) buf.append(ch, 0, start-1); String newVal = interp(new String(ch,start, len)); buf.append(newVal); buf.append(ch, start+len, ch.length-(start+len)); super.characters(buf.toString().toCharArray(), start, newVal.length()); } protected String getLocationString() { return this.location; } /** * Interpolate variable values into a string. * * @param str String with {var} tokens * @return <code>str</code>, with {variables} replaced by values. If an * unknown variable token is encountered it is ignored. */ private String interp(String str) { StringBuffer buf = new StringBuffer(str.length()*2); StringTokenizer tok = new StringTokenizer(str, "{}", true); int state = 0; // 0=outside, 1=inside while (tok.hasMoreTokens()) { String token = tok.nextToken(); if (state == 0 && "{".equals(token)) { state = 1; } else if (state == 1 && "}".equals(token)) { state = 0; } else if (state == 0) { buf.append(token); } else if (state == 1) { //System.out.println("Replacing "+token+" with "+vars.get(token)); String val = (String)vars.get(token); if (val == null) { buf.append("{").append(token).append("}"); } else{ buf.append(val); } } } return buf.toString(); } }