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.slc.rpmfactory.core;
17  
18  import java.util.HashSet;
19  import java.util.Iterator;
20  import java.util.Set;
21  
22  import javax.jcr.Node;
23  import javax.jcr.RepositoryException;
24  import javax.jcr.Session;
25  import javax.jcr.nodetype.NodeType;
26  import javax.jcr.security.AccessControlException;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.argeo.cms.ArgeoNames;
31  import org.argeo.jcr.JcrUtils;
32  import org.argeo.jcr.proxy.AbstractUrlProxy;
33  import org.argeo.slc.SlcConstants;
34  import org.argeo.slc.SlcException;
35  import org.argeo.slc.SlcNames;
36  import org.argeo.slc.SlcTypes;
37  import org.argeo.slc.repo.RepoConstants;
38  import org.argeo.slc.rpmfactory.RpmProxyService;
39  import org.argeo.slc.rpmfactory.RpmRepository;
40  
41  /** Synchronises the node repository with remote Maven repositories */
42  public class RpmProxyServiceImpl extends AbstractUrlProxy implements
43  		RpmProxyService, ArgeoNames, SlcNames {
44  	private final static Log log = LogFactory.getLog(RpmProxyServiceImpl.class);
45  
46  	private Set<RpmRepository> defaultRepositories = new HashSet<RpmRepository>();
47  
48  	@Override
49  	protected void beforeInitSessionSave(Session session)
50  			throws RepositoryException {
51  		JcrUtils.addPrivilege(session, "/", "anonymous", "jcr:read");
52  		try {
53  			JcrUtils.addPrivilege(session, "/", SlcConstants.ROLE_SLC,
54  					"jcr:all");
55  		} catch (AccessControlException e) {
56  			if (log.isTraceEnabled())
57  				log.trace("Cannot give jcr:all privileges to "+SlcConstants.ROLE_SLC);
58  		}
59  
60  		JcrUtils.mkdirsSafe(session, RepoConstants.PROXIED_REPOSITORIES);
61  	}
62  
63  	/**
64  	 * Retrieve and add this file to the repository
65  	 */
66  	@Override
67  	protected Node retrieve(Session session, String path) {
68  		StringBuilder relativePathBuilder = new StringBuilder();
69  		String repoId = extractRepoId(path, relativePathBuilder);
70  		// remove starting '/'
71  		String relativePath = relativePathBuilder.toString().substring(1);
72  
73  		RpmRepository sourceRepo = null;
74  		for (Iterator<RpmRepository> reposIt = defaultRepositories.iterator(); reposIt
75  				.hasNext();) {
76  			RpmRepository rpmRepo = reposIt.next();
77  			if (rpmRepo.getId().equals(repoId)) {
78  				sourceRepo = rpmRepo;
79  				break;
80  			}
81  		}
82  
83  		if (sourceRepo == null)
84  			throw new SlcException("No RPM repository found for " + path);
85  
86  		try {
87  			String baseUrl = sourceRepo.getUrl();
88  			String remoteUrl = baseUrl + relativePath;
89  			Node node = proxyUrl(session, remoteUrl, path);
90  			if (node != null) {
91  				registerSource(sourceRepo, node, remoteUrl);
92  				if (log.isDebugEnabled())
93  					log.debug("Imported " + remoteUrl + " to " + node);
94  				return node;
95  			}
96  		} catch (Exception e) {
97  			throw new SlcException("Cannot proxy " + path, e);
98  		}
99  		JcrUtils.discardQuietly(session);
100 		throw new SlcException("No proxy found for " + path);
101 	}
102 
103 	protected void registerSource(RpmRepository sourceRepo, Node node,
104 			String remoteUrl) throws RepositoryException {
105 		node.addMixin(SlcTypes.SLC_KNOWN_ORIGIN);
106 		Node origin;
107 		if (!node.hasNode(SLC_ORIGIN))
108 			origin = node.addNode(SLC_ORIGIN, SlcTypes.SLC_PROXIED);
109 		else
110 			origin = node.getNode(SLC_ORIGIN);
111 
112 		// proxied repository
113 		Node proxiedRepository;
114 		String proxiedRepositoryPath = RepoConstants.PROXIED_REPOSITORIES + '/'
115 				+ sourceRepo.getId();
116 		Session session = node.getSession();
117 		if (session.itemExists(proxiedRepositoryPath)) {
118 			proxiedRepository = session.getNode(proxiedRepositoryPath);
119 		} else {
120 			proxiedRepository = session.getNode(
121 					RepoConstants.PROXIED_REPOSITORIES).addNode(
122 					sourceRepo.getId());
123 			proxiedRepository.addMixin(NodeType.MIX_REFERENCEABLE);
124 			JcrUtils.urlToAddressProperties(proxiedRepository,
125 					sourceRepo.getUrl());
126 			proxiedRepository.setProperty(SLC_URL, sourceRepo.getUrl());
127 		}
128 
129 		origin.setProperty(SLC_PROXY, proxiedRepository);
130 		JcrUtils.urlToAddressProperties(origin, remoteUrl);
131 	}
132 
133 	/** Returns the first token of the path */
134 	protected String extractRepoId(String path, StringBuilder relativePath) {
135 		StringBuilder workspace = new StringBuilder();
136 		StringBuilder buf = workspace;
137 		for (int i = 1; i < path.length(); i++) {
138 			char c = path.charAt(i);
139 			if (c == '/') {
140 				buf = relativePath;
141 			}
142 			buf.append(c);
143 		}
144 		return workspace.toString();
145 	}
146 
147 	@Override
148 	protected Boolean shouldUpdate(Session clientSession, String nodePath) {
149 		// if (nodePath.contains("/repodata/"))
150 		// return true;
151 		return super.shouldUpdate(clientSession, nodePath);
152 	}
153 
154 	public void setDefaultRepositories(Set<RpmRepository> defaultRepositories) {
155 		this.defaultRepositories = defaultRepositories;
156 	}
157 }