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 }