View Javadoc
1   package org.argeo.slc.repo.osgi;
2   
3   import java.io.BufferedInputStream;
4   import java.io.FileNotFoundException;
5   import java.io.IOException;
6   import java.io.InputStream;
7   import java.net.MalformedURLException;
8   import java.net.URL;
9   import java.net.URLConnection;
10  import java.util.ArrayList;
11  import java.util.HashMap;
12  import java.util.List;
13  import java.util.Map;
14  
15  import javax.jcr.Node;
16  import javax.jcr.Repository;
17  import javax.jcr.RepositoryException;
18  import javax.jcr.Session;
19  import javax.jcr.security.Privilege;
20  
21  import org.apache.commons.io.IOUtils;
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.argeo.jcr.JcrUtils;
25  import org.argeo.slc.SlcConstants;
26  import org.argeo.slc.SlcException;
27  import org.argeo.slc.SlcNames;
28  import org.argeo.slc.SlcTypes;
29  import org.argeo.slc.repo.NodeIndexer;
30  import org.argeo.slc.repo.OsgiFactory;
31  import org.argeo.slc.repo.RepoConstants;
32  import org.argeo.slc.repo.maven.MavenConventionsUtils;
33  import org.eclipse.aether.artifact.Artifact;
34  import org.eclipse.aether.artifact.DefaultArtifact;
35  
36  /** Default implementation of {@link OsgiFactory}. */
37  public class OsgiFactoryImpl implements OsgiFactory, SlcNames {
38  	private final static Log log = LogFactory.getLog(OsgiFactoryImpl.class);
39  
40  	private String workspace;
41  	private Repository distRepository;
42  	private Repository javaRepository;
43  
44  	private List<NodeIndexer> nodeIndexers = new ArrayList<NodeIndexer>();
45  
46  	/** key is URI prefix, value list of base URLs */
47  	private Map<String, List<String>> mirrors = new HashMap<String, List<String>>();
48  
49  	private List<String> mavenRepositories = new ArrayList<String>();
50  	private String downloadBase = RepoConstants.DIST_DOWNLOAD_BASEPATH;
51  	private String mavenProxyBase = downloadBase + "/maven";
52  
53  	public void init() {
54  		if (workspace == null)
55  			throw new SlcException("A workspace must be specified");
56  
57  		// default Maven repo
58  		if (mavenRepositories.size() == 0) {
59  			// mavenRepositories
60  			// .add("http://search.maven.org/remotecontent?filepath=");
61  			mavenRepositories.add("http://repo1.maven.org/maven2");
62  		}
63  
64  		Session javaSession = null;
65  		Session distSession = null;
66  		try {
67  			// TODO rather user a JavaRepoManager that will also implicitely
68  			// manage the indexing of newly created nodes.
69  			javaSession = JcrUtils.loginOrCreateWorkspace(javaRepository, workspace);
70  			distSession = JcrUtils.loginOrCreateWorkspace(distRepository, workspace);
71  
72  			// Privileges
73  			JcrUtils.addPrivilege(javaSession, "/", SlcConstants.ROLE_SLC, Privilege.JCR_ALL);
74  			JcrUtils.addPrivilege(distSession, "/", SlcConstants.ROLE_SLC, Privilege.JCR_ALL);
75  		} catch (RepositoryException e) {
76  			throw new SlcException("Cannot initialize OSGi Factory " + workspace, e);
77  		} finally {
78  			JcrUtils.logoutQuietly(javaSession);
79  			JcrUtils.logoutQuietly(distSession);
80  		}
81  	}
82  
83  	public void destroy() {
84  
85  	}
86  
87  	public Session openJavaSession() throws RepositoryException {
88  		return javaRepository.login(workspace);
89  	}
90  
91  	public Session openDistSession() throws RepositoryException {
92  		return distRepository.login(workspace);
93  	}
94  
95  	public void indexNode(Node node) {
96  		for (NodeIndexer nodeIndexer : nodeIndexers) {
97  			nodeIndexer.index(node);
98  		}
99  	}
100 
101 	public Node getMaven(Session distSession, String coords) throws RepositoryException {
102 		Artifact artifact = new DefaultArtifact(coords);
103 		String path = MavenConventionsUtils.artifactPath(mavenProxyBase, artifact);
104 
105 		// exists
106 		if (distSession.itemExists(path))
107 			return distSession.getNode(path);
108 
109 		for (String mavenRepo : mavenRepositories) {
110 			String url = MavenConventionsUtils.artifactUrl(mavenRepo, artifact);
111 			try {
112 				Node node = loadUrlToPath(url, distSession, path);
113 				if (node != null) {
114 					// checksums
115 					try {
116 						loadUrlToPath(url + ".md5", distSession, path + ".md5");
117 					} catch (FileNotFoundException e) {
118 						// silent
119 					}
120 					try {
121 						loadUrlToPath(url + ".sha1", distSession, path + ".sha1");
122 					} catch (FileNotFoundException e) {
123 						// silent
124 					}
125 					return node;
126 				}
127 			} catch (FileNotFoundException e) {
128 				if (log.isDebugEnabled())
129 					log.debug("Maven " + coords + " could not be downloaded from " + url);
130 			}
131 		}
132 		throw new SlcException("Could not download Maven " + coords);
133 	}
134 
135 	public Node getDist(Session distSession, String uri) throws RepositoryException {
136 		String distPath = downloadBase + '/' + JcrUtils.urlAsPath(uri);
137 
138 		// already retrieved
139 		if (distSession.itemExists(distPath))
140 			return distSession.getNode(distPath);
141 
142 		// find mirror
143 		List<String> urlBases = null;
144 		String uriPrefix = null;
145 		uriPrefixes: for (String uriPref : mirrors.keySet()) {
146 			if (uri.startsWith(uriPref)) {
147 				if (mirrors.get(uriPref).size() > 0) {
148 					urlBases = mirrors.get(uriPref);
149 					uriPrefix = uriPref;
150 					break uriPrefixes;
151 				}
152 			}
153 		}
154 		if (urlBases == null)
155 			try {
156 				return loadUrlToPath(uri, distSession, distPath);
157 			} catch (FileNotFoundException e) {
158 				throw new SlcException("Cannot download " + uri, e);
159 			}
160 
161 		// try to download
162 		for (String urlBase : urlBases) {
163 			String relativePath = uri.substring(uriPrefix.length());
164 			String url = urlBase + relativePath;
165 			try {
166 				return loadUrlToPath(url, distSession, distPath);
167 			} catch (FileNotFoundException e) {
168 				if (log.isDebugEnabled())
169 					log.debug("Cannot download " + url + ", trying another mirror");
170 			}
171 		}
172 
173 		throw new SlcException("Could not download " + uri);
174 	}
175 
176 	/** Actually downloads a file to an internal location */
177 	protected Node loadUrlToPath(String url, Session distSession, String path)
178 			throws RepositoryException, FileNotFoundException {
179 		if (log.isDebugEnabled())
180 			log.debug("Downloading " + url + "...");
181 
182 		InputStream in = null;
183 		URLConnection conn = null;
184 		Node folderNode = JcrUtils.mkfolders(distSession, JcrUtils.parentPath(path));
185 		try {
186 			URL u = new URL(url);
187 			conn = u.openConnection();
188 			conn.connect();
189 			in = new BufferedInputStream(conn.getInputStream());
190 			// byte[] arr = IOUtils.toByteArray(in);
191 			// Node fileNode = JcrUtils.copyBytesAsFile(folderNode,
192 			// JcrUtils.nodeNameFromPath(path), arr);
193 			Node fileNode = JcrUtils.copyStreamAsFile(folderNode, JcrUtils.nodeNameFromPath(path), in);
194 			fileNode.addMixin(SlcTypes.SLC_KNOWN_ORIGIN);
195 			Node origin = fileNode.addNode(SLC_ORIGIN, SlcTypes.SLC_PROXIED);
196 			JcrUtils.urlToAddressProperties(origin, url);
197 			distSession.save();
198 			return fileNode;
199 		} catch (MalformedURLException e) {
200 			throw new SlcException("URL " + url + " not valid.", e);
201 		} catch (FileNotFoundException e) {
202 			throw e;
203 		} catch (IOException e) {
204 			throw new SlcException("Cannot load " + url + " to " + path, e);
205 		} finally {
206 			IOUtils.closeQuietly(in);
207 		}
208 
209 	}
210 
211 	public void setWorkspace(String workspace) {
212 		this.workspace = workspace;
213 	}
214 
215 	public void setDistRepository(Repository distRepository) {
216 		this.distRepository = distRepository;
217 	}
218 
219 	public void setJavaRepository(Repository javaRepository) {
220 		this.javaRepository = javaRepository;
221 	}
222 
223 	public void setNodeIndexers(List<NodeIndexer> nodeIndexers) {
224 		this.nodeIndexers = nodeIndexers;
225 	}
226 
227 	public void setMirrors(Map<String, List<String>> mirrors) {
228 		this.mirrors = mirrors;
229 	}
230 
231 	public void setMavenRepositories(List<String> mavenRepositories) {
232 		this.mavenRepositories = mavenRepositories;
233 	}
234 
235 	public void setMavenProxyBase(String mavenProxyBase) {
236 		this.mavenProxyBase = mavenProxyBase;
237 	}
238 
239 }