• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright 2011 See AUTHORS file.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  ******************************************************************************/
16 
17 package com.badlogic.gdx.setup;
18 
19 import java.io.*;
20 import java.util.ArrayList;
21 import java.util.HashMap;
22 import java.util.List;
23 import java.util.Map;
24 
25 import javax.swing.JOptionPane;
26 
27 import com.badlogic.gdx.setup.DependencyBank.ProjectDependency;
28 import com.badlogic.gdx.setup.DependencyBank.ProjectType;
29 import com.badlogic.gdx.setup.Executor.CharCallback;
30 
31 /** Command line tool to generate libgdx projects
32  * @author badlogic
33  * @author Tomski */
34 public class GdxSetup {
isSdkLocationValid(String sdkLocation)35 	public static boolean isSdkLocationValid (String sdkLocation) {
36 		return new File(sdkLocation, "tools").exists() && new File(sdkLocation, "platforms").exists();
37 	}
38 
isEmptyDirectory(String destination)39 	public static boolean isEmptyDirectory (String destination) {
40 		if (new File(destination).exists()) {
41 			return new File(destination).list().length == 0;
42 		} else {
43 			return true;
44 		}
45 	}
46 
isSdkUpToDate(String sdkLocation)47 	public static boolean isSdkUpToDate (String sdkLocation) {
48 		File buildTools = new File(sdkLocation, "build-tools");
49 		if (!buildTools.exists()) {
50 			JOptionPane.showMessageDialog(null, "You have no build tools!\nUpdate your Android SDK with build tools version: "
51 				+ DependencyBank.buildToolsVersion);
52 			return false;
53 		}
54 
55 		File apis = new File(sdkLocation, "platforms");
56 		if (!apis.exists()) {
57 			JOptionPane.showMessageDialog(null, "You have no Android APIs!\nUpdate your Android SDK with API level: "
58 				+ DependencyBank.androidAPILevel);
59 			return false;
60 		}
61 		String newestLocalTool = getLatestTools(buildTools);
62 		int[] localToolVersion = convertTools(newestLocalTool);
63 		int[] targetToolVersion = convertTools(DependencyBank.buildToolsVersion);
64 		if (compareVersions(targetToolVersion, localToolVersion)) {
65 			int value = JOptionPane.showConfirmDialog(null,
66 				"You have a more recent version of android build tools than the recommended.\nDo you want to use your more recent version?",
67 				"Warning!", JOptionPane.YES_NO_OPTION);
68 			if (value != 0) {
69 				JOptionPane.showMessageDialog(null, "Using build tools: " + DependencyBank.buildToolsVersion);
70 			} else {
71 				DependencyBank.buildToolsVersion = newestLocalTool;
72 			}
73 		} else {
74 			if (!versionsEqual(localToolVersion, targetToolVersion)) {
75 				JOptionPane.showMessageDialog(null, "Please update your Android SDK, you need build tools: "
76 					+ DependencyBank.buildToolsVersion);
77 				return false;
78 			}
79 		}
80 
81 		int newestLocalApi = getLatestApi(apis);
82 		if (newestLocalApi > Integer.valueOf(DependencyBank.androidAPILevel)) {
83 			int value = JOptionPane.showConfirmDialog(null,
84 				"You have a more recent Android API than the recommended.\nDo you want to use your more recent version?", "Warning!",
85 				JOptionPane.YES_NO_OPTION);
86 			if (value != 0) {
87 				JOptionPane.showMessageDialog(null, "Using API level: " + DependencyBank.androidAPILevel);
88 			} else {
89 				DependencyBank.androidAPILevel = String.valueOf(newestLocalApi);
90 			}
91 		} else {
92 			if (newestLocalApi != Integer.valueOf(DependencyBank.androidAPILevel)) {
93 				JOptionPane.showMessageDialog(null, "Please update your Android SDK, you need the Android API: "
94 					+ DependencyBank.androidAPILevel);
95 				return false;
96 			}
97 		}
98 		return true;
99 	}
100 
getLatestApi(File apis)101 	private static int getLatestApi (File apis) {
102 		int apiLevel = 0;
103 		for (File api : apis.listFiles()) {
104 			int level = readAPIVersion(api);
105 			if (level > apiLevel) apiLevel = level;
106 		}
107 		return apiLevel;
108 	}
109 
getLatestTools(File buildTools)110 	private static String getLatestTools (File buildTools) {
111 		String version = null;
112 		int[] versionSplit = new int[3];
113 		int[] testSplit = new int[3];
114 		for (File toolsVersion : buildTools.listFiles()) {
115 			if (version == null) {
116 				version = readBuildToolsVersion(toolsVersion);
117 				versionSplit = convertTools(version);
118 				continue;
119 			}
120 			testSplit = convertTools(readBuildToolsVersion(toolsVersion));
121 			if (compareVersions(versionSplit, testSplit)) {
122 				version = readBuildToolsVersion(toolsVersion);
123 				versionSplit = convertTools(version);
124 			}
125 		}
126 		if (version != null) {
127 			return version;
128 		} else {
129 			return "0.0.0";
130 		}
131 	}
132 
readAPIVersion(File parentFile)133 	private static int readAPIVersion (File parentFile) {
134 		File properties = new File(parentFile, "source.properties");
135 		FileReader reader;
136 		BufferedReader buffer;
137 		try {
138 			reader = new FileReader(properties);
139 			buffer = new BufferedReader(reader);
140 
141 			String line = null;
142 
143 			while ((line = buffer.readLine()) != null) {
144 				if (line.contains("AndroidVersion.ApiLevel")) {
145 
146 					String versionString = line.split("\\=")[1];
147 					int apiLevel = Integer.parseInt(versionString);
148 
149 					buffer.close();
150 					reader.close();
151 
152 					return apiLevel;
153 				}
154 			}
155 		} catch (FileNotFoundException e) {
156 			e.printStackTrace();
157 		} catch (IOException e) {
158 			e.printStackTrace();
159 		} catch (NumberFormatException e) {
160 			e.printStackTrace();
161 		}
162 		return 0;
163 	}
164 
readBuildToolsVersion(File parentFile)165 	private static String readBuildToolsVersion (File parentFile) {
166 		File properties = new File(parentFile, "source.properties");
167 		FileReader reader;
168 		BufferedReader buffer;
169 		try {
170 			reader = new FileReader(properties);
171 			buffer = new BufferedReader(reader);
172 
173 			String line = null;
174 
175 			while ((line = buffer.readLine()) != null) {
176 				if (line.contains("Pkg.Revision")) {
177 
178 					String versionString = line.split("\\=")[1];
179 					int count = versionString.split("\\.").length;
180 					for (int i = 0; i < 3 - count; i++) {
181 						versionString += ".0";
182 					}
183 
184 					buffer.close();
185 					reader.close();
186 
187 					return versionString;
188 				}
189 			}
190 		} catch (FileNotFoundException e) {
191 			e.printStackTrace();
192 		} catch (IOException e) {
193 			e.printStackTrace();
194 		}
195 		return "0.0.0";
196 	}
197 
versionsEqual(int[] testVersion, int[] targetVersion)198 	private static boolean versionsEqual(int[] testVersion, int[] targetVersion) {
199 		for (int i = 0; i < 3; i++) {
200 			if (testVersion[i] != targetVersion[i]) return false;
201 		}
202 		return true;
203 	}
204 
compareVersions(int[] version, int[] testVersion)205 	private static boolean compareVersions(int[] version, int[] testVersion) {
206 		if (testVersion[0] > version[0]) {
207 			return true;
208 		} else if (testVersion[0] == version[0]) {
209 			if (testVersion[1] > version[1]) {
210 				return true;
211 			} else if (testVersion[1] == version[1]) {
212 				return testVersion[2] > version[2];
213 			}
214 		}
215 		return false;
216 	}
217 
convertTools(String toolsVersion)218 	private static int[] convertTools (String toolsVersion) {
219 		String[] stringSplit = toolsVersion.split("\\.");
220 		int[] versionSplit = new int[3];
221 		if (stringSplit.length == 3) {
222 			try {
223 				versionSplit[0] = Integer.parseInt(stringSplit[0]);
224 				versionSplit[1] = Integer.parseInt(stringSplit[1]);
225 				versionSplit[2] = Integer.parseInt(stringSplit[2]);
226 				return versionSplit;
227 			} catch (NumberFormatException nfe) {
228 				return new int[] {0, 0, 0};
229 			}
230 		} else {
231 			return new int[] {0, 0, 0};
232 		}
233 	}
234 
build(ProjectBuilder builder, String outputDir, String appName, String packageName, String mainClass, String sdkLocation, CharCallback callback, List<String> gradleArgs)235 	public void build (ProjectBuilder builder, String outputDir, String appName, String packageName, String mainClass,
236 		String sdkLocation, CharCallback callback, List<String> gradleArgs) {
237 		Project project = new Project();
238 
239 		String packageDir = packageName.replace('.', '/');
240 		String sdkPath = sdkLocation.replace('\\', '/');
241 
242 		if (!isSdkLocationValid(sdkLocation)) {
243 			System.out.println("Android SDK location '" + sdkLocation + "' doesn't contain an SDK");
244 		}
245 
246 		// root dir/gradle files
247 		project.files.add(new ProjectFile("gitignore", ".gitignore", false));
248 		project.files.add(new TemporaryProjectFile(builder.settingsFile, "settings.gradle", false));
249 		project.files.add(new TemporaryProjectFile(builder.buildFile, "build.gradle", true));
250 		project.files.add(new ProjectFile("gradlew", false));
251 		project.files.add(new ProjectFile("gradlew.bat", false));
252 		project.files.add(new ProjectFile("gradle/wrapper/gradle-wrapper.jar", false));
253 		project.files.add(new ProjectFile("gradle/wrapper/gradle-wrapper.properties", false));
254 		project.files.add(new ProjectFile("gradle.properties"));
255 
256 		// core project
257 		project.files.add(new ProjectFile("core/build.gradle"));
258 		project.files.add(new ProjectFile("core/src/MainClass", "core/src/" + packageDir + "/" + mainClass + ".java", true));
259 		if (builder.modules.contains(ProjectType.HTML)) {
260 			project.files.add(new ProjectFile("core/CoreGdxDefinition", "core/src/" + mainClass + ".gwt.xml", true));
261 		}
262 
263 		// desktop project
264 		if (builder.modules.contains(ProjectType.DESKTOP)) {
265 			project.files.add(new ProjectFile("desktop/build.gradle"));
266 			project.files.add(new ProjectFile("desktop/src/DesktopLauncher", "desktop/src/" + packageDir + "/desktop/DesktopLauncher.java", true));
267 		}
268 
269 		// Assets
270 		String assetPath = builder.modules.contains(ProjectType.ANDROID) ? "android/assets" : "core/assets";
271 		project.files.add(new ProjectFile("android/assets/badlogic.jpg", assetPath + "/badlogic.jpg", false));
272 
273 		// android project
274 		if (builder.modules.contains(ProjectType.ANDROID)) {
275 			project.files.add(new ProjectFile("android/res/values/strings.xml"));
276 			project.files.add(new ProjectFile("android/res/values/styles.xml", false));
277 			project.files.add(new ProjectFile("android/res/drawable-hdpi/ic_launcher.png", false));
278 			project.files.add(new ProjectFile("android/res/drawable-mdpi/ic_launcher.png", false));
279 			project.files.add(new ProjectFile("android/res/drawable-xhdpi/ic_launcher.png", false));
280 			project.files.add(new ProjectFile("android/res/drawable-xxhdpi/ic_launcher.png", false));
281 			project.files.add(new ProjectFile("android/src/AndroidLauncher", "android/src/" + packageDir + "/AndroidLauncher.java", true));
282 			project.files.add(new ProjectFile("android/AndroidManifest.xml"));
283 			project.files.add(new ProjectFile("android/build.gradle", true));
284 			project.files.add(new ProjectFile("android/ic_launcher-web.png", false));
285 			project.files.add(new ProjectFile("android/proguard-project.txt", false));
286 			project.files.add(new ProjectFile("android/project.properties", false));
287 			project.files.add(new ProjectFile("local.properties", true));
288 		}
289 
290 		// html project
291 		if (builder.modules.contains(ProjectType.HTML)) {
292 			project.files.add(new ProjectFile("html/build.gradle"));
293 			project.files.add(new ProjectFile("html/src/HtmlLauncher", "html/src/" + packageDir + "/client/HtmlLauncher.java", true));
294 			project.files.add(new ProjectFile("html/GdxDefinition", "html/src/" + packageDir + "/GdxDefinition.gwt.xml", true));
295 			project.files.add(new ProjectFile("html/GdxDefinitionSuperdev", "html/src/" + packageDir + "/GdxDefinitionSuperdev.gwt.xml", true));
296 			project.files.add(new ProjectFile("html/war/index", "html/webapp/index.html", true));
297 			project.files.add(new ProjectFile("html/war/styles.css", "html/webapp/styles.css", false));
298 			project.files.add(new ProjectFile("html/war/refresh.png", "html/webapp/refresh.png", false));
299 			project.files.add(new ProjectFile("html/war/soundmanager2-jsmin.js", "html/webapp/soundmanager2-jsmin.js", false));
300 			project.files.add(new ProjectFile("html/war/soundmanager2-setup.js", "html/webapp/soundmanager2-setup.js", false));
301 			project.files.add(new ProjectFile("html/war/WEB-INF/web.xml", "html/webapp/WEB-INF/web.xml", true));
302 		}
303 
304 		// ios robovm
305 		if (builder.modules.contains(ProjectType.IOS)) {
306 			project.files.add(new ProjectFile("ios/src/IOSLauncher", "ios/src/" + packageDir + "/IOSLauncher.java", true));
307 			project.files.add(new ProjectFile("ios/data/Default.png", false));
308 			project.files.add(new ProjectFile("ios/data/Default@2x.png", false));
309 			project.files.add(new ProjectFile("ios/data/Default@2x~ipad.png", false));
310 			project.files.add(new ProjectFile("ios/data/Default-568h@2x.png", false));
311 			project.files.add(new ProjectFile("ios/data/Default~ipad.png", false));
312 			project.files.add(new ProjectFile("ios/data/Default-375w-667h@2x.png", false));
313 			project.files.add(new ProjectFile("ios/data/Default-414w-736h@3x.png", false));
314 			project.files.add(new ProjectFile("ios/data/Icon.png", false));
315 			project.files.add(new ProjectFile("ios/data/Icon@2x.png", false));
316 			project.files.add(new ProjectFile("ios/data/Icon-72.png", false));
317 			project.files.add(new ProjectFile("ios/data/Icon-72@2x.png", false));
318 			project.files.add(new ProjectFile("ios/build.gradle", true));
319 			project.files.add(new ProjectFile("ios/Info.plist.xml", false));
320 			project.files.add(new ProjectFile("ios/robovm.properties"));
321 			project.files.add(new ProjectFile("ios/robovm.xml", true));
322 		}
323 
324 		if(builder.modules.contains(ProjectType.IOSMOE)) {
325 			project.files.add(new ProjectFile("ios-moe/resources/Default.png", false));
326 			project.files.add(new ProjectFile("ios-moe/resources/Default@2x.png", false));
327 			project.files.add(new ProjectFile("ios-moe/resources/Default@2x~ipad.png", false));
328 			project.files.add(new ProjectFile("ios-moe/resources/Default-568h@2x.png", false));
329 			project.files.add(new ProjectFile("ios-moe/resources/Default~ipad.png", false));
330 			project.files.add(new ProjectFile("ios-moe/resources/Default-375w-667h@2x.png", false));
331 			project.files.add(new ProjectFile("ios-moe/resources/Default-414w-736h@3x.png", false));
332 			project.files.add(new ProjectFile("ios-moe/resources/Icon.png", false));
333 			project.files.add(new ProjectFile("ios-moe/resources/Icon@2x.png", false));
334 			project.files.add(new ProjectFile("ios-moe/resources/Icon-72.png", false));
335 			project.files.add(new ProjectFile("ios-moe/resources/Icon-72@2x.png", false));
336 			project.files.add(new ProjectFile("ios-moe/src/IOSMoeLauncher", "ios-moe/src/" + packageDir + "/IOSMoeLauncher.java", true));
337 			project.files.add(new ProjectFile("ios-moe/xcode/ios-moe/build.xcconfig", false));
338 			project.files.add(new ProjectFile("ios-moe/xcode/ios-moe/custom.xcconfig", false));
339 			project.files.add(new ProjectFile("ios-moe/xcode/ios-moe-Test/build.xcconfig", false));
340 			project.files.add(new ProjectFile("ios-moe/xcode/ios-moe-Test/Info-Test.plist", false));
341 			project.files.add(new ProjectFile("ios-moe/xcode/ios-moe/Info.plist", true));
342 			project.files.add(new ProjectFile("ios-moe/xcode/ios-moe/main.cpp", false));
343 			project.files.add(new ProjectFile("ios-moe/xcode/ios-moe.xcodeproj/project.pbxproj", true));
344 			project.files.add(new ProjectFile("ios-moe/build.gradle", true));
345 		}
346 
347 		Map<String, String> values = new HashMap<String, String>();
348 		values.put("%APP_NAME%", appName);
349 		values.put("%APP_NAME_ESCAPED%", appName.replace("'", "\\'"));
350 		values.put("%PACKAGE%", packageName);
351 		values.put("%PACKAGE_DIR%", packageDir);
352 		values.put("%MAIN_CLASS%", mainClass);
353 		values.put("%ANDROID_SDK%", sdkPath);
354 		values.put("%ASSET_PATH%", assetPath);
355 		values.put("%BUILD_TOOLS_VERSION%", DependencyBank.buildToolsVersion);
356 		values.put("%API_LEVEL%", DependencyBank.androidAPILevel);
357 		values.put("%GWT_VERSION%", DependencyBank.gwtVersion);
358 		if (builder.modules.contains(ProjectType.HTML)) {
359 			values.put("%GWT_INHERITS%", parseGwtInherits(builder));
360 		}
361 
362 		copyAndReplace(outputDir, project, values);
363 
364 		builder.cleanUp();
365 
366 		// HACK executable flag isn't preserved for whatever reason...
367 		new File(outputDir, "gradlew").setExecutable(true);
368 
369 		Executor.execute(new File(outputDir), "gradlew.bat", "gradlew", "clean" + parseGradleArgs(builder.modules, gradleArgs), callback);
370 	}
371 
copyAndReplace(String outputDir, Project project, Map<String, String> values)372 	private void copyAndReplace (String outputDir, Project project, Map<String, String> values) {
373 		File out = new File(outputDir);
374 		if (!out.exists() && !out.mkdirs()) {
375 			throw new RuntimeException("Couldn't create output directory '" + out.getAbsolutePath() + "'");
376 		}
377 
378 		for (ProjectFile file : project.files) {
379 			copyFile(file, out, values);
380 		}
381 	}
382 
readResource(String resource, String path)383 	private byte[] readResource (String resource, String path) {
384 		InputStream in = null;
385 		try {
386 			ByteArrayOutputStream bytes = new ByteArrayOutputStream();
387 			byte[] buffer = new byte[1024 * 10];
388 			in = GdxSetup.class.getResourceAsStream(path + resource);
389 			if (in == null) throw new RuntimeException("Couldn't read resource '" + resource + "'");
390 			int read = 0;
391 			while ((read = in.read(buffer)) > 0) {
392 				bytes.write(buffer, 0, read);
393 			}
394 			return bytes.toByteArray();
395 		} catch (IOException e) {
396 			throw new RuntimeException("Couldn't read resource '" + resource + "'", e);
397 		} finally {
398 			if (in != null) try {
399 				in.close();
400 			} catch (IOException e) {
401 			}
402 		}
403 	}
404 
readResource(File file)405 	private byte[] readResource (File file) {
406 		InputStream in = null;
407 		try {
408 			ByteArrayOutputStream bytes = new ByteArrayOutputStream();
409 			byte[] buffer = new byte[1024 * 10];
410 			in = new FileInputStream(file);
411 			if (in == null) throw new RuntimeException("Couldn't read resource '" + file.getAbsoluteFile() + "'");
412 			int read = 0;
413 			while ((read = in.read(buffer)) > 0) {
414 				bytes.write(buffer, 0, read);
415 			}
416 			return bytes.toByteArray();
417 		} catch (Throwable e) {
418 			throw new RuntimeException("Couldn't read resource '" + file.getAbsoluteFile() + "'", e);
419 		} finally {
420 			if (in != null) try {
421 				in.close();
422 			} catch (IOException e) {
423 			}
424 		}
425 	}
426 
readResourceAsString(String resource, String path)427 	private String readResourceAsString (String resource, String path) {
428 		try {
429 			return new String(readResource(resource, path), "UTF-8");
430 		} catch (UnsupportedEncodingException e) {
431 			throw new RuntimeException(e);
432 		}
433 	}
434 
readResourceAsString(File file)435 	private String readResourceAsString (File file) {
436 		try {
437 			return new String(readResource(file), "UTF-8");
438 		} catch (UnsupportedEncodingException e) {
439 			throw new RuntimeException(e);
440 		}
441 	}
442 
writeFile(File outFile, byte[] bytes)443 	private void writeFile (File outFile, byte[] bytes) {
444 		OutputStream out = null;
445 
446 		try {
447 			out = new BufferedOutputStream(new FileOutputStream(outFile));
448 			out.write(bytes);
449 		} catch (IOException e) {
450 			throw new RuntimeException("Couldn't write file '" + outFile.getAbsolutePath() + "'", e);
451 		} finally {
452 			if (out != null) try {
453 				out.close();
454 			} catch (IOException e) {
455 			}
456 		}
457 	}
458 
writeFile(File outFile, String text)459 	private void writeFile (File outFile, String text) {
460 		try {
461 			writeFile(outFile, text.getBytes("UTF-8"));
462 		} catch (UnsupportedEncodingException e) {
463 			throw new RuntimeException(e);
464 		}
465 	}
466 
copyFile(ProjectFile file, File out, Map<String, String> values)467 	private void copyFile (ProjectFile file, File out, Map<String, String> values) {
468 		File outFile = new File(out, file.outputName);
469 		if (!outFile.getParentFile().exists() && !outFile.getParentFile().mkdirs()) {
470 			throw new RuntimeException("Couldn't create dir '" + outFile.getAbsolutePath() + "'");
471 		}
472 
473 		boolean isTemp = file instanceof TemporaryProjectFile ? true : false;
474 
475 		if (file.isTemplate) {
476 			String txt;
477 			if (isTemp) {
478 				txt = readResourceAsString(((TemporaryProjectFile)file).file);
479 			} else {
480 				txt = readResourceAsString(file.resourceName, file.resourceLoc);
481 			}
482 			txt = replace(txt, values);
483 			writeFile(outFile, txt);
484 		} else {
485 			if (isTemp) {
486 				writeFile(outFile, readResource(((TemporaryProjectFile)file).file));
487 			} else {
488 				writeFile(outFile, readResource(file.resourceName, file.resourceLoc));
489 			}
490 		}
491 	}
492 
replace(String txt, Map<String, String> values)493 	private String replace (String txt, Map<String, String> values) {
494 		for (String key : values.keySet()) {
495 			String value = values.get(key);
496 			txt = txt.replace(key, value);
497 		}
498 		return txt;
499 	}
500 
printHelp()501 	private static void printHelp () {
502 		System.out
503 			.println("Usage: GdxSetup --dir <dir-name> --name <app-name> --package <package> --mainClass <mainClass> --sdkLocation <SDKLocation> [--excludeModules <modules>] [--extensions <extensions>]");
504 		System.out.println("dir ... the directory to write the project files to");
505 		System.out.println("name ... the name of the application");
506 		System.out.println("package ... the Java package name of the application");
507 		System.out.println("mainClass ... the name of your main ApplicationListener");
508 		System.out.println("sdkLocation ... the location of your android SDK. Uses ANDROID_HOME if not specified. Ignored if android module is excluded");
509 		System.out.println("excludeModules ... the modules to exclude on the project generation separated by ';'. Optional");
510 		System.out.println("extensions ... the extensions to include in the project separated by ';'. Optional");
511 	}
512 
parseArgs(String[] args)513 	private static Map<String, String> parseArgs (String[] args) {
514 		if (args.length % 2 != 0) {
515 			printHelp();
516 			System.exit(-1);
517 		}
518 
519 		Map<String, String> params = new HashMap<String, String>();
520 		for (int i = 0; i < args.length; i += 2) {
521 			String param = args[i].replace("--", "");
522 			String value = args[i + 1];
523 			params.put(param, value);
524 		}
525 		return params;
526 	}
527 
parseExcludedModules(String excludedModules)528 	 private static List<String> parseExcludedModules (String excludedModules) {
529 		  List<String> excludedModulesList = new ArrayList<String>();
530 
531 		  while (excludedModules.contains(";")) {
532 				excludedModulesList.add(excludedModules.substring(0, excludedModules.indexOf(";")).toLowerCase());
533 				excludedModules = excludedModules.substring(excludedModules.indexOf(";") + 1);
534 		  }
535 		  excludedModulesList.add(excludedModules.toLowerCase());
536 
537 		  return excludedModulesList;
538 	 }
539 
parseDependencies(String dependencies, DependencyBank bank)540 	 private static List<Dependency> parseDependencies (String dependencies, DependencyBank bank) {
541 		  List<String> dependencyNames = new ArrayList<String>();
542 		  while (dependencies.contains(";")) {
543 				dependencyNames.add(dependencies.substring(0, dependencies.indexOf(";")).toLowerCase());
544 				dependencies = dependencies.substring(dependencies.indexOf(";") + 1);
545 		  }
546 		  dependencyNames.add(dependencies.toLowerCase());
547 
548 		  Map<String, Dependency> dependencyMap = new HashMap<String, Dependency>();
549 		  for (ProjectDependency pd : ProjectDependency.values()) {
550 				dependencyMap.put(pd.name().toLowerCase(), bank.getDependency(pd));
551 		  }
552 
553 		  List<Dependency> dependencyList = new ArrayList<Dependency>();
554 		  dependencyList.add(bank.getDependency(ProjectDependency.GDX));
555 		  for (String name : dependencyNames) {
556 				if (dependencyMap.containsKey(name)) {
557 					 System.out.println("Extension " + name + " found");
558 					 dependencyList.add(dependencyMap.get(name));
559 				} else
560 					 System.out.println("Extension " + name + " not found");
561 		  }
562 
563 		  return dependencyList;
564 	 }
565 
parseGwtInherits(ProjectBuilder builder)566 	private String parseGwtInherits (ProjectBuilder builder) {
567 		String parsed = "";
568 
569 		for (Dependency dep : builder.dependencies) {
570 			if (dep.getGwtInherits() != null) {
571 				for (String inherit : dep.getGwtInherits()) {
572 					parsed += "\t<inherits name='" + inherit + "' />\n";
573 				}
574 			}
575 		}
576 
577 		return parsed;
578 	}
579 
parseGradleArgs(List<ProjectType> modules, List<String> args)580 	private String parseGradleArgs (List<ProjectType> modules, List<String> args) {
581 		String argString = "";
582 		if (args == null) return argString;
583 		for (String argument : args) {
584 			if (argument.equals("afterEclipseImport") && !modules.contains(ProjectType.DESKTOP)) continue;
585 			argString += " " + argument;
586 		}
587 		return argString;
588 	}
589 
containsDependency(List<Dependency> dependencyList, ProjectDependency projectDependency)590 	private boolean containsDependency (List<Dependency> dependencyList, ProjectDependency projectDependency) {
591 		for (Dependency dep : dependencyList) {
592 			if (dep.getName().equals(projectDependency.name())) {
593 				return true;
594 			}
595 		}
596 		return false;
597 	}
598 
main(String[] args)599 	public static void main (String[] args) throws IOException {
600 		Map<String, String> params = parseArgs(args);
601 		List<String> excludedModules = null;
602 		if (params.containsKey("excludeModules"))
603 			excludedModules = parseExcludedModules(params.get("excludeModules"));
604 
605 		if (!params.containsKey("dir") ||
606 			!params.containsKey("name") ||
607 			!params.containsKey("package") ||
608 			!params.containsKey("mainClass") ||
609 			(!params.containsKey("sdkLocation") && System.getenv("ANDROID_HOME") == null &&
610 				(excludedModules == null || !excludedModules.contains("android")))) {
611 			new GdxSetupUI();
612 			printHelp();
613 		} else {
614 			String sdkLocation = "";
615 			 if (excludedModules == null || !excludedModules.contains("android")) {
616 				  if (System.getenv("ANDROID_HOME") != null && !params.containsKey("sdkLocation")) {
617 						sdkLocation = System.getenv("ANDROID_HOME");
618 				  } else {
619 						sdkLocation = params.get("sdkLocation");
620 				  }
621 			 }
622 
623 			DependencyBank bank = new DependencyBank();
624 			ProjectBuilder builder = new ProjectBuilder(bank);
625 			List<ProjectType> projects = new ArrayList<ProjectType>();
626 
627 			projects.add(ProjectType.CORE);
628 			 if (excludedModules == null) {
629 				  projects.add(ProjectType.DESKTOP);
630 				  projects.add(ProjectType.ANDROID);
631 				  projects.add(ProjectType.IOS);
632 				  projects.add(ProjectType.IOSMOE);
633 				  projects.add(ProjectType.HTML);
634 			 } else {
635 				  if (!excludedModules.contains("desktop"))
636 						projects.add(ProjectType.DESKTOP);
637 				  if (!excludedModules.contains("android"))
638 						projects.add(ProjectType.ANDROID);
639 				  if (!excludedModules.contains("ios"))
640 						projects.add(ProjectType.IOS);
641 				  if (!excludedModules.contains("iosmoe"))
642 					  	projects.add(ProjectType.IOSMOE);
643 				  if (!excludedModules.contains("html"))
644 						projects.add(ProjectType.HTML);
645 			 }
646 
647 			List<Dependency> dependencies = new ArrayList<Dependency>();
648 			if (params.containsKey("extensions")) {
649 				 dependencies.addAll(parseDependencies(params.get("extensions"), bank));
650 			} else {
651 				 dependencies.add(bank.getDependency(ProjectDependency.GDX));
652 			}
653 
654 			builder.buildProject(projects, dependencies);
655 			builder.build();
656 			new GdxSetup().build(builder, params.get("dir"), params.get("name"), params.get("package"), params.get("mainClass"),
657 				sdkLocation, new CharCallback() {
658 					@Override
659 					public void character (char c) {
660 						System.out.print(c);
661 					}
662 				}, null);
663 		}
664 	}
665 }
666