001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: /*
043: * DesignTimeDataSourceServiceImpl.java
044: *
045: * Created on June 2, 2006, 5:54 PM
046: *
047: * To change this template, choose Tools | Template Manager
048: * and open the template in the editor.
049: */
050:
051: package org.netbeans.modules.visualweb.project.jsf.services;
052:
053: import org.netbeans.modules.j2ee.deployment.common.api.ConfigurationException;
054: import org.netbeans.modules.visualweb.api.j2ee.common.RequestedJdbcResource;
055: import java.util.HashSet;
056:
057: import java.util.Iterator;
058: import java.util.List;
059: import java.util.Set;
060: import org.netbeans.api.db.explorer.ConnectionManager;
061: import org.netbeans.api.db.explorer.DatabaseConnection;
062:
063: import org.netbeans.api.project.Project;
064: import org.netbeans.modules.j2ee.deployment.common.api.Datasource;
065: import org.netbeans.modules.j2ee.deployment.common.api.DatasourceAlreadyExistsException;
066: import org.netbeans.modules.j2ee.deployment.devmodules.spi.J2eeModuleProvider;
067:
068: import org.openide.ErrorManager;
069: import org.openide.util.Utilities;
070:
071: /**
072: *
073: * @author marcow
074: */
075: public class DesignTimeDataSourceServiceImpl implements
076: DesignTimeDataSourceService {
077: static private final String DATASOURCE_PREFIX = "java:comp/env/"; // NOI18N
078: static private final String NON_DEFAULT_DATASOURCE_PREFIX = "java:/"; // NOI18N
079:
080: /** Creates a new instance of DesignTimeDataSourceServiceImpl */
081: public DesignTimeDataSourceServiceImpl() {
082: }
083:
084: public boolean updateProjectDataSource(Project project,
085: RequestedJdbcResource req) {
086: J2eeModuleProvider jmp = (J2eeModuleProvider) project
087: .getLookup().lookup(J2eeModuleProvider.class);
088: Set dss = null;
089: try {
090: dss = jmp.getModuleDatasources();
091: } catch (ConfigurationException e) {
092: dss = new HashSet();
093: // TODO: give some feedback to the user
094: }
095: boolean notFound = true;
096: Iterator it = dss.iterator();
097:
098: while (it.hasNext()) {
099: Datasource ds = (Datasource) it.next();
100:
101: if (req.getResourceName().equals(ds.getJndiName())
102: && req.getDriverClassName().equals(
103: ds.getDriverClassName())
104: && (req.getUrl() != null
105: && req.getUrl().equals(ds.getUrl()) || req
106: .getUrl() == null
107: && ds.getUrl() == null)
108: && (req.getUsername() != null
109: && req.getUsername().equals(
110: ds.getUsername()) || req
111: .getUsername() == null
112: && ds.getUsername() == null)
113: && (req.getPassword() != null
114: && req.getPassword().equals(
115: ds.getPassword()) || req
116: .getPassword() == null
117: && ds.getPassword() == null)) {
118: notFound = false;
119: }
120: }
121:
122: if (notFound) {
123: try {
124: jmp.getConfigSupport().createDatasource(
125: req.getResourceName(), req.getUrl(),
126: req.getUsername(), req.getPassword(),
127: req.getDriverClassName());
128: } catch (ConfigurationException e) {
129: // TODO: give some feedback to the user
130: } catch (DatasourceAlreadyExistsException e) {
131: List dsList = e.getDatasources();
132:
133: if (dsList.size() != 1) {
134: ErrorManager
135: .getDefault()
136: .log(
137: ErrorManager.WARNING,
138: "DS - "
139: + req.getResourceName()
140: + ": Here should only one DS exist!");
141: ErrorManager.getDefault().notify(
142: ErrorManager.INFORMATIONAL, e);
143:
144: return false;
145: } else {
146: Datasource eDs = (Datasource) dsList.get(0);
147:
148: // Compare with the DS we wanted to create.
149: if (eDs.getJndiName().equals(req.getResourceName())
150: && eDs.getDriverClassName().equals(
151: req.getDriverClassName())
152: && (eDs.getUrl() != null
153: && eDs.getUrl()
154: .equals(req.getUrl()) || eDs
155: .getUrl() == null
156: && req.getUrl() == null)
157: && (eDs.getUsername() != null
158: && eDs.getUsername().equals(
159: req.getUsername()) || eDs
160: .getUsername() == null
161: && req.getUsername() == null)
162: && (eDs.getPassword() != null
163: && eDs.getPassword().equals(
164: req.getPassword()) || eDs
165: .getPassword() == null
166: && req.getPassword() == null)) {
167: ErrorManager
168: .getDefault()
169: .log(
170: ErrorManager.INFORMATIONAL,
171: "DS - "
172: + req.getResourceName()
173: + ": OK, we have the same DS on the server already. I hope there is nothing else to configure for this project.");
174: } else {
175: ErrorManager
176: .getDefault()
177: .log(
178: ErrorManager.WARNING,
179: "DS - "
180: + req.getResourceName()
181: + ": There is a DS on the server with the same JNDI name but different parameters! Trouble ahead!!");
182: ErrorManager.getDefault().notify(
183: ErrorManager.WARNING, e);
184:
185: return false;
186: }
187: }
188: }
189: }
190:
191: return true;
192: }
193:
194: // create a JNDI name for resource reference name
195: public boolean updateResourceReference(Project project,
196: RequestedJdbcResource req) {
197: J2eeModuleProvider jmp = project.getLookup().lookup(
198: J2eeModuleProvider.class);
199: Set dss = null;
200: try {
201: dss = jmp.getModuleDatasources();
202: } catch (ConfigurationException e) {
203: dss = new HashSet();
204: // TODO: give some feedback to the user
205: }
206:
207: Iterator it = dss.iterator();
208:
209: while (it.hasNext()) {
210: Datasource ds = (Datasource) it.next();
211: try {
212: if ((req.getUrl().equals(ds.getUrl()))
213: && (req.getUsername().equals(ds.getUsername()))) {
214: jmp.getConfigSupport().bindDatasourceReference(
215: req.getResourceName(), ds.getJndiName());
216: }
217: } catch (ConfigurationException e) {
218: return false;
219: }
220: }
221:
222: return true;
223: }
224:
225: public Set<RequestedJdbcResource> getServerDataSources(Project p) {
226: J2eeModuleProvider jmp = (J2eeModuleProvider) p.getLookup()
227: .lookup(J2eeModuleProvider.class);
228: Set<Datasource> dss = null;
229: try {
230: dss = jmp.getServerDatasources();
231: } catch (ConfigurationException e) {
232: dss = new HashSet<Datasource>();
233: // TODO: give some feedback to the user
234: }
235: Set<RequestedJdbcResource> reqDss = new HashSet<RequestedJdbcResource>();
236: Iterator<Datasource> it = dss.iterator();
237:
238: // stripDATASOURCE_PREFIX is a hack for JBoss and other application servers due to differences in JNDI string format
239: // for issue 101812
240: while (it.hasNext()) {
241: Datasource ds = it.next();
242: RequestedJdbcResource r = new RequestedJdbcResource(
243: stripDATASOURCE_PREFIX(ds.getJndiName()), ds
244: .getDriverClassName(), ds.getUrl(), ds
245: .getUsername(), ds.getPassword());
246:
247: reqDss.add(r);
248: }
249:
250: return reqDss;
251: }
252:
253: public Set<RequestedJdbcResource> getProjectDataSources(Project p) {
254: J2eeModuleProvider jmp = (J2eeModuleProvider) p.getLookup()
255: .lookup(J2eeModuleProvider.class);
256:
257: Set<Datasource> dss = null;
258: try {
259: dss = jmp.getModuleDatasources();
260: } catch (ConfigurationException e) {
261: dss = new HashSet<Datasource>();
262: // TODO: give some feedback to the user
263: }
264:
265: Set<RequestedJdbcResource> reqDss = new HashSet<RequestedJdbcResource>();
266: Iterator<Datasource> it = dss.iterator();
267:
268: // stripDATASOURCE_PREFIX is a hack for JBoss and other application servers due to differences in JNDI string format
269: // for issue 101812
270: while (it.hasNext()) {
271: Datasource ds = it.next();
272: RequestedJdbcResource r = new RequestedJdbcResource(
273: stripDATASOURCE_PREFIX(ds.getJndiName()), ds
274: .getDriverClassName(), ds.getUrl(), ds
275: .getUsername(), ds.getPassword());
276:
277: reqDss.add(r);
278: }
279:
280: return reqDss;
281: }
282:
283: private String stripDATASOURCE_PREFIX(String orig) {
284: if (orig == null) {
285: return orig;
286: }
287: if (orig.startsWith(NON_DEFAULT_DATASOURCE_PREFIX)) {
288: return orig.substring(NON_DEFAULT_DATASOURCE_PREFIX
289: .length());
290: }
291: if (!orig.startsWith(DATASOURCE_PREFIX)) {
292: return orig;
293: }
294: if (orig.equals(DATASOURCE_PREFIX)) {
295: return orig;
296: }
297: return orig.substring(DATASOURCE_PREFIX.length());
298: }
299:
300: /**
301: * Returns set of broken datasources
302: *
303: * @param project
304: * @return Set<Datasource> returns a set of data sources that don't have corresponding database connections
305: */
306: public Set<RequestedJdbcResource> getBrokenDatasources(
307: Project project) {
308: J2eeModuleProvider jmp = (J2eeModuleProvider) project
309: .getLookup().lookup(J2eeModuleProvider.class);
310:
311: Set<Datasource> dss = null;
312: try {
313: dss = jmp.getModuleDatasources();
314: } catch (ConfigurationException e) {
315: dss = new HashSet<Datasource>();
316: }
317:
318: Set<Datasource> brokenDatasources = new HashSet<Datasource>();
319: Iterator<Datasource> it = dss.iterator();
320: while (it.hasNext()) {
321: Datasource ds = it.next();
322: if (!isFound(ds)) {
323: brokenDatasources.add(ds);
324: }
325: }
326:
327: Set<RequestedJdbcResource> brokenReqDss = new HashSet<RequestedJdbcResource>();
328: it = brokenDatasources.iterator();
329:
330: while (it.hasNext()) {
331: Datasource ds = it.next();
332: RequestedJdbcResource r = new RequestedJdbcResource(ds
333: .getJndiName(), ds.getDriverClassName(), ds
334: .getUrl(), ds.getUsername(), ds.getPassword());
335:
336: brokenReqDss.add(r);
337: }
338:
339: return brokenReqDss;
340: }
341:
342: private boolean isFound(Datasource ds) {
343: boolean found = false;
344: String url = ds.getUrl();
345: String username = ds.getUsername();
346: DatabaseConnection[] dbConns = ConnectionManager.getDefault()
347: .getConnections();
348: for (int i = 0; i < dbConns.length; i++) {
349: DatabaseConnection dbCon = dbConns[i];
350: String url1 = dbCon.getDatabaseURL();
351: String username1 = dbCon.getUser();
352: if (matchURL(url, url1, true)
353: && Utilities.compareObjects(username, username1)) {
354: found = true;
355: }
356: }
357: return found;
358: }
359:
360: private boolean matchURL(String jdbcResourceUrl, String dsInfoUrl,
361: boolean ignoreCase) {
362: if (ignoreCase) {
363: jdbcResourceUrl = jdbcResourceUrl.toLowerCase();
364: dsInfoUrl = dsInfoUrl.toLowerCase();
365: }
366: if (jdbcResourceUrl.equals(dsInfoUrl)) {
367: return true;
368: }
369:
370: if (jdbcResourceUrl.contains("derby")) {
371: String newJdbcResourceUrl = jdbcResourceUrl.substring(0,
372: jdbcResourceUrl.lastIndexOf(":"))
373: + jdbcResourceUrl.substring(jdbcResourceUrl
374: .lastIndexOf("/"));
375: if (newJdbcResourceUrl.equals(dsInfoUrl)) {
376: return true;
377: }
378: }
379:
380: int nextIndex = 0;
381: if ((jdbcResourceUrl != null) && (dsInfoUrl != null)) {
382: char[] jdbcResourceUrlChars = jdbcResourceUrl.toCharArray();
383: char[] dsInfoUrlChars = dsInfoUrl.toCharArray();
384: // determine the shortest of the two arrays
385: int length = jdbcResourceUrlChars.length;
386: if (length > dsInfoUrlChars.length) {
387: length = dsInfoUrlChars.length;
388: }
389: for (int i = 0; i < length - 1; i++) {
390: if ((jdbcResourceUrlChars[i] != dsInfoUrlChars[i])
391: && jdbcResourceUrlChars[i] == ':') {
392: nextIndex = 1;
393: } else if (jdbcResourceUrlChars[i + nextIndex] != dsInfoUrlChars[i]) {
394: return false;
395: }
396: }
397: }
398: return true;
399: }
400:
401: public boolean isDatasourceCreationSupported(Project project) {
402: J2eeModuleProvider jmp = project.getLookup().lookup(
403: J2eeModuleProvider.class);
404: return jmp.getConfigSupport().isDatasourceCreationSupported();
405: }
406: }
|