001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *  http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    
020    package org.apache.geronimo.plugin.car;
021    
022    import org.apache.geronimo.kernel.config.InvalidConfigException;
023    import org.apache.geronimo.kernel.config.NoSuchConfigException;
024    import org.apache.geronimo.kernel.config.ConfigurationData;
025    import org.apache.geronimo.kernel.repository.Artifact;
026    import org.apache.geronimo.kernel.repository.ArtifactManager;
027    import org.apache.geronimo.kernel.repository.ArtifactResolver;
028    import org.apache.geronimo.kernel.repository.DefaultArtifactManager;
029    import org.apache.geronimo.kernel.repository.Environment;
030    import org.apache.geronimo.kernel.repository.FileWriteMonitor;
031    import org.apache.geronimo.kernel.repository.Dependency;
032    import org.apache.geronimo.kernel.repository.WritableListableRepository;
033    import org.apache.geronimo.system.repository.Maven2Repository;
034    import org.apache.geronimo.system.configuration.RepositoryConfigurationStore;
035    import org.apache.geronimo.system.resolver.ExplicitDefaultArtifactResolver;
036    
037    import org.apache.maven.artifact.repository.ArtifactRepository;
038    import org.apache.maven.plugin.logging.Log;
039    
040    import java.io.File;
041    import java.io.FileInputStream;
042    import java.io.IOException;
043    import java.io.InputStream;
044    import java.io.BufferedInputStream;
045    
046    import java.util.Iterator;
047    import java.util.HashSet;
048    import java.util.LinkedHashSet;
049    import java.util.Set;
050    import java.util.Collections;
051    
052    /**
053     * Installs CAR files into a target repository to support assembly.
054     *
055     * @goal installConfig
056     * 
057     * @version $Rev: 451661 $ $Date: 2006-09-30 13:45:53 -0700 (Sat, 30 Sep 2006) $
058     */
059    public class InstallConfigMojo
060        extends AbstractCarMojo
061    {
062        /**
063         * Root file of the TargetRepository.
064         *
065         * @parameter expression="${project.build.directory}"
066         */
067        private String targetRoot = null;
068    
069        /**
070         * The location of the target repository relative to targetRoot.
071         * 
072         * @parameter default-value="archive-tmp/repository"
073         * @required
074         */
075        private String targetRepository = null;
076    
077        /**
078         * Configuration to be installed specified as groupId/artifactId/version/type
079         * if none specified, plugin will install all dependencies of type "car"
080         *
081         * @parameter
082         * @optional
083         */
084        private String artifact = null;
085    
086        /**
087         * Location of the source repository for the dependencies
088         *
089         * @parameter expression="${localRepository}"
090         * @required
091         */
092        private ArtifactRepository sourceRepository = null;
093        
094        /**
095         * The location where the properties mapping will be generated.
096         *
097         * @parameter expression="${project.build.directory}/explicit-versions.properties"
098         * @required
099         */
100        private File explicitResolutionProperties = null;
101    
102        /**
103         * The Geronimo repository artifact resolver.
104         *
105         * <p>
106         * Using a custom name here to prevent problems that happen when Plexus
107         * injects the Maven resolver into the base-class.
108         */
109        private ArtifactResolver geronimoArtifactResolver;
110    
111        private WritableListableRepository targetRepo;
112    
113        private RepositoryConfigurationStore targetStore;
114    
115        private WritableListableRepository sourceRepo;
116    
117        private RepositoryConfigurationStore sourceStore;
118    
119        protected void doExecute() throws Exception {
120            generateExplicitVersionProperties(explicitResolutionProperties);
121            
122            sourceRepo = new Maven2Repository(new File(sourceRepository.getBasedir()));
123            sourceStore = new RepositoryConfigurationStore(sourceRepo);
124    
125            File targetRepoFile = new File(targetRoot, targetRepository);
126            if (!targetRepoFile.exists()) {
127                targetRepoFile.mkdirs();
128            }
129            
130            targetRepo = new Maven2Repository(targetRepoFile);
131            targetStore = new RepositoryConfigurationStore(targetRepo);
132    
133            Artifact configId;
134            ArtifactManager artifactManager = new DefaultArtifactManager();
135            geronimoArtifactResolver = new ExplicitDefaultArtifactResolver(
136                explicitResolutionProperties.getPath(),
137                artifactManager,
138                Collections.singleton(sourceRepo),
139                null);
140    
141            if ( artifact != null ) {
142                configId = Artifact.create(artifact);
143                execute(configId);
144            }
145            else {
146                Iterator itr = getDependencies().iterator();
147                while (itr.hasNext()) {
148                    org.apache.maven.artifact.Artifact mavenArtifact = (org.apache.maven.artifact.Artifact) itr.next();
149                    if ("car".equals(mavenArtifact.getType())) {
150                        configId = new Artifact(mavenArtifact.getGroupId(), mavenArtifact.getArtifactId(), mavenArtifact.getVersion(), "car");
151                        execute(configId);
152                    }
153                }
154            }
155        }
156    
157        /**
158         * Retrieves all artifact dependencies.
159         *
160         * @return A HashSet of artifacts
161         */
162        protected Set getDependencies() {
163            Set dependenciesSet = new HashSet();
164    
165            if (project.getArtifact() != null && project.getArtifact().getFile() != null) {
166                dependenciesSet.add(project.getArtifact());
167            }
168    
169            Set projectArtifacts = project.getArtifacts();
170            if (projectArtifacts != null) {
171                dependenciesSet.addAll(projectArtifacts);
172            }
173    
174            return dependenciesSet;
175        }
176    
177        private void execute(final Artifact configArtifact) throws Exception {
178            assert configArtifact != null;
179    
180            LinkedHashSet dependencies;
181    
182            StartFileWriteMonitor monitor = new StartFileWriteMonitor(log);
183    
184            // does this configuration exist?
185            if (!sourceRepo.contains(configArtifact)) {
186                throw new NoSuchConfigException(configArtifact);
187            }
188    
189            // is this config already installed?
190            if (targetStore.containsConfiguration(configArtifact)) {
191                log.info("Configuration already present in configuration store: " + configArtifact);
192                return;
193            }
194    
195            if (sourceStore.containsConfiguration(configArtifact)) {
196                // Copy the configuration into the target configuration store
197                if (!targetStore.containsConfiguration(configArtifact)) {
198                    File sourceFile = sourceRepo.getLocation(configArtifact);
199                    InputStream in = new BufferedInputStream(new FileInputStream(sourceFile));
200                    try {
201                        targetStore.install(in, (int)sourceFile.length(), configArtifact, monitor);
202                    }
203                    finally {
204                        in.close();
205                    }
206                }
207    
208                // Determine the dependencies of this configuration
209                try {
210                    ConfigurationData configurationData = targetStore.loadConfiguration(configArtifact);
211                    Environment environment = configurationData.getEnvironment();
212                    dependencies = new LinkedHashSet();
213                    for (Iterator iterator = environment.getDependencies().iterator(); iterator.hasNext();) {
214                        Dependency dependency = (Dependency) iterator.next();
215                        dependencies.add(dependency.getArtifact());
216                    }
217    
218                    log.info("Installed configuration: " + configArtifact);
219                }
220                catch (IOException e) {
221                    throw new InvalidConfigException("Unable to load configuration: " + configArtifact, e);
222                }
223                catch (NoSuchConfigException e) {
224                    throw new InvalidConfigException("Unable to load configuration: " + configArtifact, e);
225                }
226            }
227            else {
228                if (!sourceRepo.contains(configArtifact)) {
229                    throw new RuntimeException("Dependency: " + configArtifact + " not found in local maven repo: for configuration: " + this.artifact);
230                }
231    
232                // Copy the artifact into the target repo
233                if (!targetRepo.contains(configArtifact)) {
234                    File sourceFile = sourceRepo.getLocation(configArtifact);
235                    InputStream in = new BufferedInputStream(new FileInputStream(sourceFile));
236                    try {
237                        targetRepo.copyToRepository(in, (int)sourceFile.length(), configArtifact, monitor);
238                    }
239                    finally {
240                        in.close();
241                    }
242                }
243    
244                // Determine the dependencies of this artifact
245                dependencies = sourceRepo.getDependencies(configArtifact);
246            }
247            
248            dependencies = geronimoArtifactResolver.resolveInClassLoader(dependencies);
249            for (Iterator iterator = dependencies.iterator(); iterator.hasNext();) {
250                Artifact a = (Artifact)iterator.next();
251                execute(a);
252            }
253        }
254    
255        private static class StartFileWriteMonitor
256            implements FileWriteMonitor
257        {
258            private Log log;
259    
260            public StartFileWriteMonitor(final Log log) {
261                this.log = log;
262            }
263    
264            public void writeStarted(String fileDescription, int fileSize) {
265                log.info("Copying: " + fileDescription);
266            }
267    
268            public void writeProgress(int bytes) {
269                // ???
270            }
271    
272            public void writeComplete(int bytes) {
273                // ???
274            }
275        }
276    }