001: /*
002: * uDig - User Friendly Desktop Internet GIS client http://udig.refractions.net (C) 2004,
003: * Refractions Research Inc. This library is free software; you can redistribute it and/or modify it
004: * under the terms of the GNU Lesser General Public License as published by the Free Software
005: * Foundation; version 2.1 of the License. This library is distributed in the hope that it will be
006: * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
007: * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
008: */
009: package net.refractions.udig.project.internal;
010:
011: import java.io.ByteArrayInputStream;
012: import java.io.ByteArrayOutputStream;
013: import java.io.File;
014: import java.io.Serializable;
015: import java.io.UnsupportedEncodingException;
016: import java.net.URL;
017: import java.net.URLDecoder;
018: import java.net.URLEncoder;
019: import java.util.Collections;
020: import java.util.HashMap;
021: import java.util.List;
022: import java.util.Map;
023:
024: import net.refractions.udig.catalog.CatalogPlugin;
025: import net.refractions.udig.catalog.ICatalog;
026: import net.refractions.udig.catalog.IGeoResource;
027: import net.refractions.udig.catalog.IService;
028: import net.refractions.udig.catalog.IServiceFactory;
029: import net.refractions.udig.catalog.ServiceParameterPersister;
030: import net.refractions.udig.project.internal.impl.LayerImpl;
031: import net.refractions.udig.ui.ProgressManager;
032:
033: import org.eclipse.core.runtime.Platform;
034: import org.eclipse.core.runtime.preferences.IEclipsePreferences;
035: import org.eclipse.core.runtime.preferences.IExportedPreferences;
036: import org.eclipse.core.runtime.preferences.IPreferencesService;
037: import org.eclipse.emf.common.util.URI;
038: import org.osgi.service.prefs.BackingStoreException;
039: import org.osgi.service.prefs.Preferences;
040:
041: /**
042: * Persists the connection parameters of the services that the resource needs for its resources.
043: * This is done so that if a map is sent to a friend the services can be created from the data provided by
044: * the map alone.
045: *
046: * @author Jesse
047: * @since 1.0.0
048: */
049: public class CatalogRef {
050: protected Layer layer;
051:
052: protected static final String ENCODING = ProjectPlugin.Implementation.ENCODING;
053:
054: private static final String ERROR_SAVING = "Error saving"; //$NON-NLS-1$
055:
056: private static final String REFERENCE_FILE = "PATH_OF_POINT_OF_REFERENCE";
057:
058: /**
059: * @uml.property name="connectionParams"
060: * @uml.associationEnd qualifier="key:java.lang.Object java.util.Map<String,Serializable>"
061: */
062: protected Map<URL, Map<String, Serializable>> connectionParams = Collections
063: .synchronizedMap(new HashMap<URL, Map<String, Serializable>>());
064:
065: private volatile boolean loaded = false;
066:
067: /**
068: * Construct <code>LayerRef</code>.
069: *
070: * @param layer
071: */
072: public CatalogRef(Layer layer) {
073: this .layer = layer;
074: }
075:
076: /**
077: * Construct <code>LayerRef</code>.
078: */
079: public CatalogRef() {
080: // do nothing
081: }
082:
083: /**
084: * @see java.lang.Object#toString()
085: */
086: public String toString() {
087: try {
088: List<IGeoResource> resources = layer.getGeoResources();
089: Preferences toSave = Platform.getPreferencesService()
090: .getRootNode().node(ProjectPlugin.ID).node(
091: layerIDToString());
092: if (resources != LayerImpl.NULL) {
093: connectionParams.clear();
094:
095: ServiceParameterPersister persister = new LayerCatalogRefPersister(
096: connectionParams, getMapFile());
097:
098: persister.store(ProgressManager.instance().get(),
099: toSave, resources);
100:
101: // Note: store clears the preferences so this has to be after store
102: String canonicalPath = getMapFile().getCanonicalPath();
103: String encode = URLEncoder.encode(canonicalPath,
104: ENCODING);
105: toSave.put(REFERENCE_FILE, encode);
106: }
107:
108: ByteArrayOutputStream out = new ByteArrayOutputStream();
109: Platform.getPreferencesService().exportPreferences(
110: (IEclipsePreferences) toSave, out, null);
111: toSave.clear();
112:
113: return URLEncoder.encode(out.toString(), ENCODING);
114: } catch (Throwable t) {
115: ProjectPlugin
116: .log(
117: "Error saving parameters for layer: " + (layer == null ? "unkown id" : layer.getID()) + " this map cannot be sent to a collegue", t); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
118: return ERROR_SAVING;
119: }
120: }
121:
122: private File getMapFile() {
123: return new File(layer.getMapInternal().eResource().getURI()
124: .toFileString());
125: }
126:
127: private String layerIDToString()
128: throws UnsupportedEncodingException {
129: if (layer != null && layer.getID() != null)
130: return URLEncoder
131: .encode(layer.getID().toString(), ENCODING);
132: else
133: return "ID_" + System.currentTimeMillis(); //$NON-NLS-1$
134: }
135:
136: /**
137: * Reaods the parameters for the resource's parameters from the string and stores them.
138: * Services aren't created until load() is called.
139: *
140: * @param string
141: */
142: public void parseResourceParameters(String string) {
143: if (string == null || string.length() == 0) {
144: return;
145: }
146: String decoded;
147: try {
148: decoded = URLDecoder.decode(string, ENCODING);
149: } catch (UnsupportedEncodingException e) {
150: decoded = string;
151: }
152:
153: ByteArrayInputStream input = new ByteArrayInputStream(decoded
154: .getBytes());
155: try {
156: IPreferencesService preferencesService = Platform
157: .getPreferencesService();
158: IExportedPreferences paramsNode = preferencesService
159: .readPreferences(input);
160:
161: String mapFile = findParameterNode(paramsNode).get(
162: REFERENCE_FILE, null);
163: File file = mapFile != null ? new File(URLDecoder.decode(
164: mapFile, ENCODING)) : null;
165:
166: ServiceParameterPersister persister = new LayerCatalogRefPersister(
167: connectionParams, file);
168:
169: persister.restore(findParameterNode(paramsNode));
170: } catch (Throwable e) {
171: // ok maybe it is an from an older version of uDig so try the oldCatalogRef
172: try {
173: OldCatalogRef old = new OldCatalogRef();
174: old.parseResourceParameters(string);
175: connectionParams = old.connectionParams;
176: } catch (Throwable e2) {
177: ProjectPlugin
178: .log(
179: "CatalogRef#parseResourceParameters, couldn't load paramters", e); //$NON-NLS-1$
180: }
181: }
182:
183: }
184:
185: private Preferences findParameterNode(
186: IExportedPreferences paramsNode)
187: throws BackingStoreException {
188: String[] name = paramsNode.childrenNames();
189:
190: Preferences plugin = paramsNode.node(name[0]);
191: name = plugin.childrenNames();
192:
193: return plugin.node(name[0]);
194: }
195:
196: /**
197: * @return Returns the layer.
198: * @uml.property name="layer"
199: */
200: public Layer getLayer() {
201: return layer;
202: }
203:
204: /**
205: * @param layer The layer to set.
206: * @uml.property name="layer"
207: */
208: public void setLayer(Layer layer) {
209: this .layer = layer;
210: }
211:
212: /**
213: * Adds the required services into the catalog.
214: */
215: public void load() {
216: ICatalog catalog = CatalogPlugin.getDefault().getLocalCatalog();
217: IServiceFactory serviceFactory = CatalogPlugin.getDefault()
218: .getServiceFactory();
219: synchronized (connectionParams) {
220: for (Map.Entry<URL, Map<String, Serializable>> entry : connectionParams
221: .entrySet()) {
222: if (catalog.getById(IService.class, entry.getKey(),
223: ProgressManager.instance().get()) == null) {
224: for (IService service : serviceFactory.acquire(
225: entry.getKey(), entry.getValue())) {
226: catalog.add(service);
227: }
228: }
229: }
230: }
231: loaded = true;
232: }
233:
234: /**
235: * Returns true if the required GeoResources have been added to the catalog.
236: *
237: * @return
238: * @uml.property name="loaded"
239: */
240: public boolean isLoaded() {
241: return loaded;
242: }
243:
244: private static class LayerCatalogRefPersister extends
245: ServiceParameterPersister {
246:
247: private Map<URL, Map<String, Serializable>> allParams;
248:
249: public LayerCatalogRefPersister(
250: Map<URL, Map<String, Serializable>> allParams,
251: File mapFile) {
252: super (CatalogPlugin.getDefault().getLocalCatalog(),
253: CatalogPlugin.getDefault().getServiceFactory(),
254: mapFile);
255: this .allParams = allParams;
256: }
257:
258: @Override
259: protected void locateService(URL url,
260: Map<String, Serializable> map) {
261: if (allParams.containsKey(url))
262: ProjectPlugin
263: .log("LayerCatalogRefPersister#locateService: duplicate resource ids when loading paramers"); //$NON-NLS-1$
264:
265: allParams.put(url, map);
266: }
267:
268: }
269: }
|