Revision 875

View differences:

org.gvsig.geotools.proj/trunk/org.gvsig.geotools.proj/org.gvsig.geotools.proj.esri/src/main/resources/META-INF/services/org.opengis.referencing.operation.CoordinateOperationAuthorityFactory
1
org.gvsig.geotools.proj.esri.ThreadedHsqlEsriFactory
2

  
org.gvsig.geotools.proj/trunk/org.gvsig.geotools.proj/org.gvsig.geotools.proj.esri/src/main/resources/META-INF/services/org.opengis.referencing.cs.CSAuthorityFactory
1
org.gvsig.geotools.proj.esri.ThreadedHsqlEsriFactory
2

  
org.gvsig.geotools.proj/trunk/org.gvsig.geotools.proj/org.gvsig.geotools.proj.esri/src/main/resources/META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory
1
org.gvsig.geotools.proj.esri.ThreadedHsqlEsriFactory
2

  
org.gvsig.geotools.proj/trunk/org.gvsig.geotools.proj/org.gvsig.geotools.proj.esri/src/main/resources/META-INF/services/org.opengis.referencing.datum.DatumAuthorityFactory
1
org.gvsig.geotools.proj.esri.ThreadedHsqlEsriFactory
2

  
org.gvsig.geotools.proj/trunk/org.gvsig.geotools.proj/org.gvsig.geotools.proj.esri/src/main/java/org/gvsig/geotools/proj/esri/EsriFactoryUsingHSQL.java
1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2018 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.geotools.proj.esri;
25

  
26
import java.sql.Connection;
27
import java.sql.PreparedStatement;
28
import java.sql.ResultSet;
29
import java.sql.SQLException;
30
import java.sql.Statement;
31
import java.text.ParseException;
32
import java.util.Hashtable;
33
import java.util.LinkedHashSet;
34
import java.util.Map;
35
import java.util.Set;
36
import java.util.regex.Matcher;
37
import java.util.regex.Pattern;
38
import javax.sql.DataSource;
39
import org.geotools.factory.Hints;
40
import org.geotools.metadata.iso.citation.Citations;
41
import org.geotools.referencing.factory.epsg.DirectEpsgFactory;
42
import org.geotools.referencing.factory.epsg.FactoryUsingAnsiSQL;
43
import org.geotools.referencing.wkt.Parser;
44
import org.geotools.resources.i18n.ErrorKeys;
45
import org.geotools.resources.i18n.Errors;
46
import org.opengis.metadata.citation.Citation;
47
import org.opengis.referencing.FactoryException;
48
import org.opengis.referencing.IdentifiedObject;
49
import org.opengis.referencing.NoSuchAuthorityCodeException;
50
import org.opengis.referencing.crs.CRSFactory;
51
import org.opengis.referencing.crs.CompoundCRS;
52
import org.opengis.referencing.crs.CoordinateReferenceSystem;
53
import org.opengis.referencing.crs.GeocentricCRS;
54
import org.opengis.referencing.crs.GeographicCRS;
55
import org.opengis.referencing.cs.CartesianCS;
56
import org.opengis.referencing.cs.CoordinateSystem;
57
import org.opengis.referencing.cs.EllipsoidalCS;
58
import org.opengis.referencing.cs.SphericalCS;
59
import org.opengis.referencing.cs.VerticalCS;
60
import org.opengis.referencing.datum.EngineeringDatum;
61
import org.opengis.referencing.datum.GeodeticDatum;
62
import org.opengis.referencing.datum.VerticalDatum;
63
import org.opengis.referencing.operation.Conversion;
64
import org.opengis.referencing.operation.CoordinateOperation;
65
import org.opengis.referencing.operation.Projection;
66

  
67
/**
68
 * A factory to retrieve and create CRSs from ESRI HSQL database.
69
 *
70
 * @author Cesar Martinez Izquierdo
71
 */
72
class EsriFactoryUsingHSQL extends DirectEpsgFactory {
73
	
74
    /** Cache of parsed CoordinateReferenceSystem WKT by ESRI_NUMBER */
75
    private Hashtable cache = new Hashtable();
76
    
77

  
78
    /** Constructs the factory for the given connection to the HSQL database. */
79
    public EsriFactoryUsingHSQL(final Hints hints, final Connection connection) {
80
        super(hints, connection);
81
    }
82

  
83
    public EsriFactoryUsingHSQL(final Hints hints, final DataSource dataSource) {
84
        super(hints, dataSource);
85
    }
86

  
87
    @Override
88
    public String adaptSQL(String query) {
89
        return query;
90
    }
91

  
92
    /**
93
     * Shutdown the HSQL database engine. This method is invoked automatically at JVM shutdown time
94
     * just before to close the connection.
95
     */
96
    protected void shutdown(final boolean active) throws SQLException {
97
        if (active) {
98
            final Statement statement = getConnection().createStatement();
99
            statement.execute("SHUTDOWN");
100
            statement.close();
101
        }
102
        super.shutdown(active);
103
    }
104
    
105
    @Override
106
    public Citation getAuthority() {
107
    	return Citations.ESRI;
108
    }
109
   
110
    @Override
111
	public synchronized CoordinateReferenceSystem createCoordinateReferenceSystem(String code) throws FactoryException {
112
		String wkt = null;
113
		String ESRI_NUMBER = code.substring(code.indexOf(":")+1, code.length());
114
		int cod = Integer.parseInt(ESRI_NUMBER);
115
        
116
		if( cache.contains( ESRI_NUMBER ) ){
117
            Object value = cache.get( ESRI_NUMBER );
118
            if( value instanceof Throwable ){
119
                throw new FactoryException( "WKT for "+code+" could not be parsed", (Throwable) value );
120
            }
121
            if( value instanceof CoordinateReferenceSystem){
122
                return (CoordinateReferenceSystem) value;
123
            }
124
        }
125
		ResultSet result = null;
126
		
127
		try {
128
        	 
129
            String sentence = "SELECT ESRI_WKT"
130
            + " FROM ESRI"
131
            + " WHERE ESRI_CODE = ?";
132
            
133
            String codeStr = code.substring(code.indexOf(":")+1, code.length());
134
            int codeInt = Integer.parseInt(codeStr);
135
        
136
        	PreparedStatement st = null;
137
        	st = getConnection().prepareStatement(sentence);
138
        	st.setInt(1, codeInt);
139
			result = st.executeQuery();
140
			st.close();
141
        	if (result.next()) {
142
                wkt    = result.getString("esri_wkt");
143
                if( wkt.indexOf( cod ) == -1){
144
                	wkt = wkt.trim();
145
                	wkt = wkt.substring(0, wkt.length()-1 );
146
                	wkt += ",AUTHORITY[\"ESRI\",\""+cod+"\"]]";
147
                }
148
                Parser parser = new Parser();
149
                return parser.parseCoordinateReferenceSystem(wkt);
150
            }
151
        } catch (SQLException exception) {
152
        	throw new FactoryException(exception);
153
        } catch (ParseException exception) {
154
        	throw new FactoryException(exception);
155
        } finally {
156
        	if (result!=null) {
157
        		try {
158
					result.close();
159
				} catch (SQLException e) {}
160
        	}
161
        };
162
        throw new NoSuchAuthorityCodeException("No such authority code", "ESRI", code);
163
	}
164
    
165
    @Override
166
    public Set<String> getAuthorityCodes(Class<? extends IdentifiedObject> type) throws FactoryException {
167
    	LinkedHashSet<String> codes = new LinkedHashSet<String>(); 
168
		ResultSet result = null;
169
		try {
170
        	 
171
            String sentence = "SELECT ESRI_CODE"
172
            + " FROM ESRI ORDER BY ESRI_CODE ASC";
173
            
174
        	Statement st = null;
175
        	st = getConnection().createStatement();
176
        	result = st.executeQuery(sentence);
177
			st.close();
178
        	while (result.next()) {
179
                int code = result.getInt(1);
180
                codes.add(Integer.toString(code));
181
            }
182
        } catch (SQLException exception) {
183
        	throw new FactoryException(exception);
184
        } finally {
185
        	if (result!=null) {
186
        		try {
187
					result.close();
188
				} catch (SQLException e) {}
189
        	}
190
        };
191
    	return codes;
192
    }
193
}
org.gvsig.geotools.proj/trunk/org.gvsig.geotools.proj/org.gvsig.geotools.proj.esri/src/main/java/org/gvsig/geotools/proj/esri/ThreadedHsqlEsriFactory.java
1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2018 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 *
24
 * This class is based on ThreadedEpsgFactory class from Geotools project.
25
 * 
26
 *    GeoTools - The Open Source Java GIS Toolkit
27
 *    http://geotools.org
28
 *
29
 *    (C) 2005-2008, Open Source Geospatial Foundation (OSGeo)
30
 *
31
 *    This library is free software; you can redistribute it and/or
32
 *    modify it under the terms of the GNU Lesser General Public
33
 *    License as published by the Free Software Foundation;
34
 *    version 2.1 of the License.
35
 *
36
 *    This library is distributed in the hope that it will be useful,
37
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
38
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
39
 *    Lesser General Public License for more details.
40
 */
41
package org.gvsig.geotools.proj.esri;
42

  
43
import java.io.File;
44
import java.io.FileOutputStream;
45
import java.io.IOException;
46
import java.io.InputStream;
47
import java.io.RandomAccessFile;
48
import java.nio.channels.FileChannel;
49
import java.nio.channels.FileLock;
50
import java.nio.channels.OverlappingFileLockException;
51
import java.sql.SQLException;
52
import java.util.logging.Level;
53
import java.util.logging.LogRecord;
54
import java.util.logging.Logger;
55
import java.util.zip.ZipEntry;
56
import java.util.zip.ZipInputStream;
57

  
58
import javax.naming.InitialContext;
59
import javax.naming.NamingException;
60
import javax.naming.NoInitialContextException;
61
import javax.sql.DataSource;
62

  
63
import org.geotools.factory.GeoTools;
64
import org.geotools.factory.Hints;
65
import org.geotools.metadata.iso.citation.Citations;
66
import org.geotools.referencing.factory.AbstractAuthorityFactory;
67
import org.geotools.referencing.factory.epsg.ThreadedEpsgFactory;
68
import org.geotools.resources.i18n.ErrorKeys;
69
import org.geotools.resources.i18n.Errors;
70
import org.geotools.resources.i18n.LoggingKeys;
71
import org.geotools.resources.i18n.Loggings;
72
import org.geotools.util.Version;
73
import org.geotools.util.logging.Logging;
74
import org.gvsig.proj.catalog.CRSCatalogLibrary;
75
import org.gvsig.proj.catalog.CRSCatalogLocator;
76
import org.hsqldb.jdbc.JDBCDataSource;
77
import org.opengis.metadata.citation.Citation;
78

  
79
/**
80
 * Connection to the ESRI database in HSQL database engine format using JDBC. The ESRI database
81
 * has been obtained from the gvSIG JCRS library. The SQL scripts are bundled
82
 * into this plugin. The database version is given in the {@linkplain
83
 * org.opengis.metadata.citation.Citation#getEdition edition attribute} of the {@linkplain
84
 * org.opengis.referencing.AuthorityFactory#getAuthority authority}. The HSQL database is read only.
85
 *
86
 * <p>
87
 *
88
 * <H3>Implementation note</H3>
89
 *
90
 * The SQL scripts are executed the first time a connection is required. The database is then
91
 * created as cached tables ({@code HSQL.properties} and {@code HSQL.data} files) in a temporary
92
 * directory. Future connections to the ESRI database while reuse the cached tables, if available.
93
 * Otherwise, the scripts will be executed again in order to recreate them.
94
 *
95
 * <p>If the ESRI database should be created in a different directory (or already exists in that
96
 * directory), it may be specified as a {@linkplain System#getProperty(String) system property}
97
 * nammed {@value #DIRECTORY_KEY}.
98
 *
99
 * @author Cesar Martinez Izquierdo, based on ThreadedEpsgFactory
100
 */
101
public class ThreadedHsqlEsriFactory extends ThreadedEpsgFactory {
102
    /**
103
     * Current version of ESRI definitions plugin.
104
     */
105
    public static final Version VERSION = new Version("1.0jcrs");
106

  
107
    /**
108
     * The key for fetching the database directory from {@linkplain System#getProperty(String)
109
     * system properties}.
110
     */
111
    public static final String DIRECTORY_KEY = "ESRI-HSQL.directory";
112

  
113
    /** The name of the ZIP file to read in order to create the cached database. */
114
    private static final String ZIP_FILE = "ESRI.zip";
115

  
116
    /** The database name. */
117
    public static final String DATABASE_NAME = "ESRI";
118

  
119
    /** The successful database creation marker */
120
    static final String MARKER_FILE = "ESRI_creation_marker.txt";
121

  
122
    /** The database creation lock file */
123
    static final String LOCK_FILE = "ESRI_creation_lock.txt";
124

  
125
    /** The prefix to put in front of URL to the database. */
126
    static final String PREFIX = "jdbc:hsqldb:file:";
127

  
128
    /** The logger name. */
129
    static final String LOGGER = "org.gvsig.geotools.proj.esri";
130
    
131
    /** The default priority level for this factory. */
132
    static final int PRIORITY = MAXIMUM_PRIORITY - 10;
133

  
134
    /**
135
     * Creates a new instance of this factory. If the {@value #DIRECTORY_KEY} {@linkplain
136
     * System#getProperty(String) system property} is defined and contains the name of a directory
137
     * with a valid {@linkplain File#getParent parent}, then the {@value #DATABASE_NAME} database
138
     * will be saved in that directory. Otherwise, a temporary directory will be used.
139
     */
140
    public ThreadedHsqlEsriFactory() {
141
        this(null);
142
    }
143
    
144

  
145
    /**
146
     * Returns the authority for this EPSG database. This authority will contains the database
147
     * version in the {@linkplain Citation#getEdition edition} attribute, together with the
148
     * {@linkplain Citation#getEditionDate edition date}.
149
     */
150
    @Override
151
    public Citation getAuthority() {
152
        return Citations.ESRI;
153
    }
154

  
155
    /**
156
     * Creates a new instance of this data source using the specified hints. The priority is set to
157
     * a lower value than the {@linkplain FactoryOnAccess}'s one in order to give precedence to the
158
     * Access-backed database, if presents. Priorities are set that way because:
159
     *
160
     * <ul>
161
     *   <li>The MS-Access format is the primary EPSG database format.
162
     *   <li>If a user downloads the MS-Access database himself, he probably wants to use it.
163
     * </ul>
164
     */
165
    public ThreadedHsqlEsriFactory(final Hints hints) {
166
        super(hints, PRIORITY + 1);
167
    }
168

  
169
    /**
170
     * Returns the default directory for the EPSG database. If the {@value #DIRECTORY_KEY}
171
     * {@linkplain System#getProperty(String) system property} is defined and contains the name of a
172
     * directory with a valid {@linkplain File#getParent parent}, then the {@value #DATABASE_NAME}
173
     * database will be saved in that directory. Otherwise, a temporary directory will be used.
174
     */
175
    private static File getDirectory() {
176
        try {
177
        	final File directory = CRSCatalogLocator.getManager().getSystemDataPath();
178
        	if (directory != null && (directory.isDirectory() || directory.mkdir())) {
179
                return directory;
180
            }
181
        } catch (SecurityException e) {
182
            /*
183
             * Can't fetch the base directory from system properties.
184
             * Fallback on the default temporary directory.
185
             */
186
        }
187
        return new File(getTemporaryDirectory(), DATABASE_NAME + File.separator + "v" + VERSION);
188
    }
189

  
190
    /** Returns the directory to use in the temporary directory folder. */
191
    private static File getTemporaryDirectory() {
192
        File directory = new File(System.getProperty("java.io.tmpdir", "."), "GeoTools");
193
        if (directory.isDirectory() || directory.mkdir()) {
194
            directory = new File(directory, "Databases/HSQL");
195
            if (directory.isDirectory() || directory.mkdirs()) {
196
                return directory;
197
            }
198
        }
199
        return null;
200
    }
201

  
202
    /**
203
     * Extract the directory from the specified data source, or {@code null} if this information is
204
     * not available.
205
     */
206
    private static File getDirectory(final DataSource source) {
207
        if (source instanceof JDBCDataSource) {
208
            String path = ((JDBCDataSource) source).getDatabase();
209
            if (path != null && PREFIX.regionMatches(true, 0, path, 0, PREFIX.length())) {
210
                path = path.substring(PREFIX.length());
211
                return new File(path).getParentFile();
212
            }
213
        }
214
        return null;
215
    }
216

  
217
    /** Returns a data source for the HSQL database. */
218
    protected DataSource createDataSource() throws SQLException {
219
        final Logger logger = Logging.getLogger(LOGGER);
220
        logger.log(Level.FINE, "Building new data source for " + getClass().getName());
221

  
222
        final JDBCDataSource source = new JDBCDataSource();
223
        File directory = getDirectory();
224
        if (directory != null) {
225
            /*
226
             * Constructs the full path to the HSQL database. Note: we do not use
227
             * File.toURI() because HSQL doesn't seem to expect an encoded URL
228
             * (e.g. "%20" instead of spaces).
229
             */
230
            final StringBuilder url = new StringBuilder(PREFIX);
231
            final String path = directory.getAbsolutePath().replace(File.separatorChar, '/');
232
            if (path.length() == 0 || path.charAt(0) != '/') {
233
                url.append('/');
234
            }
235
            url.append(path);
236
            if (url.charAt(url.length() - 1) != '/') {
237
                url.append('/');
238
            }
239
            url.append(DATABASE_NAME);
240
            url.append(";shutdown=true;readonly=true");
241
            //url.append(";shutdown=true");
242
            source.setDatabase(url.toString());
243
        }
244
        /*
245
         * If the temporary directory do not exists or can't be created, lets the 'database'
246
         * attribute unset. If the user do not set it explicitly (through JNDI or by overrding
247
         * this method), an exception will be thrown when 'createBackingStore()' will be invoked.
248
         */
249
        source.setUser("SA"); // System administrator. No password.
250
        source.setPassword("");
251
        return source;
252
    }
253

  
254
    /**
255
     * Returns {@code true} if the database contains data. This method returns {@code false} if an
256
     * empty EPSG database has been automatically created by HSQL and not yet populated.
257
     */
258
    private static boolean dataExists(File directory) throws SQLException {
259
        // check if the marker file is there, and all the other database files as well
260
        // (as some windows cleanup tools delete the .data file only)
261
        return new File(directory, MARKER_FILE).exists()
262
                //&& new File(directory, DATABASE_NAME + ".data").exists()
263
                && new File(directory, DATABASE_NAME + ".properties").exists()
264
                && new File(directory, DATABASE_NAME + ".script").exists();
265
    }
266

  
267
    /**
268
     * Returns the backing-store factory for HSQL syntax. If the cached tables are not available,
269
     * they will be created now from the SQL scripts bundled in this plugin.
270
     *
271
     * @param hints A map of hints, including the low-level factories to use for CRS creation.
272
     * @return The EPSG factory using HSQL syntax.
273
     * @throws SQLException if connection to the database failed.
274
     */
275
    protected AbstractAuthorityFactory createBackingStore(final Hints hints) throws SQLException {
276
        final Logger logger = Logging.getLogger(LOGGER);
277
        logger.log(Level.FINE, "Building backing store for " + getClass().getName());
278

  
279
        final DataSource source = getDataSource();
280
        final File directory = getDirectory(source);
281
        directory.mkdirs();
282
        if (!dataExists(directory)) {
283
            FileLock lock = null;
284
            try {
285
                // get an exclusive lock
286
                lock = acquireLock(directory);
287

  
288
                // if after getting the lock the database is still incomplete let's work on it
289
                if (!dataExists(directory)) {
290
                    /*
291
                     * HSQL has created automatically an empty database. We need to populate it.
292
                     * Executes the SQL scripts bundled in the JAR. In theory, each line contains
293
                     * a full SQL statement. For this plugin however, we have compressed "INSERT
294
                     * INTO" statements using Compactor class in this package.
295
                     */
296
                    final LogRecord record =
297
                            Loggings.format(
298
                                    Level.FINE,
299
                                    LoggingKeys.CREATING_CACHED_EPSG_DATABASE_$1,
300
                                    VERSION);
301
                    record.setLoggerName(logger.getName());
302
                    logger.log(record);
303

  
304
                    InputStream in = ThreadedHsqlEsriFactory.class.getResourceAsStream(ZIP_FILE);
305
                    ZipInputStream zin =
306
                            new ZipInputStream(in);
307
                    ZipEntry ze = null;
308
                    byte[] buf = new byte[1024];
309
                    int read = 0;
310
                    while ((ze = zin.getNextEntry()) != null) {
311
                        FileOutputStream fout =
312
                                new FileOutputStream(new File(directory, ze.getName()));
313
                        while ((read = zin.read(buf)) > 0) {
314
                            fout.write(buf, 0, read);
315
                        }
316
                        zin.closeEntry();
317
                        fout.close();
318
                    }
319
                    zin.close();
320

  
321
                    // mark the successful creation
322
                    new File(directory, MARKER_FILE).createNewFile();
323
                }
324
            } catch (IOException exception) {
325
                SQLException e = new SQLException(Errors.format(ErrorKeys.CANT_READ_$1, ZIP_FILE));
326
                e.initCause(
327
                        exception); // TODO: inline cause when we will be allowed to target Java 6.
328
                throw e;
329
            } catch (Exception exc) {
330
            	exc.printStackTrace();
331
            	
332
            }
333
            finally {
334
                if (lock != null) {
335
                    try {
336
                        lock.release();
337
                        lock.channel().close();
338
                        new File(directory, LOCK_FILE).delete();
339
                    } catch (IOException e) {
340
                        // does not matter, was just cleanup
341
                    }
342
                }
343
            }
344
        }
345
        EsriFactoryUsingHSQL factory =
346
                new EsriFactoryUsingHSQL(hints, getDataSource()) {
347
                    @Override
348
                    protected void shutdown(boolean active) throws SQLException {
349
                        // Disabled because finalizer shutdown causes concurrent EPSG lookup via
350
                        // other FactoryUsingHSQL instances using the same database URL and thus
351
                        // the same org.hsqldb.Database instance to fail in, for example,
352
                        // GeoServer gs-main unit tests.
353
                        // Note that createDataSource() opens the database with "shutdown=true"
354
                        // so the database will be shutdown when the last session is closed.
355
                    }
356
                };
357
        factory.setValidationQuery("CALL NOW()");
358
        return factory;
359
    }
360

  
361
    /**
362
     * @param directory
363
     * @return
364
     * @throws IOException
365
     */
366
    FileLock acquireLock(File directory) throws IOException {
367
        // Get a file channel for the file
368
        File file = new File(directory, LOCK_FILE);
369
        FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
370

  
371
        // Use the file channel to create a lock on the file.
372
        // This method blocks until it can retrieve the lock.
373
        FileLock lock = channel.lock();
374

  
375
        // Try acquiring the lock without blocking. This method returns
376
        // null or throws an exception if the file is already locked.
377
        while (!lock.isValid()) {
378
            try {
379
                lock = channel.tryLock();
380
            } catch (OverlappingFileLockException e) {
381
                // File is already locked in this thread or virtual machine
382
            }
383
            // wait for the other process to unlock it, should take a couple of seconds
384
            try {
385
                Thread.sleep(500);
386
            } catch (InterruptedException e) {
387
                // someone waked us earlier, no problem
388
            }
389
        }
390

  
391
        return lock;
392
    }
393
}
org.gvsig.geotools.proj/trunk/org.gvsig.geotools.proj/org.gvsig.geotools.proj.esri/pom.xml
1
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
3
  <modelVersion>4.0.0</modelVersion>
4
  <groupId>org.gvsig</groupId>
5
  <artifactId>org.gvsig.geotools.proj.esri</artifactId>
6
  <packaging>jar</packaging>
7
  <version>1.0.0</version>
8
  <name>${project.artifactId}</name>
9
  <parent>
10
    <groupId>org.gvsig</groupId>
11
    <artifactId>org.gvsig.geotools.proj</artifactId>
12
    <version>1.0.0-SNAPSHOT</version>
13
  </parent>
14
  <description>Esri definitions and geotools plugin to register ESRI authority</description>
15
  <organization>
16
    <name>gvSIG Association</name>
17
    <url>http://www.gvsig.com/</url>
18
  </organization>
19
  <url>http://devel.gvsig.org/sites/${project.artifactId}/${project.version}</url>
20
  <dependencies>
21
    <dependency>
22
      <groupId>org.geotools</groupId>
23
      <artifactId>gt-referencing</artifactId>
24
    </dependency>
25
    <dependency>
26
      <groupId>org.geotools</groupId>
27
      <artifactId>gt-epsg-hsql</artifactId>
28
    </dependency>
29
    <dependency>
30
      <groupId>org.hsqldb</groupId>
31
      <artifactId>hsqldb</artifactId>
32
    </dependency>
33
    <dependency>
34
      <groupId>org.slf4j</groupId>
35
      <artifactId>slf4j-api</artifactId>
36
    </dependency>
37
    <dependency>
38
      <groupId>org.slf4j</groupId>
39
      <artifactId>slf4j-api</artifactId>
40
    </dependency>
41
    <dependency>
42
      <groupId>org.gvsig</groupId>
43
      <artifactId>org.gvsig.proj.catalog.api</artifactId>
44
    </dependency>
45
  </dependencies>
46
</project>
org.gvsig.geotools.proj/trunk/org.gvsig.geotools.proj/pom.xml
213 213
            </dependency>
214 214
        	<dependency>
215 215
            	<groupId>org.gvsig</groupId>
216
            	<artifactId>org.gvsig.geotools.proj.esri</artifactId>
217
                <version>1.0.0</version>
218
            	<type>jar</type>
219
        	</dependency>
220
        	<dependency>
221
            	<groupId>org.gvsig</groupId>
216 222
            	<artifactId>org.gvsig.geotools.proj.epsggriddata</artifactId>
217 223
                <version>1.0.0</version>
218 224
            	<type>jar</type>
219 225
        	</dependency>
220 226
            <!-- external -->
221 227
            <dependency>
228
                <groupId>org.slf4j</groupId>
229
                <artifactId>slf4j-api</artifactId>
230
                <version>1.5.5</version>
231
            </dependency>
232
            <dependency>
222 233
                <groupId>org.geotools</groupId>
223 234
                <artifactId>gt-referencing</artifactId>
224 235
                <version>${geotools.version}</version>
......
233 244
                <artifactId>gt-epsg-extension</artifactId>
234 245
                <version>${geotools.version}</version>
235 246
            </dependency>
247
			<dependency>
248
				<groupId>org.hsqldb</groupId>
249
				<artifactId>hsqldb</artifactId>
250
				<version>2.4.1</version>
251
			</dependency>
236 252

  
237 253
            <!-- submodules -->
238 254
            <dependency>
......
412 428
        <module>org.gvsig.geotools.proj.app</module>
413 429
        <module>org.gvsig.geotools.proj.catalog.app</module>
414 430
        <module>org.gvsig.geotools.proj.main</module>
431
        <module>org.gvsig.geotools.proj.esri</module>
432
        <module>org.gvsig.geotools.proj.epsggriddata</module>
415 433
    </modules>
416 434
</project>
org.gvsig.geotools.proj/trunk/org.gvsig.geotools.proj/org.gvsig.geotools.proj.main/src/main/java/org/gvsig/geotools/proj/main/TestCtPanel.java
69 69

  
70 70
			SwingUtilities.invokeLater(new Runnable() {
71 71
				public void run() {
72
					CoordinateTransformationSelectorComponent selector = manager.createCoordinateTransformSelectionComponent();
72
					CoordinateTransformationSelectorComponent selector = manager.createCoordinateTransformSelectorComponent();
73 73
					selector.setCoordinateTransformation(aTrans);
74
					//DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) ((CtSelectorController) selector).getTree().getCellRenderer();
75
					//Color c = renderer.getBackgroundSelectionColor();
76
					//renderer.setBackgroundSelectionColor(Color.BLUE);
77
					//renderer.setBackground(Color.YELLOW);
78
					selector.setSourceCoordinateReferenceSystem(crs23030);
79
					//selector.setTargetCoordinateReferenceSystem(crs4326);
74
					selector.setSourceCoordinateReferenceSystem(crs23030, true);
75
					selector.setTargetCoordinateReferenceSystem(crs4326, true);
80 76

  
81 77
					frame.add(selector.asJComponent());
82 78
					frame.setSize(400, 600);
org.gvsig.geotools.proj/trunk/org.gvsig.geotools.proj/org.gvsig.geotools.proj.main/src/main/java/org/gvsig/geotools/proj/main/TestCrsPanel.java
41 41
		
42 42
		try {
43 43
		DefaultCoordinateReferenceSystemSwingManager manager = (DefaultCoordinateReferenceSystemSwingManager) CoordinateReferenceSystemSwingLocator.getSwingManager();
44
		//INSERT INTO ESRI VALUES(103952,'PROJCS["NAD_1983_HARN_Adj_WI_GreenLake_Feet",GEOGCS["GCS_NAD_1983_HARN_Adj_WI_GreenLake",DATUM["D_NAD_1983_HARN_Adj_WI_GL_MQ",SPHEROID["GRS_1980_Adj_WI_GL_MQ",6378375.601,298.268379664173]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",495000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-89.24166666666667],PARAMETER["Standard_Parallel_1",43.66666666666666],PARAMETER["Standard_Parallel_2",43.94722222222222],PARAMETER["Latitude_Of_Origin",43.09444444444445],UNIT["Foot_US",0.3048006096012192]]','NAD_1983_HARN_Adj_WI_GreenLake_Feet','GCS_NAD_1983_HARN_Adj_WI_GreenLake','D_NAD_1983_HARN_Adj_WI_GL_MQ')
45
		manager.getCatalogManager().getCRSDefinition("ESRI:103952");
46
		
47
//		INSERT INTO ESRI VALUES(30179,'PROJCS["Japan_Zone_19",GEOGCS["GCS_Tokyo",DATUM["D_Tokyo",SPHEROID["Bessel_1841",6377397.155,299.15281
48
//				28]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],PARAMETER["False_Easting",0.0],PARA
49
//				METER["False_Northing",0.0],PARAMETER["Central_Meridian",154.0],PARAMETER["Scale_Factor",0.9999],PARAMETER["Latitude_Of_Origin",26.0]
50
//				,UNIT["Meter",1.0]]','Japan_Zone_19','GCS_Tokyo','D_Tokyo')
51
		manager.getCatalogManager().getCRSDefinition("ESRI:30179");
52
		//INSERT INTO ESRI VALUES(4326,'GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]]','','GCS_WGS_1984','D_WGS_1984')
53
		manager.getCatalogManager().getCRSDefinition("ESRI:4326");
54
		
44 55
		manager.getCoordinateReferenceSystemHistory().add(manager.getCatalogManager().getCRSDefinition("EPSG:3857"));
45 56
		manager.getCoordinateReferenceSystemHistory().add(manager.getCatalogManager().getCRSDefinition("EPSG:23030"));
46 57
		
47
		CoordinateReferenceSystemSelectorComponent selector = manager.createCoordinateReferenceSystemSelectionComponent();
58
		CoordinateReferenceSystemSelectorComponent selector = manager.createCoordinateReferenceSystemSelectorComponent();
48 59
		selector.setCustomGroupLabel("Layer");
49 60
		
50 61
		selector.addCustomCRS(manager.getCatalogManager().getCRSDefinition("EPSG:25830"));
org.gvsig.geotools.proj/trunk/org.gvsig.geotools.proj/org.gvsig.geotools.proj.main/pom.xml
62 62
    </dependency>
63 63
    <dependency>
64 64
      <groupId>org.gvsig</groupId>
65
      <artifactId>org.gvsig.i18n</artifactId>
66
      <scope>runtime</scope>
67
    </dependency>
68
    <dependency>
69
      <groupId>org.gvsig</groupId>
65 70
      <artifactId>org.gvsig.geotools.proj.catalog.impl</artifactId>
66 71
      <scope>compile</scope>
67 72
    </dependency>
......
82 87
    </dependency>
83 88
    <dependency>
84 89
      <groupId>org.gvsig</groupId>
90
      <artifactId>org.gvsig.geotools.proj.esri</artifactId>
91
      <type>jar</type>
92
    </dependency>
93
    <dependency>
94
      <groupId>org.gvsig</groupId>
85 95
      <artifactId>org.gvsig.geotools.proj.epsggriddata</artifactId>
86 96
      <type>jar</type>
87 97
    </dependency>
org.gvsig.geotools.proj/trunk/org.gvsig.geotools.proj/org.gvsig.geotools.proj.catalog.impl/src/main/java/org/gvsig/geotools/proj/catalog/GtCRSCatalogManager.java
1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2018 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
1 24
package org.gvsig.geotools.proj.catalog;
2 25

  
3 26
import java.io.File;
......
75 98
import org.opengis.referencing.operation.MathTransform;
76 99
import org.opengis.referencing.operation.Projection;
77 100

  
101
/**
102
 * Implementation of CRSCatalogManager based on Geotools
103
 * 
104
 * @author Cesar Martinez Izquierdo
105
 *
106
 */
78 107
public class GtCRSCatalogManager implements CRSCatalogManager {
79 108
	private static final String EPSG_DB_SUBFOLDER = "epsg";	
80 109
	private static final List<TextSerialization.Format> SUPPORTED_FORMATS = Arrays.asList(TextSerialization.Format.WKT1);
......
134 163

  
135 164
	@Override
136 165
	public List<String> search(String searchString) {
137
		// FIXME handle other authorities
138
		return searchEpsg(searchString, null, null);
166
		
167
		ArrayList<String> result = new ArrayList<String>();
168
		for (String auth: getAuthorityNames()) {
169
			List<String> authResult = search(auth, searchString, null, null);
170
			result.addAll(authResult);
171
		}
172
		return result;
139 173
	}
140 174

  
141 175
	@Override
142 176
	public List<String> search(String authority, String searchString) {
143 177
		// FIXME handle other authorities
144
		if (authority.equals("EPSG")) {
145
			return searchEpsg(searchString, null, null);
178
		if ("EPSG".equals(authority) || "ESRI".equals(authority)) {
179
		
180
			return search(authority, searchString, null, null);
146 181
		}
147 182
		return Collections.emptyList();
148 183
	}
......
150 185
	@Override
151 186
	public List<String> search(String authority, String searchString, CRSType[] includeTypes, CRSType[] excludeTypes) {
152 187
		// FIXME handle other authorities
153
		if (authority.equals("EPSG")) {
154
			return searchEpsg(searchString, includeTypes, excludeTypes);
188
		if ("EPSG".equals(authority) || "ESRI".equals(authority)) {
189
			CRSAuthorityFactory factory = ReferencingFactoryFinder.getCRSAuthorityFactory(authority, null);
190
			if (factory instanceof ThreadedEpsgFactory) {
191
				ThreadedEpsgFactory epsgFactory = (ThreadedEpsgFactory) factory;
192
				try {
193
					DataSource ds = epsgFactory.getDataSource();
194
					Connection c = ds.getConnection();
195
					if ("EPSG".equals(authority)) {
196
						return searchEpsg(searchString, c, includeTypes, excludeTypes);
197
					}
198
					if ("ESRI".equals(authority)) {
199
						return searchEsri(searchString, c, includeTypes, excludeTypes);
200
					}
201
				} catch (SQLException e) {
202
					// TODO Auto-generated catch block
203
					e.printStackTrace();
204
				}
205
			}
155 206
		}
156 207
		return Collections.emptyList();
157 208
	}
158 209

  
159
	
160
	protected List<String> searchEpsg(String searchString, CRSType[] includeTypes, CRSType[] excludeTypes) {
161
		// FIXME handle other authorities
162
		CRSAuthorityFactory factory = ReferencingFactoryFinder.getCRSAuthorityFactory("EPSG", null);
163
		if (factory instanceof ThreadedEpsgFactory) {
164
			ThreadedEpsgFactory epsgFactory = (ThreadedEpsgFactory) factory;
165
			try {
166
				DataSource ds = epsgFactory.getDataSource();
167
				Connection c = ds.getConnection();
168
				return searchEpsg(searchString, c, includeTypes, excludeTypes);
169
			} catch (SQLException e) {
170
				// TODO Auto-generated catch block
171
				e.printStackTrace();
172
			}
173
		}
174
		return Collections.EMPTY_LIST;
175
	}
176
	
177 210
	private boolean isExcluded(CRSType type,  CRSType[] excludeTypes) {
178 211
		for (CRSType excluded: excludeTypes) {
179 212
			if (type.equals(excluded)) {
......
275 308
        conn.close();
276 309
        return codes;
277 310
    }
311
    
312
	
313
    public synchronized List<String> searchEsri(String searchString, Connection conn,
314
    		CRSType[] includeTypes, CRSType[] excludeTypes) throws SQLException
315
    {
316
    	ArrayList<String> codes = new ArrayList<String>();
317
    	
318
    	if (searchString == null) {
319
    		searchString = "";
320
    	}
321
    	else if (searchString.startsWith("ESRI:")) {
322
    		searchString = searchString.substring(5);
323
    	}
324
    	StringBuilder builder = new StringBuilder("SELECT ESRI_CODE"
325
                + " FROM ESRI WHERE (");
326
    	int codeInt = -1;
327
    	try {
328
    		codeInt = Integer.parseInt(searchString);
329
    		builder.append(" ESRI_CODE = ? OR");
330
    	}
331
    	catch (NumberFormatException exc) {}
332
    	
333
    	builder.append(" LCASE(ESRI_PROJ) LIKE ? OR LCASE(ESRI_DATUM) LIKE ?"
334
                + " OR LCASE(ESRI_WKT) LIKE ? )");
278 335

  
336
    	
337
    	if (includeTypes != null && includeTypes.length>0) {
338
    		boolean first = true;
339
    		for (CRSType type: includeTypes) {
340
    			String typeCondition = getEsriTypeSqlString(type);
341
    			if (typeCondition != null) {
342
    				if (first) {
343
    					first = false;
344
    					builder.append(" AND (").append(typeCondition);
345
    				}
346
    				else {
347
    					builder.append(" OR ").append(typeCondition);
348
    				}
349
    			}
350
    		}
351
    		if (!first) {
352
    			builder.append(")");
353
    		}
354
    	}
355
    	if (excludeTypes != null && excludeTypes.length>0) {
356
    		boolean first = true;
357
    		for (CRSType type: excludeTypes) {
358
    			String typeCondition = getEsriTypeSqlString(type);
359
    			if (typeCondition != null) {
360
    				if (first) {
361
    					first = false;
362
    					builder.append(" AND NOT (").append(typeCondition);
363
    				}
364
    				else {
365
    					builder.append(" OR ").append(typeCondition);
366
    				}
367
    			}
368
    		}
369
    		if (!first) {
370
    			builder.append(")");
371
    		}
372
    	}
373
    		
374
        try {
375
            // FIXME: JOIN query with area of use. Maybe also with  COORD_SYS_CODE to search for coord sys name
376
        	searchString = "%" + searchString.toLowerCase() + "%";
377
            final PreparedStatement stmt = conn.prepareStatement(builder.toString());
378
            int paramNum = 1;
379
            if (codeInt>=0) {
380
            	stmt.setInt(paramNum++, codeInt);
381
            }
382
            stmt.setString(paramNum++, searchString);
383
            stmt.setString(paramNum++, searchString);
384
            stmt.setString(paramNum++, searchString);
385
            
386
            ResultSet result = stmt.executeQuery();
387
            while (result.next()) {
388
                final String code    = result.getString(1);//getString(result, 1, code);
389
                codes.add("ESRI:"+code);
390
            }
391
            result.close();
392
        } catch (SQLException exception) {
393
            throw exception;
394
        }
395
        conn.close();
396
        return codes;
397
    }
398
    
399
    protected String getEsriTypeSqlString(CRSType type) {
400
    	if (type == CRSType.ProjectedCRSType) {
401
    		return "ESRI_PROJ <> ''";
402
    	}
403
    	if (type == CRSType.GeographicCRSType) {
404
    		return "ESRI_PROJ = ''";
405
    	}
406
    	return null;
407
    }
408

  
279 409
	@Override
280 410
	public DefaultCRSDefinition getCRSDefinition(String code) throws UnsupportedCoordinateReferenceSystemException {
281 411
		CoordinateReferenceSystem crs;
......
293 423
			throw new UnsupportedCoordinateReferenceSystemException(code, e);
294 424
		} catch (FactoryException e) {
295 425
			throw new UnsupportedCoordinateReferenceSystemException(code, e);
426
		} catch (Exception e) {
427
			throw new UnsupportedCoordinateReferenceSystemException(code, e);
296 428
		}
297 429
	}
298 430
	
......
559 691
	public void setSystemDataPath(File path) {
560 692
		System.setProperty(HsqlEpsgDatabase.DIRECTORY_KEY, path.getAbsolutePath() + "/" + EPSG_DB_SUBFOLDER);
561 693
	}
694
	
695
	@Override
696
	public File getSystemDataPath() {
697
		String directory = System.getProperty(HsqlEpsgDatabase.DIRECTORY_KEY);
698
		if (directory!=null) {
699
			return new File(directory);
700
		}
701
		return null;
702
	}
562 703

  
563 704
	@Override
564 705
	public void setUserDataPath(File path) {
org.gvsig.geotools.proj/trunk/org.gvsig.geotools.proj/org.gvsig.geotools.proj.catalog.impl/src/main/java/org/gvsig/geotools/proj/catalog/DefaultCRSDefinition.java
259 259
		if (wkt!=null) {
260 260
			return wkt;
261 261
		}
262
		if ("ESRI".equals(getAuthorityName())) {
263
			return export(Format.WKT1, WKTConvention.ESRI, 2);
264
		}
262 265
		return export(Format.WKT1);
263 266
	}
264 267
	
265 268
	@Override
266 269
	public String toString() {
267
		return (getIdentifier()!=null)?(getIdentifier() + " - " + getName()):getName();
270
		String id = getIdentifier();
271
		String name = getName();
272
		if (id != null) {
273
			if (name.startsWith(id)) {
274
				return name;
275
			}
276
			else {
277
				return id + " - " + name;
278
			}
279
		}
280
		return name;
268 281
	}
269
	
270 282

  
271 283
	@Override
272 284
	public String export(Format format) throws UnsupportedOperationException {

Also available in: Unified diff