View Javadoc

1   package uk.ac.cam.spectra.spectrasub;
2   
3   import java.io.File;
4   import java.io.IOException;
5   
6   import nu.xom.Builder;
7   import nu.xom.Document;
8   import nu.xom.Nodes;
9   import nu.xom.ParsingException;
10  import nu.xom.ValidityException;
11  
12  import org.apache.log4j.Logger;
13  import org.restlet.Client;
14  import org.restlet.data.ChallengeResponse;
15  import org.restlet.data.ChallengeScheme;
16  import org.restlet.data.MediaType;
17  import org.restlet.data.Method;
18  import org.restlet.data.Protocol;
19  import org.restlet.data.Reference;
20  import org.restlet.data.Request;
21  import org.restlet.data.Response;
22  import org.restlet.resource.FileRepresentation;
23  import org.restlet.util.Series;
24  
25  import uk.ac.cam.spectra.Constants;
26  import uk.ac.cam.spectra.Zipper;
27  
28  /**
29   * Implements package deposition using the restlet.org API.
30   * 
31   * @author ojd20
32   * @todo Which of the depositor and the packager create the archive file needs
33   *       to be cleaned up.
34   */
35  public class LNIRestletDepositor implements Depositor {
36  
37  	private static final Logger LOG = Logger
38  			.getLogger(LNIRestletDepositor.class);
39  
40  	private String collectionHandle;
41  
42  	private DataPackageDAO dataPackageDAO;
43  
44  	private String lniUrl;
45  
46  	private String authEmail;
47  
48  	private String authPass;
49  
50  	public String getCollectionHandle() {
51  		return collectionHandle;
52  	}
53  
54  	public void setCollectionHandle(String collectionHandle) {
55  		this.collectionHandle = collectionHandle;
56  	}
57  
58  	public DataPackageDAO getDataPackageDAO() {
59  		return dataPackageDAO;
60  	}
61  
62  	public void setDataPackageDAO(DataPackageDAO dataPackageDAO) {
63  		this.dataPackageDAO = dataPackageDAO;
64  	}
65  
66  	/**
67  	 * Deposits an internal package into an external LNI repository and returns
68  	 * the assigned Handle.
69  	 */
70  	public String deposit(String packageId) {
71  		// Zip up the packaging dir
72  		Zipper zipper = new Zipper();
73  		File zipFile = dataPackageDAO.createArchiveFile(packageId);
74  		try {
75  			zipper.zip(dataPackageDAO.getPackagingDirectory(packageId, false),
76  					zipFile);
77  		} catch (IOException e) {
78  			LOG.error("Problem zipping up package: " + e.getMessage(), e);
79  			throw new RuntimeException("Problem zipping up package: "
80  					+ e.getMessage(), e);
81  		}
82  
83  		Client client = new Client(Protocol.HTTP);
84  		ChallengeResponse auth = new ChallengeResponse(
85  				ChallengeScheme.HTTP_BASIC, authEmail, authPass);
86  
87  		Reference coll = lookupCollectionHandle(client, auth);
88  		String loc = putPackage(zipFile, new Client(Protocol.HTTP), auth, coll);
89  		String handle = findNewHandle(new Client(Protocol.HTTP), auth, loc);
90  		return (handle.indexOf("hdl:") == 0) ? handle.replaceFirst("hdl:",
91  				"http://hdl.handle.net/") : handle;
92  	}
93  
94  	private String findNewHandle(Client client, ChallengeResponse auth,
95  			String loc) {
96  		LOG.debug("Propfinding: " + loc);
97  		Request pfind = new Request(Method.PROPFIND, loc);
98  		pfind.setChallengeResponse(auth);
99  		Response pfindResponse = client.handle(pfind);
100 		LOG.debug("Propfind returned: " + pfindResponse.getStatus());
101 		try {
102 			Document doc = new Builder().build(pfindResponse.getEntityAsDom()
103 					.getStream());
104 			Nodes nds = doc
105 					.query(
106 							"//dav:multistatus/dav:response/dav:propstat/dav:prop/dspace:handle/text()",
107 							Constants.XPATH_CTX);
108 			String handle = nds.get(0).getValue();
109 			return handle;
110 		} catch (IOException e) {
111 			throw new RuntimeException(e);
112 		} catch (ValidityException e) {
113 			throw new RuntimeException(e);
114 		} catch (ParsingException e) {
115 			throw new RuntimeException(e);
116 		}
117 	}
118 
119 	private String putPackage(File zipFile, Client client,
120 			ChallengeResponse auth, Reference coll) {
121 		String pkgUrl = coll.toString() + "?package=METS&validate=false";
122 		LOG.debug("Package: " + pkgUrl);
123 		// PUT the package.
124 		Request put = new Request(Method.PUT, pkgUrl);
125 		put.setEntity(new FileRepresentation(zipFile,
126 				MediaType.APPLICATION_ZIP, 100000));
127 		put.setChallengeResponse(auth);
128 		Response pRes = client.handle(put);
129 		if (pRes.getStatus().getCode() > 300) {
130 			throw new RuntimeException("Could not submit to LNI: "
131 					+ pRes.getStatus() + ": "
132 					+ pRes.getStatus().getDescription());
133 		}
134 		LOG.debug("Package submit returned: " + pRes.getStatus());
135 		String loc = ((Series) pRes.getAttributes().get(
136 				"org.restlet.http.headers")).getFirstValue("Location");
137 		return loc;
138 	}
139 
140 	private Reference lookupCollectionHandle(Client client,
141 			ChallengeResponse auth) {
142 		// Do the "right thing" - getting a redirect to the collection
143 		String lookupUri = lniUrl + "/lookup/handle/" + collectionHandle;
144 		LOG.debug("Lookup: " + lookupUri);
145 		Request findColl = new Request(Method.GET, lookupUri);
146 		findColl.setChallengeResponse(auth);
147 		Response findCollR = client.handle(findColl);
148 		Reference coll = findCollR.getRedirectRef();
149 		if (coll == null) {
150 			throw new RuntimeException("Handle lookup failed: "
151 					+ findCollR.getStatus());
152 		}
153 		return coll;
154 	}
155 
156 	public String getLniUrl() {
157 		return lniUrl;
158 	}
159 
160 	public void setLniUrl(String lniUrl) {
161 		this.lniUrl = lniUrl;
162 	}
163 
164 	public String getAuthEmail() {
165 		return authEmail;
166 	}
167 
168 	public void setAuthEmail(String authEmail) {
169 		this.authEmail = authEmail;
170 	}
171 
172 	public String getAuthPass() {
173 		return authPass;
174 	}
175 
176 	public void setAuthPass(String authPass) {
177 		this.authPass = authPass;
178 	}
179 
180 }