001/*
002 *  Copyright 2016 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.repository.provider;
017
018import java.util.List;
019import java.util.Map;
020
021import javax.jcr.RepositoryException;
022
023import org.apache.jackrabbit.core.cluster.UpdateEventChannel;
024import org.apache.jackrabbit.core.id.NodeId;
025import org.apache.jackrabbit.core.id.PropertyId;
026import org.apache.jackrabbit.core.persistence.PMContext;
027import org.apache.jackrabbit.core.persistence.PersistenceManager;
028import org.apache.jackrabbit.core.persistence.pool.BundleDbPersistenceManager;
029import org.apache.jackrabbit.core.persistence.pool.DerbyPersistenceManager;
030import org.apache.jackrabbit.core.persistence.pool.MySqlPersistenceManager;
031import org.apache.jackrabbit.core.persistence.pool.OraclePersistenceManager;
032import org.apache.jackrabbit.core.persistence.pool.PostgreSQLPersistenceManager;
033import org.apache.jackrabbit.core.persistence.util.NodeInfo;
034import org.apache.jackrabbit.core.state.ChangeLog;
035import org.apache.jackrabbit.core.state.ItemStateException;
036import org.apache.jackrabbit.core.state.NoSuchItemStateException;
037import org.apache.jackrabbit.core.state.NodeReferences;
038import org.apache.jackrabbit.core.state.NodeState;
039import org.apache.jackrabbit.core.state.PropertyState;
040import org.apache.jackrabbit.core.util.db.ConnectionFactory;
041
042import org.ametys.core.datasource.AbstractDataSourceManager.DataSourceDefinition;
043import org.ametys.core.datasource.ConnectionHelper;
044import org.ametys.runtime.config.Config;
045
046/**
047 * Ametys implementation of Jackrabbit's {@link PersistenceManager}.
048 * This implementation is only a wrapper to an actual {@link BundleDbPersistenceManager}, depending on the config parameter.
049 */
050public class AmetysPersistenceManager extends BundleDbPersistenceManager
051{
052    /**
053     * Config parameter's name to use default Jackrabbit behaviour.
054     */
055    public static final String CONFIG_USE_DEFAULT = "org.ametys.plugins.repository.default-datasource";
056    
057    /**
058     * Config parameter's name referencing the datasource to use.
059     */
060    public static final String CONFIG_PM_DATASOURCE = "org.ametys.plugins.repository.datasource";
061    
062    private BundleDbPersistenceManager _wrappedPM;
063    private boolean _useDefault;
064    private String _workspace;
065    
066    /**
067     * Constructor.
068     */
069    public AmetysPersistenceManager()
070    {
071        _useDefault = Config.getInstance().getValue(CONFIG_USE_DEFAULT);
072        
073        if (_useDefault)
074        {
075            _wrappedPM = new DerbyPersistenceManager();
076            _wrappedPM.setSchemaObjectPrefix("");
077            _wrappedPM.setExternalBLOBs(true);
078        }
079        else
080        {
081            String datasource = Config.getInstance().getValue(CONFIG_PM_DATASOURCE);
082            
083            DataSourceDefinition dsDefinition = ConnectionHelper.getDataSourceDefinition(datasource);
084            
085            Map<String, Object> parameters = dsDefinition.getParameters();
086            String defUrl = (String) parameters.get("url");
087            String defDriver = (String) parameters.get("driver");
088            String defUser = (String) parameters.get("user");
089            String defPassword = (String) parameters.get("password");
090            
091            String dbType = ConnectionHelper.getDatabaseType(defUrl);
092            switch (dbType)
093            {
094                case ConnectionHelper.DATABASE_DERBY:
095                    _wrappedPM = new DerbyPersistenceManager();
096                    break;
097                case ConnectionHelper.DATABASE_MYSQL:
098                    _wrappedPM = new MySqlPersistenceManager();
099                    break;
100                case ConnectionHelper.DATABASE_ORACLE:
101                    _wrappedPM = new OraclePersistenceManager();
102                    break;
103                case ConnectionHelper.DATABASE_POSTGRES:
104                    _wrappedPM = new PostgreSQLPersistenceManager();
105                    break;
106                default:
107                    throw new IllegalArgumentException("Datasource URL " + defUrl + " is not supported for Jackrabbit PersistenceManagers.");
108            }
109            
110            _wrappedPM.setUrl(defUrl);
111            _wrappedPM.setDriver(defDriver);
112            _wrappedPM.setUser(defUser);
113            _wrappedPM.setPassword(defPassword);
114        }
115    }
116    
117    /**
118     * Get the wrapped persistence manager
119     * @return the persistence manager
120     */
121    public BundleDbPersistenceManager getWrappedPM()
122    {
123        return _wrappedPM;
124    }
125
126    /**
127     * Indicates the current JCR workspace.
128     * @param workspace the JCR workspace.
129     */
130    public void setWorkspace(String workspace)
131    {
132        _workspace = workspace;
133    }
134    
135    // Unsupported methods
136    
137    @Override
138    public void setUrl(String newUrl)
139    {
140        throw new UnsupportedOperationException("setUrl() method is not supported for AmetysPersistenceManager.");
141    }
142    
143    @Override
144    public void setUser(String unused)
145    {
146        throw new UnsupportedOperationException("setUser() method is not supported for AmetysPersistenceManager.");
147    }
148    
149    @Override
150    public void setPassword(String unused)
151    {
152        throw new UnsupportedOperationException("setPassword() method is not supported for AmetysPersistenceManager.");
153    }
154    
155    @Override
156    public void setDriver(String unused)
157    {
158        throw new UnsupportedOperationException("setDriver() method is not supported for AmetysPersistenceManager.");
159    }
160    
161    // PersistenceManager methods
162
163    @Override
164    public void init(PMContext ctx) throws Exception
165    {
166        if (_useDefault)
167        {
168            String dbUrl = "jdbc:derby:" + ctx.getHomeDir().getCanonicalPath() + "/db;create=true";
169            _wrappedPM.setUrl(dbUrl);
170        }
171        else
172        {
173            String prefix = _workspace  == null ? "version_" : _workspace + "_";
174            _wrappedPM.setSchemaObjectPrefix(prefix);
175        }
176        
177        _wrappedPM.init(ctx);
178    }
179
180    @Override
181    public void close() throws Exception
182    {
183        _wrappedPM.close();
184    }
185
186    @Override
187    public NodeState createNew(NodeId id)
188    {
189        return _wrappedPM.createNew(id);
190    }
191
192    @Override
193    public PropertyState createNew(PropertyId id)
194    {
195        return _wrappedPM.createNew(id);
196    }
197
198    @Override
199    public NodeState load(NodeId id) throws NoSuchItemStateException, ItemStateException
200    {
201        return _wrappedPM.load(id);
202    }
203
204    @Override
205    public PropertyState load(PropertyId id) throws NoSuchItemStateException, ItemStateException
206    {
207        return _wrappedPM.load(id);
208    }
209
210    @Override
211    public NodeReferences loadReferencesTo(NodeId id) throws NoSuchItemStateException, ItemStateException
212    {
213        return _wrappedPM.loadReferencesTo(id);
214    }
215
216    @Override
217    public boolean exists(NodeId id) throws ItemStateException
218    {
219        return _wrappedPM.exists(id);
220    }
221
222    @Override
223    public boolean exists(PropertyId id) throws ItemStateException
224    {
225        return _wrappedPM.exists(id);
226    }
227
228    @Override
229    public boolean existsReferencesTo(NodeId targetId) throws ItemStateException
230    {
231        return _wrappedPM.existsReferencesTo(targetId);
232    }
233
234    @Override
235    public void store(ChangeLog changeLog) throws ItemStateException
236    {
237        _wrappedPM.store(changeLog);
238    }
239
240    @Override
241    public void checkConsistency(String[] uuids, boolean recursive, boolean fix)
242    {
243        _wrappedPM.checkConsistency(uuids, recursive, fix);
244    }
245    
246    // BundleDBPersistenceManager methods
247    
248    @Override
249    public synchronized List<NodeId> getAllNodeIds(NodeId bigger, int maxCount) throws ItemStateException, RepositoryException
250    {
251        return _wrappedPM.getAllNodeIds(bigger, maxCount);
252    }
253    
254    @Override
255    public synchronized void destroy(NodeReferences refs) throws ItemStateException
256    {
257        _wrappedPM.destroy(refs);
258    }
259    
260    @Override
261    public synchronized Map<NodeId, NodeInfo> getAllNodeInfos(NodeId bigger, int maxCount) throws ItemStateException
262    {
263        return _wrappedPM.getAllNodeInfos(bigger, maxCount);
264    }
265    
266    
267    
268    @Override
269    public void setBlockOnConnectionLoss(String block)
270    {
271        _wrappedPM.setBlockOnConnectionLoss(block);
272    }
273    
274    @Override
275    public void setBundleCacheSize(String bundleCacheSize)
276    {
277        _wrappedPM.setBundleCacheSize(bundleCacheSize);
278    }
279    
280    @Override
281    public void setConnectionFactory(ConnectionFactory connectionFactory)
282    {
283        _wrappedPM.setConnectionFactory(connectionFactory);
284    }
285    
286    @Override
287    public void setConsistencyCheck(String check)
288    {
289        _wrappedPM.setConsistencyCheck(check);
290    }
291    
292    @Override
293    public void setConsistencyFix(String fix)
294    {
295        _wrappedPM.setConsistencyFix(fix);
296    }
297    
298    @Override
299    public void setErrorHandling(String errHandling)
300    {
301        _wrappedPM.setErrorHandling(errHandling);
302    }
303    
304    @Override
305    public void setEventChannel(UpdateEventChannel eventChannel)
306    {
307        _wrappedPM.setEventChannel(eventChannel);
308    }
309    
310    @Override
311    public void setExternalBLOBs(boolean externalBlobs)
312    {
313        _wrappedPM.setExternalBLOBs(externalBlobs);
314    }
315    
316    @Override
317    public void setMinBlobSize(String minBlobSize)
318    {
319        _wrappedPM.setMinBlobSize(minBlobSize);
320    }
321    
322    @Override
323    public void setSchemaObjectPrefix(String schemaPrefix)
324    {
325        _wrappedPM.setSchemaObjectPrefix(schemaPrefix);
326    }
327}