1 package org.apache.maven.tools.plugin.javadoc;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.BufferedReader;
23
24 import java.io.IOException;
25 import java.net.URI;
26 import java.nio.file.Files;
27 import java.nio.file.Path;
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Optional;
33 import java.util.regex.Pattern;
34
35 import org.apache.maven.settings.Settings;
36 import org.codehaus.plexus.languages.java.version.JavaVersion;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40
41
42
43
44
45 public class JavadocLinkGenerator
46 {
47
48
49
50
51 public enum JavadocToolVersionRange
52 {
53 JDK7_OR_LOWER( null, JavaVersion.parse( "1.8" ) ),
54 JDK8_OR_9( JavaVersion.parse( "1.8" ), JavaVersion.parse( "10" ) ),
55 JDK10_OR_HIGHER( JavaVersion.parse( "10" ), null );
56
57
58 private final JavaVersion lowerBound;
59 private final JavaVersion upperBound;
60 JavadocToolVersionRange( JavaVersion lowerBound, JavaVersion upperBound )
61 {
62 this.lowerBound = lowerBound;
63 this.upperBound = upperBound;
64 }
65
66 static JavadocToolVersionRange findMatch( JavaVersion javadocVersion )
67 {
68 for ( JavadocToolVersionRange range : values() )
69 {
70 if ( ( range.lowerBound == null || javadocVersion.isAtLeast( range.lowerBound ) )
71 && ( range.upperBound == null || javadocVersion.isBefore( range.upperBound ) ) )
72 {
73 return range;
74 }
75 }
76 throw new IllegalArgumentException( "Found no matching javadoc tool version range for " + javadocVersion );
77 }
78 }
79
80 private static final Logger LOG = LoggerFactory.getLogger( JavadocLinkGenerator.class );
81 private final List<JavadocSite> externalJavadocSites;
82 private final JavadocSite internalJavadocSite;
83
84
85
86
87
88
89
90
91 public JavadocLinkGenerator( URI internalJavadocSiteUrl,
92 String internalJavadocVersion )
93 {
94 this( internalJavadocSiteUrl, internalJavadocVersion, Collections.emptyList(), null );
95 }
96
97
98
99
100
101
102
103 public JavadocLinkGenerator( List<URI> externalJavadocSiteUrls, Settings settings )
104 {
105 this( null, null, externalJavadocSiteUrls, settings );
106 }
107
108
109
110
111
112
113
114
115
116 public JavadocLinkGenerator( URI internalJavadocSiteUrl,
117 String internalJavadocVersion,
118 List<URI> externalJavadocSiteUrls, Settings settings )
119 {
120 if ( internalJavadocSiteUrl != null )
121 {
122
123 JavaVersion javadocVersion = JavaVersion.parse( internalJavadocVersion );
124 internalJavadocSite = new JavadocSite( internalJavadocSiteUrl,
125 JavadocToolVersionRange.findMatch( javadocVersion ),
126 false );
127 }
128 else
129 {
130 internalJavadocSite = null;
131 }
132 if ( externalJavadocSiteUrls != null )
133 {
134 externalJavadocSites = new ArrayList<>( externalJavadocSiteUrls.size() );
135 for ( URI siteUrl : externalJavadocSiteUrls )
136 {
137 try
138 {
139 externalJavadocSites.add( new JavadocSite( siteUrl, settings ) );
140 }
141 catch ( IOException e )
142 {
143 LOG.warn( "Could not use {} as base URL: {}", siteUrl, e.getMessage(), e );
144 }
145 }
146 }
147 else
148 {
149 externalJavadocSites = Collections.emptyList();
150 }
151 if ( internalJavadocSite == null && externalJavadocSites.isEmpty() )
152 {
153 throw new IllegalArgumentException( "Either internal or at least one accessible external javadoc "
154 + "URLs must be given!" );
155 }
156 }
157
158
159
160
161
162
163
164
165
166
167
168 public URI createLink( FullyQualifiedJavadocReference javadocReference )
169 {
170 if ( !javadocReference.isExternal() && internalJavadocSite != null )
171 {
172 return internalJavadocSite.createLink( javadocReference );
173 }
174 else
175 {
176 JavadocSite javadocSite = externalJavadocSites.stream()
177 .filter( base -> base.hasEntryFor( javadocReference.getModuleName(),
178 javadocReference.getPackageName() ) )
179 .findFirst().orElseThrow( () -> new IllegalArgumentException( "Found no javadoc site for "
180 + javadocReference ) );
181 return javadocSite.createLink( javadocReference );
182 }
183 }
184
185
186
187
188
189
190
191
192
193
194 public URI createLink( String binaryName )
195 {
196 Map.Entry<String, String> packageAndClassName = JavadocSite.getPackageAndClassName( binaryName );
197
198 JavadocSite javadocSite = externalJavadocSites.stream()
199 .filter( base -> base.hasEntryFor( Optional.empty(),
200 Optional.of( packageAndClassName.getKey() ) ) )
201 .findFirst().orElse( null );
202 if ( javadocSite == null )
203 {
204 if ( internalJavadocSite != null )
205 {
206 javadocSite = internalJavadocSite;
207 }
208 else
209 {
210 throw new IllegalArgumentException( "Found no javadoc site for " + binaryName );
211 }
212 }
213 return javadocSite.createLink( packageAndClassName.getKey(), packageAndClassName.getValue() );
214 }
215
216 public URI getInternalJavadocSiteBaseUrl()
217 {
218 if ( internalJavadocSite == null )
219 {
220 throw new IllegalStateException( "Could not get docroot of internal javadoc as it hasn't been set" );
221 }
222 return internalJavadocSite.getBaseUri();
223 }
224
225
226
227
228
229
230
231
232
233 public static boolean isLinkValid( URI url, Path baseDirectory )
234 {
235 if ( url.isAbsolute() )
236 {
237 try ( BufferedReader reader = JavadocSite.getReader( url.toURL(), null ) )
238 {
239 if ( url.getFragment() != null )
240 {
241 Pattern pattern = JavadocSite.getAnchorPattern( url.getFragment() );
242 if ( reader.lines().noneMatch( pattern.asPredicate() ) )
243 {
244 return false;
245 }
246 }
247 }
248 catch ( IOException e )
249 {
250 return false;
251 }
252 return true;
253 }
254 else
255 {
256 Path file = baseDirectory.resolve( url.getPath() );
257 boolean exists = Files.exists( file );
258 if ( !exists )
259 {
260 LOG.debug( "Could not find file given through '{}' in resolved path '{}'", url, file );
261 }
262 return exists;
263 }
264 }
265 }