001: /* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
002: * This code is licensed under the GPL 2.0 license, availible at the root
003: * application directory.
004: */
005: package org.vfny.geoserver.global;
006:
007: import org.geotools.data.DataStore;
008: import org.geotools.data.DataStoreFinder;
009: import org.vfny.geoserver.global.dto.DataStoreInfoDTO;
010: import org.vfny.geoserver.util.DataStoreUtils;
011:
012: import java.io.File;
013: import java.net.MalformedURLException;
014: import java.net.URL;
015: import java.util.Collections;
016: import java.util.HashMap;
017: import java.util.Iterator;
018: import java.util.Map;
019: import java.util.NoSuchElementException;
020:
021: /**
022: * This is the configuration iformation for one DataStore. This class can also
023: * generate real datastores.
024: * <p>
025: * This class implements {@link org.geotools.catalog.Service} interface as a
026: * link to a catalog.
027: * </p>
028: * @author Gabriel Rold?n
029: * @author dzwiers
030: * @author Justin Deoliveira
031: * @version $Id: DataStoreInfo.java 7646 2007-10-23 13:09:32Z aaime $
032: */
033: public class DataStoreInfo extends GlobalLayerSupertype {
034: /** DataStoreInfo we are representing */
035: private DataStore dataStore = null;
036:
037: /** ref to the parent class's collection */
038: private Data data;
039: private String id;
040: private String nameSpaceId;
041: private boolean enabled;
042: private String title;
043: private String _abstract;
044: private Map connectionParams;
045:
046: /** Storage for metadata */
047: private Map meta;
048:
049: /**
050: * Directory associated with this DataStore.
051: *
052: * <p>
053: * This directory may be used for File based relative paths.
054: * </p>
055: */
056: File baseDir;
057:
058: /**
059: * URL associated with this DataStore.
060: *
061: * <p>
062: * This directory may be used for URL based relative paths.
063: * </p>
064: */
065: URL baseURL;
066:
067: /**
068: * DataStoreInfo constructor.
069: *
070: * <p>
071: * Stores the specified data for later use.
072: * </p>
073: *
074: * @param config DataStoreInfoDTO the current configuration to use.
075: * @param data Data a ref to use later to look up related informtion
076: */
077: public DataStoreInfo(DataStoreInfoDTO config, Data data) {
078: this .data = data;
079: meta = new HashMap();
080:
081: connectionParams = config.getConnectionParams();
082: enabled = config.isEnabled();
083: id = config.getId();
084: nameSpaceId = config.getNameSpaceId();
085: title = config.getTitle();
086: _abstract = config.getAbstract();
087: }
088:
089: /**
090: * toDTO purpose.
091: *
092: * <p>
093: * This method is package visible only, and returns a reference to the
094: * GeoServerDTO. This method is unsafe, and should only be used with
095: * extreme caution.
096: * </p>
097: *
098: * @return DataStoreInfoDTO the generated object
099: */
100: Object toDTO() {
101: DataStoreInfoDTO dto = new DataStoreInfoDTO();
102: dto.setAbstract(_abstract);
103: dto.setConnectionParams(connectionParams);
104: dto.setEnabled(enabled);
105: dto.setId(id);
106: dto.setNameSpaceId(nameSpaceId);
107: dto.setTitle(title);
108:
109: return dto;
110: }
111:
112: /**
113: * getId purpose.
114: *
115: * <p>
116: * Returns the dataStore's id.
117: * </p>
118: *
119: * @return String the id.
120: */
121: public String getId() {
122: return id;
123: }
124:
125: protected Map getParams() {
126: Map params = new HashMap(connectionParams);
127: params.put("namespace", getNameSpace().getURI());
128:
129: return getParams(params, data.getBaseDir().toString());
130: }
131:
132: /**
133: * Get Connect params.
134: *
135: * <p>
136: * This is used to smooth any relative path kind of issues for any file
137: * URLS. This code should be expanded to deal with any other context
138: * sensitve isses dataStores tend to have.
139: * </p>
140: *
141: * @return DOCUMENT ME!
142: *
143: * @task REVISIT: cache these?
144: */
145: public static Map getParams(Map m, String baseDir) {
146: Map params = Collections.synchronizedMap(new HashMap(m));
147:
148: for (Iterator i = params.entrySet().iterator(); i.hasNext();) {
149: Map.Entry entry = (Map.Entry) i.next();
150: String key = (String) entry.getKey();
151: Object value = entry.getValue();
152:
153: try {
154: //TODO: this code is a pretty big hack, using the name to
155: // determine if the key is a url, could be named something else
156: // and still be a url
157: if ((key != null) && key.matches(".* *url")
158: && value instanceof String) {
159: String path = (String) value;
160: LOGGER.finer("in string url");
161:
162: if (path.startsWith("file:")) {
163: File fixedPath = GeoserverDataDirectory
164: .findDataFile(path);
165: entry.setValue(fixedPath.toURL()
166: .toExternalForm());
167: }
168: } else if (value instanceof URL
169: && ((URL) value).getProtocol().equals("file")) {
170: File fixedPath = GeoserverDataDirectory
171: .findDataFile((URL) value);
172: entry.setValue(fixedPath.toURL());
173: }
174: } catch (MalformedURLException ignore) {
175: // ignore attempt to fix relative paths
176: }
177: }
178:
179: return params;
180: }
181:
182: /**
183: * By now just uses DataStoreFinder to find a new instance of a
184: * DataStoreInfo capable of process <code>connectionParams</code>. In the
185: * future we can see if it is better to cache or pool DataStores for
186: * performance, but definitely we shouldn't maintain a single
187: * DataStoreInfo as instance variable for synchronizing reassons
188: *
189: * <p>
190: * JG: Umm we actually require a single DataStoreInfo for for locking &
191: * transaction support to work. DataStoreInfo is expected to be thread
192: * aware (that is why it has Transaction Support).
193: * </p>
194: *
195: * @return DataStore
196: *
197: * @throws IllegalStateException if this DataStoreInfo is disabled by
198: * configuration
199: * @throws NoSuchElementException if no DataStoreInfo is found
200: */
201: public synchronized DataStore getDataStore()
202: throws IllegalStateException, NoSuchElementException {
203: if (!isEnabled()) {
204: throw new IllegalStateException(
205: "this datastore is not enabled, check your configuration");
206: }
207:
208: if (dataStore == null) {
209: Map m = getParams();
210: try {
211: dataStore = DataStoreUtils.getDataStore(m);
212: LOGGER.fine("connection established by " + toString());
213: } catch (Throwable ex) {
214: throw new IllegalStateException(
215: "can't create the datastore " + getId() + ": "
216: + ex.getClass().getName() + ": "
217: + ex.getMessage() + "\n"
218: + ex.toString());
219: }
220:
221: if (dataStore == null) {
222: // If datastore is not present, then disable it
223: // (although no change in config).
224: enabled = false;
225: LOGGER.fine("failed to establish connection with "
226: + toString());
227: throw new NoSuchElementException(
228: "No datastore found capable of managing "
229: + toString());
230: }
231: }
232:
233: return dataStore;
234: }
235:
236: /**
237: * getTitle purpose.
238: *
239: * <p>
240: * Returns the dataStore's title.
241: * </p>
242: *
243: * @return String the title.
244: */
245: public String getTitle() {
246: return title;
247: }
248:
249: /**
250: * getAbstract purpose.
251: *
252: * <p>
253: * Returns the dataStore's abstract.
254: * </p>
255: *
256: * @return String the abstract.
257: */
258: public String getAbstract() {
259: return _abstract;
260: }
261:
262: /**
263: * isEnabled purpose.
264: *
265: * <p>
266: * Returns true when the data store is enabled.
267: * </p>
268: *
269: * @return true when the data store is enabled.
270: */
271: public boolean isEnabled() {
272: return enabled;
273: }
274:
275: /**
276: * getNameSpace purpose.
277: *
278: * <p>
279: * Returns the namespace for this datastore.
280: * </p>
281: *
282: * @return NameSpaceInfo the namespace for this datastore.
283: */
284: public NameSpaceInfo getNameSpace() {
285: return (NameSpaceInfo) data.getNameSpace(getNamesSpacePrefix());
286: }
287:
288: /**
289: * Access namespace id
290: *
291: * @return DOCUMENT ME!
292: */
293: public String getNamesSpacePrefix() {
294: return nameSpaceId;
295: }
296:
297: /**
298: * Implement toString.
299: *
300: * @return String
301: *
302: * @see java.lang.Object#toString()
303: */
304: public String toString() {
305: return new StringBuffer("DataStoreConfig[namespace=").append(
306: getNameSpace().getPrefix()).append(", enabled=")
307: .append(isEnabled()).append(", abstract=").append(
308: getAbstract()).append(
309: ", connection parameters=").append(getParams())
310: .append("]").toString();
311: }
312:
313: /**
314: * Implement containsMetaData.
315: *
316: * @param key
317: *
318: * @return
319: *
320: * @see org.geotools.data.MetaData#containsMetaData(java.lang.String)
321: */
322: public boolean containsMetaData(String key) {
323: return meta.containsKey(key);
324: }
325:
326: /**
327: * Implement putMetaData.
328: *
329: * @param key
330: * @param value
331: *
332: * @see org.geotools.data.MetaData#putMetaData(java.lang.String,
333: * java.lang.Object)
334: */
335: public void putMetaData(String key, Object value) {
336: meta.put(key, value);
337: }
338:
339: /**
340: * Implement getMetaData.
341: *
342: * @param key
343: *
344: * @return
345: *
346: * @see org.geotools.data.MetaData#getMetaData(java.lang.String)
347: */
348: public Object getMetaData(String key) {
349: return meta.get(key);
350: }
351:
352: public void dispose() {
353: if (dataStore != null)
354: dataStore.dispose();
355: }
356: }
|