1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.mycore.pi.doi.client.crossref;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.net.URISyntaxException;
24 import java.nio.charset.StandardCharsets;
25 import java.util.List;
26 import java.util.Locale;
27 import java.util.stream.Collectors;
28
29 import org.apache.commons.io.IOUtils;
30 import org.apache.http.HttpEntity;
31 import org.apache.http.client.methods.CloseableHttpResponse;
32 import org.apache.http.client.methods.HttpPost;
33 import org.apache.http.client.utils.URIBuilder;
34 import org.apache.http.entity.ContentType;
35 import org.apache.http.entity.mime.MultipartEntityBuilder;
36 import org.apache.http.impl.client.CloseableHttpClient;
37 import org.apache.http.impl.client.HttpClientBuilder;
38 import org.apache.logging.log4j.LogManager;
39 import org.apache.logging.log4j.Logger;
40 import org.jdom2.Document;
41 import org.jdom2.output.Format;
42 import org.jdom2.output.XMLOutputter;
43 import org.mycore.pi.exceptions.MCRDatacenterException;
44 import org.mycore.pi.exceptions.MCRPersistentIdentifierException;
45
46 import jakarta.validation.constraints.NotNull;
47
48 public class MCRCrossrefClient {
49
50 public static final Logger LOGGER = LogManager.getLogger();
51
52 private static final String HTTP_SCHEME_PREFIX = "http://";
53
54 private static final String HTTPS_SCHEME_PREFIX = "https://";
55
56 private static final String NOT_NULL_MESSAGE = "%s needs to be not null!";
57
58 private static final String DEPOSIT_PATH = "servlet/deposit";
59
60 private static final String OPERATION_PARAM = "operation";
61
62 private static final String USER_PARAM = "login_id";
63
64 private static final String PASSWORD_PARAM = "login_passwd";
65
66 private static final String OPERATION_DOMDUPLOAD = "doMDUpload";
67
68 private static final XMLOutputter METADATA_OUTPUTTER = new XMLOutputter(Format.getPrettyFormat());
69
70 private String host, username, password;
71
72 public MCRCrossrefClient(@NotNull String host, @NotNull String username, @NotNull String password) {
73 if (host == null) {
74 throw new IllegalArgumentException(String.format(Locale.ROOT, NOT_NULL_MESSAGE, "Host"));
75 }
76 if (username == null) {
77 throw new IllegalArgumentException(String.format(Locale.ROOT, NOT_NULL_MESSAGE, "Username"));
78 }
79 if (password == null) {
80 throw new IllegalArgumentException(String.format(Locale.ROOT, NOT_NULL_MESSAGE, "Password"));
81 }
82
83 this.host = host;
84 this.username = username;
85 this.password = password;
86
87 if (host.endsWith("/")) {
88 this.host = this.host.substring(0, host.length() - 1);
89 }
90
91 if (this.host.startsWith(HTTP_SCHEME_PREFIX)) {
92 this.host = this.host.substring(HTTP_SCHEME_PREFIX.length());
93 } else if (this.host.startsWith(HTTPS_SCHEME_PREFIX)) {
94 this.host = this.host.substring(HTTPS_SCHEME_PREFIX.length());
95 }
96 }
97
98 private static CloseableHttpClient getHttpClient() {
99 return HttpClientBuilder.create().build();
100 }
101
102 public void doMDUpload(Document metadata) throws MCRPersistentIdentifierException {
103 final HttpPost postRequest;
104
105 try {
106 final URIBuilder uriBuilder;
107 uriBuilder = new URIBuilder("https://" + this.host + "/" + DEPOSIT_PATH);
108 addAuthParameters(uriBuilder);
109 uriBuilder.addParameter(OPERATION_PARAM, OPERATION_DOMDUPLOAD);
110 postRequest = new HttpPost(uriBuilder.build());
111 } catch (URISyntaxException e) {
112 throw new MCRPersistentIdentifierException(
113 String.format(Locale.ROOT, "Can not build a valid URL with host: %s", this.host));
114 }
115
116 final String metadataXmlAsString = METADATA_OUTPUTTER.outputString(metadata);
117
118 HttpEntity reqEntity = MultipartEntityBuilder.create()
119 .addBinaryBody("fname", metadataXmlAsString.getBytes(StandardCharsets.UTF_8), ContentType.APPLICATION_XML,
120 "crossref_query.xml")
121 .build();
122 postRequest.setEntity(reqEntity);
123
124 try (CloseableHttpClient client = getHttpClient()) {
125 try (CloseableHttpResponse response = client.execute(postRequest)) {
126 final int statusCode = response.getStatusLine().getStatusCode();
127 final HttpEntity entity = response.getEntity();
128 String message = "";
129
130 switch (statusCode) {
131 case 200:
132 if (entity != null) {
133 try (InputStream inputStream = entity.getContent()) {
134 List<String> doc = IOUtils.readLines(inputStream, StandardCharsets.UTF_8);
135 message = doc.stream().collect(Collectors.joining(System.lineSeparator()));
136 LOGGER.debug(message);
137 }
138 }
139 return;
140 case 503:
141 LOGGER.error("Seems like the quota of 10000 Entries is exceeded!");
142 default:
143 if (entity != null) {
144 try (InputStream inputStream = entity.getContent()) {
145 List<String> doc = IOUtils.readLines(inputStream, StandardCharsets.UTF_8);
146 message = doc.stream().collect(Collectors.joining(System.lineSeparator()));
147 }
148 }
149 throw new MCRDatacenterException(
150 String.format(Locale.ROOT, "Error while doMDUpload: (%d)%s%s%s", statusCode,
151 response.getStatusLine().getReasonPhrase(), System.lineSeparator(), message));
152 }
153 }
154 } catch (IOException e) {
155 throw new MCRDatacenterException(String.format(Locale.ROOT, "Error while sending request to %s", host), e);
156 }
157 }
158
159 private void addAuthParameters(URIBuilder uriBuilder) {
160 uriBuilder.addParameter(USER_PARAM, this.username);
161 uriBuilder.addParameter(PASSWORD_PARAM, this.password);
162 }
163
164 }