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.Configuration;
020    import org.codehaus.gmaven.feature.Feature;
021    import org.codehaus.gmaven.feature.FeatureException;
022    import org.codehaus.gmaven.feature.Provider;
023    import org.codehaus.gmaven.feature.ProviderException;
024    import org.codehaus.gmaven.feature.Version;
025    import org.slf4j.Logger;
026    import org.slf4j.LoggerFactory;
027    
028    import java.util.Collection;
029    import java.util.Collections;
030    import java.util.HashMap;
031    import java.util.Iterator;
032    import java.util.Map;
033    
034    /**
035     * Provides support for {@link Provider} implementations.
036     *
037     * @version $Id: ProviderSupport.java 9 2009-07-16 09:22:08Z user57 $
038     * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
039     */
040    public abstract class ProviderSupport
041        implements Provider
042    {
043        protected final Logger log = LoggerFactory.getLogger(getClass());
044    
045        protected final String key;
046    
047        protected final Configuration config;
048    
049        protected Version version;
050    
051        protected Boolean supported;
052    
053        protected Map features;
054    
055        protected ProviderSupport(final String key, final Configuration config) {
056            assert key != null;
057            assert config != null;
058    
059            this.key = key;
060            this.config = config;
061        }
062    
063        protected ProviderSupport(final String key) {
064            this(key, new Configuration());
065        }
066    
067        public String toString() {
068            return asString(this);
069        }
070    
071        public int hashCode() {
072            return key().hashCode();
073        }
074    
075        public String key() {
076            return key;
077        }
078    
079        public String name() {
080            return key();
081        }
082    
083        protected abstract Version detectVersion();
084    
085        public synchronized Version version() {
086            if (version == null) {
087                version = detectVersion();
088            }
089    
090            return version;
091        }
092    
093        protected boolean detectSupported() {
094            return true;
095        }
096    
097        public synchronized boolean supported() {
098            if (supported == null) {
099                supported = Boolean.valueOf(detectSupported());
100            }
101    
102            return supported.booleanValue();
103        }
104    
105        public void require() {
106            if (!supported()) {
107                throw new ProviderException("Provider not supported: " + key());
108            }
109        }
110    
111        public Configuration config() {
112            return config;
113        }
114    
115        protected abstract Map detectFeatures();
116    
117        public synchronized Collection features() {
118            if (features == null) {
119                Map detected = detectFeatures();
120    
121                log.debug("Detected features:");
122    
123                for (Iterator iter = detected.values().iterator(); iter.hasNext();) {
124                    Feature feature = (Feature)iter.next();
125    
126                    log.debug("    {}", feature);
127    
128                    // If the feature is one of ours, then register ourselves and give the feature access
129                    if (feature instanceof FeatureSupport) {
130                        ((FeatureSupport)feature).register(this);
131                    }
132                }
133                
134                features = new HashMap(detected);
135            }
136    
137            return Collections.unmodifiableCollection(features.values());
138        }
139    
140        public synchronized Feature feature(final String key) {
141            assert key != null;
142    
143            // HACK: Just make the damn thing init we can get to the map
144            if (features == null) {
145                features();
146            }
147    
148            if (!features.containsKey(key)) {
149                throw new FeatureException("Unknown feature: " + key);
150            }
151            
152            return (Feature)features.get(key);
153        }
154    
155        public Feature feature(final Class key) {
156            assert key != null;
157    
158            return feature(key.getName());
159        }
160    
161        //
162        // Common Helpers
163        //
164    
165        public static String asString(final Provider provider) {
166            assert provider != null;
167    
168            StringBuffer buff = new StringBuffer();
169    
170            buff.append("[");
171            buff.append(provider.key());
172            buff.append("]");
173    
174            // noinspection StringEquality
175            if (provider.key() != provider.name()) {
176                buff.append(" '");
177                buff.append(provider.name());
178                buff.append("'");
179            }
180    
181            buff.append(" (version: ");
182            buff.append(provider.version());
183            buff.append(", type: ");
184            buff.append(provider.getClass().getName());
185            buff.append(")");
186    
187            return buff.toString();
188        }
189    }