1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.repository;
35
36 import info.magnolia.audit.MgnlAuditLoggingContentDecorator;
37 import info.magnolia.audit.MgnlAuditLoggingContentDecoratorSessionWrapper;
38 import info.magnolia.cms.core.SystemProperty;
39 import info.magnolia.cms.core.version.MgnlVersioningSession;
40 import info.magnolia.cms.security.AccessDeniedException;
41 import info.magnolia.cms.util.ConfigUtil;
42 import info.magnolia.context.MgnlContext;
43 import info.magnolia.init.MagnoliaConfigurationProperties;
44 import info.magnolia.jcr.RuntimeRepositoryException;
45 import info.magnolia.jcr.predicate.AbstractPredicate;
46 import info.magnolia.jcr.util.NodeTypes;
47 import info.magnolia.jcr.util.NodeUtil;
48 import info.magnolia.jcr.wrapper.MgnlPropertySettingContentDecorator;
49 import info.magnolia.objectfactory.Classes;
50 import info.magnolia.objectfactory.Components;
51 import info.magnolia.repository.definition.RepositoryDefinition;
52 import info.magnolia.repository.definition.RepositoryMappingDefinition;
53 import info.magnolia.repository.definition.RepositoryMappingDefinitionReader;
54 import info.magnolia.repository.definition.WorkspaceMappingDefinition;
55 import info.magnolia.repository.mbean.TrackingSessionWrapper;
56 import info.magnolia.stats.JCRStats;
57
58 import java.io.InputStream;
59 import java.util.Collection;
60
61 import javax.inject.Inject;
62 import javax.inject.Singleton;
63 import javax.jcr.Credentials;
64 import javax.jcr.NoSuchWorkspaceException;
65 import javax.jcr.Node;
66 import javax.jcr.Repository;
67 import javax.jcr.RepositoryException;
68 import javax.jcr.Session;
69 import javax.jcr.Workspace;
70
71 import org.apache.commons.io.IOUtils;
72 import org.apache.commons.lang3.StringUtils;
73 import org.slf4j.Logger;
74 import org.slf4j.LoggerFactory;
75
76
77
78
79 @Singleton
80 public final class DefaultRepositoryManager implements RepositoryManager {
81
82 private static final Logger log = LoggerFactory.getLogger(DefaultRepositoryManager.class);
83
84 private final WorkspaceMapping workspaceMapping;
85 private final MagnoliaConfigurationProperties magnoliaConfigurationProperties;
86
87
88
89
90 @Deprecated
91 public DefaultRepositoryManager() {
92 this(Components.getComponent(MagnoliaConfigurationProperties.class), new WorkspaceMapping());
93 }
94
95 @Inject
96 public DefaultRepositoryManager(MagnoliaConfigurationProperties magnoliaConfigurationProperties, WorkspaceMapping workspaceMapping) {
97 this.magnoliaConfigurationProperties = magnoliaConfigurationProperties;
98 this.workspaceMapping = workspaceMapping;
99 }
100
101 @Override
102 public void init() {
103 log.info("Loading JCR");
104 workspaceMapping.clearRepositories();
105 try {
106 loadRepositories();
107 log.debug("JCR loaded");
108 } catch (Exception e) {
109 log.error(e.getMessage(), e);
110 }
111 }
112
113 @Override
114 public void shutdown() {
115 log.info("Shutting down JCR");
116 for (RepositoryDefinition repositoryDefinition : workspaceMapping.getRepositoryDefinitions()) {
117 Provider provider = workspaceMapping.getRepositoryProvider(repositoryDefinition.getName());
118 provider.shutdownRepository();
119 }
120 workspaceMapping.clearAll();
121 }
122
123 @Override
124 public boolean checkIfInitialized() throws AccessDeniedException, RepositoryException {
125 Collection<String> workspaceNames = workspaceMapping.getLogicalWorkspaceNames();
126 for (String workspace : workspaceNames) {
127 if (checkIfInitialized(workspace)) {
128 return true;
129 }
130 }
131 return false;
132 }
133
134 @Override
135 public boolean checkIfInitialized(String logicalWorkspace) throws RepositoryException, AccessDeniedException {
136 log.debug("Checking [{}] repository.", logicalWorkspace);
137
138 Session session = MgnlContext.getSystemContext().getJCRSession(logicalWorkspace);
139
140 if (session == null) {
141 throw new RuntimeException("Repository [" + logicalWorkspace + "] not loaded");
142 }
143
144 Node startPage = session.getRootNode();
145
146
147 Iterable<Node> children = NodeUtil.getNodes(startPage, new AbstractPredicate<Node>() {
148 @Override
149 public boolean evaluateTyped(Node content) {
150 String name;
151 try {
152 name = content.getName();
153 } catch (RepositoryException e) {
154 throw new RuntimeRepositoryException(e);
155 }
156 return (!name.startsWith(NodeTypes.JCR_PREFIX) && !name.startsWith(NodeTypes.REP_PREFIX));
157 }
158 });
159
160 if (children.iterator().hasNext()) {
161 log.debug("Content found in [{}].", logicalWorkspace);
162 return true;
163 }
164 return false;
165 }
166
167 @Override
168 public void reload() {
169
170
171
172 log.info("Reloading JCR");
173 init();
174 }
175
176 private void loadRepositories() throws Exception {
177 final String path = SystemProperty.getProperty(SystemProperty.MAGNOLIA_REPOSITORIES_CONFIG);
178 if (path == null) {
179 throw new RepositoryNotInitializedException("No value found for property " + SystemProperty.MAGNOLIA_REPOSITORIES_CONFIG + ": can not start repository.");
180 }
181 final String tokenizedConfig = ConfigUtil.getTokenizedConfigFile(path);
182 InputStream stream = IOUtils.toInputStream(tokenizedConfig);
183
184 RepositoryMappingDefinitionReader reader = new RepositoryMappingDefinitionReader();
185 RepositoryMappingDefinition mapping = reader.read(stream);
186
187 for (RepositoryDefinition repositoryDefinition : mapping.getRepositories()) {
188 if (repositoryDefinition.getWorkspaces().isEmpty()) {
189 repositoryDefinition.addWorkspace("default");
190 }
191 workspaceMapping.addRepositoryDefinition(repositoryDefinition);
192 loadRepository(repositoryDefinition);
193 }
194
195 for (WorkspaceMappingDefinition workspaceMapping : mapping.getWorkspaceMappings()) {
196 this.workspaceMapping.addWorkspaceMappingDefinition(workspaceMapping);
197 }
198
199
200 for (RepositoryDefinition repoDefinition : workspaceMapping.getRepositoryDefinitions()) {
201 String repoName = repoDefinition.getName();
202 Provider provider = workspaceMapping.getRepositoryProvider(repoName);
203 Session session = provider.getSystemSession("default");
204 try {
205 for (String wksName : session.getWorkspace().getAccessibleWorkspaceNames()) {
206 if (!hasWorkspace(wksName)) {
207 loadWorkspace(repoName, wksName);
208 }
209 }
210 } finally {
211 session.logout();
212 }
213 }
214 }
215
216 @Override
217 public void loadRepository(RepositoryDefinition definition) throws RepositoryNotInitializedException, InstantiationException, IllegalAccessException, ClassNotFoundException {
218 log.info("Loading JCR {}", definition.getName());
219
220 Class<? extends Provider> providerClass = Classes.getClassFactory().forName(definition.getProvider());
221 Provider provider = Components.getComponentProvider().newInstance(providerClass);
222 provider.init(definition);
223 Repository repository = provider.getUnderlyingRepository();
224 workspaceMapping.setRepository(definition.getName(), repository);
225 workspaceMapping.setRepositoryProvider(definition.getName(), provider);
226
227 if (definition.isLoadOnStartup()) {
228 for (String workspaceId : definition.getWorkspaces()) {
229 registerNameSpacesAndNodeTypes(workspaceId, definition, provider);
230 }
231 }
232 }
233
234 @Override
235 public void loadWorkspace(String repositoryId, String physicalWorkspaceName) throws RepositoryException {
236 log.info("Loading workspace {}", physicalWorkspaceName);
237
238 workspaceMapping.addWorkspaceMapping(new WorkspaceMappingDefinition(physicalWorkspaceName, repositoryId, physicalWorkspaceName));
239
240 Provider provider = getRepositoryProvider(repositoryId);
241 provider.registerWorkspace(physicalWorkspaceName);
242 RepositoryDefinition repositoryDefinition = workspaceMapping.getRepositoryDefinition(repositoryId);
243
244 registerNameSpacesAndNodeTypes(physicalWorkspaceName, repositoryDefinition, provider);
245 }
246
247 private void registerNameSpacesAndNodeTypes(String physicalWorkspaceName, RepositoryDefinition repositoryDefinition, Provider provider) {
248 try {
249 Session session = provider.getSystemSession(physicalWorkspaceName);
250 try {
251 provider.registerNamespace(RepositoryConstants.NAMESPACE_PREFIX, RepositoryConstants.NAMESPACE_URI, session.getWorkspace());
252 provider.registerNodeTypes();
253 } finally {
254 session.logout();
255 }
256 } catch (RepositoryException e) {
257 log.error("Failed to initialize workspace {} in repository {}", physicalWorkspaceName, repositoryDefinition.getName(), e);
258 }
259 }
260
261 @Override
262 public Session getSession(String logicalWorkspaceName, Credentials credentials) throws RepositoryException {
263 WorkspaceMappingDefinition mapping = this.workspaceMapping.getWorkspaceMapping(logicalWorkspaceName);
264 if (mapping == null) throw new NoSuchWorkspaceException(logicalWorkspaceName);
265 Repository repository = getRepository(mapping.getRepositoryName());
266 String physicalWorkspaceName = mapping.getPhysicalWorkspaceName();
267
268 Session session = repository.login(credentials, physicalWorkspaceName);
269 return wrapSession(session, logicalWorkspaceName);
270 }
271
272 @Override
273 public Session getSystemSession(String logicalWorkspaceName) throws RepositoryException {
274 WorkspaceMappingDefinition mapping = this.workspaceMapping.getWorkspaceMapping(logicalWorkspaceName);
275 if (mapping == null) throw new NoSuchWorkspaceException(logicalWorkspaceName);
276 Provider provider = getRepositoryProvider(mapping.getRepositoryName());
277 return wrapSession(provider.getSystemSession(mapping.getPhysicalWorkspaceName()), logicalWorkspaceName);
278 }
279
280 public void createWorkspace(String repository, String logicalWorkspaceName) throws RepositoryException {
281 for (WorkspaceMappingDefinition mapping : workspaceMapping.getWorkspaceMappings()) {
282 Session session = getSystemSession(mapping.getLogicalWorkspaceName());
283 try {
284 if (mapping.getRepositoryName().equals(repository)) {
285 Workspace workspace = session.getWorkspace();
286 workspace.createWorkspace(logicalWorkspaceName);
287 workspaceMapping.addWorkspaceMapping(new WorkspaceMappingDefinition(logicalWorkspaceName, repository, logicalWorkspaceName));
288 return;
289 }
290 } finally {
291 session.logout();
292 }
293 }
294 throw new RepositoryException("Repository [" + repository + "] doesn't exist.");
295 }
296
297 private Session wrapSession(Session session, String logicalWorkspaceName) {
298 session = new TrackingSessionWrapper(session, JCRStats.getInstance());
299 if ("imaging".equals(logicalWorkspaceName) || "Expressions".equals(logicalWorkspaceName) || "Store".equals(logicalWorkspaceName) || "mgnlSystem".equals(logicalWorkspaceName)) {
300
301
302 return new MgnlVersioningSession(session);
303 }
304 if (!RepositoryConstants.VERSION_STORE.equals(logicalWorkspaceName)) {
305
306 session = new MgnlVersioningSession(session);
307 }
308
309
310 session = new MgnlPropertySettingContentDecorator().wrapSession(session);
311 return new MgnlAuditLoggingContentDecoratorSessionWrapper(session, new MgnlAuditLoggingContentDecorator());
312 }
313
314 @Override
315 public boolean hasRepository(String repositoryId) {
316 return workspaceMapping.getRepositoryDefinition(repositoryId) != null;
317 }
318
319 @Override
320 public RepositoryDefinition getRepositoryDefinition(String repositoryId) {
321 return workspaceMapping.getRepositoryDefinition(repositoryId);
322 }
323
324 @Override
325 public Provider getRepositoryProvider(String repositoryId) {
326 return workspaceMapping.getRepositoryProvider(repositoryId);
327 }
328
329 @Override
330 public Repository getRepository(String repositoryId) {
331 return workspaceMapping.getRepository(repositoryId);
332 }
333
334 @Override
335 public void addWorkspaceMapping(WorkspaceMappingDefinition mapping) {
336 workspaceMapping.addWorkspaceMapping(mapping);
337 }
338
339 @Override
340 public boolean hasWorkspace(String logicalWorkspaceName) {
341 return workspaceMapping.getWorkspaceMapping(logicalWorkspaceName) != null;
342 }
343
344 @Override
345 public Collection<WorkspaceMappingDefinition> getWorkspaceMappings() {
346 return workspaceMapping.getWorkspaceMappings();
347 }
348
349 @Override
350 public WorkspaceMappingDefinition getWorkspaceMapping(String logicalWorkspaceName) {
351 return workspaceMapping.getWorkspaceMapping(logicalWorkspaceName);
352 }
353
354 @Override
355 public Collection<String> getWorkspaceNames() {
356 return workspaceMapping.getLogicalWorkspaceNames();
357 }
358
359
360
361
362
363
364 public boolean isClusteredWorkspace(String workspace) {
365 String clusterConfigFile = magnoliaConfigurationProperties.getProperty(SystemProperty.MAGNOLIA_REPOSITORIES_CLUSTER_CONFIG);
366 if (StringUtils.isBlank(clusterConfigFile)) {
367 return false;
368 }
369
370 Collection<RepositoryDefinition> repoDefinitions = workspaceMapping.getRepositoryDefinitions();
371 for (RepositoryDefinition repoDefinition : repoDefinitions) {
372 if (repoDefinition.getParameters().containsValue(clusterConfigFile) && repoDefinition.getWorkspaces().contains(workspace)) {
373 return true;
374 }
375 }
376
377 return false;
378 }
379
380 public boolean isClusterMaster() {
381 return magnoliaConfigurationProperties.hasProperty(SystemProperty.MAGNOLIA_REPOSITORIES_CLUSTER_MASTER) &&
382 magnoliaConfigurationProperties.getBooleanProperty(SystemProperty.MAGNOLIA_REPOSITORIES_CLUSTER_MASTER);
383 }
384 }