001    /*
002     * Copyright 2006 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.lang;
020    
021    import dpml.lang.Part;
022    
023    import java.io.IOException;
024    import java.net.URI;
025    import java.net.URL;
026    import java.net.URLConnection;
027    
028    import net.dpml.transit.Artifact;
029    import net.dpml.transit.Transit;
030    
031    import net.dpml.util.Logger;
032    
033    import dpml.util.DefaultLogger;
034    
035    /**
036     * Abstract component deployment strategy.
037     *
038     * @author <a href="http://www.dpml.net">Digital Product Management Library</a>
039     * @version 2.1.1
040     */
041    public abstract class Strategy implements Comparable<Strategy>
042    {
043        private static final Logger LOGGER = new DefaultLogger( "dpml.lang" );
044        
045       /**
046        * Creation of a new management strategy.
047        *
048        * @param subject the implementation class to be managed
049        * @param registry the service registry
050        * @param name the path under which the strategy will be established
051        * @return the management strategy
052        * @exception Exception if a general loading error occurs
053        */
054        public static Strategy load( Class<?> subject, ServiceRegistry registry, String name ) throws Exception
055        {
056            if( null == subject )
057            {
058                throw new NullPointerException( "subject" );
059            }
060            StrategyHandler handler = PartContentHandler.getStrategyHandler( subject );
061            Strategy strategy = handler.newStrategy( subject, name );
062            if( null == registry )
063            {
064                StandardServiceRegistry standard = new StandardServiceRegistry();
065                strategy.initialize( standard );
066            }
067            else
068            {
069                strategy.initialize( registry );
070            }
071            return strategy;
072        }
073        
074       /**
075        * Load a strategy defined by the supplied uri.
076        *
077        * @param uri the source uri to a part definition
078        * @return the strategy
079        * @exception Exception if a general loading error occurs
080        * @exception NullPointerException if the uri argument is null
081        */
082        public static Strategy load( URI uri ) throws Exception, NullPointerException
083        {
084            return load( null, null, uri, null );
085        }
086        
087       /**
088        * Load a strategy defined by the supplied uri, name, classloader and service 
089        * registry, and return a value assignable to the supplied type.
090        *
091        * @param classloader the anchor classloader
092        * @param registry the service registry
093        * @param uri the source uri to a part definition
094        * @param name the path under which the strategy will be established
095        * @return an instance of the supplied type
096        * @exception Exception if a general loading error occurs
097        * @exception NullPointerException if the uri argument is null
098        */
099        public static Strategy load( 
100          ClassLoader classloader, ServiceRegistry registry, URI uri, String name ) throws Exception, NullPointerException
101        {
102            if( null == uri )
103            {
104                throw new NullPointerException( "uri" );
105            }
106            Transit transit = Transit.getInstance();
107            URL url = Artifact.toURL( uri );
108            URLConnection connection = url.openConnection();
109            Part part = PartContentHandler.getPartContent( classloader, connection, name, true );
110            Strategy strategy = part.getStrategy();
111            if( null == registry )
112            {
113                StandardServiceRegistry standard = new StandardServiceRegistry();
114                strategy.initialize( standard );
115            }
116            else
117            {
118                strategy.initialize( registry );
119            }
120            return strategy;
121        }
122        
123        //--------------------------------------------------------------------
124        // state
125        //--------------------------------------------------------------------
126    
127        private ClassLoader m_classloader;
128        
129        //--------------------------------------------------------------------
130        // constructor
131        //--------------------------------------------------------------------
132        
133       /**
134        * Creation of a new deployment strategy.
135        * @param classloader the classloader
136        */
137        protected Strategy( ClassLoader classloader )
138        {
139            m_classloader = classloader;
140        }
141        
142        //--------------------------------------------------------------------
143        // public operations
144        //--------------------------------------------------------------------
145    
146       /**
147        * Return the classloader establised by the strategy implementation.
148        * @return the classloader
149        */
150        public ClassLoader getClassLoader()
151        {
152            return m_classloader;
153        }
154        
155       /**
156        * Return the priority assigned to this strategy.
157        * @return the priority value
158        */
159        public abstract int getPriority();
160        
161       /**
162        * Return true if this strategy is a candidate with result to the 
163        * supply of an instance assignable to the supplied type.
164        * 
165        * @param type the requested type
166        * @return type if this strategy is a condidate
167        */
168        public abstract boolean isaCandidate( Class<?> type );
169        
170       /**
171        * Instantiate a service returning an instance assigned to the supplied type.
172        *
173        * @param type the return type
174        * @return an instance of the type
175        */
176        public abstract <T>T getInstance( Class<T> type );
177        
178       /**
179        * Write the strategy to the supplied buffer in XML format.
180        * @param buffer the output buffer
181        * @param key the optional identifying key
182        * @exception IOException if an IO error occurs
183        */
184        public abstract void encode( Buffer buffer, String key ) throws IOException;
185    
186       /**
187        * Composite strategies are strategy implementations that contain subidary
188        * strategies.  During lookup operations, a subsidiary strategy may request 
189        * a service from the enclosing strategy.  To enable traversal from a subsidary
190        * to enclosing context a service registry shall be provided to all subsidiary
191        * strategies.
192        * 
193        * @param registry the service registry
194        */
195        public abstract void initialize( ServiceRegistry registry );
196        
197       /**
198        * Return the short name of this strategy.
199        * @return the name
200        */
201        public abstract String getName();
202    
203       /**
204        * Compares a supplied strategy with this strategy.  If the supplied
205        * strategy has a priority greater than this strategy the returned value
206        * is 1, otherwise if the supplied strategy has a priority lower than this
207        * strategy then the return value is -1,otherwise the returned value is 0.
208        *
209        * @param strategy the strategy to evaluate relative to this strategy
210        * @return the priority comparative index
211        */
212        public int compareTo( Strategy strategy )
213        {
214            int n = getPriority();
215            int m = strategy.getPriority();
216            if( n > m )
217            {
218                return -1;
219            }
220            else if( n == m )
221            {
222                return 0;
223            }
224            else
225            {
226                return 1;
227            }
228        }
229    
230        //--------------------------------------------------------------------
231        // protected operations
232        //--------------------------------------------------------------------
233        
234       /**
235        * Return a value assignable to the supplied type or null if the type
236        * cannot be resolved from this strategy.
237        * @param c the target class
238        * @return an instance of the class or null
239        * @exception IOException if an IO error occurs
240        */
241        public abstract <T>T getContentForClass( Class<T> c ) throws IOException;
242        
243        //--------------------------------------------------------------------
244        // private implementation
245        //--------------------------------------------------------------------
246        
247    }