001package org.kualigan.maven.plugins.kfs;
002
003import org.apache.maven.archetype.Archetype;
004import org.apache.maven.artifact.repository.ArtifactRepository;
005import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
006import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
007import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
008import org.apache.maven.plugin.AbstractMojo;
009import org.apache.maven.plugin.MojoExecutionException;
010import org.apache.maven.project.MavenProject;
011import org.codehaus.plexus.components.interactivity.Prompter;
012import org.codehaus.plexus.util.IOUtil;
013import org.codehaus.plexus.util.StringUtils;
014
015import java.io.File;
016import java.io.FileWriter;
017import java.io.InputStream;
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022import java.util.Properties;
023
024/**
025 * Migrates an existing KFS distribution to Maven as a Prototype.
026 * 
027 * @requiresProject false
028 * @goal migrate
029 */
030public class MigrateMojo extends AbstractMojo {
031    /**
032     * @component
033     */
034    private Archetype archetype;
035
036    /**
037     * @component
038     */
039    private Prompter prompter;
040
041    /**
042     * @component
043     */
044    private ArtifactRepositoryFactory artifactRepositoryFactory;
045
046    /**
047     * @component role="org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout" roleHint="default"
048     */
049    private ArtifactRepositoryLayout defaultArtifactRepositoryLayout;
050
051
052    /**
053     * @parameter expression="${localRepository}"
054     * @required
055     */
056    private ArtifactRepository localRepository;
057    
058    /**
059     * Path for where the KFS instance is we want to migrate
060     * 
061     * @parameter expression="${kfs.local.path}"
062     * @required
063     */
064    private String kfsPath;
065
066    /**
067     * @parameter expression="${packageName}"
068     */
069    private String packageName;
070
071    /**
072     * @parameter expression="${groupId}"
073     */
074    private String groupId;
075
076    /**
077     * @parameter expression="${artifactId}"
078     */
079    private String artifactId;
080
081    /**
082     * @parameter expression="${version}" default-value="1.0-SNAPSHOT"
083     * @required
084     */
085    private String version;
086
087    /**
088     * @parameter expression="${project}"
089     */
090    private MavenProject project;
091    
092    protected void setupDefaults() throws Exception {
093        if (project.getFile() != null && groupId == null) {
094            groupId = project.getGroupId();
095        }
096
097        if(groupId==null) {
098            groupId = prompter.prompt("Enter the groupId of your institution");
099        }
100
101        if (packageName == null) {
102            getLog().info("Defaulting package to group ID: " + groupId);
103
104            packageName = groupId;
105        }
106
107        if(artifactId==null) {
108            artifactId = prompter.prompt("Enter the artifactId of your plugin");
109        }
110    }
111
112    /**
113     * The following are steps to migrating a KFS distribution to Maven:
114     * <ol>
115     *   <li>Create a staging directory to copy project resources to from the kfs maven archetype</li>
116     *   <li>Create modules core, it, and web</li>
117     *   <li>Copy java source files from work to core/src/main/java</li>
118     *   <li>Copy java source files from test to it/src/test/java</li>
119     *   <li>Copy non-java, non-web resources from work to core/src/main/resources</li>
120     *   <li>Copy non-java, non-web resources from test to it/src/test/resources</li>
121     *   <li>Copy web resources from work/web-root/ to web/src/main/webapp</li>
122     *   <li>Retrieve the latest kuali POM information and create poms in ./, core/, it/, and web/</li>
123     * </ol>
124     * 
125     * Note: When copying files, files are not overwritten. This allows us to copy the archetype first and preclude andy 
126     * settings with those from the archetype.
127     * 
128     * The basic way to understand how this works is the kfs-archetype is used to create kfs
129     * maven projects, but it is dynamically generated. Then, source files are copied to it.
130     */
131    public void execute() throws MojoExecutionException {
132        final String basedir = System.getProperty("user.dir");
133        
134        try {
135            setupDefaults();
136    
137            final Map<String, String> map = new HashMap<String, String>();
138            map.put("basedir", basedir);
139            map.put("package", packageName);
140            map.put("packageName", packageName);
141            map.put("groupId", groupId);
142            map.put("artifactId", artifactId);
143            map.put("version", version);
144
145            List archetypeRemoteRepositories = new ArrayList();
146            /* TODO: Allow remote repositories later 
147
148            if (remoteRepositories != null) {
149                getLog().info("We are using command line specified remote repositories: " + remoteRepositories);
150
151                archetypeRemoteRepositories = new ArrayList();
152
153                String[] s = StringUtils.split(remoteRepositories, ",");
154
155                for (int i = 0; i < s.length; i++) {
156                    archetypeRemoteRepositories.add(createRepository(s[i], "id" + i));
157                }
158            }*/
159
160            Properties props = new Properties();
161            props.load(getClass().getResourceAsStream("plugin.properties"));
162
163            archetype.createArchetype(
164                props.getProperty("groupId"),
165                props.getProperty("artifactId"),
166                props.getProperty("version"), localRepository,
167                archetypeRemoteRepositories, map);
168
169        } catch (Exception e) {
170            throw new MojoExecutionException("Failed to create a new Jenkins plugin",e);
171        }
172    }
173    
174    /**
175     * Copy files from the archetype into the new project into the appropriate package directories.
176     * 
177     * TODO: This method currently isn't used because files don't need to be copied yet, but it should probably get used
178     * at some point
179     */
180    protected void copyFilesFromArcheType(final String basedir) {    
181        // copy view resource files. So far maven archetype doesn't seem to be able to handle it.
182        File outDir = new File(basedir, artifactId);
183        File viewDir = new File(outDir, "src/main/resources/"+groupId.replace('.','/'));
184        viewDir.mkdirs();
185
186        for( String s : new String[]{"config.jelly","global.jelly","help-name.html"} ) {
187            // TODO: Setup filtering artifactId replacement in source files
188            // FileWriter out = new FileWriter(new File(viewDir, s));
189            // out.write(IOUtil.toString(in).replace("@artifactId@", artifactId));
190            // in.close();
191            // out.close();
192        }
193    }
194
195    /**
196     * Creates an {@link ArtifactRepository} instance. This code was borrowed from the maven-hpi-plugin
197     *  
198     * @param url
199     * @param repositoryId
200     * @return ArtifactRepository
201     */ 
202    public ArtifactRepository createRepository(String url, String repositoryId) {
203
204        String updatePolicyFlag = ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS;
205
206        String checksumPolicyFlag = ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN;
207
208        ArtifactRepositoryPolicy snapshotsPolicy =
209            new ArtifactRepositoryPolicy(true, updatePolicyFlag, checksumPolicyFlag);
210
211        ArtifactRepositoryPolicy releasesPolicy =
212            new ArtifactRepositoryPolicy(true, updatePolicyFlag, checksumPolicyFlag);
213
214        return artifactRepositoryFactory.createArtifactRepository(repositoryId, url, defaultArtifactRepositoryLayout,
215            snapshotsPolicy, releasesPolicy);
216    }
217}