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