summaryrefslogtreecommitdiff
path: root/morfologik-tools/src/main/java/morfologik/tools/Launcher.java
blob: 320c1dcbd6e17c7a3ba280c51b2a4858591f0fbc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package morfologik.tools;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.TreeMap;
import java.util.jar.Manifest;

import morfologik.util.FileUtils;

/**
 * A launcher for other command-line tools.
 */
public final class Launcher {
	/**
	 * Tool description.
	 */
	final static class ToolInfo {
		public final Class<? extends Tool> clazz;
		public final String info;

		public ToolInfo(Class<? extends Tool> clazz, String info) {
			this.clazz = clazz;
			this.info = info;
		}

		public void invoke(String[] subArgs) throws Exception {
			final Method m = clazz.getMethod("main",
			        new Class[] { String[].class });
			m.invoke(null, new Object[] { subArgs });
		}
	}

	/**
	 * Command line entry point.
	 */
	public static void main(String[] args) throws Exception {
		// If so, tools are unavailable and a classpath error has been logged.
		final TreeMap<String, ToolInfo> tools = initTools();

		if (tools == null)
		{
			return;
		}

		if (args.length == 0) {
			System.out.println("Provide tool name and its command-line options. "
			    + "Available tools:");
			for (String key : tools.keySet()) {
				final ToolInfo toolInfo = tools.get(key);
				System.out.println(String.format("  %-10s - %s", key,
				        toolInfo.info));
			}
		} else {
			final String toolName = args[0];
			if (!tools.containsKey(toolName)) {
				System.out.println("Unknown tool: " + toolName);
				return;
			}

			final String[] subArgs = new String[args.length - 1];
			System.arraycopy(args, 1, subArgs, 0, subArgs.length);

			final ToolInfo toolInfo = (ToolInfo) tools.get(toolName);
			toolInfo.invoke(subArgs);
		}
	}

	/**
	 * Initialize and check tools' availability.
	 */
	static TreeMap<String, ToolInfo> initTools() {
		TreeMap<String, ToolInfo> tools = new TreeMap<String, ToolInfo>();

		tools.put("fsa_build", new ToolInfo(FSABuildTool.class,
		        "Create an automaton from plain text files."));

		tools.put("fsa_dump", new ToolInfo(FSADumpTool.class,
		        "Dump an FSA dictionary."));

		tools.put("tab2morph", new ToolInfo(MorphEncodingTool.class,
		        "Convert tabbed dictionary to fsa encoding format."));

		tools.put("plstem", new ToolInfo(PolishStemmingTool.class,
		        "Apply Polish dictionary stemming to the input."));

		// Prune unavailable tools.
		for (Iterator<ToolInfo> i = tools.values().iterator(); i.hasNext();) {
			ToolInfo ti = i.next();
			try {
				ti.clazz.newInstance().isAvailable();
			} catch (NoClassDefFoundError e) {
				logJarWarning();
				return null;
			} catch (Throwable e) {
				System.out.println("Tools could not be initialized because" +
						" of an exception during initialization: "
						+ e.getClass().getName() + ", " + e.getMessage());
				return null;
			}
		}
		
		return tools;
	}
	
	/**
	 * Log a warning about missing JAR dependencies.
	 */
	private static void logJarWarning() {
		System.out.println("Tools are unavailable, at least one JAR dependency missing.");

		try {
			final Class<Launcher> clazz = Launcher.class;
			final ClassLoader classLoader = clazz.getClassLoader();

			final String clazzName = clazz.getName().replace('.', '/') + ".class";
			// Figure out our own class path location.
			final URL launcherLocation = classLoader.getResource(clazzName);
			if (launcherLocation == null)
				return;
			
			String launcherPrefix = launcherLocation.toString()
				.replace(clazzName, "");

			// Figure our our location's MANIFEST.MF (class loader may be hitting a few).
			URL manifestResource = null;
    		Enumeration<URL> manifests = classLoader.getResources("META-INF/MANIFEST.MF");
    		while (manifests.hasMoreElements())
    		{
    			URL candidate = manifests.nextElement();
    			if (candidate.toString().startsWith(launcherPrefix))
    			{
    				manifestResource = candidate;
    				break;
    			}
    		}
    		
    		if (manifestResource == null)
    			return;

			InputStream stream = null;
			try {
				stream = manifestResource.openStream();
				Manifest manifest = new Manifest(stream);
				
				System.out.println("Required JARs: "
						+ manifest.getMainAttributes().getValue("Class-Path"));
			} catch (IOException e) {
				FileUtils.close(stream);
			}
		} catch (IOException e) {
			// Ignore.
		}
    }
}