View Javadoc
1   /*
2    * Copyright (C) 2007-2012 Argeo GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.argeo.jcr.proxy;
17  
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.net.URL;
21  
22  import javax.jcr.Binary;
23  import javax.jcr.Node;
24  import javax.jcr.Property;
25  import javax.jcr.Repository;
26  import javax.jcr.RepositoryException;
27  import javax.jcr.Session;
28  import javax.jcr.nodetype.NodeType;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.argeo.jcr.ArgeoJcrException;
33  import org.argeo.jcr.JcrUtils;
34  
35  /** Base class for URL based proxys. */
36  public abstract class AbstractUrlProxy implements ResourceProxy {
37  	private final static Log log = LogFactory.getLog(AbstractUrlProxy.class);
38  
39  	private Repository jcrRepository;
40  	private Session jcrAdminSession;
41  	private String proxyWorkspace = "proxy";
42  
43  	protected abstract Node retrieve(Session session, String path);
44  
45  	void init() {
46  		try {
47  			jcrAdminSession = JcrUtils.loginOrCreateWorkspace(jcrRepository, proxyWorkspace);
48  			beforeInitSessionSave(jcrAdminSession);
49  			if (jcrAdminSession.hasPendingChanges())
50  				jcrAdminSession.save();
51  		} catch (Exception e) {
52  			JcrUtils.discardQuietly(jcrAdminSession);
53  			throw new ArgeoJcrException("Cannot initialize Maven proxy", e);
54  		}
55  	}
56  
57  	/**
58  	 * Called before the (admin) session is saved at the end of the initialization.
59  	 * Does nothing by default, to be overridden.
60  	 */
61  	protected void beforeInitSessionSave(Session session) throws RepositoryException {
62  	}
63  
64  	void destroy() {
65  		JcrUtils.logoutQuietly(jcrAdminSession);
66  	}
67  
68  	/**
69  	 * Called before the (admin) session is logged out when resources are released.
70  	 * Does nothing by default, to be overridden.
71  	 */
72  	protected void beforeDestroySessionLogout() throws RepositoryException {
73  	}
74  
75  	public Node proxy(String path) {
76  		// we open a JCR session with client credentials in order not to use the
77  		// admin session in multiple thread or make it a bottleneck.
78  		Node nodeAdmin = null;
79  		Node nodeClient = null;
80  		Session clientSession = null;
81  		try {
82  			clientSession = jcrRepository.login(proxyWorkspace);
83  			if (!clientSession.itemExists(path) || shouldUpdate(clientSession, path)) {
84  				nodeAdmin = retrieveAndSave(path);
85  				if (nodeAdmin != null)
86  					nodeClient = clientSession.getNode(path);
87  			} else
88  				nodeClient = clientSession.getNode(path);
89  			return nodeClient;
90  		} catch (RepositoryException e) {
91  			throw new ArgeoJcrException("Cannot proxy " + path, e);
92  		} finally {
93  			if (nodeClient == null)
94  				JcrUtils.logoutQuietly(clientSession);
95  		}
96  	}
97  
98  	protected synchronized Node retrieveAndSave(String path) {
99  		try {
100 			Node node = retrieve(jcrAdminSession, path);
101 			if (node == null)
102 				return null;
103 			jcrAdminSession.save();
104 			return node;
105 		} catch (RepositoryException e) {
106 			JcrUtils.discardQuietly(jcrAdminSession);
107 			throw new ArgeoJcrException("Cannot retrieve and save " + path, e);
108 		} finally {
109 			notifyAll();
110 		}
111 	}
112 
113 	/** Session is not saved */
114 	protected synchronized Node proxyUrl(Session session, String remoteUrl, String path) throws RepositoryException {
115 		Node node = null;
116 		if (session.itemExists(path)) {
117 			// throw new ArgeoJcrException("Node " + path + " already exists");
118 		}
119 		try (InputStream in = new URL(remoteUrl).openStream()) {
120 			// URL u = new URL(remoteUrl);
121 			// in = u.openStream();
122 			node = importFile(session, path, in);
123 		} catch (IOException e) {
124 			if (log.isDebugEnabled()) {
125 				log.debug("Cannot read " + remoteUrl + ", skipping... " + e.getMessage());
126 				// log.trace("Cannot read because of ", e);
127 			}
128 			JcrUtils.discardQuietly(session);
129 			// } finally {
130 			// IOUtils.closeQuietly(in);
131 		}
132 		return node;
133 	}
134 
135 	protected synchronized Node importFile(Session session, String path, InputStream in) throws RepositoryException {
136 		Binary binary = null;
137 		try {
138 			Node content = null;
139 			Node node = null;
140 			if (!session.itemExists(path)) {
141 				node = JcrUtils.mkdirs(session, path, NodeType.NT_FILE, NodeType.NT_FOLDER, false);
142 				content = node.addNode(Node.JCR_CONTENT, NodeType.NT_UNSTRUCTURED);
143 			} else {
144 				node = session.getNode(path);
145 				content = node.getNode(Node.JCR_CONTENT);
146 			}
147 			binary = session.getValueFactory().createBinary(in);
148 			content.setProperty(Property.JCR_DATA, binary);
149 			JcrUtils.updateLastModifiedAndParents(node, null);
150 			return node;
151 		} finally {
152 			JcrUtils.closeQuietly(binary);
153 		}
154 	}
155 
156 	/** Whether the file should be updated. */
157 	protected Boolean shouldUpdate(Session clientSession, String nodePath) {
158 		return false;
159 	}
160 
161 	public void setJcrRepository(Repository jcrRepository) {
162 		this.jcrRepository = jcrRepository;
163 	}
164 
165 	public void setProxyWorkspace(String localWorkspace) {
166 		this.proxyWorkspace = localWorkspace;
167 	}
168 
169 }