Added
Link Here
|
1 |
package org.eclipse.help.internal.validation; |
2 |
|
3 |
import java.io.IOException; |
4 |
import java.io.InputStream; |
5 |
import java.net.MalformedURLException; |
6 |
import java.net.URL; |
7 |
import java.util.ArrayList; |
8 |
import java.util.HashMap; |
9 |
|
10 |
import javax.xml.parsers.ParserConfigurationException; |
11 |
|
12 |
import org.eclipse.help.IHelpResource; |
13 |
import org.eclipse.help.ILink; |
14 |
import org.eclipse.help.IToc; |
15 |
import org.eclipse.help.IUAElement; |
16 |
import org.eclipse.help.internal.protocols.HelpURLConnection; |
17 |
import org.eclipse.help.internal.toc.TocContribution; |
18 |
import org.eclipse.help.internal.toc.TocFile; |
19 |
import org.eclipse.help.internal.toc.TocFileParser; |
20 |
import org.xml.sax.SAXException; |
21 |
|
22 |
public class TocValidator { |
23 |
|
24 |
private static final boolean DEBUG = false; |
25 |
|
26 |
private HashMap processedTocs; |
27 |
private TocFileParser parser; |
28 |
|
29 |
public static class BrokenLink { |
30 |
private String tocID; |
31 |
private String href; |
32 |
private BrokenLink(String tocID, String href) { |
33 |
this.tocID = tocID; |
34 |
this.href = href; |
35 |
} |
36 |
public String getTocID() { |
37 |
return tocID; } |
38 |
public String getHref() { |
39 |
return href; } |
40 |
} |
41 |
|
42 |
/** |
43 |
* Checks the validity of all <code>href</code> attributes on <code>topic</code> elements in the toc and the |
44 |
* <code>topic</code> attribute on the <code>toc</code> element if there is one. Also checks validity of any |
45 |
* nested tocs. |
46 |
* @param hrefs gives the list of paths to toc files to validate including the plug-in id |
47 |
* (i.e. "/<plug-in id>/<path>/<file>") |
48 |
* @return An ArrayList of BrokenLink objects in the toc. If no broken links are found, an empty ArrayList |
49 |
* is returned. |
50 |
* @throws IOException |
51 |
* @throws SAXException |
52 |
* @throws ParserConfigurationException |
53 |
*/ |
54 |
public static ArrayList validate(String[] hrefs) throws IOException, SAXException, ParserConfigurationException{ |
55 |
TocValidator v = new TocValidator(); |
56 |
ArrayList result = new ArrayList(); |
57 |
for (int i = 0; i < hrefs.length; i++) |
58 |
v.processToc(hrefs[i], null, result); |
59 |
return result; |
60 |
} |
61 |
|
62 |
private TocValidator() { |
63 |
processedTocs = new HashMap(); |
64 |
parser = new TocFileParser(); |
65 |
} |
66 |
|
67 |
/* Checks validity of all links in a given toc. If all links are valid, an empty ArrayList is returned. |
68 |
* Otherwise an ArrayList of BrokenLink objects is returned. |
69 |
*/ |
70 |
private void processToc(String href, String plugin, ArrayList result) throws IOException, SAXException, ParserConfigurationException { |
71 |
String path; |
72 |
if (href.startsWith("/")) { //$NON-NLS-1$ |
73 |
href = href.substring(1); |
74 |
int index = href.indexOf("/"); //$NON-NLS-1$ |
75 |
if (index == -1) |
76 |
throw new IOException("Invalid parameters supplied to the validate method."); //$NON-NLS-1$ |
77 |
plugin = href.substring(0, index); |
78 |
path = href.substring(index+1); |
79 |
} else { |
80 |
path = href; |
81 |
} |
82 |
if (plugin == null) |
83 |
throw new IOException("Invalid parameters supplied to the validate method."); //$NON-NLS-1$ |
84 |
String key = "/" + plugin + "/" + path; //$NON-NLS-1$ //$NON-NLS-2$ |
85 |
if (processedTocs.get(key) != null) { |
86 |
if (DEBUG) |
87 |
System.out.println("Skipping toc because it has already been validated: " + key); //$NON-NLS-1$ |
88 |
return; |
89 |
} |
90 |
if (DEBUG) |
91 |
System.out.println("Starting toc: " + key); //$NON-NLS-1$ |
92 |
processedTocs.put(key, new Object()); |
93 |
TocContribution contribution = parser.parse(new TocFile(plugin,path, true, "en", null, null)); //$NON-NLS-1$ |
94 |
process(contribution.getToc(), plugin, path, result); |
95 |
} |
96 |
|
97 |
/* Checks validity of all links in the given IUAElement and recursively calls itself to check all children. |
98 |
* If there are any links to other tocs, calls the processToc method to validate them. If any broken links |
99 |
* are found, an appropriate BrokenLink object will be added to the result ArrayList. |
100 |
*/ |
101 |
private void process(IUAElement element, String plugin, String path, ArrayList result) throws SAXException, ParserConfigurationException { |
102 |
String href; |
103 |
if (element instanceof ILink) { |
104 |
href = ((ILink)element).getToc(); |
105 |
try { |
106 |
processToc(href, plugin, result); |
107 |
} catch (IOException e) { |
108 |
result.add(new BrokenLink("/" + plugin + "/" + path, href)); //$NON-NLS-1$ //$NON-NLS-2$ |
109 |
} |
110 |
} |
111 |
else if (element instanceof IHelpResource) { |
112 |
if (element instanceof IToc) |
113 |
href = ((IToc)element).getTopic(null).getHref(); |
114 |
else |
115 |
href = ((IHelpResource)element).getHref(); |
116 |
if (href != null) |
117 |
if (!checkLink(href, plugin)) { |
118 |
result.add(new BrokenLink("/" + plugin + "/" + path, href)); //$NON-NLS-1$ //$NON-NLS-2$ |
119 |
} |
120 |
} |
121 |
IUAElement [] children = element.getChildren(); |
122 |
for (int i = 0; i < children.length; i++) |
123 |
process(children[i], plugin, path, result); |
124 |
} |
125 |
|
126 |
/* Checks validity of a given link from a toc in a given plug-in. |
127 |
* returns true if the link is valid. |
128 |
*/ |
129 |
private boolean checkLink(String href, String plugin) { |
130 |
if (href.startsWith("http")) { //$NON-NLS-1$ |
131 |
if (DEBUG) |
132 |
System.out.println(" Skipping href: " + href); //$NON-NLS-1$ |
133 |
return true; |
134 |
} |
135 |
if (DEBUG) |
136 |
System.out.print(" Checking href: " + href + "..."); //$NON-NLS-1$ //$NON-NLS-2$ |
137 |
boolean result = true; |
138 |
InputStream i = null; |
139 |
try { |
140 |
HelpURLConnection c = new HelpURLConnection(createURL(href, plugin)); |
141 |
if ((i = c.getInputStream()) == null) |
142 |
result = false; |
143 |
} catch (Exception e) { |
144 |
result = false; |
145 |
} |
146 |
if (i != null) { |
147 |
try { i.close(); } catch(Exception e) { } |
148 |
i = null; |
149 |
} |
150 |
if (DEBUG) |
151 |
System.out.println(result?"pass":"fail"); //$NON-NLS-1$ //$NON-NLS-2$ |
152 |
return result; |
153 |
} |
154 |
|
155 |
// Builds a URL for a given plug-in/href to create a HelpURLConnection |
156 |
private URL createURL(String href, String plugin) throws MalformedURLException { |
157 |
StringBuffer url = new StringBuffer("file:/"); //$NON-NLS-1$ |
158 |
url.append(plugin); |
159 |
url.append("/"); //$NON-NLS-1$ |
160 |
url.append(href); |
161 |
return new URL(url.toString()); |
162 |
} |
163 |
} |