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 }