| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| package org.netbeans.modules.maven.newproject; |
| |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Enumeration; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Objects; |
| import java.util.regex.Pattern; |
| import org.netbeans.api.progress.ProgressHandle; |
| import org.netbeans.api.project.Project; |
| import org.netbeans.api.project.ProjectInformation; |
| import org.netbeans.api.project.ProjectManager; |
| import org.netbeans.api.templates.CreateDescriptor; |
| import org.netbeans.modules.maven.api.archetype.ProjectInfo; |
| import org.netbeans.modules.maven.model.Utilities; |
| import org.netbeans.modules.maven.model.pom.POMModel; |
| import org.netbeans.modules.maven.model.pom.POMModelFactory; |
| import org.netbeans.modules.xml.xam.ModelSource; |
| import org.netbeans.spi.project.ActionProgress; |
| import org.netbeans.spi.project.ActionProvider; |
| import org.netbeans.spi.project.ui.support.CommonProjectActions; |
| import org.openide.filesystems.FileObject; |
| import org.openide.filesystems.FileUtil; |
| import org.openide.util.Lookup; |
| import org.openide.util.NbBundle; |
| import org.openide.util.lookup.Lookups; |
| import org.openide.util.lookup.ProxyLookup; |
| |
| public final class TemplateUtils { |
| /** |
| * Archetype to be used with the template. |
| */ |
| public static final String PARAM_ARCHETYPE = "archetype"; // NOI18N |
| |
| /** |
| * Artifact ID for the new project. |
| */ |
| public static final String PARAM_ARTIFACT_ID = "artifactId"; // NOI18N |
| |
| /** |
| * Group ID for the new project. |
| */ |
| public static final String PARAM_GROUP_ID = "groupId"; // NOI18N |
| |
| /** |
| * Packaging for a project template. |
| */ |
| public static final String PARAM_PACKAGING = "packaging"; // NOI18N |
| |
| /** |
| * Version for the new project, will default to {@link #PARAM_VERSION_DEFAULT 1.0-SNAPSHOT} if not specified. |
| */ |
| public static final String PARAM_VERSION = "version"; // NOI18N |
| |
| /** |
| * Base package for the sources in the project |
| */ |
| public static final String PARAM_PACKAGE = "package"; // NOI18N |
| |
| /** |
| * Version for the new project, will default to 1.0-SNAPSHOT if not specified. |
| */ |
| public static final String PARAM_VERSION_DEFAULT = "1.0-SNAPSHOT"; // NOI18N |
| |
| /** |
| * Files to open after project creation. Comma-delimited list of |
| * file names, relative to the template directory. |
| */ |
| public static final String PARAM_TO_OPEN = "openFiles"; // NOI18N |
| |
| /** |
| * If the parameter value is {@link Boolean#TRUE}, will <b>build</b> |
| * the project. |
| */ |
| public static final String PARAM_INITIAL_BUILD = "buildAfterCreate"; // NOI18N |
| |
| /** |
| * If the parameter value is {@link Boolean#TRUE}, will prime the project, |
| * downloading the necessary dependent artifacts. |
| */ |
| public static final String PARAM_INITIAL_PRIME = "primedAfterCreate"; // NOI18N |
| |
| /** |
| * Name of the created main class. |
| */ |
| public static final String PARAM_MAIN_CLASS_NAME = "mainClassName"; // NOI18N |
| |
| /** |
| * The target directory |
| */ |
| public static final String PARAM_PROJDIR = CommonProjectActions.PROJECT_PARENT_FOLDER; |
| |
| private TemplateUtils() {} |
| |
| /** |
| * Performs post-creation tasks, like priming, build or file opens. |
| */ |
| @NbBundle.Messages({ |
| "# {0} - project name", |
| "ProgressTitleBuild=Building project {0}", |
| "# {0} - project name", |
| "ProgressTitlePrime=Priming project {0}", |
| "# {0} - project name", |
| "ProgressTitleBuildFailed=Failed to build project {0}", |
| "# {0} - project name", |
| "ProgressTitlePrimeFailed=Failed to prime project {0}" |
| }) |
| public static List<FileObject> afterTemplateCreation( |
| Map<Object, Object> additionalProperties, |
| CreateDescriptor desc, List<FileObject> fos, FileObject fo) throws IOException { |
| List<FileObject> pomDirs = new ArrayList<>(); |
| collectPomDirs(fo, pomDirs); |
| if (fos != null) { |
| pomDirs.addAll(fos); |
| } |
| setMainClass(additionalProperties, fo); |
| |
| // compatibility with older archetype handler |
| if (fos != null) { |
| String toOpen = Objects.toString(additionalProperties.get("archetypeOpen"), null); // NOI18N |
| if (toOpen == null) { |
| toOpen = desc.getValue(TemplateUtils.PARAM_TO_OPEN); |
| } |
| if (toOpen != null) { |
| collectFiles(fo, fos, toOpen.split(",")); // NOI18N |
| } |
| } |
| // compatibility with older archetype handler |
| boolean enableBuild = Boolean.valueOf( |
| Objects.toString( |
| additionalProperties.getOrDefault("archetypeBuild", // NOI18N |
| desc.getValue(PARAM_INITIAL_BUILD) |
| ), |
| null)); |
| |
| boolean enablePrime = Boolean.valueOf(desc.getValue(PARAM_INITIAL_PRIME)); |
| |
| if (enableBuild || enablePrime) { |
| Project prj = ProjectManager.getDefault().findProject(fo); |
| ActionProvider ap = prj == null ? null : prj.getLookup().lookup(ActionProvider.class); |
| if (ap != null) { |
| Lookup actionLookup = desc.getLookup(); |
| if (actionLookup == null || actionLookup == Lookup.EMPTY) { |
| actionLookup = prj.getLookup(); |
| } |
| |
| final String command = |
| enableBuild ? ActionProvider.COMMAND_BUILD : |
| enablePrime ? ActionProvider.COMMAND_PRIME : |
| null; |
| if (command != null) { |
| ActionProgress prg = actionLookup.lookup(ActionProgress.class); |
| if (prg == null) { |
| ProgressHandle h = actionLookup.lookup(ProgressHandle.class); |
| if (h != null) { |
| // ProgressHandle is not null ; so let's add reporting based on ActionProgress |
| // that will use ProgressHandle |
| ProjectInformation info = prj.getLookup().lookup(ProjectInformation.class); |
| String pn = info != null ? info.getDisplayName() : info.getName(); |
| if (pn == null) { |
| if (desc.getName() == null) { |
| pn = desc.getProposedName(); |
| } |
| } |
| final String fpn = pn; |
| prg = new ActionProgress() { |
| @Override |
| protected void started() { |
| h.progress(enableBuild ? |
| Bundle.ProgressTitleBuild(fpn) : Bundle.ProgressTitlePrime(fpn) |
| ); |
| } |
| |
| @Override |
| public void finished(boolean success) { |
| if (success) { |
| return; |
| } |
| h.progress(enableBuild ? |
| Bundle.ProgressTitleBuildFailed(fpn) : Bundle.ProgressTitlePrimeFailed(fpn) |
| ); |
| } |
| |
| }; |
| actionLookup = new ProxyLookup(actionLookup, Lookups.fixed(prg)); |
| } |
| } |
| ap.invokeAction(command, actionLookup); |
| } |
| } |
| } |
| return pomDirs; |
| } |
| |
| private static void collectPomDirs(FileObject dir, Collection<? super FileObject> found) { |
| if (dir == null || !dir.isFolder()) { |
| return; |
| } |
| if (dir.getFileObject("pom.xml") == null) { // NOI18N |
| return; |
| } |
| found.add(dir); |
| for (FileObject f : dir.getChildren()) { |
| collectPomDirs(f, found); |
| } |
| } |
| |
| static void collectFiles(FileObject root, Collection<? super FileObject> found, String... includes) { |
| Pattern[] check = new Pattern[includes.length]; |
| for (int i = 0; i < check.length; i++) { |
| check[i] = Pattern.compile(includes[i]); |
| } |
| |
| Enumeration<? extends FileObject> en = root.getChildren(true); |
| while (en.hasMoreElements()) { |
| FileObject fo = en.nextElement(); |
| String relPath = FileUtil.getRelativePath(root, fo); |
| if (relPath == null) { |
| continue; |
| } |
| for (Pattern p : check) { |
| if (p.matcher(relPath).matches()) { |
| found.add(fo); |
| break; |
| } |
| } |
| } |
| } |
| |
| private static void setMainClass(Map<Object, Object> properties, FileObject fo) { |
| FileObject pom = fo.getFileObject("pom.xml"); // NOI18N |
| if (pom != null) { |
| ModelSource modelSource = Utilities.createModelSource(pom); |
| POMModel model = POMModelFactory.getDefault().getModel(modelSource); |
| org.netbeans.modules.maven.model.pom.Project root = model.getProject(); |
| if (root != null) { |
| if (model.startTransaction()) { |
| try { |
| org.netbeans.modules.maven.model.pom.Properties props = root.getProperties(); |
| if (props == null) { |
| props = model.getFactory().createProperties(); |
| root.setProperties(props); |
| } |
| String packageName = (String) properties.get(TemplateUtils.PARAM_PACKAGE); |
| String mainClass = (String) properties.get(TemplateUtils.PARAM_MAIN_CLASS_NAME); |
| if (mainClass == null || mainClass.isEmpty()) { |
| mainClass = "App"; // NOI18N |
| } |
| if (packageName != null && !packageName.isEmpty()) { |
| mainClass = packageName + '.' + mainClass; |
| } |
| props.setProperty("exec.mainClass", mainClass); // NOI18N |
| } finally { |
| model.endTransaction(); |
| try { |
| Utilities.saveChanges(model); |
| } catch (IOException ex) {} |
| } |
| } |
| } |
| } |
| } |
| |
| @NbBundle.Messages({ |
| "MSG_NoArtifactId=No artifactId attribute specified for the Maven project" |
| }) |
| public static ProjectInfo createProjectInfo(String name, Map<String, Object> vals) throws IOException { |
| String artifact = (String)vals.getOrDefault(TemplateUtils.PARAM_ARTIFACT_ID, name); |
| String group = (String)vals.get(TemplateUtils.PARAM_GROUP_ID); |
| String version = (String)vals.getOrDefault(TemplateUtils.PARAM_VERSION, TemplateUtils.PARAM_VERSION_DEFAULT); |
| String pkg = (String)vals.get(TemplateUtils.PARAM_PACKAGE); |
| |
| if (artifact == null) { |
| throw new IOException(Bundle.MSG_NoArtifactId()); |
| } |
| if (group == null) { |
| group = findGroupId(pkg, artifact); |
| } |
| if (group == null) { |
| throw new IOException(Bundle.MSG_NoGroupId()); |
| } |
| return new ProjectInfo(group, artifact, version, pkg); |
| } |
| |
| private static String findGroupId(String pkg, String name) { |
| if (pkg != null && pkg.endsWith("." + name)) { |
| return pkg.substring(0, pkg.length() - 1 - name.length()); |
| } else { |
| return pkg; |
| } |
| } |
| } |