001    /*
002     * Copyright (c) 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.metro.tools;
020    
021    import java.io.IOException;
022    import java.net.URI;
023    import java.net.URISyntaxException;
024    
025    import net.dpml.component.Directive;
026    
027    import net.dpml.metro.info.PartReference;
028    import net.dpml.metro.info.Type;
029    import net.dpml.metro.builder.ComponentDecoder;
030    
031    import org.apache.tools.ant.Task;
032    import org.apache.tools.ant.BuildException;
033    
034    /**
035     * Task that handles the construction of a serialized container part.
036     *
037     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
038     * @version 1.1.3
039     */
040    public class PartDataType extends Task implements PartReferenceBuilder
041    {
042        private URI m_uri;
043        private String m_key;
044    
045       /**
046        * Set the part uri.
047        * @param uri the part uri
048        */
049        public void setUri( URI uri )
050        {
051            m_uri = uri;
052        }
053    
054       /**
055        * Set the part key.
056        * @param key the key
057        */
058        public void setKey( String key )
059        {
060            m_key = key;
061        }
062    
063        //---------------------------------------------------------------------
064        // Builder
065        //---------------------------------------------------------------------
066    
067       /**
068        * Return a uri identitifying the builder.
069        *
070        * @return the builder uri
071        */
072        public URI getBuilderURI()
073        {
074            return PART_BUILDER_URI;
075        }
076    
077       /**
078        * Return a urn identitifying the part handler for this builder.
079        *
080        * @return a strategy uri
081        */
082        public URI getPartHandlerURI()
083        {
084            return PART_HANDLER_URI;
085        }
086    
087        //---------------------------------------------------------------------
088        // PartReferenceBuilder
089        //---------------------------------------------------------------------
090    
091       /**
092        * Return the part key.
093        *
094        * @return the key
095        */
096        public String getKey()
097        {
098            if( null == m_key )
099            {
100                final String error = 
101                  "Missing key attribute for nested part reference.";
102                throw new BuildException( error );
103            }
104            return m_key;
105        }
106    
107       /**
108        * Return the part uri.
109        *
110        * @return the uri
111        */
112        public URI getURI()
113        {
114            if( null == m_uri )
115            {
116                final String error = 
117                  "Missing uri attribute for nested part reference.";
118                throw new BuildException( error );
119            }
120            return m_uri;
121        }
122    
123       /**
124        * Build the part reference.
125        * @param classloader the classloader to use
126        * @param type the underlying component type
127        * @return the part reference
128        */
129        public PartReference buildPartReference( ClassLoader classloader, Type type )
130        {
131            String key = getKey();
132            Directive directive = buildDirective( type, classloader );
133            return new PartReference( key, directive );
134        }
135    
136        private Directive buildDirective( Type type, ClassLoader classloader ) 
137        {
138            String key = getKey();
139            URI uri = getURI();
140            try
141            {
142                ComponentDecoder decoder = new ComponentDecoder();
143                return decoder.loadComponentDirective( uri );
144            }
145            catch( IOException ioe )
146            {
147                final String error =
148                  "IO error while attempting to load part ["
149                  + m_uri
150                  + "] due to: " 
151                  + ioe.getMessage();
152                throw new BuildException( error, ioe );
153            }
154            catch( Exception e )
155            {
156                final String error =
157                  "Unexpected error while attempting to load component directive ["
158                  + m_uri
159                  + "] due to: " 
160                  + e.getMessage();
161                throw new BuildException( error, e );
162            }
163        }
164    
165        private static final URI PART_HANDLER_URI = setupURI( "artifact:part:dpml/metro/dpml-metro-runtime#1.0.4" );
166        private static final URI PART_BUILDER_URI = setupURI( "artifact:part:dpml/metro/dpml-metro-tools#1.1.3" );
167    
168       /**
169        * Internal utility to create a station uri.
170        * @param spec the uri spec
171        * @return the uri
172        */
173        protected static URI setupURI( String spec )
174        {
175            try
176            {
177                return new URI( spec );
178            }
179            catch( URISyntaxException ioe )
180            {
181                return null;
182            }
183        }
184    }