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.cms.internal.kernel;
17  
18  import java.net.URI;
19  import java.net.URISyntaxException;
20  import java.util.Collection;
21  import java.util.HashMap;
22  import java.util.Map;
23  
24  import javax.jcr.Repository;
25  import javax.jcr.RepositoryException;
26  import javax.jcr.RepositoryFactory;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.apache.jackrabbit.jcr2dav.Jcr2davRepositoryFactory;
31  import org.argeo.api.NodeConstants;
32  import org.argeo.cms.internal.jcr.RepoConf;
33  import org.argeo.jcr.ArgeoJcrException;
34  import org.osgi.framework.BundleContext;
35  import org.osgi.framework.FrameworkUtil;
36  import org.osgi.framework.InvalidSyntaxException;
37  import org.osgi.framework.ServiceReference;
38  
39  /**
40   * OSGi-aware Jackrabbit repository factory which can retrieve/publish
41   * {@link Repository} as OSGi services.
42   */
43  class NodeRepositoryFactory implements RepositoryFactory {
44  	private final Log log = LogFactory.getLog(getClass());
45  	private final BundleContext bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext();
46  
47  	// private Resource fileRepositoryConfiguration = new ClassPathResource(
48  	// "/org/argeo/cms/internal/kernel/repository-localfs.xml");
49  
50  	protected Repository getRepositoryByAlias(String alias) {
51  		try {
52  			Collection<ServiceReference<Repository>> srs = bundleContext.getServiceReferences(Repository.class,
53  					"(" + NodeConstants.CN + "=" + alias + ")");
54  			if (srs.size() == 0)
55  				throw new ArgeoJcrException("No repository with alias " + alias + " found in OSGi registry");
56  			else if (srs.size() > 1)
57  				throw new ArgeoJcrException(
58  						srs.size() + " repositories with alias " + alias + " found in OSGi registry");
59  			return bundleContext.getService(srs.iterator().next());
60  		} catch (InvalidSyntaxException e) {
61  			throw new ArgeoJcrException("Cannot find repository with alias " + alias, e);
62  		}
63  	}
64  
65  	// private void publish(String alias, Repository repository, Properties
66  	// properties) {
67  	// if (bundleContext != null) {
68  	// // do not modify reference
69  	// Hashtable<String, String> props = new Hashtable<String, String>();
70  	// props.putAll(props);
71  	// props.put(JCR_REPOSITORY_ALIAS, alias);
72  	// bundleContext.registerService(Repository.class.getName(), repository,
73  	// props);
74  	// }
75  	// }
76  
77  	@SuppressWarnings({ "rawtypes" })
78  	public Repository getRepository(Map parameters) throws RepositoryException {
79  		// // check if can be found by alias
80  		// Repository repository = super.getRepository(parameters);
81  		// if (repository != null)
82  		// return repository;
83  
84  		// check if remote
85  		Repository repository;
86  		String uri = null;
87  		if (parameters.containsKey(RepoConf.labeledUri.name()))
88  			uri = parameters.get(NodeConstants.LABELED_URI).toString();
89  		else if (parameters.containsKey(KernelConstants.JACKRABBIT_REPOSITORY_URI))
90  			uri = parameters.get(KernelConstants.JACKRABBIT_REPOSITORY_URI).toString();
91  
92  		if (uri != null) {
93  			if (uri.startsWith("http")) {// http, https
94  				Object defaultWorkspace = parameters.get(RepoConf.defaultWorkspace.name());
95  				repository = createRemoteRepository(uri, defaultWorkspace != null ? defaultWorkspace.toString() : null);
96  			} else if (uri.startsWith("file"))// http, https
97  				repository = createFileRepository(uri, parameters);
98  			else if (uri.startsWith("vm")) {
99  				// log.warn("URI " + uri + " should have been managed by generic
100 				// JCR repository factory");
101 				repository = getRepositoryByAlias(getAliasFromURI(uri));
102 			} else
103 				throw new ArgeoJcrException("Unrecognized URI format " + uri);
104 
105 		}
106 
107 		else if (parameters.containsKey(NodeConstants.CN)) {
108 			// Properties properties = new Properties();
109 			// properties.putAll(parameters);
110 			String alias = parameters.get(NodeConstants.CN).toString();
111 			// publish(alias, repository, properties);
112 			// log.info("Registered JCR repository under alias '" + alias + "'
113 			// with properties " + properties);
114 			repository = getRepositoryByAlias(alias);
115 		} else
116 			throw new ArgeoJcrException("Not enough information in " + parameters);
117 
118 		if (repository == null)
119 			throw new ArgeoJcrException("Repository not found " + parameters);
120 
121 		return repository;
122 	}
123 
124 	protected Repository createRemoteRepository(String uri, String defaultWorkspace) throws RepositoryException {
125 		Map<String, String> params = new HashMap<String, String>();
126 		params.put(KernelConstants.JACKRABBIT_REPOSITORY_URI, uri);
127 		if (defaultWorkspace != null)
128 			params.put(KernelConstants.JACKRABBIT_REMOTE_DEFAULT_WORKSPACE, defaultWorkspace);
129 		Repository repository = new Jcr2davRepositoryFactory().getRepository(params);
130 		if (repository == null)
131 			throw new ArgeoJcrException("Remote Davex repository " + uri + " not found");
132 		log.info("Initialized remote Jackrabbit repository from uri " + uri);
133 		return repository;
134 	}
135 
136 	@SuppressWarnings({ "rawtypes" })
137 	protected Repository createFileRepository(final String uri, Map parameters) throws RepositoryException {
138 		throw new UnsupportedOperationException();
139 		// InputStream configurationIn = null;
140 		// try {
141 		// Properties vars = new Properties();
142 		// vars.putAll(parameters);
143 		// String dirPath = uri.substring("file:".length());
144 		// File homeDir = new File(dirPath);
145 		// if (homeDir.exists() && !homeDir.isDirectory())
146 		// throw new ArgeoJcrException("Repository home " + dirPath + " is not a
147 		// directory");
148 		// if (!homeDir.exists())
149 		// homeDir.mkdirs();
150 		// configurationIn = fileRepositoryConfiguration.getInputStream();
151 		// vars.put(RepositoryConfigurationParser.REPOSITORY_HOME_VARIABLE,
152 		// homeDir.getCanonicalPath());
153 		// RepositoryConfig repositoryConfig = RepositoryConfig.create(new
154 		// InputSource(configurationIn), vars);
155 		//
156 		// // TransientRepository repository = new
157 		// // TransientRepository(repositoryConfig);
158 		// final RepositoryImpl repository =
159 		// RepositoryImpl.create(repositoryConfig);
160 		// Session session = repository.login();
161 		// // FIXME make it generic
162 		// org.argeo.jcr.JcrUtils.addPrivilege(session, "/", "ROLE_ADMIN",
163 		// "jcr:all");
164 		// org.argeo.jcr.JcrUtils.logoutQuietly(session);
165 		// Runtime.getRuntime().addShutdownHook(new Thread("Clean JCR repository
166 		// " + uri) {
167 		// public void run() {
168 		// repository.shutdown();
169 		// log.info("Destroyed repository " + uri);
170 		// }
171 		// });
172 		// log.info("Initialized file Jackrabbit repository from uri " + uri);
173 		// return repository;
174 		// } catch (Exception e) {
175 		// throw new ArgeoJcrException("Cannot create repository " + uri, e);
176 		// } finally {
177 		// IOUtils.closeQuietly(configurationIn);
178 		// }
179 	}
180 
181 	protected String getAliasFromURI(String uri) {
182 		try {
183 			URI uriObj = new URI(uri);
184 			String alias = uriObj.getPath();
185 			if (alias.charAt(0) == '/')
186 				alias = alias.substring(1);
187 			if (alias.charAt(alias.length() - 1) == '/')
188 				alias = alias.substring(0, alias.length() - 1);
189 			return alias;
190 		} catch (URISyntaxException e) {
191 			throw new ArgeoJcrException("Cannot interpret URI " + uri, e);
192 		}
193 	}
194 
195 	/**
196 	 * Called after the repository has been initialised. Does nothing by default.
197 	 */
198 	@SuppressWarnings("rawtypes")
199 	protected void postInitialization(Repository repository, Map parameters) {
200 
201 	}
202 }