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.station.builder; 020 021 import java.io.IOException; 022 import java.net.URI; 023 import java.util.Properties; 024 025 import net.dpml.station.info.RegistryDescriptor; 026 import net.dpml.station.info.RegistryDescriptor.Entry; 027 import net.dpml.station.info.ApplicationDescriptor; 028 import net.dpml.station.info.StartupPolicy; 029 030 import net.dpml.util.DOM3DocumentBuilder; 031 032 import net.dpml.util.DecodingException; 033 import net.dpml.util.Decoder; 034 import net.dpml.util.Resolver; 035 import net.dpml.util.SimpleResolver; 036 037 import net.dpml.lang.ValueDirective; 038 import net.dpml.util.ElementHelper; 039 040 import org.w3c.dom.Document; 041 import org.w3c.dom.Element; 042 043 /** 044 * Test example application sources. 045 * 046 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a> 047 * @version 1.0.5 048 */ 049 public final class RegistryBuilder implements Decoder 050 { 051 private static final DOM3DocumentBuilder DOCUMENT_BUILDER = 052 new DOM3DocumentBuilder(); 053 054 /** 055 * Build a registry descriptior from a uri. 056 * @param uri the uri to the descriptor XML document 057 * @return the registry descriptor 058 * @exception DecodingException if a decoding error occurs 059 * @exception IOException if a IO error occurs 060 */ 061 public Object build( URI uri ) throws DecodingException, IOException 062 { 063 Document document = DOCUMENT_BUILDER.parse( uri ); 064 Element root = document.getDocumentElement(); 065 Resolver resolver = new SimpleResolver(); 066 return decode( root , resolver ); 067 } 068 069 /** 070 * Decode a registry descriptior from a DOM element. 071 * @param element the element representing the root registry 072 * @param resolver build-time uri resolver 073 * @return the registry descriptor 074 * @exception DecodingException if a decoding error occurs 075 */ 076 public Object decode( Element element, Resolver resolver ) throws DecodingException 077 { 078 String tag = element.getTagName(); 079 if( "application".equals( tag ) ) 080 { 081 return buildApplicationDescriptor( element, resolver ); 082 } 083 else if( "registry".equals( tag ) ) 084 { 085 return buildRegistryDescriptor( element, resolver ); 086 } 087 else 088 { 089 final String error = 090 "Document element name [" + tag + "] not recognized."; 091 throw new DecodingException( element, error ); 092 } 093 } 094 095 private RegistryDescriptor buildRegistryDescriptor( 096 Element element, Resolver resolver ) throws DecodingException 097 { 098 Element[] elements = ElementHelper.getChildren( element ); 099 Entry[] entries = new Entry[ elements.length ]; 100 for( int i=0; i<elements.length; i++ ) 101 { 102 Element elem = elements[i]; 103 String key = ElementHelper.getAttribute( elem, "key" ); 104 if( null == key ) 105 { 106 final String error = 107 "Missing 'key' attribute in application element."; 108 throw new DecodingException( elem, error ); 109 } 110 ApplicationDescriptor descriptor = buildApplicationDescriptor( elem, resolver ); 111 entries[i] = new Entry( key, descriptor ); 112 } 113 return new RegistryDescriptor( entries ); 114 } 115 116 private ApplicationDescriptor buildApplicationDescriptor( 117 Element element, Resolver resolver ) throws DecodingException 118 { 119 String title = ElementHelper.getAttribute( element, "title" ); 120 StartupPolicy policy = buildStartupPolicy( element ); 121 Element jvm = ElementHelper.getChild( element, "jvm" ); 122 String base = ElementHelper.getAttribute( jvm, "base" ); 123 Element startupElement = ElementHelper.getChild( jvm, "startup" ); 124 Element shutdownElement = ElementHelper.getChild( jvm, "shutdown" ); 125 int startup = buildTimeout( startupElement, ApplicationDescriptor.DEFAULT_STARTUP_TIMEOUT ); 126 int shutdown = buildTimeout( startupElement, ApplicationDescriptor.DEFAULT_SHUTDOWN_TIMEOUT ); 127 Element propertiesElement = ElementHelper.getChild( jvm, "properties" ); 128 Properties properties = buildProperties( propertiesElement ); 129 Element codebase = ElementHelper.getChild( element, "codebase" ); 130 URI uri = decodeURI( codebase ); 131 Element[] params = ElementHelper.getChildren( codebase, "param" ); 132 ValueDirective[] values = buildValueDirectives( params ); 133 134 // need to rework ApplicationDescriptor such that the codebase is presented 135 // as an abstract type - e.g. net.dpml.lang.CodeBaseDirective verus 136 // net.dpml.metro.CodeBaseDirective 137 138 return new ApplicationDescriptor( 139 uri, title, values, base, policy, startup, shutdown, properties, null ); 140 } 141 142 private URI decodeURI( Element element ) throws DecodingException 143 { 144 String uri = ElementHelper.getAttribute( element, "uri" ); 145 if( null == uri ) 146 { 147 final String error = "Missing uri attribute."; 148 throw new DecodingException( element, error ); 149 } 150 else 151 { 152 try 153 { 154 return new URI( uri ); 155 } 156 catch( Exception e ) 157 { 158 final String error = "Bad uri argument [" + uri + "]."; 159 throw new DecodingException( element, error ); 160 161 } 162 } 163 } 164 165 private StartupPolicy buildStartupPolicy( Element element ) throws DecodingException 166 { 167 String policy = ElementHelper.getAttribute( element, "policy" ); 168 if( null == policy ) 169 { 170 return StartupPolicy.MANUAL; 171 } 172 else 173 { 174 return StartupPolicy.parse( policy ); 175 } 176 } 177 178 private int buildTimeout( Element element, int fallback ) throws DecodingException 179 { 180 if( null == element ) 181 { 182 return fallback; 183 } 184 else 185 { 186 String value = ElementHelper.getValue( element ); 187 if( null == value ) 188 { 189 return fallback; 190 } 191 else 192 { 193 return Integer.parseInt( value ); 194 } 195 } 196 } 197 198 private Properties buildProperties( Element element ) throws DecodingException 199 { 200 Properties properties = new Properties(); 201 if( null == element ) 202 { 203 return properties; 204 } 205 else 206 { 207 Element[] children = ElementHelper.getChildren( element ); 208 for( int i=0; i<children.length; i++ ) 209 { 210 Element child = children[i]; 211 String name = ElementHelper.getAttribute( child, "name" ); 212 if( null == name ) 213 { 214 final String error = 215 "Property declaration does not contain a 'name' attribute."; 216 throw new DecodingException( child, error ); 217 } 218 else 219 { 220 String value = ElementHelper.getAttribute( child, "value" ); 221 properties.setProperty( name, value ); 222 } 223 } 224 return properties; 225 } 226 } 227 228 /** 229 * Construct a value directive array. 230 * @param elements the array of DOM elements representing value directive assertions 231 * @return the array of value directives 232 */ 233 protected ValueDirective[] buildValueDirectives( Element[] elements ) 234 { 235 ValueDirective[] values = new ValueDirective[ elements.length ]; 236 for( int i=0; i<elements.length; i++ ) 237 { 238 values[i] = buildValueDirective( elements[i] ); 239 } 240 return values; 241 } 242 243 /** 244 * Construct a single value directive. 245 * @param element the DOM element representing the value directive assertions 246 * @return the value directive 247 */ 248 protected ValueDirective buildValueDirective( Element element ) 249 { 250 String classname = ElementHelper.getAttribute( element, "class" ); 251 String method = ElementHelper.getAttribute( element, "method" ); 252 Element[] elements = ElementHelper.getChildren( element, "param" ); 253 if( elements.length > 0 ) 254 { 255 ValueDirective[] values = buildValueDirectives( elements ); 256 return new ValueDirective( classname, method, values ); 257 } 258 else 259 { 260 String value = ElementHelper.getAttribute( element, "value" ); 261 return new ValueDirective( classname, method, value ); 262 } 263 } 264 }