source: VirtualCollectionRegistry/trunk/VirtualCollectionRegistry/src/main/java/eu/clarin/cmdi/virtualcollectionregistry/model/GWDGPersistentIdentifierProvider.java @ 273

Last change on this file since 273 was 273, checked in by oschonef, 14 years ago
  • further work on GWDG handle service integration
  • Property svn:eol-style set to native
File size: 8.8 KB
Line 
1package eu.clarin.cmdi.virtualcollectionregistry.model;
2
3import java.net.URI;
4import java.net.URISyntaxException;
5import java.util.ArrayList;
6import java.util.Collections;
7import java.util.HashMap;
8import java.util.List;
9import java.util.Map;
10
11import javax.xml.stream.XMLInputFactory;
12import javax.xml.stream.XMLStreamConstants;
13import javax.xml.stream.XMLStreamReader;
14
15import org.apache.http.HttpEntity;
16import org.apache.http.HttpResponse;
17import org.apache.http.NameValuePair;
18import org.apache.http.StatusLine;
19import org.apache.http.auth.AuthScope;
20import org.apache.http.auth.UsernamePasswordCredentials;
21import org.apache.http.client.entity.UrlEncodedFormEntity;
22import org.apache.http.client.methods.HttpPost;
23import org.apache.http.impl.client.DefaultHttpClient;
24import org.apache.http.message.BasicNameValuePair;
25import org.apache.http.params.HttpProtocolParams;
26import org.apache.http.protocol.BasicHttpContext;
27import org.apache.http.protocol.HttpContext;
28import org.apache.http.util.EntityUtils;
29import org.slf4j.Logger;
30import org.slf4j.LoggerFactory;
31
32import eu.clarin.cmdi.virtualcollectionregistry.VirtualCollectionRegistryException;
33
34public class GWDGPersistentIdentifierProvider extends
35                PersistentIdentifierProvider {
36        private static enum Attribute {
37                PID, URL, CREATOR, EXPDATE;
38               
39                public static Attribute fromString(String s) {
40                        if (s.equalsIgnoreCase("pid")) {
41                                return PID;
42                        } else if (s.equalsIgnoreCase("url")) {
43                                return URL;
44                        } else if (s.equalsIgnoreCase("creator")) {
45                                return CREATOR;
46                        } else if (s.equalsIgnoreCase("expdate")) {
47                                return EXPDATE;
48                        }
49                        return null;
50                }
51               
52                public String toString() {
53                        switch (this) {
54                        case PID:
55                                return "pid";
56                        case URL:
57                                return "url";
58                        case CREATOR:
59                                return "creator";
60                        case EXPDATE:
61                                return "expdate";
62                        default:
63                                throw new InternalError();
64                        }
65                }
66        } // private enum Attribute
67        public static final String USERNAME = "pid_provider.username";
68        public static final String PASSWORD = "pid_provider.password";
69        private static final String SERVICE_URI_BASE =
70                "http://handle.gwdg.de:8080/pidservice/";
71        private static final String USER_AGENT =
72                "CLARIN-VirtualCollectionRegisty/1.0";
73        private static final Logger logger =
74                LoggerFactory.getLogger(GWDGPersistentIdentifierProvider.class);
75        private String base_uri = null;
76        private String username = null;
77        private String password = null;
78        private XMLInputFactory factory;
79
80        /* XXX: refactor Internal and GWDG PID class/providers, so only one
81         *        PID class exists.
82         *        Maybe: store type in generic PID class
83         *        inject dependency to PID provider in PID classes and
84         *        make factory method in provider for creating URIs
85         */
86        public GWDGPersistentIdentifierProvider(Map<String,String> config)
87                        throws VirtualCollectionRegistryException {
88                super(config);
89                try {
90                        String base_uri = getParameter(config, BASE_URI);
91                        if (!base_uri.endsWith("/")) {
92                                base_uri = base_uri + "/";
93                        }
94                        URI uri = new URI(base_uri);
95                        this.base_uri = uri.toString();
96                } catch (URISyntaxException e) {
97                        throw new VirtualCollectionRegistryException("configuration " +
98                                      "parameter \"" + BASE_URI + "\" is invalid", e);
99                }
100                this.username = getParameter(config, USERNAME);
101                this.password = getParameter(config, PASSWORD);
102               
103                this.factory = XMLInputFactory.newInstance();
104                factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
105                factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES,
106                                                        Boolean.TRUE);
107        }
108
109        public PersistentIdentifier createPersistentIdentifier(VirtualCollection vc)
110                        throws VirtualCollectionRegistryException {
111                logger.debug("creating handle for virtual collection \"{}\"",
112                                vc.getUUID());
113                try {
114                        String target  = makeCollectionURI(vc);
115                        // XXX: testing
116                        // URI serviceURI = URI.create(SERVICE_URI_BASE + "write/create");
117                        URI serviceURI = URI.create(SERVICE_URI_BASE + "write/modify");
118
119                        List<NameValuePair> params = new ArrayList<NameValuePair>();
120                        params.add(new BasicNameValuePair("url", target));
121                        // XXX: testing
122                        params.add(new BasicNameValuePair("pid", "11858/00-232Z-0000-0000-40AE-F"));
123                        Map<Attribute, String> props = invokeWebService(serviceURI, params);
124                        String pid = props.get(Attribute.PID);
125                        if (pid == null) {
126                                throw new VirtualCollectionRegistryException(
127                                        "no handle returned");
128                        }
129                        logger.info("created handle \"{}\" for virtual collection \"{}\"",
130                                        pid, vc.getUUID());
131                        return new GWDGPersistentIdentifier(vc, pid);
132                } catch (VirtualCollectionRegistryException e) {
133                        throw new RuntimeException("failed to create handle", e);
134                }
135        }
136
137        @SuppressWarnings("unused")
138        private void update(String pid, URI target) throws VirtualCollectionRegistryException {
139                List<NameValuePair> params = new ArrayList<NameValuePair>();
140                params.add(new BasicNameValuePair("pid", pid));
141                params.add(new BasicNameValuePair("url", target.toString()));
142                URI serviceURI = URI.create(SERVICE_URI_BASE + "write/modify");
143                invokeWebService(serviceURI, params);
144        }
145
146        private String makeCollectionURI(VirtualCollection vc) {
147                return base_uri + "service/clarin-virtualcollection/" + vc.getUUID();
148        }
149
150        private static String getParameter(Map<String, String> config,
151                        String parameter) throws VirtualCollectionRegistryException {
152                String value = config.get(parameter);
153                if (value == null) {
154                        throw new VirtualCollectionRegistryException("configuration "
155                                        + "parameter \"" + parameter + "\" is not set");
156                }
157                value = value.trim();
158                if (value.isEmpty()) {
159                        throw new VirtualCollectionRegistryException("configuration "
160                                        + "parameter \"" + parameter + "\" is invalid");
161                }
162                return value;
163        }
164
165        private Map<Attribute, String> invokeWebService(URI serviceTargetURI,
166                        List<NameValuePair> formparams)
167                        throws VirtualCollectionRegistryException {
168                // force xml encoding
169                formparams.add(new BasicNameValuePair("encoding", "xml"));
170
171                DefaultHttpClient client = null;
172                try {
173                        client = new DefaultHttpClient();
174                        int port = serviceTargetURI.getPort() != -1
175                                 ? serviceTargetURI.getPort()
176                     : AuthScope.ANY_PORT
177                     ;
178                        client.getCredentialsProvider().setCredentials(
179                                        new AuthScope(serviceTargetURI.getHost(), port),
180                                        new UsernamePasswordCredentials(username, password)
181                        );
182                        // disable expect continue, GWDG does not like very well
183                        client.getParams()
184                                .setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, Boolean.FALSE);
185                        // set a proper user agent
186                        client.getParams()
187                                .setParameter(HttpProtocolParams.USER_AGENT, USER_AGENT);
188                        HttpPost request = new HttpPost(serviceTargetURI);
189                        request.addHeader("Accept", "text/xml, application/xml");
190                        request.setEntity(new UrlEncodedFormEntity(formparams, "UTF-8"));
191                        HttpContext ctx = new BasicHttpContext();
192
193                        logger.debug("invoking GWDG service at {}", serviceTargetURI);
194                        HttpResponse response = client.execute(request, ctx);
195                        StatusLine status = response.getStatusLine();
196                        HttpEntity entity = response.getEntity();
197                        Map<Attribute, String> props = Collections.emptyMap();
198
199                        logger.debug("GWDG Service status: {}", status.toString());
200                        if ((status.getStatusCode() >= 200) &&
201                                (status.getStatusCode() <= 299) &&
202                                (entity != null)) {
203                                String encoding = EntityUtils.getContentCharSet(entity);
204                                if (encoding == null) {
205                                        encoding = "UTF-8";
206                                }
207
208                                XMLStreamReader reader = factory
209                                                .createXMLStreamReader(entity.getContent(), encoding);
210                                props = new HashMap<Attribute, String>(); 
211                                while (reader.hasNext()) {
212                                        reader.next();
213                                       
214                                        int type = reader.getEventType();
215                                        if (type != XMLStreamConstants.START_ELEMENT) {
216                                                continue;
217                                        }
218                                        Attribute attribute =
219                                                Attribute.fromString(reader.getLocalName());
220                                        if (attribute != null) {
221                                                if (!reader.hasNext()) {
222                                                        throw new VirtualCollectionRegistryException(
223                                                                "unexpected end of data stream");
224                                                }
225                                                reader.next();
226                                                if (reader.getEventType() !=
227                                                                XMLStreamConstants.CHARACTERS) {
228                                                        throw new VirtualCollectionRegistryException(
229                                                                "unexpected element type: " +
230                                                                reader.getEventType());
231                                                }
232                                                String value = reader.getText();
233                                                if (value == null) {
234                                                        throw new VirtualCollectionRegistryException(
235                                                                "element \"" + attribute + "\" was empty");
236                                                }
237                                                value = value.trim();
238                                                if (!value.isEmpty()) {
239                                                        props.put(attribute, value);
240                                                }
241                                        }
242                                }
243
244                        } else {
245                                logger.debug("GWDG Handle service failed: {}", status);
246                                request.abort();
247                                throw new VirtualCollectionRegistryException(
248                                        "error invoking GWDG handle service");
249                        }
250                        return props;
251                } catch (VirtualCollectionRegistryException e) {
252                        throw e;
253                } catch (Exception e) {
254                        logger.debug("GWDG Handle service failed", e);
255                        throw new VirtualCollectionRegistryException(
256                                        "error invoking GWDG handle service", e);
257                } finally {
258                        if (client != null) {
259                                client.getConnectionManager().shutdown();
260                        }
261                }
262        }
263
264} // class GWDGPersistentIdentifierProvider
Note: See TracBrowser for help on using the repository browser.