001/* 002/* 003 * IzPack - Copyright 2001-2005 Julien Ponge, All Rights Reserved. 004 * 005 * http://www.izforge.com/izpack/ 006 * http://developer.berlios.de/projects/izpack/ 007 * 008 * Copyright 2002 Marcus Wolschon 009 * Copyright 2002 Jan Blok 010 * Copyright 2004 Klaus Bartz 011 * 012 * Licensed under the Apache License, Version 2.0 (the "License"); 013 * you may not use this file except in compliance with the License. 014 * You may obtain a copy of the License at 015 * 016 * http://www.apache.org/licenses/LICENSE-2.0 017 * 018 * Unless required by applicable law or agreed to in writing, software 019 * distributed under the License is distributed on an "AS IS" BASIS, 020 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 021 * See the License for the specific language governing permissions and 022 * limitations under the License. 023 */ 024package com.izforge.izpack.ant; 025 026import java.util.Enumeration; 027import java.util.Vector; 028 029import org.apache.tools.ant.BuildException; 030import org.apache.tools.ant.Project; 031 032/** 033 * A nested element holder for the installation configuration document content. 034 * The installation document must be passed in using a CDATA element. 035 * 036 * @author Scott Stark 037 * @version $Revision: 1.1 $ 038 */ 039public class ConfigHolder 040{ 041 /** The parent element project */ 042 private Project project; 043 044 /** The config element body text with ${x} property references replaced */ 045 private String installText; 046 047 /** 048 * Taken from the ant org.apache.tools.ant.PropertyHelper and '$' replaced 049 * with '@' to deal with @{x} style property references. 050 * 051 * Parses a string containing @{xxx} style property references 052 * into two lists. The first list is a collection of text fragments, while 053 * the other is a set of string property names. null entries in the 054 * first list indicate a property reference from the second list. 055 * 056 * It can be overridden with a more efficient or customized version. 057 * 058 * @param value Text to parse. Must not be null. 059 * @param fragments List to add text fragments to. Must not be null. 060 * @param propertyRefs List to add property names to. Must not be null. 061 * 062 * @exception BuildException if the string contains an opening @{ without a 063 * closing } 064 */ 065 static void parseCompileProperties(String value, Vector fragments, Vector propertyRefs) 066 throws BuildException 067 { 068 int prev = 0; 069 int pos; 070 // search for the next instance of $ from the 'prev' position 071 while ((pos = value.indexOf("@", prev)) >= 0) 072 { 073 074 // if there was any text before this, add it as a fragment 075 // TODO, this check could be modified to go if pos>prev; 076 // seems like this current version could stick empty strings 077 // into the list 078 if (pos > 0) 079 { 080 fragments.addElement(value.substring(prev, pos)); 081 } 082 // if we are at the end of the string, we tack on a $ 083 // then move past it 084 if (pos == (value.length() - 1)) 085 { 086 fragments.addElement("@"); 087 prev = pos + 1; 088 } 089 else if (value.charAt(pos + 1) != '{') 090 { 091 // peek ahead to see if the next char is a property or not 092 // not a property: insert the char as a literal 093 /* 094 * fragments.addElement(value.substring(pos + 1, pos + 2)); prev = pos + 2; 095 */ 096 if (value.charAt(pos + 1) == '@') 097 { 098 // backwards compatibility two $ map to one mode 099 fragments.addElement("@"); 100 prev = pos + 2; 101 } 102 else 103 { 104 // new behaviour: $X maps to $X for all values of X!='$' 105 fragments.addElement(value.substring(pos, pos + 2)); 106 prev = pos + 2; 107 } 108 109 } 110 else 111 { 112 // property found, extract its name or bail on a typo 113 int endName = value.indexOf('}', pos); 114 if (endName < 0) 115 { 116 throw new BuildException("Syntax error in property: " + value); 117 } 118 String propertyName = value.substring(pos + 2, endName); 119 fragments.addElement(null); 120 propertyRefs.addElement(propertyName); 121 prev = endName + 1; 122 } 123 } 124 // no more @ signs found 125 // if there is any tail to the file, append it 126 if (prev < value.length()) 127 { 128 fragments.addElement(value.substring(prev)); 129 } 130 } 131 132 ConfigHolder(Project project) 133 { 134 this.project = project; 135 } 136 137 /** 138 * Called by ant to set the config element content. The content is scanned 139 * for @{x} style property references and replaced with the x project 140 * property. 141 * 142 * @param rawText - the raw config element body text. 143 */ 144 public void addText(String rawText) 145 { 146 // Locate the @{x} references 147 Vector fragments = new Vector(); 148 Vector propertyRefs = new Vector(); 149 parseCompileProperties(rawText, fragments, propertyRefs); 150 151 // Replace the references with the project property value 152 StringBuffer sb = new StringBuffer(); 153 Enumeration i = fragments.elements(); 154 Enumeration j = propertyRefs.elements(); 155 156 while (i.hasMoreElements()) 157 { 158 String fragment = (String) i.nextElement(); 159 if (fragment == null) 160 { 161 String propertyName = (String) j.nextElement(); 162 Object replacement = null; 163 164 // try to get it from the project 165 if (replacement == null) 166 { 167 replacement = project.getProperty(propertyName); 168 } 169 170 if (replacement == null) 171 { 172 project.log("Property @{" + propertyName + "} has not been set", 173 Project.MSG_VERBOSE); 174 } 175 if (replacement != null) 176 fragment = replacement.toString(); 177 else 178 fragment = "@{" + propertyName + "}"; 179 } 180 sb.append(fragment); 181 } 182 183 installText = sb.toString(); 184 } 185 186 /** 187 * Get the config element body text with @{x} property references replaced 188 * 189 * @return the processed config element body text. 190 */ 191 public String getText() 192 { 193 return installText; 194 } 195 196}