AbstractArtifactManager.java
001 /*
002  * Copyright 2008-2015 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 package org.codehaus.griffon.runtime.core.artifact;
017 
018 import griffon.core.artifact.ArtifactHandler;
019 import griffon.core.artifact.ArtifactManager;
020 import griffon.core.artifact.GriffonArtifact;
021 import griffon.core.artifact.GriffonClass;
022 import griffon.core.injection.Injector;
023 import griffon.exceptions.ArtifactHandlerNotFoundException;
024 import griffon.exceptions.ArtifactNotFoundException;
025 import org.slf4j.Logger;
026 import org.slf4j.LoggerFactory;
027 
028 import javax.annotation.Nonnull;
029 import javax.annotation.Nullable;
030 import javax.inject.Inject;
031 import javax.inject.Provider;
032 import java.util.ArrayList;
033 import java.util.Collections;
034 import java.util.List;
035 import java.util.Map;
036 import java.util.Set;
037 import java.util.concurrent.ConcurrentHashMap;
038 
039 import static griffon.util.GriffonNameUtils.requireNonBlank;
040 import static java.util.Arrays.asList;
041 import static java.util.Objects.requireNonNull;
042 
043 /**
044  * Base implementation of the {@code ArtifactManager} interface.
045  *
046  @author Andres Almiray
047  @since 2.0.0
048  */
049 @SuppressWarnings("rawtypes")
050 public abstract class AbstractArtifactManager implements ArtifactManager {
051     protected static final String ERROR_ARTIFACT_HANDLER_NULL = "Argument 'artifactHandler' must not be null";
052     private static final String ERROR_NAME_BLANK = "Argument 'name' must not be blank";
053     private static final String ERROR_TYPE_BLANK = "Argument 'type' must not be blank";
054     private static final String ERROR_CLASS_NULL = "Argument 'clazz' must not be null";
055     private static final String ERROR_ARTIFACT_NULL = "Argument 'artifact' must not be null";
056     private static final String ERROR_FULLY_QUALIFIED_CLASSNAME_BLANK = "Argument 'fqClassName' must not be blank";
057     private static final Logger LOG = LoggerFactory.getLogger(AbstractArtifactManager.class);
058     private final Map<String, Class<? extends GriffonArtifact>[]> artifacts = new ConcurrentHashMap<>();
059     private final Map<String, ArtifactHandler> artifactHandlers = new ConcurrentHashMap<>();
060     private final Object lock = new Object[0];
061 
062     @Inject
063     private Provider<Injector> injectorProvider;
064 
065     @Nonnull
066     protected Map<String, ArtifactHandler> getArtifactHandlers() {
067         return artifactHandlers;
068     }
069 
070     @SuppressWarnings("unchecked")
071     public final void loadArtifactMetadata() {
072         Map<String, List<Class<? extends GriffonArtifact>>> loadedArtifacts = doLoadArtifactMetadata();
073 
074         synchronized (lock) {
075             for (Map.Entry<String, List<Class<? extends GriffonArtifact>>> artifactsEntry : loadedArtifacts.entrySet()) {
076                 String type = artifactsEntry.getKey();
077                 ArtifactHandler handler = artifactHandlers.get(type);
078                 if (handler == null) {
079                     throw new ArtifactHandlerNotFoundException(type);
080                 }
081                 List<Class<? extends GriffonArtifact>> list = artifactsEntry.getValue();
082                 artifacts.put(type, list.toArray(new Class[list.size()]));
083                 handler.initialize(artifacts.get(type));
084             }
085         }
086     }
087 
088     @Nonnull
089     @Override
090     public Set<String> getAllTypes() {
091         return Collections.unmodifiableSet(artifactHandlers.keySet());
092     }
093 
094     @Override
095     @Nonnull
096     @SuppressWarnings("unchecked")
097     public <A extends GriffonArtifact> A newInstance(@Nonnull GriffonClass griffonClass) {
098         try {
099             requireNonNull(griffonClass, "Argument 'griffonClass' must not be null");
100         catch (RuntimeException re) {
101             throw new ArtifactNotFoundException(re);
102         }
103 
104         return newInstance((Class<A>griffonClass.getClazz());
105     }
106 
107     @Override
108     @Nonnull
109     @SuppressWarnings("unchecked")
110     public <A extends GriffonArtifact> A newInstance(@Nonnull Class<A> clazz) {
111         if (findGriffonClass(clazz== null) {
112             throw new ArtifactNotFoundException(clazz);
113         }
114 
115         return (AinjectorProvider.get().getInstance(clazz);
116     }
117 
118     @Nonnull
119     protected abstract Map<String, List<Class<? extends GriffonArtifact>>> doLoadArtifactMetadata();
120 
121     public void registerArtifactHandler(@Nonnull ArtifactHandler artifactHandler) {
122         requireNonNull(artifactHandler, ERROR_ARTIFACT_HANDLER_NULL);
123         LOG.debug("Registering artifact handler for type '{}': {}", artifactHandler.getType(), artifactHandler);
124         synchronized (lock) {
125             artifactHandlers.put(artifactHandler.getType(), artifactHandler);
126         }
127     }
128 
129     public void unregisterArtifactHandler(@Nonnull ArtifactHandler artifactHandler) {
130         requireNonNull(artifactHandler, ERROR_ARTIFACT_HANDLER_NULL);
131         LOG.debug("Removing artifact handler for type '{}': {}", artifactHandler.getType(), artifactHandler);
132         synchronized (lock) {
133             artifactHandlers.remove(artifactHandler.getType());
134         }
135     }
136 
137     protected boolean isArtifactTypeSupported(@Nonnull String type) {
138         requireNonBlank(type, ERROR_TYPE_BLANK);
139         return artifactHandlers.get(type!= null;
140     }
141 
142     @Nullable
143     public GriffonClass findGriffonClass(@Nonnull String name, @Nonnull String type) {
144         requireNonBlank(name, ERROR_NAME_BLANK);
145         requireNonBlank(type, ERROR_TYPE_BLANK);
146         LOG.debug("Searching for griffonClass of {}:{}", type, name);
147         synchronized (lock) {
148             ArtifactHandler handler = artifactHandlers.get(type);
149             return handler != null ? handler.findClassFor(namenull;
150         }
151     }
152 
153     @Nullable
154     @SuppressWarnings({"unchecked""rawtypes"})
155     public GriffonClass findGriffonClass(@Nonnull Class<? extends GriffonArtifact> clazz, @Nonnull String type) {
156         requireNonNull(clazz, ERROR_CLASS_NULL);
157         requireNonBlank(type, ERROR_TYPE_BLANK);
158         LOG.debug("Searching for griffonClass of {}:{}", type, clazz.getName());
159         synchronized (lock) {
160             ArtifactHandler handler = artifactHandlers.get(type);
161             return handler != null ? handler.getClassFor(clazznull;
162         }
163     }
164 
165     @Nullable
166     public <A extends GriffonArtifact> GriffonClass findGriffonClass(@Nonnull A artifact) {
167         requireNonNull(artifact, ERROR_ARTIFACT_NULL);
168         synchronized (lock) {
169             return findGriffonClass(artifact.getClass());
170         }
171     }
172 
173     @Nullable
174     @SuppressWarnings({"unchecked""rawtypes"})
175     public GriffonClass findGriffonClass(@Nonnull Class<? extends GriffonArtifact> clazz) {
176         requireNonNull(clazz, ERROR_CLASS_NULL);
177         LOG.debug("Searching for griffonClass of {}", clazz.getName());
178         synchronized (lock) {
179             for (ArtifactHandler handler : artifactHandlers.values()) {
180                 GriffonClass griffonClass = handler.getClassFor(clazz);
181                 if (griffonClass != nullreturn griffonClass;
182             }
183         }
184         return null;
185     }
186 
187     @Nullable
188     public GriffonClass findGriffonClass(@Nonnull String fqClassName) {
189         requireNonBlank(fqClassName, ERROR_FULLY_QUALIFIED_CLASSNAME_BLANK);
190         LOG.debug("Searching for griffonClass of {}", fqClassName);
191         synchronized (lock) {
192             for (ArtifactHandler handler : artifactHandlers.values()) {
193                 GriffonClass griffonClass = handler.getClassFor(fqClassName);
194                 if (griffonClass != nullreturn griffonClass;
195             }
196         }
197         return null;
198     }
199 
200     @Nonnull
201     public List<GriffonClass> getClassesOfType(@Nonnull String type) {
202         requireNonBlank(type, ERROR_TYPE_BLANK);
203         synchronized (lock) {
204             if (artifacts.containsKey(type)) {
205                 return asList(artifactHandlers.get(type).getClasses());
206             }
207         }
208         return EMPTY_GRIFFON_CLASS_LIST;
209     }
210 
211     @Nonnull
212     public List<GriffonClass> getAllClasses() {
213         List<GriffonClass> all = new ArrayList<>();
214         synchronized (lock) {
215             for (ArtifactHandler handler : artifactHandlers.values()) {
216                 all.addAll(asList(handler.getClasses()));
217             }
218         }
219         return Collections.unmodifiableList(all);
220     }
221 
222     protected <A extends GriffonArtifact> boolean isClassOfType(@Nonnull String type, @Nonnull Class<A> clazz) {
223         for (Class<? extends GriffonArtifact> klass : artifacts.get(type)) {
224             if (klass.getName().equals(clazz.getName())) {
225                 return true;
226             }
227         }
228         return false;
229     }
230 }