View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.archetype;
20  
21  import javax.inject.Inject;
22  import javax.inject.Named;
23  import javax.inject.Singleton;
24  
25  import java.io.File;
26  import java.io.FileInputStream;
27  import java.io.IOException;
28  import java.nio.file.Files;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.zip.ZipEntry;
32  import java.util.zip.ZipOutputStream;
33  
34  import org.apache.maven.archetype.catalog.Archetype;
35  import org.apache.maven.archetype.catalog.ArchetypeCatalog;
36  import org.apache.maven.archetype.creator.ArchetypeCreator;
37  import org.apache.maven.archetype.generator.ArchetypeGenerator;
38  import org.apache.maven.archetype.source.ArchetypeDataSource;
39  import org.apache.maven.archetype.source.ArchetypeDataSourceException;
40  import org.codehaus.plexus.util.IOUtil;
41  import org.eclipse.aether.RepositorySystemSession;
42  import org.eclipse.aether.repository.RemoteRepository;
43  import org.slf4j.Logger;
44  import org.slf4j.LoggerFactory;
45  
46  /**
47   * @author Jason van Zyl
48   */
49  @Named
50  @Singleton
51  public class DefaultArchetypeManager implements ArchetypeManager {
52      private static final Logger LOGGER = LoggerFactory.getLogger(DefaultArchetypeManager.class);
53  
54      @Inject
55      @Named("fileset")
56      private ArchetypeCreator creator;
57  
58      @Inject
59      private ArchetypeGenerator generator;
60  
61      @Inject
62      private Map<String, ArchetypeDataSource> archetypeSources;
63  
64      @Override
65      public ArchetypeCreationResult createArchetypeFromProject(ArchetypeCreationRequest request) {
66          ArchetypeCreationResult result = new ArchetypeCreationResult();
67  
68          creator.createArchetype(request, result);
69  
70          return result;
71      }
72  
73      @Override
74      public ArchetypeGenerationResult generateProjectFromArchetype(ArchetypeGenerationRequest request) {
75          ArchetypeGenerationResult result = new ArchetypeGenerationResult();
76  
77          generator.generateArchetype(request, result);
78  
79          return result;
80      }
81  
82      @Override
83      public File archiveArchetype(File archetypeDirectory, File outputDirectory, String finalName) throws IOException {
84          File jarFile = new File(outputDirectory, finalName + ".jar");
85  
86          zip(archetypeDirectory, jarFile);
87  
88          return jarFile;
89      }
90  
91      public void zip(File sourceDirectory, File archive) throws IOException {
92          if (!archive.getParentFile().exists()) {
93              archive.getParentFile().mkdirs();
94          }
95  
96          if (!archive.exists() && !archive.createNewFile()) {
97              LOGGER.warn("Could not create new file \"" + archive.getPath() + "\" or the file already exists.");
98          }
99  
100         try (ZipOutputStream zos = new ZipOutputStream(Files.newOutputStream(archive.toPath()))) {
101             zos.setLevel(9);
102 
103             zipper(zos, sourceDirectory.getAbsolutePath().length(), sourceDirectory);
104         }
105     }
106 
107     private void zipper(ZipOutputStream zos, int offset, File currentSourceDirectory) throws IOException {
108         File[] files = currentSourceDirectory.listFiles();
109 
110         if (files.length == 0) {
111             // add an empty directory
112             String dirName = currentSourceDirectory.getAbsolutePath().substring(offset + 1);
113 
114             if (File.separatorChar != '/') {
115                 dirName = dirName.replace('\\', '/');
116             }
117 
118             zos.putNextEntry(new ZipEntry(dirName + '/'));
119         }
120 
121         for (int i = 0; i < files.length; i++) {
122             if (files[i].isDirectory()) {
123                 zipper(zos, offset, files[i]);
124             } else {
125                 String fileName = files[i].getAbsolutePath().substring(offset + 1);
126 
127                 if (File.separatorChar != '/') {
128                     fileName = fileName.replace('\\', '/');
129                 }
130 
131                 ZipEntry e = new ZipEntry(fileName);
132 
133                 zos.putNextEntry(e);
134 
135                 try (FileInputStream is = new FileInputStream(files[i])) {
136                     IOUtil.copy(is, zos);
137                 }
138 
139                 zos.closeEntry();
140             }
141         }
142     }
143 
144     @Override
145     public ArchetypeCatalog getInternalCatalog() {
146         try {
147             ArchetypeDataSource source = archetypeSources.get("internal-catalog");
148 
149             return source.getArchetypeCatalog(null, null);
150         } catch (ArchetypeDataSourceException e) {
151             LOGGER.warn("failed to read catalog: " + e.getMessage(), LOGGER.isDebugEnabled() ? e : null);
152             return new ArchetypeCatalog();
153         }
154     }
155 
156     @Override
157     public ArchetypeCatalog getLocalCatalog(RepositorySystemSession repositorySession) {
158         try {
159             ArchetypeDataSource source = archetypeSources.get("catalog");
160 
161             return source.getArchetypeCatalog(repositorySession, null);
162         } catch (ArchetypeDataSourceException e) {
163             LOGGER.warn("failed to read catalog: " + e.getMessage(), LOGGER.isDebugEnabled() ? e : null);
164             return new ArchetypeCatalog();
165         }
166     }
167 
168     @Override
169     public ArchetypeCatalog getRemoteCatalog(
170             RepositorySystemSession repositorySession, List<RemoteRepository> remoteRepositories) {
171         try {
172             ArchetypeDataSource source = archetypeSources.get("remote-catalog");
173 
174             return source.getArchetypeCatalog(repositorySession, remoteRepositories);
175         } catch (ArchetypeDataSourceException e) {
176             LOGGER.warn("failed to download from remote" + e.getMessage(), LOGGER.isDebugEnabled() ? e : null);
177             return new ArchetypeCatalog();
178         }
179     }
180 
181     @Override
182     public File updateLocalCatalog(RepositorySystemSession repositorySystemSession, Archetype archetype) {
183         try {
184             ArchetypeDataSource source = archetypeSources.get("catalog");
185 
186             return source.updateCatalog(repositorySystemSession, archetype);
187         } catch (ArchetypeDataSourceException e) {
188             LOGGER.warn("failed to update catalog", e);
189         }
190         return null;
191     }
192 }