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.datasourcesexplorer;
017
018import java.sql.Connection;
019import java.sql.DatabaseMetaData;
020import java.sql.ResultSet;
021import java.util.ArrayList;
022import java.util.HashMap;
023import java.util.List;
024import java.util.Map;
025
026import org.apache.avalon.framework.parameters.Parameters;
027import org.apache.avalon.framework.service.ServiceException;
028import org.apache.avalon.framework.service.ServiceManager;
029import org.apache.cocoon.ProcessingException;
030import org.apache.cocoon.acting.ServiceableAction;
031import org.apache.cocoon.environment.ObjectModelHelper;
032import org.apache.cocoon.environment.Redirector;
033import org.apache.cocoon.environment.Request;
034import org.apache.cocoon.environment.SourceResolver;
035import org.apache.commons.lang3.StringUtils;
036
037import org.ametys.core.cocoon.JSonReader;
038import org.ametys.core.datasource.AbstractDataSourceManager.DataSourceDefinition;
039import org.ametys.core.datasource.ConnectionHelper;
040import org.ametys.core.datasource.DataSourceConsumerExtensionPoint;
041import org.ametys.core.datasource.LDAPDataSourceManager;
042import org.ametys.core.datasource.SQLDataSourceManager;
043import org.ametys.plugins.datasourcesexplorer.LDAPConnector.DN;
044
045/**
046 * Generates the list of tables on the given datasource id
047 */
048public class GetDatasources extends ServiceableAction
049{
050    private SQLDataSourceManager _sqlDataSourceManager;
051    private LDAPDataSourceManager _ldapDataSourceManager;
052    private DataSourceConsumerExtensionPoint _dataSourceConsumerEP;
053    private LDAPConnector _ldapConnector;
054
055    @Override
056    public void service(ServiceManager smanager) throws ServiceException
057    {
058        super.service(smanager);
059        
060        _sqlDataSourceManager = (SQLDataSourceManager) smanager.lookup(SQLDataSourceManager.ROLE);
061        _ldapDataSourceManager = (LDAPDataSourceManager) smanager.lookup(LDAPDataSourceManager.ROLE);
062        _ldapConnector = (LDAPConnector) smanager.lookup(LDAPConnector.ROLE);
063        _dataSourceConsumerEP = (DataSourceConsumerExtensionPoint) smanager.lookup(DataSourceConsumerExtensionPoint.ROLE);
064    }
065    
066    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
067    {
068        Map<String, Object> results = new HashMap<>();
069        
070        Request request = ObjectModelHelper.getRequest(objectModel);
071        request.setAttribute(JSonReader.OBJECT_TO_READ, results);
072
073        String id = request.getParameter("node");
074        if (StringUtils.isBlank(id))
075        {
076            id = "root";
077        }
078
079        Object children;
080        if ("root".equals(id))
081        {
082            children = _datasources2JSON();
083        }
084        else if (id.startsWith(SQLDataSourceManager.SQL_DATASOURCE_PREFIX))
085        {
086            children = _sqlDatasource2JSON(id);
087        }
088        else
089        {
090            children = _ldapDatasource2JSON(id);
091        }
092        
093        results.put("id", id);
094        results.put("children", children);
095        
096        return EMPTY_MAP;
097    }
098
099    private Object _datasources2JSON()
100    {
101        List<Map<String, Object>> datasources = new ArrayList<>();
102
103        for (DataSourceDefinition dataSourceDefinition : _sqlDataSourceManager.getDataSourceDefinitions(true, true, false).values())
104        {
105            Map<String, Object> datasource = new HashMap<>();
106            datasources.add(datasource);
107            
108            boolean isInUse = _dataSourceConsumerEP.isInUse(dataSourceDefinition.getId()) || (dataSourceDefinition.isDefault() && _dataSourceConsumerEP.isInUse(_sqlDataSourceManager.getDefaultDataSourceId()));
109            
110            datasource.put("id", dataSourceDefinition.getId());
111            datasource.put("nodetype", "datasource");
112            datasource.put("type", "SQL");
113            datasource.put("isDefault", dataSourceDefinition.isDefault());
114            datasource.put("isInUse", isInUse);
115            datasource.put("text", dataSourceDefinition.getName());
116            datasource.put("description", dataSourceDefinition.getDescription());
117            datasource.put("iconCls", "ametysicon-data110");
118            datasource.put("leaf", "false");
119        }
120        
121        for (DataSourceDefinition dataSourceDefinition : _ldapDataSourceManager.getDataSourceDefinitions(true, true, false).values())
122        {
123            Map<String, Object> datasource = new HashMap<>();
124            datasources.add(datasource);
125            
126            boolean isInUse = _dataSourceConsumerEP.isInUse(dataSourceDefinition.getId()) || (dataSourceDefinition.isDefault() && _dataSourceConsumerEP.isInUse(_sqlDataSourceManager.getDefaultDataSourceId()));
127            
128            datasource.put("id", dataSourceDefinition.getId());
129            datasource.put("nodetype", "datasource");
130            datasource.put("type", "LDAP");
131            datasource.put("isDefault", dataSourceDefinition.isDefault());
132            datasource.put("isInUse", isInUse);
133            datasource.put("text", dataSourceDefinition.getName());
134            datasource.put("description", dataSourceDefinition.getDescription());
135            datasource.put("iconCls", "ametysicon-agenda3");
136            datasource.put("leaf", "false");
137        }
138
139        return datasources;
140    }
141
142    private Object _sqlDatasource2JSON(String sqlDatasourceId) throws ProcessingException
143    {
144        List<Map<String, String>> tables = new ArrayList<>();
145        
146        Connection connection = null;
147        ResultSet rs = null;
148        try
149        {
150            connection = ConnectionHelper.getConnection(sqlDatasourceId);
151            
152            String databaseType = ConnectionHelper.getDatabaseType(connection);
153            if (databaseType == null)
154            {
155                throw new IllegalArgumentException("The datasource '" + sqlDatasourceId + "' does not exist");
156            }
157            
158            DatabaseMetaData md = connection.getMetaData();
159            rs = md.getTables(null, null, "%", null);
160            while (rs.next()) 
161            {
162                Map<String, String> table = new HashMap<>();
163                table.put("id", rs.getString(3));
164                table.put("datasourceId", sqlDatasourceId);
165                table.put("nodetype", "sqltable");
166                table.put("text", rs.getString(3));
167                table.put("iconCls", "ametysicon-tables1");
168                table.put("leaf", "true");
169                tables.add(table);
170            }
171        }
172        catch (Exception e) 
173        {
174            throw new ProcessingException("Cannot list SQL tables of datasource '" + sqlDatasourceId + "'", e);
175        }
176        finally 
177        {
178            ConnectionHelper.cleanup(rs);
179            ConnectionHelper.cleanup(connection);
180        }
181        
182        return tables;
183    }
184    
185    private Object _ldapDatasource2JSON(String ldapDatasourcePath) throws ProcessingException
186    {
187        List<Map<String, String>> nodes = new ArrayList<>();
188
189        String ldapDatasourceId = StringUtils.substringBefore(ldapDatasourcePath, ";");
190        String currentDN = StringUtils.substringAfter(ldapDatasourcePath, ";");
191        
192        for (DN dn : _ldapConnector.getChildren(ldapDatasourceId, currentDN))
193        {
194            Map<String, String> node = new HashMap<>();
195            node.put("id", ldapDatasourceId + ";" + dn.getDN() + (StringUtils.isEmpty(currentDN) ? "" : "," + currentDN));
196            node.put("datasourceId", ldapDatasourceId);
197            node.put("nodetype", "ldapnode");
198            node.put("text", dn.getLabel());
199            node.put("iconCls", "ametysicon-menu");
200            node.put("leaf", dn.hasChild() ? "false" : "true");
201            nodes.add(node);
202        }
203        
204        return nodes;
205    }
206}