001package org.andromda.maven.plugin; 002 003import java.io.File; 004import java.io.InputStream; 005import java.net.MalformedURLException; 006import java.net.URL; 007import java.text.Format; 008import java.text.SimpleDateFormat; 009import java.util.Date; 010import org.andromda.core.common.ResourceUtils; 011import org.andromda.core.configuration.Configuration; 012import org.andromda.core.configuration.Model; 013import org.andromda.core.configuration.Repository; 014import org.apache.commons.lang.StringUtils; 015import org.apache.maven.plugin.MojoExecutionException; 016 017/** 018 * Exports the MagicDraw project file to EMF XMI 019 * (requires valid MagicDraw installation in MD_HOME, but 020 * only if target files are not up-to-date) 021 * 022 * @goal export2emf 023 * @phase generate-sources 024 * @author Jens Vagts 025 */ 026public class MagicDrawExportEMFXMIMojo 027 extends AbstractAndroMDAMojo 028{ 029 /** 030 * Name of the environment variable pointing to the MagicDraw home directory 031 */ 032 private final String MD_HOME = "MD_HOME"; 033 034 /** 035 * The home/root directory of the magicdraw installation. 036 * 037 * @parameter expression="${magicDrawHome}" 038 */ 039 private String magicDrawHome; 040 041 /** 042 * @see org.andromda.maven.plugin.AbstractAndroMDAMojo#execute(org.andromda.core.configuration.Configuration) 043 */ 044 public void execute(final Configuration configuration) 045 throws MojoExecutionException 046 { 047 try 048 { 049 //export each file (uri) of each model in each repository 050 final Repository[] repositories = configuration.getRepositories(); 051 if (repositories == null || repositories.length == 0) { 052 getLog().info("No repositories for export in configuration defined."); 053 return; 054 } 055 int repositoryCount = repositories.length; 056 for (int ctr = 0; ctr < repositoryCount; ctr++) 057 { 058 final Repository repository = repositories[ctr]; 059 if (repository != null) 060 { 061 final Model[] models = repository.getModels(); 062 final int modelCount = models.length; 063 for (int ctr2 = 0; ctr2 < modelCount; ctr2++) 064 { 065 final Model model = models[ctr2]; 066 if ("emf-uml2".equals(model.getType())) 067 { 068 String[] uris = model.getUris(); 069 for (int u = 0; u < uris.length; u++) 070 { 071 exportFile(uris[u]); 072 } 073 } 074 } 075 } 076 } 077 078 } 079 catch (Throwable throwable) 080 { 081 throw new MojoExecutionException("Error exporting MagicDraw project file to EMF XMI", throwable); 082 } 083 } 084 085 private void exportFile(String dest) throws Exception { 086 final String UML2EXT = ".uml2"; 087 final String MDEXT1 = ".xml.zip"; 088 final String MDEXT2 = ".mdzip"; 089 090 //get the source file name from the destination name (we expect xml.zip) 091 if (!dest.endsWith(UML2EXT)) 092 { 093 getLog().warn("Ignoring model file " + dest + ", since it seems not to be of type 'uml2'"); 094 return; 095 } 096 097 //check for first MD extension 098 //(use URL.getFile() to get rid of spaces in file name) 099 String source = StringUtils.replace(dest, UML2EXT, MDEXT1); 100 URL sourceUrl = null; 101 try { 102 sourceUrl = new URL(ResourceUtils.normalizePath(source)); 103 } catch (MalformedURLException e) { 104 throw new MojoExecutionException("Invalid source model file name [" + source + "]: " + e.getMessage()); 105 } 106 107 //check for for second MD extension 108 File sourceFile = new File(sourceUrl.getFile()); 109 if (!sourceFile.exists()) 110 { 111 source = StringUtils.replace(dest, UML2EXT, MDEXT2); 112 try { 113 sourceUrl = new URL(ResourceUtils.normalizePath(source)); 114 } catch (MalformedURLException e) { 115 throw new MojoExecutionException("Invalid source model file name [" + source + "]: " + e.getMessage()); 116 } 117 } 118 sourceFile = new File(sourceUrl.getFile()); 119 if (!sourceFile.exists()) 120 { 121 throw new MojoExecutionException("Model file [" + source + "] does not exist"); 122 } 123 124 //check for destination (emf) file 125 URL destUrl = null; 126 try { 127 destUrl = new URL(ResourceUtils.normalizePath(dest)); 128 } catch (MalformedURLException e) { 129 throw new MojoExecutionException("Invalid destination model file name [" + dest + "]: " + e.getMessage()); 130 } 131 132 File destFile = new File(destUrl.getFile()); 133 if (!destFile.exists()) 134 { 135 getLog().debug("No old model file [" + dest + "] existing"); 136 } 137 else 138 { 139 if (getLog().isDebugEnabled()) 140 { 141 Format formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 142 getLog().debug("- MagicDraw model file ["+sourceFile.getName()+"] date = " + formatter.format(new Date(sourceFile.lastModified()))); 143 getLog().debug("- EMF model file ["+destFile.getName()+"] date = " + formatter.format(new Date(destFile.lastModified()))); 144 } 145 if (destFile.lastModified() >= sourceFile.lastModified()) 146 { 147 getLog().info("Model file [" + dest + "] is up-to-date"); 148 return; 149 } 150 } 151 152 //check for valid magic draw installation 153 checkForMagicDraw(); 154 155 //perform the export via MagicDraw 156 getLog().info("Exporting model file [" + source + "] ..."); 157 String command = '\"' + exporterPath + '\"' 158 + " project_file=\"" + sourceFile.getPath() + '\"' 159 + " destination_dir=\"" + sourceFile.getParent() + '\"' 160 + " load_all_modules=true"; 161 Process process = Runtime.getRuntime().exec(command); 162 163 //since at least the windows version forks the magicdraw process, 164 //we have to synchronize via input stream reading 165 InputStream is = process.getInputStream(); 166 final byte[] buf = new byte[128]; 167 int length; 168 while ((length = is.read(buf)) > 0) 169 { 170 getLog().info(new String(buf, 0, length)); 171 } 172 process.waitFor(); 173 process.destroy(); 174 int err = process.exitValue(); 175 if (err != 0) 176 { 177 throw new MojoExecutionException("MagicDraw export returned error code " + err); 178 } 179 getLog().info("Successfully exported model file."); 180 } 181 182 /** 183 * only check once for magic draw installation 184 */ 185 private boolean checkedMagicDraw = false; 186 187 /** 188 * The export executable file extension (.exe for Windows, nothing for *ix) 189 */ 190 private String exportExt = ""; 191 192 /** 193 * The full path name to the exporter plugin executable 194 */ 195 private String exporterPath; 196 197 private void checkForMagicDraw() throws MojoExecutionException 198 { 199 if (!checkedMagicDraw) 200 { 201 if (magicDrawHome == null) 202 { 203 magicDrawHome = System.getenv(MD_HOME); 204 } 205 206 if (magicDrawHome == null) 207 { 208 throw new MojoExecutionException("MagicDraw home directory not defined: please define either a configuration variable \"magicDrawHome\" in your pom or the environment variable \""+ MD_HOME + "\"!"); 209 } 210 211 File home = new File(magicDrawHome); 212 if (!home.exists()) 213 { 214 throw new MojoExecutionException("Invalid MagicDraw home directory specified: " + magicDrawHome); 215 } 216 217 //check for running os 218 String os = System.getProperty("os.name"); 219 if (os.contains("Windows")) 220 { 221 exportExt = ".exe"; 222 } 223 224 //check for plugin name (has changed from MD 11.5 to 11.6) 225 String pluginName115 = "com.nomagic.magicdraw.emfuml2export"; 226 String pluginName116 = "com.nomagic.magicdraw.emfuml2xmi"; 227 String pluginName15 = "com.nomagic.magicdraw.emfuml2xmi_v1"; 228 exporterPath = magicDrawHome 229 + File.separator + "plugins" 230 + File.separator + pluginName15 231 + File.separator + "exportEMFXMI" + exportExt; 232 File exporter = new File(exporterPath); 233 if (!exporter.exists()) 234 { 235 exporterPath = magicDrawHome 236 + File.separator + "plugins" 237 + File.separator + pluginName116 238 + File.separator + "exportEMFXMI" + exportExt; 239 exporter = new File(exporterPath); 240 if (!exporter.exists()) 241 { 242 exporterPath = magicDrawHome 243 + File.separator + "plugins" 244 + File.separator + pluginName115 245 + File.separator + "exportEMFXMI" + exportExt; 246 } 247 } 248 249 exporter = new File(exporterPath); 250 if (!exporter.exists()) 251 { 252 throw new MojoExecutionException("No exporter plugin found in MagicDraw home directory " + magicDrawHome); 253 } 254 255 checkedMagicDraw = true; 256 } 257 } 258}