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().getValueAsBoolean(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().getValueAsString(CONFIG_PM_DATASOURCE);
082            
083            DataSourceDefinition dsDefinition = ConnectionHelper.getDataSourceDefinition(datasource);
084            
085            Map<String, String> parameters = dsDefinition.getParameters();
086            String defUrl = parameters.get("url");
087            String defDriver = parameters.get("driver");
088            String defUser = parameters.get("user");
089            String defPassword = 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     * Indicates the current JCR workspace.
119     * @param workspace the JCR workspace.
120     */
121    public void setWorkspace(String workspace)
122    {
123        _workspace = workspace;
124    }
125    
126    // Unsupported methods
127    
128    @Override
129    public void setUrl(String newUrl)
130    {
131        throw new UnsupportedOperationException("setUrl() method is not supported for AmetysPersistenceManager.");
132    }
133    
134    @Override
135    public void setUser(String unused)
136    {
137        throw new UnsupportedOperationException("setUser() method is not supported for AmetysPersistenceManager.");
138    }
139    
140    @Override
141    public void setPassword(String unused)
142    {
143        throw new UnsupportedOperationException("setPassword() method is not supported for AmetysPersistenceManager.");
144    }
145    
146    @Override
147    public void setDriver(String unused)
148    {
149        throw new UnsupportedOperationException("setDriver() method is not supported for AmetysPersistenceManager.");
150    }
151    
152    // PersistenceManager methods
153
154    @Override
155    public void init(PMContext ctx) throws Exception
156    {
157        if (_useDefault)
158        {
159            String dbUrl = "jdbc:derby:" + ctx.getHomeDir().getCanonicalPath() + "/db;create=true";
160            _wrappedPM.setUrl(dbUrl);
161        }
162        else
163        {
164            String prefix = _workspace  == null ? "version_" : _workspace + "_";
165            _wrappedPM.setSchemaObjectPrefix(prefix);
166        }
167        
168        _wrappedPM.init(ctx);
169    }
170
171    @Override
172    public void close() throws Exception
173    {
174        _wrappedPM.close();
175    }
176
177    @Override
178    public NodeState createNew(NodeId id)
179    {
180        return _wrappedPM.createNew(id);
181    }
182
183    @Override
184    public PropertyState createNew(PropertyId id)
185    {
186        return _wrappedPM.createNew(id);
187    }
188
189    @Override
190    public NodeState load(NodeId id) throws NoSuchItemStateException, ItemStateException
191    {
192        return _wrappedPM.load(id);
193    }
194
195    @Override
196    public PropertyState load(PropertyId id) throws NoSuchItemStateException, ItemStateException
197    {
198        return _wrappedPM.load(id);
199    }
200
201    @Override
202    public NodeReferences loadReferencesTo(NodeId id) throws NoSuchItemStateException, ItemStateException
203    {
204        return _wrappedPM.loadReferencesTo(id);
205    }
206
207    @Override
208    public boolean exists(NodeId id) throws ItemStateException
209    {
210        return _wrappedPM.exists(id);
211    }
212
213    @Override
214    public boolean exists(PropertyId id) throws ItemStateException
215    {
216        return _wrappedPM.exists(id);
217    }
218
219    @Override
220    public boolean existsReferencesTo(NodeId targetId) throws ItemStateException
221    {
222        return _wrappedPM.existsReferencesTo(targetId);
223    }
224
225    @Override
226    public void store(ChangeLog changeLog) throws ItemStateException
227    {
228        _wrappedPM.store(changeLog);
229    }
230
231    @Override
232    public void checkConsistency(String[] uuids, boolean recursive, boolean fix)
233    {
234        _wrappedPM.checkConsistency(uuids, recursive, fix);
235    }
236    
237    // BundleDBPersistenceManager methods
238    
239    @Override
240    public synchronized List<NodeId> getAllNodeIds(NodeId bigger, int maxCount) throws ItemStateException, RepositoryException
241    {
242        return _wrappedPM.getAllNodeIds(bigger, maxCount);
243    }
244    
245    @Override
246    public synchronized void destroy(NodeReferences refs) throws ItemStateException
247    {
248        _wrappedPM.destroy(refs);
249    }
250    
251    @Override
252    public synchronized Map<NodeId, NodeInfo> getAllNodeInfos(NodeId bigger, int maxCount) throws ItemStateException
253    {
254        return _wrappedPM.getAllNodeInfos(bigger, maxCount);
255    }
256    
257    
258    
259    @Override
260    public void setBlockOnConnectionLoss(String block)
261    {
262        _wrappedPM.setBlockOnConnectionLoss(block);
263    }
264    
265    @Override
266    public void setBundleCacheSize(String bundleCacheSize)
267    {
268        _wrappedPM.setBundleCacheSize(bundleCacheSize);
269    }
270    
271    @Override
272    public void setConnectionFactory(ConnectionFactory connectionFactory)
273    {
274        _wrappedPM.setConnectionFactory(connectionFactory);
275    }
276    
277    @Override
278    public void setConsistencyCheck(String check)
279    {
280        _wrappedPM.setConsistencyCheck(check);
281    }
282    
283    @Override
284    public void setConsistencyFix(String fix)
285    {
286        _wrappedPM.setConsistencyFix(fix);
287    }
288    
289    @Override
290    public void setErrorHandling(String errHandling)
291    {
292        _wrappedPM.setErrorHandling(errHandling);
293    }
294    
295    @Override
296    public void setEventChannel(UpdateEventChannel eventChannel)
297    {
298        _wrappedPM.setEventChannel(eventChannel);
299    }
300    
301    @Override
302    public void setExternalBLOBs(boolean externalBlobs)
303    {
304        _wrappedPM.setExternalBLOBs(externalBlobs);
305    }
306    
307    @Override
308    public void setMinBlobSize(String minBlobSize)
309    {
310        _wrappedPM.setMinBlobSize(minBlobSize);
311    }
312    
313    @Override
314    public void setSchemaObjectPrefix(String schemaPrefix)
315    {
316        _wrappedPM.setSchemaObjectPrefix(schemaPrefix);
317    }
318}