Java tutorial
/******************************************************************************* * Copyright (c) 2016 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.fusesource.ide.projecttemplates.wizards; import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.InvocationTargetException; import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.Set; import org.apache.maven.model.Build; import org.apache.maven.model.Model; import org.apache.maven.model.Plugin; import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.Xpp3DomBuilder; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.MessageDialogWithToggle; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.OpenStrategy; import org.eclipse.m2e.core.MavenPlugin; import org.eclipse.m2e.core.internal.IMavenConstants; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IPerspectiveDescriptor; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPreferenceConstants; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.WorkbenchException; import org.eclipse.ui.ide.IDE; import org.eclipse.ui.internal.ide.IDEInternalPreferences; import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; import org.eclipse.ui.internal.util.PrefUtil; import org.eclipse.ui.internal.wizards.newresource.ResourceMessages; import org.fusesource.ide.camel.editor.utils.CamelUtils; import org.fusesource.ide.camel.model.service.core.util.CamelFilesFinder; import org.fusesource.ide.camel.model.service.core.util.JavaCamelFilesFinder; import org.fusesource.ide.projecttemplates.adopters.AbstractProjectTemplate; import org.fusesource.ide.projecttemplates.impl.simple.EmptyProjectTemplate; import org.fusesource.ide.projecttemplates.internal.Messages; import org.fusesource.ide.projecttemplates.internal.ProjectTemplatesActivator; import org.fusesource.ide.projecttemplates.util.BasicProjectCreator; import org.fusesource.ide.projecttemplates.util.BuildAndRefreshJobWaiterUtil; import org.fusesource.ide.projecttemplates.util.NewProjectMetaData; /** * @author Aurelien Pupier * */ public final class FuseIntegrationProjectCreatorRunnable implements IRunnableWithProgress { public static final String FUSE_PERSPECTIVE_ID = "org.fusesource.ide.branding.perspective"; //$NON-NLS-1$ private static final String ORG_APACHE_FELIX = "org.apache.felix"; private static final String MAVEN_BUNDLE_PLUGIN = "maven-bundle-plugin"; private final NewProjectMetaData metadata; private boolean isJavaEditorToOpen = false; /** * @param metadata */ public FuseIntegrationProjectCreatorRunnable(NewProjectMetaData metadata) { this.metadata = metadata; } @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.FuseIntegrationProjectCreatorRunnable_CreatingTheProjectMonitorMessage, 7); // first create the project skeleton BasicProjectCreator c = new BasicProjectCreator(metadata); boolean ok = c.create(subMonitor.newChild(1)); IProject prj = c.getProject(); if (ok) { // then configure the project for the given template AbstractProjectTemplate template = metadata.getTemplate(); if (metadata.isBlankProject()) { // we create a blank project template = new EmptyProjectTemplate(); } // now execute the template try { template.create(prj, metadata, subMonitor.newChild(1)); } catch (CoreException ex) { ProjectTemplatesActivator.pluginLog().logError("Unable to create project...", ex); //$NON-NLS-1$ } } // switch perspective if needed IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); IPerspectiveDescriptor finalPersp = PlatformUI.getWorkbench().getPerspectiveRegistry() .findPerspectiveWithId(FUSE_PERSPECTIVE_ID); IPerspectiveDescriptor currentPersp = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage() .getPerspective(); final boolean switchPerspective = currentPersp.getId().equals(finalPersp.getId()) ? false : confirmPerspectiveSwitch(workbenchWindow, finalPersp); if (switchPerspective) { // switch to Fuse perspective if necessary. switchToFusePerspective(workbenchWindow); subMonitor.worked(1); } // refresh try { prj.refreshLocal(IProject.DEPTH_INFINITE, subMonitor.newChild(1)); // update the pom maven bundle plugin config to reflect project name as Bundle-(Symbolic)Name updateBundlePluginConfiguration(prj, subMonitor.newChild(1)); } catch (CoreException ex) { ProjectTemplatesActivator.pluginLog().logError(ex); } // delete invalid MANIFEST files IResource rs = prj.findMember("src/META-INF/"); //$NON-NLS-1$ if (rs != null && rs.exists()) { try { rs.delete(true, subMonitor.newChild(1)); } catch (CoreException ex) { ProjectTemplatesActivator.pluginLog().logError(ex); } } // finally open the camel context file openCamelContextFile(prj, subMonitor.newChild(1)); subMonitor.done(); } /** * responsible to update the manifest.mf to use the project name as Bundle-SymbolicName * * @param project * @param monitor * @throws CoreException */ protected void updateBundlePluginConfiguration(IProject project, IProgressMonitor monitor) throws CoreException { try { File pomFile = project.getFile(IMavenConstants.POM_FILE_NAME).getLocation().toFile(); Model pomModel = MavenPlugin.getMaven().readModel(pomFile); customizeBundlePlugin(pomModel, project); try (OutputStream out = new BufferedOutputStream(new FileOutputStream(pomFile))) { MavenPlugin.getMaven().writeModel(pomModel, out); project.getFile(IMavenConstants.POM_FILE_NAME).refreshLocal(IResource.DEPTH_ZERO, monitor); } } catch (CoreException | XmlPullParserException | IOException e1) { ProjectTemplatesActivator.pluginLog().logError(e1); } } private void customizeBundlePlugin(Model pomModel, IProject project) throws XmlPullParserException, IOException { Build build = pomModel.getBuild(); Map<String, Plugin> pluginsByName = build.getPluginsAsMap(); Plugin plugin = pluginsByName.get(ORG_APACHE_FELIX + ":" + MAVEN_BUNDLE_PLUGIN); //$NON-NLS-1$ if (plugin != null) { manageConfigurations(plugin, project, pomModel); } } private void manageConfigurations(Plugin plugin, IProject project, Model pomModel) throws XmlPullParserException, IOException { Xpp3Dom config = (Xpp3Dom) plugin.getConfiguration(); if (config == null) { config = Xpp3DomBuilder.build(new ByteArrayInputStream(("<configuration>" + //$NON-NLS-1$ "</configuration>").getBytes(StandardCharsets.UTF_8)), //$NON-NLS-1$ StandardCharsets.UTF_8.name()); plugin.setConfiguration(config); } manageInstructions(config, project, pomModel); } private void manageInstructions(Xpp3Dom config, IProject project, Model pomModel) throws XmlPullParserException, IOException { Xpp3Dom instructions = config.getChild("instructions"); //$NON-NLS-1$ if (instructions == null) { instructions = Xpp3DomBuilder.build(new ByteArrayInputStream(("<instructions>" + //$NON-NLS-1$ "</instructions>").getBytes(StandardCharsets.UTF_8)), //$NON-NLS-1$ StandardCharsets.UTF_8.name()); config.addChild(instructions); } manageCustomInstructions(instructions, project, pomModel); } private void manageCustomInstructions(Xpp3Dom instructions, IProject project, Model pomModel) throws XmlPullParserException, IOException { Xpp3Dom bundleSymbolicName = instructions.getChild("Bundle-SymbolicName"); //$NON-NLS-1$ if (bundleSymbolicName == null) { bundleSymbolicName = Xpp3DomBuilder.build( new ByteArrayInputStream( ("<Bundle-SymbolicName>" + getBundleSymbolicNameForProjectName(project.getName()) //$NON-NLS-1$ + "</Bundle-SymbolicName>").getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8.name()); instructions.addChild(bundleSymbolicName); } String description = pomModel.getDescription(); String desc = description != null && description.trim().length() > 0 ? description : String.format("%s.%s", pomModel.getGroupId(), pomModel.getArtifactId()); Xpp3Dom bundleName = instructions.getChild("Bundle-Name"); //$NON-NLS-1$ if (bundleName == null) { bundleName = Xpp3DomBuilder.build( new ByteArrayInputStream( ("<Bundle-Name>" + String.format("%s [%s]", desc, project.getName()) + "</Bundle-Name>") //$NON-NLS-1$ .getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8.name()); instructions.addChild(bundleName); } } /** * converts a project name into a bundle symbolic name * * @param projectName * @return */ public String getBundleSymbolicNameForProjectName(String projectName) { return projectName.replaceAll("[^a-zA-Z0-9-_]", ""); } /** * Switches, if necessary, the perspective of active workbench window to * Fuse perspective. * * @param workbenchWindow */ void switchToFusePerspective(final IWorkbenchWindow workbenchWindow) { IPerspectiveDescriptor activePerspective = workbenchWindow.getActivePage().getPerspective(); if (activePerspective == null || !activePerspective.getId().equals(FUSE_PERSPECTIVE_ID)) { workbenchWindow.getShell().getDisplay().syncExec(new Runnable() { @Override public void run() { try { workbenchWindow.getWorkbench().showPerspective(FUSE_PERSPECTIVE_ID, workbenchWindow); } catch (WorkbenchException e) { ProjectTemplatesActivator.pluginLog().logError(e); } } }); } } /** * Prompts the user for whether to switch perspectives. * * @param window * The workbench window in which to switch perspectives; must not * be <code>null</code> * @param finalPersp * The perspective to switch to; must not be <code>null</code>. * * @return <code>true</code> if it's OK to switch, <code>false</code> * otherwise */ private boolean confirmPerspectiveSwitch(IWorkbenchWindow window, IPerspectiveDescriptor finalPersp) { IPreferenceStore store = IDEWorkbenchPlugin.getDefault().getPreferenceStore(); String pspm = store.getString(IDEInternalPreferences.PROJECT_SWITCH_PERSP_MODE); if (!IDEInternalPreferences.PSPM_PROMPT.equals(pspm)) { // Return whether or not we should always switch return IDEInternalPreferences.PSPM_ALWAYS.equals(pspm); } String desc = finalPersp.getDescription(); String message; if (desc == null || desc.length() == 0) { message = NLS.bind(ResourceMessages.NewProject_perspSwitchMessage, finalPersp.getLabel()); } else { message = NLS.bind(ResourceMessages.NewProject_perspSwitchMessageWithDesc, new String[] { finalPersp.getLabel(), desc }); } MessageDialogWithToggle dialog = MessageDialogWithToggle.openYesNoQuestion(window.getShell(), ResourceMessages.NewProject_perspSwitchTitle, message, null /* use the default message for the toggle */, false /* toggle is initially unchecked */, store, IDEInternalPreferences.PROJECT_SWITCH_PERSP_MODE); int result = dialog.getReturnCode(); // If we are not going to prompt anymore propagate the choice. if (dialog.getToggleState()) { String preferenceValue; if (result == IDialogConstants.YES_ID) { // Doesn't matter if it is replace or new window // as we are going to use the open perspective setting preferenceValue = IWorkbenchPreferenceConstants.OPEN_PERSPECTIVE_REPLACE; } else { preferenceValue = IWorkbenchPreferenceConstants.NO_NEW_PERSPECTIVE; } // update PROJECT_OPEN_NEW_PERSPECTIVE to correspond PrefUtil.getAPIPreferenceStore().setValue(IDE.Preferences.PROJECT_OPEN_NEW_PERSPECTIVE, preferenceValue); } return result == IDialogConstants.YES_ID; } /** * Open the first detected camel context file in the editor * * @param project */ private void openCamelContextFile(IProject project, IProgressMonitor monitor) { if (project != null) { final IFile[] holder = new IFile[1]; searchCamelContextXMLFile(project, holder); try { if (holder[0] == null && project.hasNature(JavaCore.NATURE_ID)) { searchCamelContextJavaFile(project, monitor, holder); isJavaEditorToOpen = true; } } catch (CoreException e1) { ProjectTemplatesActivator.pluginLog().logError(e1); } if (holder[0] != null) { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { try { if (!holder[0].exists()) { new BuildAndRefreshJobWaiterUtil().waitJob(monitor); } IWorkbenchPage activePage = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getActivePage(); if (isJavaEditorToOpen) { IDE.openEditor(activePage, holder[0], OpenStrategy.activateOnOpen()); } else { IDE.setDefaultEditor(holder[0], CamelUtils.CAMEL_EDITOR_ID); IDE.openEditor(activePage, holder[0], CamelUtils.CAMEL_EDITOR_ID, OpenStrategy.activateOnOpen()); } } catch (PartInitException e) { ProjectTemplatesActivator.pluginLog() .logError("Cannot open camel context file in editor", e); //$NON-NLS-1$ } } }); } } } /** * @param project * @param monitor * @param holder */ private void searchCamelContextJavaFile(IProject project, IProgressMonitor monitor, final IFile[] holder) { IFile f = new JavaCamelFilesFinder().findJavaDSLRouteBuilderClass(project, monitor); if (f != null) { holder[0] = f; } } /** * @param project * @param holder */ private void searchCamelContextXMLFile(IProject project, final IFile[] holder) { Set<IFile> camelFiles = new CamelFilesFinder().findFiles(project); if (!camelFiles.isEmpty()) { holder[0] = camelFiles.iterator().next(); } } }