001 /* 002 * Copyright 2005 Stephen J. McConnell 003 * 004 * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0 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 013 * implied. 014 * 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019 package net.dpml.tools.info; 020 021 import java.io.File; 022 import java.io.IOException; 023 import java.io.FileNotFoundException; 024 import java.io.FileInputStream; 025 import java.io.BufferedInputStream; 026 import java.net.URI; 027 import java.net.URL; 028 import java.util.Properties; 029 import java.util.Arrays; 030 031 import net.dpml.transit.Artifact; 032 import net.dpml.transit.Transit; 033 034 import net.dpml.util.ElementHelper; 035 036 import org.w3c.dom.Element; 037 038 /** 039 * Utility class used for construction of a module model from an XML source. 040 * 041 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 042 * @version 1.1.3 043 */ 044 public final class BuilderDirectiveHelper 045 { 046 private static final String BUILDER_ELEMENT_NAME = "builder"; 047 private static final String LISTENERS_ELEMENT_NAME = "listeners"; 048 private static final String LISTENER_ELEMENT_NAME = "listener"; 049 private static final String PROPERTIES_ELEMENT_NAME = "properties"; 050 private static final String PROPERTY_ELEMENT_NAME = "property"; 051 052 private BuilderDirectiveHelper() 053 { 054 // static utility class 055 } 056 057 /** 058 * Construct a builder directive from XML source. 059 * @param source the XML source file 060 * @return the builder directive 061 * @exception IOException if an IO exception occurs 062 */ 063 public static BuilderDirective build( File source ) throws IOException 064 { 065 if( null == source ) 066 { 067 throw new NullPointerException( "source" ); 068 } 069 if( !source.exists() ) 070 { 071 throw new FileNotFoundException( source.toString() ); 072 } 073 if( source.isDirectory() ) 074 { 075 final String error = 076 "File [" 077 + source 078 + "] references a directory."; 079 throw new IllegalArgumentException( error ); 080 } 081 FileInputStream input = new FileInputStream( source ); 082 BufferedInputStream buffer = new BufferedInputStream( input ); 083 try 084 { 085 final Element root = ElementHelper.getRootElement( input ); 086 File base = source.getParentFile(); 087 return buildMainDirective( root ); 088 } 089 catch( Throwable e ) 090 { 091 final String error = 092 "An error occured while attempting to create the builder configuration from the source: " 093 + source; 094 IOException ioe = new IOException( error ); 095 ioe.initCause( e ); 096 throw ioe; 097 } 098 finally 099 { 100 input.close(); 101 } 102 } 103 104 /** 105 * Creates a builder configuration using the default configuration. 106 * @return the builder directive 107 * @exception Exception if an error occurs 108 */ 109 public static BuilderDirective build() throws Exception 110 { 111 File prefs = Transit.DPML_PREFS; 112 File config = new File( prefs, "dpml/tools/xmls/builder.xml" ); 113 if( config.exists() ) 114 { 115 return build( config ); 116 } 117 else 118 { 119 final String error = 120 "Missing builder configuration: " 121 + config; 122 throw new FileNotFoundException( error ); 123 } 124 } 125 126 private static URL convertToURL( URI uri ) throws Exception 127 { 128 if( Artifact.isRecognized( uri ) ) 129 { 130 Artifact artifact = Artifact.createArtifact( uri ); 131 return artifact.toURL(); 132 } 133 else 134 { 135 return uri.toURL(); 136 } 137 } 138 139 /** 140 * Build the configuration using an XML element. 141 * @param element the builder root element 142 * @return the builder directive 143 * @exception IOException if an I/O error occurs 144 */ 145 private static BuilderDirective buildMainDirective( Element element ) throws Exception 146 { 147 final String elementName = element.getTagName(); 148 if( !BUILDER_ELEMENT_NAME.equals( elementName ) ) 149 { 150 final String error = 151 "Element is not a builder configuration."; 152 throw new IllegalArgumentException( error ); 153 } 154 155 // get type descriptors, modules and properties 156 157 String phase = ElementHelper.getAttribute( element, "default", "installation" ); 158 159 Properties properties = null; 160 ListenerDirective[] listeners = new ListenerDirective[0]; 161 Element[] children = ElementHelper.getChildren( element ); 162 for( int i=0; i<children.length; i++ ) 163 { 164 Element child = children[i]; 165 final String tag = child.getTagName(); 166 if( PROPERTIES_ELEMENT_NAME.equals( tag ) ) 167 { 168 properties = buildProperties( child ); 169 } 170 else if( LISTENERS_ELEMENT_NAME.equals( tag ) ) 171 { 172 listeners = buildListenerDirectives( child ); 173 } 174 else 175 { 176 final String error = 177 "Illegal element name [" + tag + "] within 'builder' element."; 178 throw new IllegalArgumentException( error ); 179 } 180 } 181 Arrays.sort( listeners ); 182 return new BuilderDirective( listeners, phase, properties ); 183 } 184 185 private static ListenerDirective[] buildListenerDirectives( Element element ) throws Exception 186 { 187 Element[] children = ElementHelper.getChildren( element ); 188 ListenerDirective[] types = new ListenerDirective[ children.length ]; 189 for( int i=0; i<children.length; i++ ) 190 { 191 Element child = children[i]; 192 types[i] = buildListenerDirective( child ); 193 } 194 return types; 195 } 196 197 private static ListenerDirective buildListenerDirective( Element element ) throws Exception 198 { 199 final String tag = element.getTagName(); 200 if( LISTENER_ELEMENT_NAME.equals( tag ) ) 201 { 202 final String name = ElementHelper.getAttribute( element, "name", null ); 203 final String spec = ElementHelper.getAttribute( element, "uri", null ); 204 final URI uri = createURI( spec ); 205 final String classname = ElementHelper.getAttribute( element, "class", null ); 206 final String value = ElementHelper.getAttribute( element, "priority", null ); 207 int priority = Integer.parseInt( value ); 208 final String deps = ElementHelper.getAttribute( element, "depends", null ); 209 final Properties properties = buildProperties( element ); 210 return new ListenerDirective( name, priority, uri, classname, properties ); 211 } 212 else 213 { 214 final String error = 215 "Invalid resource element name [" 216 + tag 217 + "]."; 218 throw new IllegalArgumentException( error ); 219 } 220 } 221 222 private static Properties buildProperties( Element element ) 223 { 224 Properties properties = new Properties(); 225 Element[] children = ElementHelper.getChildren( element ); 226 for( int i=0; i<children.length; i++ ) 227 { 228 Element child = children[i]; 229 String tag = child.getTagName(); 230 if( PROPERTY_ELEMENT_NAME.equals( tag ) ) 231 { 232 String key = ElementHelper.getAttribute( child, "name", null ); 233 if( null == key ) 234 { 235 final String error = 236 "Property declaration does not contain a 'name' attribute."; 237 throw new IllegalArgumentException( error ); 238 } 239 else 240 { 241 String value = ElementHelper.getAttribute( child, "value", null ); 242 properties.setProperty( key, value ); 243 } 244 } 245 } 246 return properties; 247 } 248 249 private static URI createURI( String spec ) throws Exception 250 { 251 if( null == spec ) 252 { 253 return null; 254 } 255 else 256 { 257 return new URI( spec ); 258 } 259 } 260 261 }