001: package org.apache.ojb.broker.metadata;
002:
003: /* Copyright 2002-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: import org.apache.commons.lang.SerializationUtils;
019: import org.apache.commons.lang.SystemUtils;
020: import org.apache.ojb.broker.PBKey;
021: import org.apache.ojb.broker.util.logging.Logger;
022: import org.apache.ojb.broker.util.logging.LoggerFactory;
023:
024: import java.io.Serializable;
025: import java.util.ArrayList;
026: import java.util.HashMap;
027: import java.util.Hashtable;
028: import java.util.Iterator;
029: import java.util.List;
030:
031: import javax.sql.DataSource;
032:
033: public class ConnectionRepository implements Serializable, XmlCapable {
034: private static final long serialVersionUID = -5581126412817848887L;
035: private static Logger log = LoggerFactory
036: .getLogger(ConnectionRepository.class);
037:
038: private HashMap jcdMap;
039: private Hashtable jcdAliasToPBKeyMap;
040: private JdbcMetadataUtils utils;
041:
042: public ConnectionRepository() {
043: jcdMap = new HashMap();
044: jcdAliasToPBKeyMap = new Hashtable();
045: utils = new JdbcMetadataUtils();
046: }
047:
048: /**
049: * Returns the matching {@link JdbcConnectionDescriptor}
050: * or <code>null</code> if no descriptor could be found. The user name
051: * and pass word will be set to match the supplied </code>PBKey</code>
052: * object. If the original user name and pass word are desired, the PBKey
053: * should be obtained with {@link #getStandardPBKeyForJcdAlias(String)}.
054: */
055: public JdbcConnectionDescriptor getDescriptor(PBKey pbKey) {
056: JdbcConnectionDescriptor result = (JdbcConnectionDescriptor) jcdMap
057: .get(pbKey);
058: if (result == null) {
059: result = deepCopyOfFirstFound(pbKey.getAlias());
060: if (result != null) {
061: result.setUserName(pbKey.getUser());
062: result.setPassWord(pbKey.getPassword());
063: // this build connection descriptor could not be the default connection
064: result.setDefaultConnection(false);
065: log
066: .info("Automatic create of new jdbc-connection-descriptor for PBKey "
067: + pbKey);
068: addDescriptor(result);
069: } else {
070: log.info("Could not find "
071: + JdbcConnectionDescriptor.class.getName()
072: + " for PBKey " + pbKey);
073: }
074: }
075: return result;
076: }
077:
078: /**
079: * Returns a deep copy of the first found connection descriptor
080: * with the given <code>jcdAlias</code> name or <code>null</code>
081: * if none found.
082: */
083: private JdbcConnectionDescriptor deepCopyOfFirstFound(
084: String jcdAlias) {
085: Iterator it = jcdMap.values().iterator();
086: JdbcConnectionDescriptor jcd;
087: while (it.hasNext()) {
088: jcd = (JdbcConnectionDescriptor) it.next();
089: if (jcdAlias.equals(jcd.getJcdAlias())) {
090: return (JdbcConnectionDescriptor) SerializationUtils
091: .clone(jcd);
092: }
093: }
094: return null;
095: }
096:
097: /**
098: * Return the matching {@link org.apache.ojb.broker.PBKey} for
099: * the given jcdAlias name, or <code>null</code> if no match
100: * was found.
101: */
102: public PBKey getStandardPBKeyForJcdAlias(String jcdAlias) {
103: return (PBKey) jcdAliasToPBKeyMap.get(jcdAlias);
104: }
105:
106: /**
107: * Add a new {@link JdbcConnectionDescriptor}.
108: */
109: public void addDescriptor(JdbcConnectionDescriptor jcd) {
110: synchronized (jcdMap) {
111: if (jcdMap.containsKey(jcd.getPBKey())) {
112: throw new MetadataException(
113: "Found duplicate connection descriptor using PBKey "
114: + jcd.getPBKey()
115: + ", remove the old descriptor first, before add the new one. "
116: + jcd);
117: }
118: jcdMap.put(jcd.getPBKey(), jcd);
119: // only if the jcdAlias was not found, put the new PBKey,
120: // because we don't want to replace the original PBKey with
121: // automatic generated descriptors PBKey's - see method getDescriptor(PBKey key)
122: if (!jcdAliasToPBKeyMap.containsKey(jcd.getJcdAlias())) {
123: jcdAliasToPBKeyMap.put(jcd.getJcdAlias(), jcd
124: .getPBKey());
125: }
126: if (log.isDebugEnabled())
127: log.debug("New descriptor was added: " + jcd);
128: }
129: }
130:
131: /**
132: * Creates and adds a new connection descriptor for the given JDBC connection url.
133: * This method tries to guess the platform to be used, but it should be checked
134: * afterwards nonetheless using the {@link JdbcConnectionDescriptor#getDbms()} method.
135: * For properties that are not part of the url, the following standard values are
136: * explicitly set:
137: * <ul>
138: * <li>jdbc level = 2.0</li>
139: * </ul>
140: *
141: * @param jcdAlias The connection alias for the created connection; if 'default' is used,
142: * then the new descriptor will become the default connection descriptor
143: * @param jdbcDriver The fully qualified jdbc driver name
144: * @param jdbcConnectionUrl The connection url of the form '[protocol]:[sub protocol]:{database-specific path]'
145: * where protocol is usually 'jdbc'
146: * @param username The user name (can be <code>null</code>)
147: * @param password The password (can be <code>null</code>)
148: * @return The created connection descriptor
149: * @see JdbcConnectionDescriptor#getDbms()
150: */
151: public JdbcConnectionDescriptor addDescriptor(String jcdAlias,
152: String jdbcDriver, String jdbcConnectionUrl,
153: String username, String password) {
154: JdbcConnectionDescriptor jcd = new JdbcConnectionDescriptor();
155: HashMap props = utils.parseConnectionUrl(jdbcConnectionUrl);
156:
157: jcd.setJcdAlias(jcdAlias);
158: jcd.setProtocol((String) props
159: .get(JdbcMetadataUtils.PROPERTY_PROTOCOL));
160: jcd.setSubProtocol((String) props
161: .get(JdbcMetadataUtils.PROPERTY_SUBPROTOCOL));
162: jcd.setDbAlias((String) props
163: .get(JdbcMetadataUtils.PROPERTY_DBALIAS));
164:
165: String platform = utils.findPlatformFor(jcd.getSubProtocol(),
166: jdbcDriver);
167:
168: jcd.setDbms(platform);
169: jcd.setJdbcLevel(2.0);
170: jcd.setDriver(jdbcDriver);
171: if (username != null) {
172: jcd.setUserName(username);
173: jcd.setPassWord(password);
174: }
175: if ("default".equals(jcdAlias)) {
176: jcd.setDefaultConnection(true);
177: // arminw: MM will search for the default key
178: // MetadataManager.getInstance().setDefaultPBKey(jcd.getPBKey());
179: }
180:
181: addDescriptor(jcd);
182: return jcd;
183: }
184:
185: /**
186: * Creates and adds a new connection descriptor for the given JDBC data source.
187: * This method tries to guess the platform to be used, but it should be checked
188: * afterwards nonetheless using the {@link JdbcConnectionDescriptor#getDbms()} method.
189: * Note that the descriptor won't have a value for the driver because it is not possible
190: * to retrieve the driver classname from the data source.
191: *
192: * @param jcdAlias The connection alias for the created connection; if 'default' is used,
193: * then the new descriptor will become the default connection descriptor
194: * @param dataSource The data source
195: * @param username The user name (can be <code>null</code>)
196: * @param password The password (can be <code>null</code>)
197: * @return The created connection descriptor
198: * @see JdbcConnectionDescriptor#getDbms()
199: */
200: public JdbcConnectionDescriptor addDescriptor(String jcdAlias,
201: DataSource dataSource, String username, String password) {
202: JdbcConnectionDescriptor jcd = new JdbcConnectionDescriptor();
203:
204: jcd.setJcdAlias(jcdAlias);
205: jcd.setDataSource(dataSource);
206: if (username != null) {
207: jcd.setUserName(username);
208: jcd.setPassWord(password);
209: }
210: utils
211: .fillJCDFromDataSource(jcd, dataSource, username,
212: password);
213: if ("default".equals(jcdAlias)) {
214: jcd.setDefaultConnection(true);
215: // arminw: MM will search for the default key
216: // MetadataManager.getInstance().setDefaultPBKey(jcd.getPBKey());
217: }
218: addDescriptor(jcd);
219: return jcd;
220: }
221:
222: /**
223: * Remove a descriptor.
224: * @param validKey This could be the {@link JdbcConnectionDescriptor}
225: * itself, or the associated {@link JdbcConnectionDescriptor#getPBKey PBKey}.
226: */
227: public void removeDescriptor(Object validKey) {
228: PBKey pbKey;
229: if (validKey instanceof PBKey) {
230: pbKey = (PBKey) validKey;
231: } else if (validKey instanceof JdbcConnectionDescriptor) {
232: pbKey = ((JdbcConnectionDescriptor) validKey).getPBKey();
233: } else {
234: throw new MetadataException(
235: "Could not remove descriptor, given object was no vaild key: "
236: + validKey);
237: }
238: Object removed = null;
239: synchronized (jcdMap) {
240: removed = jcdMap.remove(pbKey);
241: jcdAliasToPBKeyMap.remove(pbKey.getAlias());
242: }
243: log.info("Remove descriptor: " + removed);
244: }
245:
246: /**
247: * Return a deep copy of all managed {@link JdbcConnectionDescriptor}.
248: */
249: public List getAllDescriptor() {
250: return (List) SerializationUtils.clone(new ArrayList(jcdMap
251: .values()));
252: }
253:
254: public String toXML() {
255: String eol = SystemUtils.LINE_SEPARATOR;
256: // use copy to avoid sync problems
257: HashMap map = (HashMap) jcdMap.clone();
258: StringBuffer buf = new StringBuffer();
259: Iterator it = map.values().iterator();
260: while (it.hasNext()) {
261: JdbcConnectionDescriptor jcd = (JdbcConnectionDescriptor) it
262: .next();
263: buf.append(jcd.toXML());
264: buf.append(eol);
265: }
266: return buf.toString();
267: }
268: }
|