001 /* 002 * Copyright (C) 2006-2007 the original author or authors. 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 implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.codehaus.gmaven.feature.support; 018 019 import org.codehaus.gmaven.feature.Component; 020 import org.codehaus.gmaven.feature.Configuration; 021 import org.codehaus.gmaven.feature.Feature; 022 import org.codehaus.gmaven.feature.FeatureException; 023 import org.codehaus.gmaven.feature.Provider; 024 import org.slf4j.Logger; 025 import org.slf4j.LoggerFactory; 026 027 /** 028 * Provides support for {@link Feature} implementations. 029 * 030 * @version $Id: FeatureSupport.java 76 2009-12-05 12:04:30Z user57 $ 031 * @author <a href="mailto:jason@planet57.com">Jason Dillon</a> 032 */ 033 public abstract class FeatureSupport 034 implements Feature 035 { 036 protected final Logger log = LoggerFactory.getLogger(getClass()); 037 038 protected final String key; 039 040 protected final Configuration config; 041 042 protected final boolean supported; 043 044 protected Provider provider; 045 046 protected FeatureSupport(final String key, final boolean supported) { 047 assert key != null; 048 049 this.key = key; 050 this.supported = supported; 051 this.config = new Configuration(); 052 } 053 054 protected FeatureSupport(final String key) { 055 this(key, true); 056 } 057 058 public String toString() { 059 return asString(this); 060 } 061 062 public int hashCode() { 063 return key().hashCode(); 064 } 065 066 public String key() { 067 return key; 068 } 069 070 public String name() { 071 return key(); 072 } 073 074 public boolean supported() { 075 return supported; 076 } 077 078 public void require() { 079 if (!supported()) { 080 throw new FeatureException("Feature not supported: " + key()); 081 } 082 } 083 084 public Configuration config() { 085 return config; 086 } 087 088 public Component create(final Configuration context) throws Exception { 089 assert context != null; 090 091 Component component = create(); 092 093 // Merge in the context 094 Configuration c = component.config(); 095 c.merge(context); 096 097 return component; 098 } 099 100 public Component create() throws Exception { 101 // First we need to be supported, so require it 102 require(); 103 104 // Then install the provider CL into the TCL to get better behaved CL mucko 105 final ClassLoader tcl = Thread.currentThread().getContextClassLoader(); 106 Thread.currentThread().setContextClassLoader(provider().getClass().getClassLoader()); 107 108 try { 109 Component component = doCreate(); 110 111 // Merge our configuration 112 Configuration c = component.config(); 113 c.merge(config()); 114 115 return component; 116 } 117 finally { 118 // Reset back to the previous TCL 119 Thread.currentThread().setContextClassLoader(tcl); 120 } 121 } 122 123 protected abstract Component doCreate() throws Exception; 124 125 // 126 // Provider registration hooks to work with ProviderSupport 127 // 128 129 /* package */ synchronized void register(final Provider provider) { 130 if (this.provider != null) { 131 throw new IllegalStateException( 132 "Duplicate provider registration with feature: " + this + 133 ", previous provider: " + this.provider + 134 ", current provider: " + provider); 135 } 136 137 this.provider = provider; 138 } 139 140 protected synchronized Provider provider() { 141 if (provider == null) { 142 throw new IllegalStateException("Provider has not been registered with feature: " + this); 143 } 144 145 return provider; 146 } 147 148 public static String asString(final Feature feature) { 149 assert feature != null; 150 151 StringBuffer buff = new StringBuffer(); 152 153 buff.append("["); 154 buff.append(feature.key()); 155 buff.append("]"); 156 157 // noinspection StringEquality 158 if (feature.key() != feature.name()) { 159 buff.append(" '"); 160 buff.append(feature.name()); 161 buff.append("'"); 162 } 163 164 buff.append(" (supported: "); 165 buff.append(feature.supported()); 166 buff.append(", type: "); 167 buff.append(feature.getClass().getName()); 168 buff.append(")"); 169 170 return buff.toString(); 171 } 172 }