001: package net.refractions.udig.catalog.ui.workflow;
002:
003: import java.io.File;
004: import java.io.IOException;
005: import java.io.Serializable;
006: import java.net.URL;
007: import java.text.MessageFormat;
008: import java.util.ArrayList;
009: import java.util.Collection;
010: import java.util.Collections;
011: import java.util.HashMap;
012: import java.util.HashSet;
013: import java.util.Iterator;
014: import java.util.List;
015: import java.util.Map;
016: import java.util.Set;
017: import java.util.Map.Entry;
018:
019: import net.refractions.udig.catalog.CatalogPlugin;
020: import net.refractions.udig.catalog.ICatalog;
021: import net.refractions.udig.catalog.IGeoResource;
022: import net.refractions.udig.catalog.IResolve;
023: import net.refractions.udig.catalog.IService;
024: import net.refractions.udig.catalog.IServiceFactory;
025: import net.refractions.udig.catalog.URLUtils;
026: import net.refractions.udig.catalog.ui.CatalogUIPlugin;
027: import net.refractions.udig.catalog.ui.UDIGConnectionFactory;
028: import net.refractions.udig.catalog.ui.UDIGConnectionFactoryDescriptor;
029: import net.refractions.udig.catalog.ui.internal.Messages;
030: import net.refractions.udig.catalog.ui.workflow.Workflow.State;
031:
032: import org.eclipse.core.runtime.IProgressMonitor;
033: import org.eclipse.core.runtime.SubProgressMonitor;
034:
035: public class ConnectionState extends Workflow.State {
036:
037: /** selected descriptor from previous page **/
038: UDIGConnectionFactoryDescriptor descriptor;
039:
040: /** the connection factory **/
041: ;
042: UDIGConnectionFactory factory;
043:
044: /** connection errors **/
045: Map<IService, Throwable> errors;
046:
047: /** list of services **/
048: Collection<IService> services;
049:
050: /** connection information **/
051: Map<String, Serializable> params;
052: List<URL> urls;
053:
054: private boolean validateServices;
055:
056: /**
057: * Create instance
058: * @param descriptor The connection factory descriptor to use in state
059: * @param validateServices indicates whether the service should be probed for its members and metadata.
060: */
061: public ConnectionState(UDIGConnectionFactoryDescriptor descriptor,
062: boolean validateServices) {
063: this .descriptor = descriptor;
064: factory = descriptor.getConnectionFactory();
065: this .validateServices = validateServices;
066: }
067:
068: @Override
069: public boolean run(IProgressMonitor monitor) throws IOException {
070: if (factory == null)
071: return false; //something went wrong, crap out
072: monitor.beginTask(Messages.ConnectionState_task,
073: IProgressMonitor.UNKNOWN);
074: errors = null;
075: try {
076: if (urls == null && params == null) {
077: //use the context object to try to build connection info
078: Object context = getWorkflow().getContext();
079:
080: params = factory.createConnectionParameters(context);
081: if (params != null && params.isEmpty())
082: params = null;
083: URL url = factory.createConnectionURL(context);
084: if (url != null) {
085: urls = new ArrayList<URL>();
086: urls.add(url);
087: }
088:
089: if (params == null && urls == null)
090: return false; //could not build connection info
091: }
092:
093: //use the parameters/url to acquire a set of services
094: IServiceFactory sFactory = CatalogPlugin.getDefault()
095: .getServiceFactory();
096: monitor.setTaskName(Messages.ConnectionState_task);
097:
098: if (urls != null) {
099: services = new HashSet<IService>();
100: for (URL url : urls) {
101: List<IService> service = searchLocalCatalog(url,
102: monitor);
103: if (service == null || service.isEmpty())
104: useServiceFactory(sFactory, url);
105: else
106: services.addAll(service);
107: }
108: } else {
109: List<IService> results = sFactory.acquire(params);
110: services = new HashSet<IService>();
111: for (IService service : results) {
112: List<IService> tmp = searchLocalCatalog(service
113: .getIdentifier(), monitor);
114: if (tmp == null || tmp.isEmpty()) {
115: services.add(service);
116: } else {
117: services.add(tmp.get(0));
118: }
119: }
120: }
121: } catch (Throwable t) {
122: CatalogPlugin.log(t.getLocalizedMessage(), t);
123: return false;
124: }
125:
126: try {
127: // make the connection, catch errors for post handling
128: errors = new HashMap<IService, Throwable>();
129: for (Iterator<IService> itr = services.iterator(); itr
130: .hasNext();) {
131: IService service = itr.next();
132: try {
133: SubProgressMonitor membersMonitor = new SubProgressMonitor(
134: monitor, 2);
135: monitor.setTaskName(MessageFormat.format(
136: Messages.ConnectionState_findLayers,
137: new Object[] { formatServiceID(service) }));
138: List<? extends IGeoResource> resources = service
139: .members(membersMonitor);
140:
141: if (true || !validateServices)
142: continue;
143: try {
144: SubProgressMonitor infoMonitor = new SubProgressMonitor(
145: monitor, 8);
146: try {
147: for (IGeoResource resource : resources) {
148: try {
149: monitor
150: .setTaskName(MessageFormat
151: .format(
152: Messages.ConnectionState_loadingLayer,
153: new Object[] { resource
154: .getIdentifier()
155: .getRef() }));
156: resource.getInfo(infoMonitor);
157: } catch (Exception e) {
158: CatalogUIPlugin.log("", e); //$NON-NLS-1$
159: }
160: }
161: } finally {
162: infoMonitor.done();
163: }
164:
165: } finally {
166: membersMonitor.done();
167: }
168: } catch (Throwable t) {
169: t.printStackTrace();
170: errors.put(service, t);
171: itr.remove();
172: }
173: }
174: if (!services.isEmpty()) {
175: return true;
176: }
177: } finally {
178: monitor.done();
179: }
180:
181: //even if errors occured, we are still done
182: // return true;
183: return errors == null || errors.isEmpty();
184: }
185:
186: private List<IService> searchLocalCatalog(URL url,
187: IProgressMonitor monitor) {
188: ICatalog localCatalog = CatalogPlugin.getDefault()
189: .getLocalCatalog();
190: List<IResolve> results = localCatalog.find(url, monitor);
191: List<IService> services = new ArrayList<IService>();
192: for (Iterator<IResolve> iter = results.iterator(); iter
193: .hasNext();) {
194: IResolve resolve = iter.next();
195: if (resolve instanceof IService)
196: services.add((IService) resolve);
197: }
198: if (results.isEmpty())
199: return null;
200: if (params != null) {
201: List<IService> matches = new ArrayList<IService>();
202: SERVICES: for (IService service : services) {
203:
204: Map<String, Serializable> connectionParams = service
205: .getConnectionParams();
206: if (params.size() != connectionParams.size())
207: continue SERVICES;
208:
209: Set<Entry<String, Serializable>> entries = connectionParams
210: .entrySet();
211: MAP_COMPARISION: for (Entry<String, Serializable> entry : entries) {
212: Serializable value = params.get(entry.getKey());
213: if (value == null) {
214: if (entry.getValue() == null)
215: continue MAP_COMPARISION;
216: else
217: continue SERVICES;
218: }
219: // permit more forgiving comparison of URLs.
220: if (value instanceof URL
221: || entry.getValue() instanceof URL) {
222: if (!(entry.getValue() instanceof URL)
223: || !(value instanceof URL))
224: continue SERVICES;
225:
226: if (!URLUtils.urlEquals((URL) value,
227: (URL) entry.getValue(), false))
228: continue SERVICES;
229: //TODO try to check IP in a non-blocking or quick manner.
230: } else if (!value.equals(entry.getValue())) {
231: continue SERVICES;
232: }
233:
234: }
235: }
236: return matches;
237: }
238: return services;
239: }
240:
241: private void useServiceFactory(IServiceFactory sFactory, URL url) {
242: if (params != null) {
243: services.addAll(sFactory.acquire(url, params));
244: } else
245: services.addAll(sFactory.acquire(url));
246: }
247:
248: private String formatServiceID(IService service) {
249: URL identifier = service.getIdentifier();
250: if ("file".equals(identifier.getProtocol())) { //$NON-NLS-1$
251: File file = new File(identifier.getFile());
252: return file.getName();
253: }
254: String host = identifier.getHost();
255: return host;
256: }
257:
258: @Override
259: public boolean hasNext() {
260: return errors != null && !errors.isEmpty();
261: }
262:
263: @Override
264: public State next() {
265: if (services.isEmpty())
266: return new ConnectionFailureState(urls, params);
267: //if errors occured, go a handling state, otherwise defer back to pipe
268: return null;
269: }
270:
271: public UDIGConnectionFactoryDescriptor getDescriptor() {
272: return descriptor;
273: }
274:
275: public UDIGConnectionFactory getConnectionFactory() {
276: return factory;
277: }
278:
279: public Collection<IService> getServices() {
280: return services;
281: }
282:
283: public void setParams(Map<String, Serializable> params) {
284: this .params = params;
285: }
286:
287: public void setURLs(List<URL> urls) {
288: this .urls = urls;
289: if (urls != null && urls.isEmpty())
290: this .urls = null;
291: }
292:
293: @Override
294: public String getName() {
295: return Messages.ConnectionState_name;
296: }
297:
298: public boolean isValidateState() {
299: return validateServices;
300: }
301:
302: public void setValidateState(boolean validateState) {
303: this .validateServices = validateState;
304: }
305:
306: public Map<IService, Throwable> getErrors() {
307: if (errors == null)
308: return Collections.emptyMap();
309: return errors;
310: }
311: }
|