View Javadoc

1   /**
2    * This file Copyright (c) 2003-2011 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
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   * Manages all used Repositories.
70   *
71   * @version $Id$
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         // TODO cant we login without using the system context?
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         // return any kind of children
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         // TODO what exactly is this method supposed to do?!
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             //do not wrap version store in versioning session or we get infinite redirect loop and stack overflow
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 }