Java tutorial
/******************************************************************************* * Copyright (C) 2005 - 2014 TIBCO Software Inc. All rights reserved. * http://www.jaspersoft.com. * * Unless you have purchased a commercial license agreement from Jaspersoft, * the following license terms apply: * * This program and the accompanying materials * are 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 ******************************************************************************/ package com.jaspersoft.studio.components.customvisualization.creation.wizard; import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.StringWriter; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import net.sf.jasperreports.eclipse.ui.util.UIUtils; import net.sf.jasperreports.eclipse.wizard.project.ProjectUtil; import org.apache.commons.io.FileUtils; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.ui.INewWizard; import org.eclipse.ui.IWorkbench; import com.jaspersoft.studio.JaspersoftStudioPlugin; import com.jaspersoft.studio.components.customvisualization.creation.CustomComponentNature; import com.jaspersoft.studio.components.customvisualization.creation.ModuleDefinition; import com.jaspersoft.studio.components.customvisualization.creation.ModuleManager; import com.jaspersoft.studio.components.customvisualization.creation.VelocityLibrary; import com.jaspersoft.studio.components.customvisualization.creation.VelocityShimLibrary; import com.jaspersoft.studio.components.customvisualization.messages.Messages; import com.jaspersoft.studio.utils.VelocityUtils; import com.jaspersoft.studio.wizards.JSSWizard; /** * Wizard to create a custom visualization component project * * @author Orlandin Marco * */ public class CustomVisualizationComponentWizard extends JSSWizard implements INewWizard { /** * Key to write or read the selected module in the first step from the wizard settings */ protected static final String SELECTED_MODULE_KEY = "selectedModule"; /** * Engine to fill the build.js template */ private VelocityEngine ve = VelocityUtils.getConfiguredVelocityEngine(); /** * Path of the build.js template */ private static final String BUILD_FILE = "com/jaspersoft/studio/components/customvisualization/creation/resources/build.vm"; //$NON-NLS-1$ /** * Page to select the javascript module used by the project */ private CustomVisualizationComponentListPage page0; /** * Page to get a summary of all the libraries used by the project */ private CustomVisualizationComponentSummaryPage page1; /** * Page to review the licenses of all the libraries used by the project */ private CustomVisualizationComponentLicensePage page2; public CustomVisualizationComponentWizard() { super(); setWindowTitle(Messages.CustomVisualizationComponentWizard_title); } @Override public void init(IWorkbench workbench, IStructuredSelection selection) { page0 = new CustomVisualizationComponentListPage(); addPage(page0); page1 = new CustomVisualizationComponentSummaryPage(); addPage(page1); page2 = new CustomVisualizationComponentLicensePage(); addPage(page2); } /** * Create the project inside the workspace and all it's content */ @Override public boolean performFinish() { IProgressMonitor monitor = new NullProgressMonitor(); String projectName = page0.getProjectName(); ModuleDefinition selected = page0.getSelectedModule(); boolean result = createProject(projectName, monitor); if (result) { IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); IProject project = root.getProject(projectName); File dest = new File(root.getRawLocation().toFile(), projectName); List<VelocityLibrary> libraries = new ArrayList<VelocityLibrary>(); List<VelocityShimLibrary> shimLibraries = new ArrayList<VelocityShimLibrary>(); try { String outputScriptName = projectName + ".min.js"; //Add the main module and all it's dependencies addModule(selected, shimLibraries, libraries, dest); for (ModuleDefinition requiredLibrary : selected.getRequiredLibraries()) { addModule(requiredLibrary, shimLibraries, libraries, dest); } String cssFileName = generateCSS(project, monitor, selected); String renderFileName = generateRender(project, monitor, selected); libraries.add(new VelocityLibrary(selected.getModuleName(), removeJsExtension(renderFileName))); String buildFile = generateBuildFile(libraries, shimLibraries, selected.getModuleName(), outputScriptName); createFile("build.js", project, buildFile, monitor); //$NON-NLS-1$ //Eventually create a sample for the current project createSample(selected, outputScriptName, cssFileName, project, monitor); try { project.refreshLocal(IProject.DEPTH_INFINITE, new NullProgressMonitor()); } catch (CoreException e) { e.printStackTrace(); } } catch (FileNotFoundException ex) { MessageDialog.openError(UIUtils.getShell(), Messages.CustomVisualizationComponentWizard_errorTitle, ex.getMessage()); return false; } } return result; } /** * Check if the selected module provide some samples, like a sample jrxml or its resources. * In this case it add the jr nature to the project and copy all the specified resources * inside the project * * @param selectedModule the selected module * @param scriptName the name of the output script that will be generated when the project component is compiled * @param cssName name of the css file if any, could be null if no css is provided * @param project the current project * @param monitor monitor to execute the operation */ private void createSample(ModuleDefinition selectedModule, String scriptName, String cssName, IProject project, IProgressMonitor monitor) { if (!selectedModule.getSampleResources().isEmpty()) { try { //It uses the samples, add the jr nature to the project if (!ProjectUtil.hasJRNature(monitor, project)) { ProjectUtil.createJRProject(monitor, project); } } catch (Exception e) { e.printStackTrace(); } for (String resourcePath : selectedModule.getSampleResources()) { InputStream resource = selectedModule.getResource(resourcePath); if (resource != null) { String resourceName = getResourceName(resourcePath); if (resourceName.toLowerCase().endsWith(".jrxml")) { //It's a jrxml, call the generate method to provide some project dependent informations String jrxmlContent = generateJRXML(resourcePath, scriptName, cssName); createFile(resourceName, project, jrxmlContent, monitor); } else { //It's another resource file (maybe required from the jrxml), simply create it in the folder createFile(resourceName, project, resource, monitor); } } } } } /** * Generate a sample jrxml for the project by starting from an * existing jrxml and doing some substitution. Actually only the * script name is write inside the final sample jrxml * * @param jrxmlPath path to the sample template * @param scriptName name of the script to use along with the template * to generate the sample jrxml * @param cssName name of the css file if any, could be null if no css is provided * @return the content of the sample jrxml */ private String generateJRXML(String jrxmlPath, String scriptName, String cssName) { VelocityContext functionContext = new VelocityContext(); functionContext.put("scriptname", scriptName); //$NON-NLS-1$ functionContext.put("cssname", cssName); //$NON-NLS-1$ Template functionTemplate = ve.getTemplate(jrxmlPath); StringWriter fsw = new StringWriter(); functionTemplate.merge(functionContext, fsw); return fsw.toString(); } /** * Return a resource name starting from it's path. To * find the resource name the last / is searched, if not found * it will return the path itself, otherwise the substring after * the last / * * @param resourcePath a path of a resource * @return a not null string */ private String getResourceName(String resourcePath) { int slash = resourcePath.lastIndexOf("/"); if (slash == -1) return resourcePath; else return resourcePath.substring(slash + 1); } /** * Get a resource name and if it ends with the js extension * then the extension is removed * * @param source the name of the resource * @return the name without the extension if it was a .js, otherwise the source */ private String removeJsExtension(String source) { if (source.toLowerCase().endsWith(".js")) return source.substring(0, source.length() - 3); return source; } /** * Add a module to the project, it's library is added on the project folder and * are created the informations to have it added to the build.js file * * @param module the module to add * @param shimmedList the list of library to added to the shim list * @param librariesList the list of library to add to the path list * @param projectFolder the project folder * @throws FileNotFoundException throw the exception if the library file can not be found */ private void addModule(ModuleDefinition module, List<VelocityShimLibrary> shimmedList, List<VelocityLibrary> librariesList, File projectFolder) throws FileNotFoundException { //Check if the name is null because a module could not have a library String fileName = module.getLibraryFilename(); if (fileName != null) { File resourceFile = ModuleManager.getLibraryFile(module); if (resourceFile != null && resourceFile.exists()) { File workspaceCopy = new File(projectFolder, fileName); try { FileUtils.copyFile(resourceFile, workspaceCopy); } catch (IOException e) { e.printStackTrace(); } //ADD THE LIBRARY TO THE LIBRARIES LIST librariesList.add(new VelocityLibrary(module.getVariableName(), removeJsExtension(fileName))); //CHECK IF THE MODULE MUST BE SHIMMED if (module.isNeedShim()) { String dependencies = ""; //$NON-NLS-1$ for (int i = 0; i < module.getShimDependencies().size(); i++) { dependencies += "'" + module.getShimDependencies().get(i) + "'"; //$NON-NLS-1$ //$NON-NLS-2$ if (i < (module.getShimDependencies().size() - 1)) { dependencies += ","; //$NON-NLS-1$ } } VelocityShimLibrary shimLibrary = new VelocityShimLibrary(module.getVariableName(), module.getShimExportName(), dependencies); shimmedList.add(shimLibrary); } } else { String errorMessage = MessageFormat.format( Messages.CustomVisualizationComponentWizard_errorDescription, new Object[] { module.getLibraryURL() }); throw new FileNotFoundException(errorMessage); } } } /** * Generate for the new custom visualization component project the css file * * @param container the container where the fill will be placed * @param monitor the monitor to execute the operation * @param library the module selected by the user in the wizard page * @return the name of the css file or null if no css is provided by the module */ private String generateCSS(IProject container, IProgressMonitor monitor, ModuleDefinition module) { String cssContent = module.getCssResource(); if (cssContent != null) { String cssName = container.getName() + ".css"; createFile(cssName, container, cssContent, monitor); //$NON-NLS-1$ return cssName; } return null; } /** * Generate for the new custom visualization component project the render file * * @param container the container where the fill will be placed * @param monitor the monitor to execute the operation * @param library the module selected by the user in the wizard page */ private String generateRender(IProject container, IProgressMonitor monitor, ModuleDefinition library) { String renderContent = library.getRenderResource(); if (renderContent != null) { String renderFileName = container.getName() + ".js"; createFile(renderFileName, container, renderContent, monitor); //$NON-NLS-1$ return renderFileName; } return null; } /** * Generate the build.js file using the template mixed with the * data provided during the wizard * * @param libraries the list of javascript libraries to include inside the build file * @param shimLibraries the list of javascript shimmed libraries to include inside the build file * @param modulename the name of the folder where the project is contained, that it is used as module name */ private String generateBuildFile(List<VelocityLibrary> libraries, List<VelocityShimLibrary> shimLibraries, String moduleName, String outputName) { VelocityContext functionContext = new VelocityContext(); functionContext.put("libraries", libraries); //$NON-NLS-1$ functionContext.put("hasShim", shimLibraries.size() > 0); //$NON-NLS-1$ functionContext.put("shimlibraries", shimLibraries); //$NON-NLS-1$ functionContext.put("modulename", moduleName); //$NON-NLS-1$ functionContext.put("outputname", outputName); //$NON-NLS-1$ Template functionTemplate = ve.getTemplate(BUILD_FILE); StringWriter fsw = new StringWriter(); functionTemplate.merge(functionContext, fsw); return fsw.toString(); } /** * Add a textual file to the project * * @param name the name of the file * @param container the container of the file * @param content the textual content of the file * @param progressMonitor a progress monitor * @return the added file */ protected static IFile createFile(String name, IContainer container, String content, IProgressMonitor progressMonitor) { try { final InputStream stream = new ByteArrayInputStream( content.getBytes(container.getDefaultCharset(true))); return createFile(name, container, stream, progressMonitor); } catch (Exception ex) { ex.printStackTrace(); } return null; } /** * Add a file to the project * * @param name the name of the file * @param container the container of the file * @param stream the binary content of the file * @param progressMonitor a progress monitor * @return the added file */ protected static IFile createFile(String name, IContainer container, InputStream stream, IProgressMonitor progressMonitor) { final IFile file = container.getFile(new Path(name)); try { if (file.exists()) { file.setContents(stream, true, true, progressMonitor); } else { file.create(stream, true, progressMonitor); } stream.close(); } catch (final Exception e) { JaspersoftStudioPlugin.getInstance().logError(e); } progressMonitor.worked(1); return file; } /** * Create an empty project inside the workspace with the nature of a custom visualization * component * * @param projectName the name of the project * @param monitor monitor to execute the operation * @return true if the project was created correctly, false otherwise */ private boolean createProject(String projectName, IProgressMonitor monitor) { IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName); try { if (!project.exists()) { project.create(monitor); project.open(monitor); ProjectUtil.addNature(project, CustomComponentNature.NATURE_ID, monitor); //IFolder folder = project.getFolder(PreferenceConstants.getPreferenceStore().getString(PreferenceConstants.SRCBIN_BINNAME)); //folder.create(IResource.FORCE | IResource.DERIVED, true, monitor); //folder.setDerived(true, monitor); project.refreshLocal(IResource.DEPTH_INFINITE, monitor); IProjectDescription description = project.getDescription(); description.setName(Messages.CustomVisualizationComponentWizard_projectDescription); project.setDescription(description, monitor); return true; } } catch (CoreException e) { e.printStackTrace(); } return false; } /** * Can finish if all the pages are complete or if only the first page is available * and it is complete */ @Override public boolean canFinish() { if (!page0.hasLibraryPage()) return page0.isPageComplete(); else return super.canFinish(); } }