Mercurial > hg > LGDataverses
diff src/main/java/edu/harvard/iq/dataverse/HandlenetServiceBean.java @ 10:a50cf11e5178
Rewrite LGDataverse completely upgrading to dataverse4.0
author | Zoe Hong <zhong@mpiwg-berlin.mpg.de> |
---|---|
date | Tue, 08 Sep 2015 17:00:21 +0200 |
parents | |
children | c2e2d794847f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main/java/edu/harvard/iq/dataverse/HandlenetServiceBean.java Tue Sep 08 17:00:21 2015 +0200 @@ -0,0 +1,304 @@ +/* + Copyright (C) 2005-2012, by the President and Fellows of Harvard College. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + Dataverse Network - A web application to share, preserve and analyze research data. + Developed at the Institute for Quantitative Social Science, Harvard University. + Version 3.0. +*/ + +package edu.harvard.iq.dataverse; + +import edu.harvard.iq.dataverse.settings.SettingsServiceBean; + +import java.io.File; +import java.io.FileInputStream; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.ejb.EJB; +import javax.ejb.Stateless; +import java.security.PrivateKey; + +/* Handlenet imports: */ +import net.handle.hdllib.AbstractMessage; +import net.handle.hdllib.AbstractResponse; +import net.handle.hdllib.AdminRecord; +import net.handle.hdllib.ClientSessionTracker; +import net.handle.hdllib.CreateHandleRequest; +import net.handle.hdllib.DeleteHandleRequest; +import net.handle.hdllib.Encoder; +import net.handle.hdllib.HandleException; +import net.handle.hdllib.HandleResolver; +import net.handle.hdllib.HandleValue; +import net.handle.hdllib.ModifyValueRequest; +import net.handle.hdllib.PublicKeyAuthenticationInfo; +import net.handle.hdllib.ResolutionRequest; +import net.handle.hdllib.ResolutionResponse; +import net.handle.hdllib.Util; + +/** + * + * @author Leonid Andreev + * + * This is a *partial* implementation of the Handles global id + * service. + * As of now, it only does the registration updates, to accommodate + * the modifyRegistration datasets API sub-command. + */ +@Stateless +public class HandlenetServiceBean { + @EJB + DataverseServiceBean dataverseService; + @EJB + SettingsServiceBean settingsService; + private static final Logger logger = Logger.getLogger("edu.harvard.iq.dataverse.HandlenetServiceBean"); + + private static final String HANDLE_PROTOCOL_TAG = "hdl"; + + public HandlenetServiceBean() { + } + + public void reRegisterHandle(Dataset dataset) { + if (!HANDLE_PROTOCOL_TAG.equals(dataset.getProtocol())) { + logger.warning("reRegisterHandle called on a dataset with the non-handle global id: "+dataset.getId()); + } + + String handle = getDatasetHandle(dataset); + + boolean handleRegistered = isHandleRegistered(handle); + + if (handleRegistered) { + // Rebuild/Modify an existing handle + + logger.info("Re-registering an existing handle id "+handle); + + String authHandle = getHandleAuthority(dataset); + + HandleResolver resolver = new HandleResolver(); + + String datasetUrl = getRegistrationUrl(dataset); + + logger.info("New registration URL: "+datasetUrl); + + PublicKeyAuthenticationInfo auth = getAuthInfo(dataset.getAuthority()); + + try { + + AdminRecord admin = new AdminRecord(authHandle.getBytes("UTF8"), 300, + true, true, true, true, true, true, + true, true, true, true, true, true); + + int timestamp = (int) (System.currentTimeMillis() / 1000); + + HandleValue[] val = {new HandleValue(100, "HS_ADMIN".getBytes("UTF8"), + Encoder.encodeAdminRecord(admin), + HandleValue.TTL_TYPE_RELATIVE, 86400, + timestamp, null, true, true, true, false), new HandleValue(1, "URL".getBytes("UTF8"), + datasetUrl.getBytes(), + HandleValue.TTL_TYPE_RELATIVE, 86400, + timestamp, null, true, true, true, false)}; + + ModifyValueRequest req = new ModifyValueRequest(handle.getBytes("UTF8"), val, auth); + + resolver.traceMessages = true; + AbstractResponse response = resolver.processRequest(req); + if (response.responseCode == AbstractMessage.RC_SUCCESS) { + logger.info("\nGot Response: \n" + response); + } else { + logger.info("\nGot Error: \n" + response); + } + } catch (Throwable t) { + logger.fine("\nError: " + t); + } + } else { + // Create a new handle from scratch: + logger.info("Handle " + handle + " not registered. Registering (creating) from scratch."); + registerNewHandle(dataset); + } + } + + public void registerNewHandle(Dataset dataset) { + String handlePrefix = dataset.getAuthority(); + String handle = getDatasetHandle(dataset); + String datasetUrl = getRegistrationUrl(dataset); + + logger.info("Creating NEW handle " + handle); + + String authHandle = getHandleAuthority(dataset); + + PublicKeyAuthenticationInfo auth = getAuthInfo(handlePrefix); + HandleResolver resolver = new HandleResolver(); + + int index = 300; + + try { + + AdminRecord admin = new AdminRecord(authHandle.getBytes("UTF8"), 300, + true, true, true, true, true, true, + true, true, true, true, true, true); + + int timestamp = (int) (System.currentTimeMillis() / 1000); + + HandleValue[] val = {new HandleValue(100, "HS_ADMIN".getBytes("UTF8"), + Encoder.encodeAdminRecord(admin), + HandleValue.TTL_TYPE_RELATIVE, 86400, + timestamp, null, true, true, true, false), new HandleValue(1, "URL".getBytes("UTF8"), + datasetUrl.getBytes(), + HandleValue.TTL_TYPE_RELATIVE, 86400, + timestamp, null, true, true, true, false)}; + + CreateHandleRequest req + = new CreateHandleRequest(handle.getBytes("UTF8"), val, auth); + + resolver.traceMessages = true; + AbstractResponse response = resolver.processRequest(req); + if (response.responseCode == AbstractMessage.RC_SUCCESS) { + logger.info("Success! Response: \n" + response); + } else { + logger.warning("Error response: \n" + response); + } + } catch (Throwable t) { + logger.warning("\nError (caught exception): " + t); + } + } + + public boolean isHandleRegistered(String handle){ + boolean handleRegistered = false; + ResolutionRequest req = buildResolutionRequest(handle); + AbstractResponse response = null; + HandleResolver resolver = new HandleResolver(); + try { + response = resolver.processRequest(req); + } catch (HandleException ex) { + logger.info("Caught exception trying to process lookup request"); + ex.printStackTrace(); + } + if((response!=null && response.responseCode==AbstractMessage.RC_SUCCESS)) { + logger.info("Handle "+handle+" registered."); + handleRegistered = true; + } + return handleRegistered; + } + + private ResolutionRequest buildResolutionRequest(final String handle) { + String handlePrefix = handle.substring(0,handle.indexOf("/")); + + PublicKeyAuthenticationInfo auth = getAuthInfo(handlePrefix); + + byte[][] types = null; + int[] indexes = null; + ResolutionRequest req = + new ResolutionRequest(Util.encodeString(handle), + types, indexes, + auth); + req.certify = false; + req.cacheCertify = true; + req.authoritative = false; + req.ignoreRestrictedValues = true; + return req; + } + + private PublicKeyAuthenticationInfo getAuthInfo(String handlePrefix) { + byte[] key = null; + String adminCredFile = System.getProperty("dataverse.handlenet.admcredfile"); + + key = readKey(adminCredFile); + PrivateKey privkey = null; + privkey = readPrivKey(key, adminCredFile); + String authHandle = getHandleAuthority(handlePrefix); + PublicKeyAuthenticationInfo auth = + new PublicKeyAuthenticationInfo(Util.encodeString(authHandle), 300, privkey); + return auth; + } + private String getRegistrationUrl(Dataset dataset) { + String siteUrl = getSiteUrl(); + + String targetUrl = siteUrl + "/dataset.xhtml?persistentId=hdl:" + dataset.getAuthority() + + "/" + dataset.getIdentifier(); + return targetUrl; + } + + public String getSiteUrl() { + String hostUrl = System.getProperty("dataverse.siteUrl"); + if (hostUrl != null && !"".equals(hostUrl)) { + return hostUrl; + } + String hostName = System.getProperty("dataverse.fqdn"); + if (hostName == null) { + try { + hostName = InetAddress.getLocalHost().getCanonicalHostName(); + } catch (UnknownHostException e) { + return null; + } + } + hostUrl = "https://" + hostName; + return hostUrl; + } + + private byte[] readKey(final String file) { + byte[] key = null; + try { + File f = new File(file); + FileInputStream fs = new FileInputStream(f); + key = new byte[(int)f.length()]; + int n=0; + while(n<key.length) { + key[n++] = (byte)fs.read(); + } + } catch (Throwable t){ + logger.severe("Cannot read private key " + file +": " + t); + } + return key; + } + + private PrivateKey readPrivKey(byte[] key, final String file) { + PrivateKey privkey=null; + + String secret = System.getProperty("dataverse.handlenet.admprivphrase"); + byte secKey[] = null; + try { + if(Util.requiresSecretKey(key)){ + secKey = secret.getBytes(); + } + key = Util.decrypt(key, secKey); + privkey = Util.getPrivateKeyFromBytes(key, 0); + } catch (Throwable t){ + logger.severe("Can't load private key in " + file +": " + t); + } + return privkey; + } + + private String getDatasetHandle(Dataset dataset) { + /* + * This is different from dataset.getGlobalId() in that we don't + * need the "hdl:" prefix. + */ + String handle = dataset.getAuthority() + "/" + dataset.getIdentifier(); + return handle; + } + + private String getHandleAuthority(Dataset dataset){ + return getHandleAuthority(dataset.getAuthority()); + } + + private String getHandleAuthority(String handlePrefix) { + return "0.NA/" + handlePrefix; + } +} + + +