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