1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
package org.xwiki.repository.internal.resources; |
21 |
|
|
22 |
|
import java.io.IOException; |
23 |
|
import java.net.ProxySelector; |
24 |
|
import java.net.URI; |
25 |
|
import java.net.URISyntaxException; |
26 |
|
import java.net.URL; |
27 |
|
|
28 |
|
import javax.inject.Inject; |
29 |
|
import javax.inject.Named; |
30 |
|
import javax.inject.Singleton; |
31 |
|
import javax.ws.rs.GET; |
32 |
|
import javax.ws.rs.Path; |
33 |
|
import javax.ws.rs.PathParam; |
34 |
|
import javax.ws.rs.QueryParam; |
35 |
|
import javax.ws.rs.WebApplicationException; |
36 |
|
import javax.ws.rs.core.Response; |
37 |
|
import javax.ws.rs.core.Response.ResponseBuilder; |
38 |
|
import javax.ws.rs.core.Response.Status; |
39 |
|
|
40 |
|
import org.apache.http.HttpEntity; |
41 |
|
import org.apache.http.HttpResponse; |
42 |
|
import org.apache.http.client.methods.HttpGet; |
43 |
|
import org.apache.http.impl.client.DefaultHttpClient; |
44 |
|
import org.apache.http.impl.conn.ProxySelectorRoutePlanner; |
45 |
|
import org.apache.http.params.CoreConnectionPNames; |
46 |
|
import org.apache.http.params.CoreProtocolPNames; |
47 |
|
import org.restlet.data.Disposition; |
48 |
|
import org.restlet.data.MediaType; |
49 |
|
import org.restlet.representation.InputRepresentation; |
50 |
|
import org.xwiki.component.annotation.Component; |
51 |
|
import org.xwiki.extension.Extension; |
52 |
|
import org.xwiki.extension.ExtensionFile; |
53 |
|
import org.xwiki.extension.ExtensionId; |
54 |
|
import org.xwiki.extension.ResolveException; |
55 |
|
import org.xwiki.extension.repository.DefaultExtensionRepositoryDescriptor; |
56 |
|
import org.xwiki.extension.repository.ExtensionRepository; |
57 |
|
import org.xwiki.extension.repository.ExtensionRepositoryDescriptor; |
58 |
|
import org.xwiki.extension.repository.ExtensionRepositoryFactory; |
59 |
|
import org.xwiki.extension.repository.ExtensionRepositoryManager; |
60 |
|
import org.xwiki.model.reference.AttachmentReference; |
61 |
|
import org.xwiki.model.reference.AttachmentReferenceResolver; |
62 |
|
import org.xwiki.query.QueryException; |
63 |
|
import org.xwiki.rendering.listener.reference.ResourceReference; |
64 |
|
import org.xwiki.rendering.listener.reference.ResourceType; |
65 |
|
import org.xwiki.repository.Resources; |
66 |
|
import org.xwiki.repository.internal.XWikiRepositoryModel; |
67 |
|
import org.xwiki.repository.internal.reference.ExtensionResourceReference; |
68 |
|
|
69 |
|
import com.xpn.xwiki.XWikiContext; |
70 |
|
import com.xpn.xwiki.XWikiException; |
71 |
|
import com.xpn.xwiki.doc.XWikiAttachment; |
72 |
|
import com.xpn.xwiki.doc.XWikiDocument; |
73 |
|
import com.xpn.xwiki.objects.BaseObject; |
74 |
|
|
75 |
|
|
76 |
|
@version |
77 |
|
@since |
78 |
|
|
79 |
|
@Component |
80 |
|
@Named("org.xwiki.repository.internal.resources.ExtensionVersionFileRESTResource") |
81 |
|
@Path(Resources.EXTENSION_VERSION_FILE) |
82 |
|
@Singleton |
|
|
| 57.4% |
Uncovered Elements: 40 (94) |
Complexity: 18 |
Complexity Density: 0.25 |
|
83 |
|
public class ExtensionVersionFileRESTResource extends AbstractExtensionRESTResource |
84 |
|
{ |
85 |
|
@Inject |
86 |
|
private AttachmentReferenceResolver<String> attachmentResolver; |
87 |
|
|
88 |
|
@Inject |
89 |
|
private ExtensionRepositoryManager extensionRepositoryManager; |
90 |
|
|
|
|
| 63.6% |
Uncovered Elements: 4 (11) |
Complexity: 4 |
Complexity Density: 0.57 |
|
91 |
20 |
@GET... |
92 |
|
public Response downloadExtension(@PathParam(Resources.PPARAM_EXTENSIONID) String extensionId, |
93 |
|
@PathParam(Resources.PPARAM_EXTENSIONVERSION) String extensionVersion, |
94 |
|
@QueryParam(ExtensionResourceReference.PARAM_REPOSITORYID) String repositoryId, |
95 |
|
@QueryParam(ExtensionResourceReference.PARAM_REPOSITORYTYPE) String repositoryType, |
96 |
|
@QueryParam(ExtensionResourceReference.PARAM_REPOSITORYURI) String repositoryURI) |
97 |
|
throws XWikiException, QueryException, URISyntaxException, IOException, ResolveException |
98 |
|
{ |
99 |
20 |
ResponseBuilder response; |
100 |
|
|
101 |
20 |
if (repositoryId != null) { |
102 |
0 |
response = |
103 |
|
downloadRemoteExtension(new ExtensionResourceReference(extensionId, extensionVersion, repositoryId)); |
104 |
20 |
} else if (repositoryType != null && repositoryURI != null) { |
105 |
0 |
response = downloadRemoteExtension( |
106 |
|
new ExtensionResourceReference(extensionId, extensionVersion, repositoryType, new URI(repositoryURI))); |
107 |
|
} else { |
108 |
20 |
response = downloadLocalExtension(extensionId, extensionVersion); |
109 |
|
} |
110 |
|
|
111 |
20 |
return response.build(); |
112 |
|
} |
113 |
|
|
|
|
| 48.1% |
Uncovered Elements: 27 (52) |
Complexity: 7 |
Complexity Density: 0.17 |
|
114 |
20 |
private ResponseBuilder downloadLocalExtension(String extensionId, String extensionVersion)... |
115 |
|
throws ResolveException, IOException, QueryException, XWikiException |
116 |
|
{ |
117 |
20 |
XWikiDocument extensionDocument = getExistingExtensionDocumentById(extensionId); |
118 |
|
|
119 |
20 |
checkRights(extensionDocument); |
120 |
|
|
121 |
20 |
BaseObject extensionObject = getExtensionObject(extensionDocument); |
122 |
20 |
BaseObject extensionVersionObject = getExtensionVersionObject(extensionDocument, extensionVersion); |
123 |
|
|
124 |
20 |
ResponseBuilder response = null; |
125 |
|
|
126 |
20 |
ResourceReference resourceReference = |
127 |
|
this.repositoryManager.getDownloadReference(extensionDocument, extensionVersionObject); |
128 |
|
|
129 |
20 |
if (ResourceType.ATTACHMENT.equals(resourceReference.getType())) { |
130 |
|
|
131 |
17 |
AttachmentReference attachmentReference = this.attachmentResolver.resolve(resourceReference.getReference(), |
132 |
|
extensionDocument.getDocumentReference()); |
133 |
|
|
134 |
17 |
XWikiContext xcontext = getXWikiContext(); |
135 |
|
|
136 |
17 |
XWikiDocument document = |
137 |
|
xcontext.getWiki().getDocument(attachmentReference.getDocumentReference(), xcontext); |
138 |
|
|
139 |
17 |
checkRights(document); |
140 |
|
|
141 |
17 |
XWikiAttachment xwikiAttachment = document.getAttachment(attachmentReference.getName()); |
142 |
|
|
143 |
17 |
response = getAttachmentResponse(xwikiAttachment); |
144 |
3 |
} else if (ResourceType.URL.equals(resourceReference.getType())) { |
145 |
|
|
146 |
0 |
URL url = new URL(resourceReference.getReference()); |
147 |
|
|
148 |
0 |
DefaultHttpClient httpClient = new DefaultHttpClient(); |
149 |
|
|
150 |
0 |
httpClient.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "XWikiExtensionRepository"); |
151 |
0 |
httpClient.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 60000); |
152 |
0 |
httpClient.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000); |
153 |
|
|
154 |
0 |
ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner( |
155 |
|
httpClient.getConnectionManager().getSchemeRegistry(), ProxySelector.getDefault()); |
156 |
0 |
httpClient.setRoutePlanner(routePlanner); |
157 |
|
|
158 |
0 |
HttpGet getMethod = new HttpGet(url.toString()); |
159 |
|
|
160 |
0 |
HttpResponse subResponse; |
161 |
0 |
try { |
162 |
0 |
subResponse = httpClient.execute(getMethod); |
163 |
|
} catch (Exception e) { |
164 |
0 |
throw new IOException("Failed to request [" + getMethod.getURI() + "]", e); |
165 |
|
} |
166 |
|
|
167 |
0 |
response = Response.status(subResponse.getStatusLine().getStatusCode()); |
168 |
|
|
169 |
|
|
170 |
|
|
171 |
0 |
HttpEntity entity = subResponse.getEntity(); |
172 |
0 |
InputRepresentation content = |
173 |
|
new InputRepresentation( |
174 |
0 |
entity.getContent(), entity.getContentType() != null |
175 |
|
? new MediaType(entity.getContentType().getValue()) : MediaType.APPLICATION_OCTET_STREAM, |
176 |
|
entity.getContentLength()); |
177 |
|
|
178 |
0 |
String type = getValue(extensionObject, XWikiRepositoryModel.PROP_EXTENSION_TYPE); |
179 |
|
|
180 |
0 |
Disposition disposition = new Disposition(Disposition.TYPE_ATTACHMENT); |
181 |
0 |
disposition.setFilename(extensionId + '-' + extensionVersion + '.' + type); |
182 |
0 |
content.setDisposition(disposition); |
183 |
|
|
184 |
0 |
response.entity(content); |
185 |
3 |
} else if (ExtensionResourceReference.TYPE.equals(resourceReference.getType())) { |
186 |
3 |
ExtensionResourceReference extensionResource; |
187 |
3 |
if (resourceReference instanceof ExtensionResourceReference) { |
188 |
3 |
extensionResource = (ExtensionResourceReference) resourceReference; |
189 |
|
} else { |
190 |
0 |
extensionResource = new ExtensionResourceReference(resourceReference.getReference()); |
191 |
|
} |
192 |
|
|
193 |
3 |
response = downloadRemoteExtension(extensionResource); |
194 |
|
} else { |
195 |
0 |
throw new WebApplicationException(Status.NOT_FOUND); |
196 |
|
} |
197 |
|
|
198 |
20 |
return response; |
199 |
|
} |
200 |
|
|
|
|
| 67.9% |
Uncovered Elements: 9 (28) |
Complexity: 7 |
Complexity Density: 0.32 |
|
201 |
3 |
private ResponseBuilder downloadRemoteExtension(ExtensionResourceReference extensionResource)... |
202 |
|
throws ResolveException, IOException |
203 |
|
{ |
204 |
3 |
ExtensionRepository repository = null; |
205 |
3 |
if (extensionResource.getRepositoryId() != null) { |
206 |
3 |
repository = this.extensionRepositoryManager.getRepository(extensionResource.getRepositoryId()); |
207 |
|
} |
208 |
|
|
209 |
3 |
if (repository == null && extensionResource.getRepositoryType() != null |
210 |
|
&& extensionResource.getRepositoryURI() != null) { |
211 |
0 |
ExtensionRepositoryDescriptor repositoryDescriptor = new DefaultExtensionRepositoryDescriptor("tmp", |
212 |
|
extensionResource.getRepositoryType(), extensionResource.getRepositoryURI()); |
213 |
0 |
try { |
214 |
0 |
ExtensionRepositoryFactory repositoryFactory = |
215 |
|
this.componentManager.getInstance(ExtensionRepositoryFactory.class, repositoryDescriptor.getType()); |
216 |
|
|
217 |
0 |
repository = repositoryFactory.createRepository(repositoryDescriptor); |
218 |
|
} catch (Exception e) { |
219 |
|
|
220 |
0 |
this.logger.warning("Invalid repository in download link [" + extensionResource + "]"); |
221 |
|
} |
222 |
|
|
223 |
|
} |
224 |
|
|
225 |
|
|
226 |
3 |
Extension downloadExtension; |
227 |
3 |
if (repository == null) { |
228 |
0 |
downloadExtension = this.extensionRepositoryManager |
229 |
|
.resolve(new ExtensionId(extensionResource.getExtensionId(), extensionResource.getExtensionVersion())); |
230 |
|
} else { |
231 |
3 |
downloadExtension = repository |
232 |
|
.resolve(new ExtensionId(extensionResource.getExtensionId(), extensionResource.getExtensionVersion())); |
233 |
|
} |
234 |
|
|
235 |
|
|
236 |
|
|
237 |
3 |
ExtensionFile extensionFile = downloadExtension.getFile(); |
238 |
3 |
long length = extensionFile.getLength(); |
239 |
|
|
240 |
|
|
241 |
|
|
242 |
3 |
InputRepresentation content = new InputRepresentation(extensionFile.openStream(), MediaType.ALL, length); |
243 |
|
|
244 |
3 |
Disposition disposition = new Disposition(Disposition.TYPE_ATTACHMENT); |
245 |
3 |
disposition.setFilename(downloadExtension.getId().toString() + '.' + downloadExtension.getType()); |
246 |
3 |
content.setDisposition(disposition); |
247 |
|
|
248 |
3 |
ResponseBuilder response = Response.ok(); |
249 |
3 |
response.entity(content); |
250 |
|
|
251 |
3 |
return response; |
252 |
|
} |
253 |
|
} |