1
2
3
4
5
6
7
8
9
10
11 package org.mule.tools.schemadocs;
12
13 import org.mule.util.IOUtils;
14
15 import java.io.File;
16 import java.io.FileOutputStream;
17 import java.io.FilenameFilter;
18 import java.io.IOException;
19 import java.io.InputStream;
20 import java.io.OutputStream;
21 import java.io.OutputStreamWriter;
22 import java.net.JarURLConnection;
23 import java.net.MalformedURLException;
24 import java.net.URL;
25 import java.util.Arrays;
26 import java.util.Enumeration;
27 import java.util.Iterator;
28 import java.util.LinkedList;
29 import java.util.List;
30 import java.util.jar.JarEntry;
31
32 import javax.xml.parsers.ParserConfigurationException;
33 import javax.xml.transform.Source;
34 import javax.xml.transform.Templates;
35 import javax.xml.transform.Transformer;
36 import javax.xml.transform.TransformerException;
37 import javax.xml.transform.TransformerFactory;
38 import javax.xml.transform.stream.StreamResult;
39 import javax.xml.transform.stream.StreamSource;
40
41 import org.apache.commons.logging.Log;
42 import org.apache.commons.logging.LogFactory;
43 import org.springframework.core.io.Resource;
44 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
45
46
47 public class SchemaDocsMain
48 {
49
50 public static final String BACKUP = ".bak";
51 public static final String XSD = ".xsd";
52 public static final String MULE = "mule";
53 public static final String TAG = "tag";
54 public static final String XSL_FILE = "rename-tag.xsl";
55 public static final List TARGET_PATH = Arrays.asList(new String[]{"tools", "schemadocs", "target"});
56 public static final String[] BLOCKED = new String[]{"wssecurity"};
57
58 protected final Log logger = LogFactory.getLog(getClass());
59
60 public static void main(String[] args)
61 throws IOException, TransformerException, ParserConfigurationException
62 {
63 if (null == args || args.length != 3)
64 {
65 throw new IllegalArgumentException("Needs 3 arguments: prefix, postfix and destination");
66 }
67 new SchemaDocsMain(args[0], args[1], args[2]);
68 }
69
70 public SchemaDocsMain(String prefix, String postfix, String normalizedPath)
71 throws IOException, TransformerException, ParserConfigurationException
72 {
73 logger.info("Generating " + normalizedPath);
74 logger.debug("prefix: " + prefix);
75 logger.debug("postfix: " + postfix);
76 File normalized = inTargetDir(normalizedPath);
77 backup(normalized);
78 InputStream xslSource = IOUtils.getResourceAsStream(XSL_FILE, getClass());
79 if (null == xslSource)
80 {
81 throw new IllegalStateException("Cannot open " + XSL_FILE);
82 }
83 create(normalized, false);
84 OutputStream out = new FileOutputStream(normalized);
85 logger.debug("out: " + out);
86 OutputStreamWriter outWriter = new OutputStreamWriter(out);
87 IOUtils.copy(IOUtils.getResourceAsStream(prefix, getClass()), outWriter);
88 outWriter.flush();
89 processSchema(xslSource, out);
90 out.flush();
91 IOUtils.copy(IOUtils.getResourceAsStream(postfix, getClass()), outWriter);
92 outWriter.close();
93 }
94
95 protected void create(File file, boolean dir) throws IOException
96 {
97 if (!file.getParentFile().exists())
98 {
99 create(file.getParentFile(), true);
100 }
101 logger.debug("creating " + file);
102 if (dir)
103 {
104 file.mkdir();
105 }
106 else
107 {
108 file.createNewFile();
109 }
110 }
111
112
113 protected File inTargetDir(String path)
114 {
115 if (path.startsWith(File.separator))
116 {
117 return new File(path);
118 }
119 else
120 {
121 File dir = new File(".");
122 Iterator dirs = TARGET_PATH.iterator();
123 boolean foundPath = false;
124 while (dirs.hasNext())
125 {
126 File next = new File(dir, (String) dirs.next());
127 if (next.exists())
128 {
129 foundPath = true;
130 dir = next;
131 }
132 else if (foundPath)
133 {
134
135
136
137 throw new IllegalArgumentException("Could not find " + next + " while placing in target directory");
138 }
139 }
140 File target = new File(dir, path);
141 logger.info("Target: " + target);
142 return target;
143 }
144 }
145
146 protected void processSchema(InputStream xslSource, OutputStream out)
147 throws TransformerException, IOException, ParserConfigurationException
148 {
149 TransformerFactory factory = TransformerFactory.newInstance();
150 Templates template = factory.newTemplates(new StreamSource(xslSource));
151 Transformer xformer = template.newTransformer();
152 Iterator urls = listSchema2().iterator();
153 while (urls.hasNext())
154 {
155 URL url = (URL) urls.next();
156 String tag = tagFromFileName(url.getFile());
157 logger.info(tag + " : " + url);
158 xformer.setParameter(TAG, tag);
159 Source source = new StreamSource(url.openStream());
160 xformer.transform(source, new StreamResult(out));
161
162 out.flush();
163 }
164 }
165
166
167 protected static String tagFromFileName(String name)
168 {
169 String dropExtension = toLeftOf(name, ".", name);
170 String dropSlash = toRightOf(dropExtension, "/", dropExtension, true);
171 String dropBackslash = toRightOf(dropSlash, "\\", dropSlash, true);
172 return toRightOf(dropBackslash, "-", "mule", false);
173 }
174
175 protected static String toRightOf(String text, String delim, String deflt, boolean far)
176 {
177 int index = far ? text.lastIndexOf(delim) : text.indexOf(delim);
178 if (index > -1)
179 {
180 return text.substring(index+1);
181 }
182 else
183 {
184 return deflt;
185 }
186 }
187
188 protected static String toLeftOf(String text, String delim, String deflt)
189 {
190 int index = text.lastIndexOf(delim);
191 if (index > -1)
192 {
193 return text.substring(0, index);
194 }
195 else
196 {
197 return deflt;
198 }
199 }
200
201
202 protected List listSchema1() throws IOException
203 {
204 PathMatchingResourcePatternResolver resolver =
205 new PathMatchingResourcePatternResolver(getClass().getClassLoader());
206 Resource[] resources = resolver.getResources("**/META-INF/*.xsd");
207 List list = new LinkedList();
208 for (int i = 0; i < resources.length; ++i)
209 {
210 list.add(resources[i].getURL());
211 }
212 return list;
213 }
214
215
216
217 protected List listSchema2() throws IOException
218 {
219 ClassLoader loader = getClass().getClassLoader();
220 List files = new LinkedList();
221 Enumeration resources = loader.getResources("META-INF");
222 FilenameFilter filter =
223 new FilenameFilter() {
224 public boolean accept(File dir, String name)
225 {
226 if (name.startsWith(MULE) && name.endsWith(XSD))
227 {
228 for (int i = 0; i < BLOCKED.length; ++i)
229 {
230 if (name.indexOf(BLOCKED[i]) > -1)
231 {
232 return false;
233 }
234 }
235 return true;
236 }
237 else
238 {
239 return false;
240 }
241 }
242 };
243 while (resources.hasMoreElements())
244 {
245 URL url = (URL) resources.nextElement();
246 logger.debug("url: " + url);
247 if (url.toString().startsWith("jar:"))
248 {
249 readFromJar(url, files);
250 }
251 else if ("file".equals(url.getProtocol()))
252 {
253 readFromDirectory(new File(url.getFile()), files, filter);
254 }
255 }
256 return files;
257 }
258
259
260 protected void readFromDirectory(File dir, List files, FilenameFilter filter) throws MalformedURLException
261 {
262 String[] names = dir.list(filter);
263 for (int i = 0; i < names.length; ++i)
264 {
265 String name = names[i];
266 logger.debug("file: " + name);
267 files.add(new File(dir, name).toURL());
268 }
269 }
270
271
272 protected void readFromJar(URL jarUrl, List resources) throws IOException
273 {
274 JarURLConnection jarConnection = (JarURLConnection) jarUrl.openConnection();
275 Enumeration entries = jarConnection.getJarFile().entries();
276 while (entries.hasMoreElements())
277 {
278 JarEntry entry = (JarEntry) entries.nextElement();
279 String name = new File(entry.getName()).getName();
280 if (name.startsWith(MULE) && name.endsWith(XSD))
281 {
282 logger.debug("entry: " + entry);
283 resources.add(new URL(jarUrl, entry.getName()));
284 }
285 }
286 }
287
288 protected void backup(File file) throws IOException
289 {
290 if (file.exists())
291 {
292 File backup = new File(file.getAbsoluteFile().getParent(), file.getName() + BACKUP);
293 if (backup.exists())
294 {
295 logger.debug("deleting " + backup.getCanonicalPath());
296 backup.delete();
297 }
298 logger.debug("renaming " + file.getCanonicalPath() + " to " + backup.getCanonicalPath());
299 file.renameTo(backup);
300 }
301 }
302
303 }